diff --git a/foundry.toml b/foundry.toml index acbf4b9a..a6c68942 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,5 +1,5 @@ [profile.default] -solc_version = "0.8.23" +solc_version = "0.8.25" evm_version = "cancun" src = "src" out = "out" diff --git a/package.json b/package.json index 00642f4e..18f3e44a 100644 --- a/package.json +++ b/package.json @@ -29,24 +29,19 @@ "dependencies": { "@ERC4337/account-abstraction": "github:kopy-kat/account-abstraction#develop", "@ERC4337/account-abstraction-v0.6": "github:eth-infinitism/account-abstraction#v0.6.0", - "@prb/math": "^4.0.2", + "@prb/math": "^4.1.0", "@rhinestone/erc4337-validation": "^0.0.4", - "@rhinestone/module-bases": "github:rhinestonewtf/module-bases#1ea072eb328dd4bb1a540a52432ef98562314121", - "@rhinestone/safe7579": "github:rhinestonewtf/safe7579#v1.0.0", "@rhinestone/sentinellist": "github:rhinestonewtf/sentinellist", - "@rhinestone/registry": "github:rhinestonewtf/registry#v1.0", "@safe-global/safe-contracts": "^1.4.1", - "@zerodev/kernel": "github:kopy-kat/kernel#patch", "ds-test": "github:dapphub/ds-test", - "erc7579": "github:erc7579/erc7579-implementation", "excessively-safe-call": "github:nomad-xyz/ExcessivelySafeCall", "forge-std": "github:foundry-rs/forge-std", "solady": "github:vectorized/solady", "solarray": "github:sablier-labs/solarray" }, "devDependencies": { - "@changesets/cli": "^2.27.2", - "solhint": "^5.0.1" + "@changesets/cli": "^2.27.9", + "solhint": "^5.0.3" }, "files": [ "src", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 894beaa5..c4fbe277 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,53 +15,38 @@ importers: specifier: github:eth-infinitism/account-abstraction#v0.6.0 version: accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) '@prb/math': - specifier: ^4.0.2 + specifier: ^4.1.0 version: 4.1.0 '@rhinestone/erc4337-validation': specifier: ^0.0.4 version: 0.0.4(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - '@rhinestone/module-bases': - specifier: github:rhinestonewtf/module-bases#1ea072eb328dd4bb1a540a52432ef98562314121 - version: https://codeload.github.com/rhinestonewtf/module-bases/tar.gz/1ea072eb328dd4bb1a540a52432ef98562314121(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - '@rhinestone/registry': - specifier: github:rhinestonewtf/registry#v1.0 - version: https://codeload.github.com/rhinestonewtf/registry/tar.gz/1371979a97293e0c6188afcd923784f6a718ae7d - '@rhinestone/safe7579': - specifier: github:rhinestonewtf/safe7579#v1.0.0 - version: https://codeload.github.com/rhinestonewtf/safe7579/tar.gz/33f110f08ed5fcab75c29d7cfb93f7f3e4da76a7(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5))(typescript@4.9.5) '@rhinestone/sentinellist': specifier: github:rhinestonewtf/sentinellist - version: https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/67e42f0eb3cf355ddba5a017892f9cc28d924875 + version: https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/e722c5cc68c570d535bc3c9f85b3ce90cdc38807 '@safe-global/safe-contracts': specifier: ^1.4.1 version: 1.4.1(ethers@5.7.2) - '@zerodev/kernel': - specifier: github:kopy-kat/kernel#patch - version: kernel@https://codeload.github.com/kopy-kat/kernel/tar.gz/acc457ce5169929ce3ce0f06a9540f85ccc8b25f ds-test: specifier: github:dapphub/ds-test version: https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0 - erc7579: - specifier: github:erc7579/erc7579-implementation - version: erc7579-implementation@https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/2081c0f9dc31b2e054a91956968180ea3fccf307(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) excessively-safe-call: specifier: github:nomad-xyz/ExcessivelySafeCall version: '@nomad-xyz/excessively-safe-call@https://codeload.github.com/nomad-xyz/ExcessivelySafeCall/tar.gz/81cd99ce3e69117d665d7601c330ea03b97acce0' forge-std: specifier: github:foundry-rs/forge-std - version: https://codeload.github.com/foundry-rs/forge-std/tar.gz/da591f56d8884c5824c0c1b3103fbcfd81123c4c + version: https://codeload.github.com/foundry-rs/forge-std/tar.gz/0e7097750918380d84dd3cfdef595bee74dabb70 solady: specifier: github:vectorized/solady - version: https://codeload.github.com/vectorized/solady/tar.gz/0c60a26df3a34004006194ccc9fbf8e21be5c9bc + version: https://codeload.github.com/vectorized/solady/tar.gz/4c8be46dbc8d2d319cc6acf058a6aa79c0b78eb1 solarray: specifier: github:sablier-labs/solarray version: https://codeload.github.com/sablier-labs/solarray/tar.gz/6bf10cb34cdace52a3ba5fe437e78cc82df92684 devDependencies: '@changesets/cli': - specifier: ^2.27.2 + specifier: ^2.27.9 version: 2.27.9 solhint: - specifier: ^5.0.1 + specifier: ^5.0.3 version: 5.0.3(typescript@4.9.5) packages: @@ -404,32 +389,9 @@ packages: '@prb/math@4.1.0': resolution: {integrity: sha512-ef5Xrlh3BeX4xT5/Wi810dpEPq2bYPndRxgFIaKSU1F/Op/s8af03kyom+mfU7gEpvfIZ46xu8W0duiHplbBMg==} - '@rhinestone/checknsignatures@https://codeload.github.com/rhinestonewtf/checknsignatures/tar.gz/ef8e54b1df861681059b60be32ef9576030ea984': - resolution: {tarball: https://codeload.github.com/rhinestonewtf/checknsignatures/tar.gz/ef8e54b1df861681059b60be32ef9576030ea984} - version: 0.0.1 - - '@rhinestone/erc4337-validation@0.0.1-alpha.2': - resolution: {integrity: sha512-sxBSHoR0hV0rN2bv5HfINHR3RyBChfd0OWH0TP8nlA9FolJ1EezLByxcyrvAgi2QLQ2Zf2zVcNky1qYdfF4NjQ==} - '@rhinestone/erc4337-validation@0.0.4': resolution: {integrity: sha512-9GPvOvmM9j5ZZRCFeujPacUyByRnrGL22/5177hRzXh5mLq/A22EyvVIVNcsWMvNiLcHAV4dkkKpXaljxNOT9A==} - '@rhinestone/module-bases@https://codeload.github.com/rhinestonewtf/module-bases/tar.gz/1ea072eb328dd4bb1a540a52432ef98562314121': - resolution: {tarball: https://codeload.github.com/rhinestonewtf/module-bases/tar.gz/1ea072eb328dd4bb1a540a52432ef98562314121} - version: 0.0.1 - - '@rhinestone/registry@https://codeload.github.com/rhinestonewtf/registry/tar.gz/1371979a97293e0c6188afcd923784f6a718ae7d': - resolution: {tarball: https://codeload.github.com/rhinestonewtf/registry/tar.gz/1371979a97293e0c6188afcd923784f6a718ae7d} - version: 1.0.0 - - '@rhinestone/safe7579@https://codeload.github.com/rhinestonewtf/safe7579/tar.gz/33f110f08ed5fcab75c29d7cfb93f7f3e4da76a7': - resolution: {tarball: https://codeload.github.com/rhinestonewtf/safe7579/tar.gz/33f110f08ed5fcab75c29d7cfb93f7f3e4da76a7} - version: 1.0.0 - - '@rhinestone/sentinellist@https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/67e42f0eb3cf355ddba5a017892f9cc28d924875': - resolution: {tarball: https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/67e42f0eb3cf355ddba5a017892f9cc28d924875} - version: 1.0.1 - '@rhinestone/sentinellist@https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/e722c5cc68c570d535bc3c9f85b3ce90cdc38807': resolution: {tarball: https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/e722c5cc68c570d535bc3c9f85b3ce90cdc38807} version: 1.0.1 @@ -554,10 +516,6 @@ packages: abbrev@1.0.9: resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} - accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/6f02f5a28a20e804d0410b4b5b570dd4b076dcf9: - resolution: {tarball: https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/6f02f5a28a20e804d0410b4b5b570dd4b076dcf9} - version: 0.7.0 - accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/7174d6d845618dbd11cee68eefa715f5263690b6: resolution: {tarball: https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/7174d6d845618dbd11cee68eefa715f5263690b6} version: 0.6.0 @@ -689,8 +647,8 @@ packages: bn.js@4.11.6: resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} - bn.js@4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + bn.js@4.12.1: + resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} bn.js@5.2.1: resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} @@ -940,14 +898,6 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - erc7579-implementation@https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/0f321b8544cea7ad3be1b5669c7998329636ef84: - resolution: {tarball: https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/0f321b8544cea7ad3be1b5669c7998329636ef84} - version: 0.3.1 - - erc7579-implementation@https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/2081c0f9dc31b2e054a91956968180ea3fccf307: - resolution: {tarball: https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/2081c0f9dc31b2e054a91956968180ea3fccf307} - version: 0.3.1 - error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1108,14 +1058,6 @@ packages: resolution: {tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/8a225d81aa8e2e013580564588c79abb65eacc9e} version: 1.9.3 - forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/ae570fec082bfe1c1f45b0acca4a2b4f84d345ce: - resolution: {tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/ae570fec082bfe1c1f45b0acca4a2b4f84d345ce} - version: 1.7.6 - - forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/da591f56d8884c5824c0c1b3103fbcfd81123c4c: - resolution: {tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/da591f56d8884c5824c0c1b3103fbcfd81123c4c} - version: 1.9.4 - form-data-encoder@2.1.4: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} @@ -1441,10 +1383,6 @@ packages: resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} engines: {node: '>=10.0.0'} - kernel@https://codeload.github.com/kopy-kat/kernel/tar.gz/acc457ce5169929ce3ce0f06a9540f85ccc8b25f: - resolution: {tarball: https://codeload.github.com/kopy-kat/kernel/tar.gz/acc457ce5169929ce3ce0f06a9540f85ccc8b25f} - version: 3.0.0 - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1627,8 +1565,8 @@ packages: resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} engines: {node: '>=6.5.0', npm: '>=3'} - object-inspect@1.13.2: - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + object-inspect@1.13.3: + resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} engines: {node: '>= 0.4'} obliterator@2.0.4: @@ -1947,18 +1885,10 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - solady@https://codeload.github.com/vectorized/solady/tar.gz/0c60a26df3a34004006194ccc9fbf8e21be5c9bc: - resolution: {tarball: https://codeload.github.com/vectorized/solady/tar.gz/0c60a26df3a34004006194ccc9fbf8e21be5c9bc} - version: 0.0.264 - solady@https://codeload.github.com/vectorized/solady/tar.gz/4c8be46dbc8d2d319cc6acf058a6aa79c0b78eb1: resolution: {tarball: https://codeload.github.com/vectorized/solady/tar.gz/4c8be46dbc8d2d319cc6acf058a6aa79c0b78eb1} version: 0.0.267 - solady@https://codeload.github.com/vectorized/solady/tar.gz/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e: - resolution: {tarball: https://codeload.github.com/vectorized/solady/tar.gz/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e} - version: 0.0.168 - solarray@https://codeload.github.com/sablier-labs/solarray/tar.gz/6bf10cb34cdace52a3ba5fe437e78cc82df92684: resolution: {tarball: https://codeload.github.com/sablier-labs/solarray/tar.gz/6bf10cb34cdace52a3ba5fe437e78cc82df92684} version: 1.0.0 @@ -1968,10 +1898,6 @@ packages: engines: {node: '>=10.0.0'} hasBin: true - solhint@4.5.4: - resolution: {integrity: sha512-Cu1XiJXub2q1eCr9kkJ9VPv1sGcmj3V7Zb76B0CoezDOB9bu3DxKIFFH7ggCl9fWpEPD6xBmRLfZrYijkVmujQ==} - hasBin: true - solhint@5.0.3: resolution: {integrity: sha512-OLCH6qm/mZTCpplTXzXTJGId1zrtNuDYP5c2e6snIv/hdRVxPfBBz/bAlL91bY/Accavkayp2Zp2BaDSrLVXTQ==} hasBin: true @@ -2840,32 +2766,6 @@ snapshots: '@prb/math@4.1.0': {} - '@rhinestone/checknsignatures@https://codeload.github.com/rhinestonewtf/checknsignatures/tar.gz/ef8e54b1df861681059b60be32ef9576030ea984': - dependencies: - forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/0e7097750918380d84dd3cfdef595bee74dabb70 - solady: https://codeload.github.com/vectorized/solady/tar.gz/4c8be46dbc8d2d319cc6acf058a6aa79c0b78eb1 - - '@rhinestone/erc4337-validation@0.0.1-alpha.2(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5))(typescript@4.9.5)': - dependencies: - '@openzeppelin/contracts': 5.0.1 - account-abstraction: accountabstraction@https://codeload.github.com/kopy-kat/account-abstraction/tar.gz/c5887153fbfe3ed09b2637cac39873f96d676f38(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - account-abstraction-v0.6: accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - ds-test: https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0 - forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/0e7097750918380d84dd3cfdef595bee74dabb70 - prettier: 2.8.8 - solady: https://codeload.github.com/vectorized/solady/tar.gz/0c60a26df3a34004006194ccc9fbf8e21be5c9bc - solhint: 4.5.4(typescript@4.9.5) - transitivePeerDependencies: - - bufferutil - - encoding - - ethers - - hardhat - - lodash - - supports-color - - typechain - - typescript - - utf-8-validate - '@rhinestone/erc4337-validation@0.0.4(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5))': dependencies: '@openzeppelin/contracts': 5.0.1 @@ -2874,52 +2774,7 @@ snapshots: ds-test: https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0 forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/8a225d81aa8e2e013580564588c79abb65eacc9e prettier: 2.8.8 - solady: https://codeload.github.com/vectorized/solady/tar.gz/0c60a26df3a34004006194ccc9fbf8e21be5c9bc - transitivePeerDependencies: - - bufferutil - - encoding - - ethers - - hardhat - - lodash - - supports-color - - typechain - - utf-8-validate - - '@rhinestone/module-bases@https://codeload.github.com/rhinestonewtf/module-bases/tar.gz/1ea072eb328dd4bb1a540a52432ef98562314121(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5))': - dependencies: - '@ERC4337/account-abstraction': accountabstraction@https://codeload.github.com/kopy-kat/account-abstraction/tar.gz/c5887153fbfe3ed09b2637cac39873f96d676f38(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - erc7579: erc7579-implementation@https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/0f321b8544cea7ad3be1b5669c7998329636ef84(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/0e7097750918380d84dd3cfdef595bee74dabb70 - transitivePeerDependencies: - - bufferutil - - encoding - - ethers - - hardhat - - lodash - - supports-color - - typechain - - utf-8-validate - - '@rhinestone/registry@https://codeload.github.com/rhinestonewtf/registry/tar.gz/1371979a97293e0c6188afcd923784f6a718ae7d': - dependencies: - '@openzeppelin/contracts': 5.0.1 - forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/ae570fec082bfe1c1f45b0acca4a2b4f84d345ce - solady: https://codeload.github.com/vectorized/solady/tar.gz/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e - - '@rhinestone/safe7579@https://codeload.github.com/rhinestonewtf/safe7579/tar.gz/33f110f08ed5fcab75c29d7cfb93f7f3e4da76a7(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5))(typescript@4.9.5)': - dependencies: - '@ERC4337/account-abstraction': accountabstraction@https://codeload.github.com/kopy-kat/account-abstraction/tar.gz/c5887153fbfe3ed09b2637cac39873f96d676f38(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - '@ERC4337/account-abstraction-v0.6': accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - '@rhinestone/checknsignatures': https://codeload.github.com/rhinestonewtf/checknsignatures/tar.gz/ef8e54b1df861681059b60be32ef9576030ea984 - '@rhinestone/erc4337-validation': 0.0.1-alpha.2(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5))(typescript@4.9.5) - '@rhinestone/module-bases': https://codeload.github.com/rhinestonewtf/module-bases/tar.gz/1ea072eb328dd4bb1a540a52432ef98562314121(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - '@rhinestone/sentinellist': https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/67e42f0eb3cf355ddba5a017892f9cc28d924875 - '@safe-global/safe-contracts': 1.4.1(ethers@5.7.2) - ds-test: https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0 - erc7579: erc7579-implementation@https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/2081c0f9dc31b2e054a91956968180ea3fccf307(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/da591f56d8884c5824c0c1b3103fbcfd81123c4c - solady: https://codeload.github.com/vectorized/solady/tar.gz/0c60a26df3a34004006194ccc9fbf8e21be5c9bc - solarray: https://codeload.github.com/sablier-labs/solarray/tar.gz/6bf10cb34cdace52a3ba5fe437e78cc82df92684 + solady: https://codeload.github.com/vectorized/solady/tar.gz/4c8be46dbc8d2d319cc6acf058a6aa79c0b78eb1 transitivePeerDependencies: - bufferutil - encoding @@ -2928,13 +2783,8 @@ snapshots: - lodash - supports-color - typechain - - typescript - utf-8-validate - '@rhinestone/sentinellist@https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/67e42f0eb3cf355ddba5a017892f9cc28d924875': - dependencies: - forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/da591f56d8884c5824c0c1b3103fbcfd81123c4c - '@rhinestone/sentinellist@https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/e722c5cc68c570d535bc3c9f85b3ce90cdc38807': dependencies: forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/0e7097750918380d84dd3cfdef595bee74dabb70 @@ -3090,33 +2940,6 @@ snapshots: abbrev@1.0.9: {} - accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/6f02f5a28a20e804d0410b4b5b570dd4b076dcf9(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)): - dependencies: - '@nomiclabs/hardhat-etherscan': 2.1.8(hardhat@2.22.15(typescript@4.9.5)) - '@openzeppelin/contracts': 5.1.0 - '@thehubbleproject/bls': 0.5.1 - '@typechain/hardhat': 2.3.1(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - '@types/debug': 4.1.12 - '@types/mocha': 9.1.1 - debug: 4.3.7(supports-color@8.1.1) - ethereumjs-util: 7.1.5 - ethereumjs-wallet: 1.0.2 - hardhat-deploy: 0.11.45 - hardhat-deploy-ethers: 0.3.0-beta.13(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5)) - solidity-coverage: 0.8.13(hardhat@2.22.15(typescript@4.9.5)) - source-map-support: 0.5.21 - table: 6.8.2 - typescript: 4.9.5 - transitivePeerDependencies: - - bufferutil - - encoding - - ethers - - hardhat - - lodash - - supports-color - - typechain - - utf-8-validate - accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)): dependencies: '@gnosis.pm/safe-contracts': 1.3.0(ethers@5.7.2) @@ -3283,7 +3106,7 @@ snapshots: bn.js@4.11.6: {} - bn.js@4.12.0: {} + bn.js@4.12.1: {} bn.js@5.2.1: {} @@ -3532,7 +3355,7 @@ snapshots: elliptic@6.5.4: dependencies: - bn.js: 4.12.0 + bn.js: 4.12.1 brorand: 1.1.0 hash.js: 1.1.7 hmac-drbg: 1.0.1 @@ -3542,7 +3365,7 @@ snapshots: elliptic@6.6.0: dependencies: - bn.js: 4.12.0 + bn.js: 4.12.1 brorand: 1.1.0 hash.js: 1.1.7 hmac-drbg: 1.0.1 @@ -3561,40 +3384,6 @@ snapshots: env-paths@2.2.1: {} - erc7579-implementation@https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/0f321b8544cea7ad3be1b5669c7998329636ef84(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)): - dependencies: - '@rhinestone/sentinellist': https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/e722c5cc68c570d535bc3c9f85b3ce90cdc38807 - account-abstraction: accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/6f02f5a28a20e804d0410b4b5b570dd4b076dcf9(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - ds-test: https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0 - forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/0e7097750918380d84dd3cfdef595bee74dabb70 - solady: https://codeload.github.com/vectorized/solady/tar.gz/4c8be46dbc8d2d319cc6acf058a6aa79c0b78eb1 - transitivePeerDependencies: - - bufferutil - - encoding - - ethers - - hardhat - - lodash - - supports-color - - typechain - - utf-8-validate - - erc7579-implementation@https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/2081c0f9dc31b2e054a91956968180ea3fccf307(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)): - dependencies: - '@rhinestone/sentinellist': https://codeload.github.com/rhinestonewtf/sentinellist/tar.gz/67e42f0eb3cf355ddba5a017892f9cc28d924875 - account-abstraction: accountabstraction@https://codeload.github.com/eth-infinitism/account-abstraction/tar.gz/6f02f5a28a20e804d0410b4b5b570dd4b076dcf9(ethers@5.7.2)(hardhat@2.22.15(typescript@4.9.5))(lodash@4.17.21)(typechain@5.2.0(typescript@4.9.5)) - ds-test: https://codeload.github.com/dapphub/ds-test/tar.gz/e282159d5170298eb2455a6c05280ab5a73a4ef0 - forge-std: https://codeload.github.com/foundry-rs/forge-std/tar.gz/da591f56d8884c5824c0c1b3103fbcfd81123c4c - solady: https://codeload.github.com/vectorized/solady/tar.gz/0c60a26df3a34004006194ccc9fbf8e21be5c9bc - transitivePeerDependencies: - - bufferutil - - encoding - - ethers - - hardhat - - lodash - - supports-color - - typechain - - utf-8-validate - error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -3666,13 +3455,13 @@ snapshots: ethereumjs-abi@0.6.8: dependencies: - bn.js: 4.12.0 + bn.js: 4.12.1 ethereumjs-util: 6.2.1 ethereumjs-util@6.2.1: dependencies: '@types/bn.js': 4.11.6 - bn.js: 4.12.0 + bn.js: 4.12.1 create-hash: 1.2.0 elliptic: 6.6.0 ethereum-cryptography: 0.1.3 @@ -3816,10 +3605,6 @@ snapshots: forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/8a225d81aa8e2e013580564588c79abb65eacc9e: {} - forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/ae570fec082bfe1c1f45b0acca4a2b4f84d345ce: {} - - forge-std@https://codeload.github.com/foundry-rs/forge-std/tar.gz/da591f56d8884c5824c0c1b3103fbcfd81123c4c: {} - form-data-encoder@2.1.4: {} form-data@4.0.1: @@ -4238,8 +4023,6 @@ snapshots: node-gyp-build: 4.8.2 readable-stream: 3.6.2 - kernel@https://codeload.github.com/kopy-kat/kernel/tar.gz/acc457ce5169929ce3ce0f06a9540f85ccc8b25f: {} - keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -4411,7 +4194,7 @@ snapshots: bn.js: 4.11.6 strip-hex-prefix: 1.0.0 - object-inspect@1.13.2: {} + object-inspect@1.13.3: {} obliterator@2.0.4: {} @@ -4706,7 +4489,7 @@ snapshots: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - object-inspect: 1.13.2 + object-inspect: 1.13.3 signal-exit@3.0.7: {} @@ -4718,12 +4501,8 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - solady@https://codeload.github.com/vectorized/solady/tar.gz/0c60a26df3a34004006194ccc9fbf8e21be5c9bc: {} - solady@https://codeload.github.com/vectorized/solady/tar.gz/4c8be46dbc8d2d319cc6acf058a6aa79c0b78eb1: {} - solady@https://codeload.github.com/vectorized/solady/tar.gz/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e: {} - solarray@https://codeload.github.com/sablier-labs/solarray/tar.gz/6bf10cb34cdace52a3ba5fe437e78cc82df92684: {} solc@0.8.26(debug@4.3.7): @@ -4738,31 +4517,6 @@ snapshots: transitivePeerDependencies: - debug - solhint@4.5.4(typescript@4.9.5): - dependencies: - '@solidity-parser/parser': 0.18.0 - ajv: 6.12.6 - antlr4: 4.13.2 - ast-parents: 0.0.1 - chalk: 4.1.2 - commander: 10.0.1 - cosmiconfig: 8.3.6(typescript@4.9.5) - fast-diff: 1.3.0 - glob: 8.1.0 - ignore: 5.3.2 - js-yaml: 4.1.0 - latest-version: 7.0.0 - lodash: 4.17.21 - pluralize: 8.0.0 - semver: 7.6.3 - strip-ansi: 6.0.1 - table: 6.8.2 - text-table: 0.2.0 - optionalDependencies: - prettier: 2.8.8 - transitivePeerDependencies: - - typescript - solhint@5.0.3(typescript@4.9.5): dependencies: '@solidity-parser/parser': 0.18.0 diff --git a/remappings.txt b/remappings.txt index 5cb8e23c..39151b0b 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,22 +1,13 @@ -@rhinestone/=node_modules/@rhinestone/ -sentinellist/=node_modules/@rhinestone/sentinellist/src/ erc4337-validation/=node_modules/@rhinestone/erc4337-validation/src/ -safe7579/=node_modules/@rhinestone/safe7579/src/ -modulekit/=node_modules/@rhinestone/modulekit/src/ -module-bases/=node_modules/@rhinestone/module-bases/src/ -registry/=node_modules/@rhinestone/registry/src/ - @ERC4337/=node_modules/@ERC4337/ account-abstraction/=node_modules/@ERC4337/account-abstraction/contracts/ account-abstraction-v0.6/=node_modules/@ERC4337/account-abstraction-v0.6/contracts/ - +modulekit/=node_modules/@rhinestone/modulekit/src/ @openzeppelin/=node_modules/@openzeppelin/ @safe-global/=node_modules/@safe-global/ ds-test/=node_modules/ds-test/src/ -erc7579/=node_modules/erc7579/src/ forge-std/=node_modules/forge-std/src/ solady/=node_modules/solady/src/ solarray/=node_modules/solarray/src/ @prb/math/=node_modules/@prb/math/src/ -kernel/=node_modules/@zerodev/kernel/src/ ExcessivelySafeCall/=node_modules/excessively-safe-call/src/ diff --git a/src/Accounts.sol b/src/Accounts.sol index 6cf5f3e0..3f08e0d9 100644 --- a/src/Accounts.sol +++ b/src/Accounts.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-import */ -import { Execution, IERC7579Account } from "./external/ERC7579.sol"; +import { Execution } from "src/accounts/erc7579/lib/ExecutionLib.sol"; +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; diff --git a/src/Core.sol b/src/Core.sol index 05206d24..ede044ab 100644 --- a/src/Core.sol +++ b/src/Core.sol @@ -1,2 +1,2 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; diff --git a/src/Helpers.sol b/src/Helpers.sol index 6cf3c402..50535554 100644 --- a/src/Helpers.sol +++ b/src/Helpers.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-import */ import { ERC4337Helpers } from "./test/utils/ERC4337Helpers.sol"; diff --git a/src/Integrations.sol b/src/Integrations.sol index 39ba82f0..ff6d239f 100644 --- a/src/Integrations.sol +++ b/src/Integrations.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-import */ import { ERC20Integration } from "./integrations/ERC20.sol"; diff --git a/src/Interfaces.sol b/src/Interfaces.sol index 2487bf99..55d0b530 100644 --- a/src/Interfaces.sol +++ b/src/Interfaces.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-import */ /*////////////////////////////////////////////////////////////// ERCs //////////////////////////////////////////////////////////////*/ -import { IERC1271, EIP1271_MAGIC_VALUE } from "module-bases/interfaces/IERC1271.sol"; -import { IERC7484 } from "module-bases/interfaces/IERC7484.sol"; +import { IERC1271, EIP1271_MAGIC_VALUE } from "src/module-bases/interfaces/IERC1271.sol"; +import { IERC7484 } from "src/module-bases/interfaces/IERC7484.sol"; /*////////////////////////////////////////////////////////////// Modules //////////////////////////////////////////////////////////////*/ -import { IStatelessValidator } from "module-bases/interfaces/IStatelessValidator.sol"; +import { IStatelessValidator } from "src/module-bases/interfaces/IStatelessValidator.sol"; /*////////////////////////////////////////////////////////////// Misc @@ -21,4 +21,4 @@ import { IERC6682, IERC3156FlashLender, IERC3156FlashBorrower -} from "module-bases/interfaces/Flashloan.sol"; +} from "src/module-bases/interfaces/Flashloan.sol"; diff --git a/src/Mocks.sol b/src/Mocks.sol index e5057398..9300956b 100644 --- a/src/Mocks.sol +++ b/src/Mocks.sol @@ -1,24 +1,25 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-import */ /*////////////////////////////////////////////////////////////// Aux //////////////////////////////////////////////////////////////*/ -import { MockRegistry } from "module-bases/mocks/MockRegistry.sol"; -import { MockTarget } from "module-bases/mocks/MockTarget.sol"; -import { MockHookMultiPlexer } from "module-bases/mocks/MockHookMultiPlexer.sol"; -import { MockPolicy } from "module-bases/mocks/MockPolicy.sol"; +import { MockRegistry } from "src/module-bases/mocks/MockRegistry.sol"; +import { MockTarget } from "src/module-bases/mocks/MockTarget.sol"; +import { MockHookMultiPlexer } from "src/module-bases/mocks/MockHookMultiPlexer.sol"; +import { MockPolicy } from "src/module-bases/mocks/MockPolicy.sol"; /*////////////////////////////////////////////////////////////// Modules //////////////////////////////////////////////////////////////*/ -import { MockValidator } from "module-bases/mocks/MockValidator.sol"; -import { MockExecutor } from "module-bases/mocks/MockExecutor.sol"; -import { MockHook } from "module-bases/mocks/MockHook.sol"; -import { MockFallback } from "module-bases/mocks/MockFallback.sol"; +import { MockValidator } from "src/module-bases/mocks/MockValidator.sol"; +import { MockStatelessValidator } from "src/module-bases/mocks/MockStatelessValidator.sol"; +import { MockExecutor } from "src/module-bases/mocks/MockExecutor.sol"; +import { MockHook } from "src/module-bases/mocks/MockHook.sol"; +import { MockFallback } from "src/module-bases/mocks/MockFallback.sol"; /*////////////////////////////////////////////////////////////// Tokens diff --git a/src/ModuleKit.sol b/src/ModuleKit.sol index af4e881f..9ea450d8 100644 --- a/src/ModuleKit.sol +++ b/src/ModuleKit.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-import */ import { diff --git a/src/Modules.sol b/src/Modules.sol index a14e0a3a..2abb20e0 100644 --- a/src/Modules.sol +++ b/src/Modules.sol @@ -1,23 +1,24 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-import */ -import { ERC7579ValidatorBase } from "module-bases/ERC7579ValidatorBase.sol"; -import { ERC7579ExecutorBase } from "module-bases/ERC7579ExecutorBase.sol"; -import { ERC7579HookBase } from "module-bases/ERC7579HookBase.sol"; -import { ERC7579HookDestruct } from "module-bases/ERC7579HookDestruct.sol"; -import { ERC7579FallbackBase } from "module-bases/ERC7579FallbackBase.sol"; -import { SchedulingBase } from "module-bases/SchedulingBase.sol"; +import { ERC7579ValidatorBase } from "src/module-bases/ERC7579ValidatorBase.sol"; +import { ERC7579StatelessValidatorBase } from "src/module-bases/ERC7579StatelessValidatorBase.sol"; +import { ERC7579ExecutorBase } from "src/module-bases/ERC7579ExecutorBase.sol"; +import { ERC7579HookBase } from "src/module-bases/ERC7579HookBase.sol"; +import { ERC7579HookDestruct } from "src/module-bases/ERC7579HookDestruct.sol"; +import { ERC7579FallbackBase } from "src/module-bases/ERC7579FallbackBase.sol"; +import { SchedulingBase } from "src/module-bases/SchedulingBase.sol"; import { - IERC7579Validator, - IERC7579Executor, - IERC7579Fallback, - IERC7579Hook -} from "./external/ERC7579.sol"; -import { ERC7484RegistryAdapter } from "module-bases/ERC7484RegistryAdapter.sol"; -import { ERC7579ModuleBase } from "module-bases/ERC7579ModuleBase.sol"; -import { TrustedForwarder } from "module-bases/utils/TrustedForwarder.sol"; -import { ERC1271Policy } from "module-bases/ERC1271Policy.sol"; -import { ERC7579ActionPolicy } from "module-bases/ERC7579ActionPolicy.sol"; -import { ERC7579PolicyBase } from "module-bases/ERC7579PolicyBase.sol"; -import { ERC7579UserOpPolicy } from "module-bases/ERC7579UserOpPolicy.sol"; + IValidator as IERC7579Validator, + IExecutor as IERC7579Executor, + IFallback as IERC7579Fallback, + IHook as IERC7579Hook +} from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { ERC7484RegistryAdapter } from "src/module-bases/ERC7484RegistryAdapter.sol"; +import { ERC7579ModuleBase } from "src/module-bases/ERC7579ModuleBase.sol"; +import { TrustedForwarder } from "src/module-bases/utils/TrustedForwarder.sol"; +import { ERC1271Policy } from "src/module-bases/ERC1271Policy.sol"; +import { ERC7579ActionPolicy } from "src/module-bases/ERC7579ActionPolicy.sol"; +import { ERC7579PolicyBase } from "src/module-bases/ERC7579PolicyBase.sol"; +import { ERC7579UserOpPolicy } from "src/module-bases/ERC7579UserOpPolicy.sol"; diff --git a/src/accounts/common/interfaces/IERC4337Account.sol b/src/accounts/common/interfaces/IERC4337Account.sol new file mode 100644 index 00000000..2948acf8 --- /dev/null +++ b/src/accounts/common/interfaces/IERC4337Account.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; + +interface IERC4337Account { + /** + * Validate user's signature and nonce + * the entryPoint will make the call to the recipient only if this validation call returns + * successfully. + * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). + * This allows making a "simulation call" without a valid signature + * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to + * signal failure. + * + * @dev Must validate caller is the entryPoint. + * Must validate the signature and nonce + * @param userOp - The operation that is about to be executed. + * @param userOpHash - Hash of the user's request data. can be used as the basis for + * signature. + * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint. + * This is the minimum amount to transfer to the sender(entryPoint) + * to be + * able to make the call. The excess is left as a deposit in the + * entrypoint + * for future calls. Can be withdrawn anytime using + * "entryPoint.withdrawTo()". + * In case there is a paymaster in the request (or the current + * deposit is high + * enough), this value will be zero. + * @return validationData - Packaged ValidationData structure. use `_packValidationData` + * and + * `_unpackValidationData` to encode and decode. + * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark + * signature failure, + * otherwise, an address of an "authorizer" contract. + * <6-byte> validUntil - Last timestamp this operation is valid. 0 + * for "indefinite" + * <6-byte> validAfter - First timestamp this operation is valid + * If an account doesn't use time-range, it + * is enough to + * return SIG_VALIDATION_FAILED value (1) for + * signature failure. + * Note that the validation code cannot use block.timestamp (or + * block.number) directly. + */ + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) + external + payable + returns (uint256 validationData); + + /** + * Account may implement this execute method. + * passing this methodSig at the beginning of callData will cause the entryPoint to pass the + * full UserOp (and hash) + * to the account. + * The account should skip the methodSig, and use the callData (and optionally, other UserOp + * fields) + * + * @param userOp - The operation that was just validated. + * @param userOpHash - Hash of the user's request data. + */ + function executeUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + payable; +} diff --git a/src/accounts/common/interfaces/IERC7579Account.sol b/src/accounts/common/interfaces/IERC7579Account.sol new file mode 100644 index 00000000..537a1054 --- /dev/null +++ b/src/accounts/common/interfaces/IERC7579Account.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { CallType, ExecType, ModeCode } from "../lib/ModeLib.sol"; + +struct Execution { + address target; + uint256 value; + bytes callData; +} + +interface IERC7579Account { + event ModuleInstalled(uint256 moduleTypeId, address module); + event ModuleUninstalled(uint256 moduleTypeId, address module); + + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by ERC-4337 EntryPoint.sol + * @dev Ensure adequate authorization control: i.e. onlyEntryPointOrSelf + * + * @dev MSA MUST implement this function signature. + * If a mode is requested that is not supported by the Account, it MUST revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function execute(ModeCode mode, bytes calldata executionCalldata) external payable; + + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by Executor Modules + * @dev Ensure adequate authorization control: i.e. onlyExecutorModule + * + * @dev MSA MUST implement this function signature. + * If a mode is requested that is not supported by the Account, it MUST revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function executeFromExecutor( + ModeCode mode, + bytes calldata executionCalldata + ) + external + payable + returns (bytes[] memory returnData); + + /** + * @dev ERC-1271 isValidSignature + * This function is intended to be used to validate a smart account signature + * and may forward the call to a validator module + * + * @param hash The hash of the data that is signed + * @param data The data that is signed + */ + function isValidSignature(bytes32 hash, bytes calldata data) external view returns (bytes4); + + /** + * @dev installs a Module of a certain type on the smart account + * @dev Implement Authorization control of your chosing + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param initData arbitrary data that may be required on the module during `onInstall` + * initialization. + */ + function installModule( + uint256 moduleTypeId, + address module, + bytes calldata initData + ) + external + payable; + + /** + * @dev uninstalls a Module of a certain type on the smart account + * @dev Implement Authorization control of your chosing + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param deInitData arbitrary data that may be required on the module during `onUninstall` + * de-initialization. + */ + function uninstallModule( + uint256 moduleTypeId, + address module, + bytes calldata deInitData + ) + external + payable; + + /** + * Function to check if the account supports a certain CallType or ExecType (see ModeLib.sol) + * @param encodedMode the encoded mode + */ + function supportsExecutionMode(ModeCode encodedMode) external view returns (bool); + + /** + * Function to check if the account supports installation of a certain module type Id + * @param moduleTypeId the module type ID according the ERC-7579 spec + */ + function supportsModule(uint256 moduleTypeId) external view returns (bool); + + /** + * Function to check if the account has a certain module installed + * @param moduleTypeId the module type ID according the ERC-7579 spec + * Note: keep in mind that some contracts can be multiple module types at the same time. It + * thus may be necessary to query multiple module types + * @param module the module address + * @param additionalContext additional context data that the smart account may interpret to + * identifiy conditions under which the module is installed. + * usually this is not necessary, but for some special hooks that + * are stored in mappings, this param might be needed + */ + function isModuleInstalled( + uint256 moduleTypeId, + address module, + bytes calldata additionalContext + ) + external + view + returns (bool); + + /** + * @dev Returns the account id of the smart account + * @return accountImplementationId the account id of the smart account + * the accountId should be structured like so: + * "vendorname.accountname.semver" + */ + function accountId() external view returns (string memory accountImplementationId); +} diff --git a/src/accounts/common/interfaces/IERC7579Modules.sol b/src/accounts/common/interfaces/IERC7579Modules.sol new file mode 100644 index 00000000..c984c87f --- /dev/null +++ b/src/accounts/common/interfaces/IERC7579Modules.sol @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; + +uint256 constant VALIDATION_SUCCESS = 0; +uint256 constant VALIDATION_FAILED = 1; + +uint256 constant MODULE_TYPE_VALIDATOR = 1; +uint256 constant MODULE_TYPE_EXECUTOR = 2; +uint256 constant MODULE_TYPE_FALLBACK = 3; +uint256 constant MODULE_TYPE_HOOK = 4; + +interface IModule { + error AlreadyInitialized(address smartAccount); + error NotInitialized(address smartAccount); + + /** + * @dev This function is called by the smart account during installation of the module + * @param data arbitrary data that may be required on the module during `onInstall` + * initialization + * + * MUST revert on error (i.e. if module is already enabled) + */ + function onInstall(bytes calldata data) external; + + /** + * @dev This function is called by the smart account during uninstallation of the module + * @param data arbitrary data that may be required on the module during `onUninstall` + * de-initialization + * + * MUST revert on error + */ + function onUninstall(bytes calldata data) external; + + /** + * @dev Returns boolean value if module is a certain type + * @param moduleTypeId the module type ID according the ERC-7579 spec + * + * MUST return true if the module is of the given type and false otherwise + */ + function isModuleType(uint256 moduleTypeId) external view returns (bool); + + /** + * @dev Returns if the module was already initialized for a provided smartaccount + */ + function isInitialized(address smartAccount) external view returns (bool); +} + +interface IValidator is IModule { + error InvalidTargetAddress(address target); + + /** + * @dev Validates a transaction on behalf of the account. + * This function is intended to be called by the MSA during the ERC-4337 validaton phase + * Note: solely relying on bytes32 hash and signature is not sufficient for some + * validation implementations (i.e. SessionKeys often need access to userOp.calldata) + * @param userOp The user operation to be validated. The userOp MUST NOT contain any metadata. + * The MSA MUST clean up the userOp before sending it to the validator. + * @param userOpHash The hash of the user operation to be validated + * @return return value according to ERC-4337 + */ + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + payable + returns (uint256); + + /** + * Validator can be used for ERC-1271 validation + */ + function isValidSignatureWithSender( + address sender, + bytes32 hash, + bytes calldata data + ) + external + view + returns (bytes4); +} + +interface IExecutor is IModule { } + +interface IHook is IModule { + function preCheck( + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + external + returns (bytes memory hookData); + + function postCheck(bytes calldata hookData) external; +} + +interface IFallback is IModule { } + +interface IPolicy is IModule { + function checkUserOpPolicy( + bytes32 id, + PackedUserOperation calldata userOp + ) + external + payable + returns (uint256); + function checkSignaturePolicy( + bytes32 id, + address sender, + bytes32 hash, + bytes calldata sig + ) + external + view + returns (uint256); +} + +interface ISigner is IModule { + function checkUserOpSignature( + bytes32 id, + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + payable + returns (uint256); + function checkSignature( + bytes32 id, + address sender, + bytes32 hash, + bytes calldata sig + ) + external + view + returns (bytes4); +} diff --git a/src/accounts/common/lib/ModeLib.sol b/src/accounts/common/lib/ModeLib.sol new file mode 100644 index 00000000..4500cd65 --- /dev/null +++ b/src/accounts/common/lib/ModeLib.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.0 <0.9.0; + +/** + * @title ModeLib + * @author rhinestone | zeroknots.eth, Konrad Kopp (@kopy-kat) + * To allow smart accounts to be very simple, but allow for more complex execution, A custom mode + * encoding is used. + * Function Signature of execute function: + * function execute(ModeCode mode, bytes calldata executionCalldata) external payable; + * This allows for a single bytes32 to be used to encode the execution mode, calltype, execType and + * context. + * NOTE: Simple Account implementations only have to scope for the most significant byte. Account that + * implement + * more complex execution modes may use the entire bytes32. + * + * |--------------------------------------------------------------------| + * | CALLTYPE | EXECTYPE | UNUSED | ModeSelector | ModePayload | + * |--------------------------------------------------------------------| + * | 1 byte | 1 byte | 4 bytes | 4 bytes | 22 bytes | + * |--------------------------------------------------------------------| + * + * CALLTYPE: 1 byte + * CallType is used to determine how the executeCalldata paramter of the execute function has to be + * decoded. + * It can be either single, batch or delegatecall. In the future different calls could be added. + * CALLTYPE can be used by a validation module to determine how to decode . + * + * EXECTYPE: 1 byte + * ExecType is used to determine how the account should handle the execution. + * It can indicate if the execution should revert on failure or continue execution. + * In the future more execution modes may be added. + * Default Behavior (EXECTYPE = 0x00) is to revert on a single failed execution. If one execution in + * a batch fails, the entire batch is reverted + * + * UNUSED: 4 bytes + * Unused bytes are reserved for future use. + * + * ModeSelector: bytes4 + * The "optional" mode selector can be used by account vendors, to implement custom behavior in + * their accounts. + * the way a ModeSelector is to be calculated is bytes4(keccak256("vendorname.featurename")) + * this is to prevent collisions between different vendors, while allowing innovation and the + * development of new features without coordination between ERC-7579 implementing accounts + * + * ModePayload: 22 bytes + * Mode payload is used to pass additional data to the smart account execution, this may be + * interpreted depending on the ModeSelector + * + * ExecutionCallData: n bytes + * single, delegatecall or batch exec abi.encoded as bytes + */ + +// Custom type for improved developer experience +type ModeCode is bytes32; + +type CallType is bytes1; + +type ExecType is bytes1; + +type ModeSelector is bytes4; + +type ModePayload is bytes22; + +// Default CallType +CallType constant CALLTYPE_SINGLE = CallType.wrap(0x00); +// Batched CallType +CallType constant CALLTYPE_BATCH = CallType.wrap(0x01); +CallType constant CALLTYPE_STATIC = CallType.wrap(0xFE); +// @dev Implementing delegatecall is OPTIONAL! +// implement delegatecall with extreme care. +CallType constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF); + +// @dev default behavior is to revert on failure +// To allow very simple accounts to use mode encoding, the default behavior is to revert on failure +// Since this is value 0x00, no additional encoding is required for simple accounts +ExecType constant EXECTYPE_DEFAULT = ExecType.wrap(0x00); +// @dev account may elect to change execution behavior. For example "try exec" / "allow fail" +ExecType constant EXECTYPE_TRY = ExecType.wrap(0x01); + +ModeSelector constant MODE_DEFAULT = ModeSelector.wrap(bytes4(0x00000000)); +// Example declaration of a custom mode selector +ModeSelector constant MODE_OFFSET = ModeSelector.wrap(bytes4(keccak256("default.mode.offset"))); + +/** + * @dev ModeLib is a helper library to encode/decode ModeCodes + */ +library ModeLib { + function decode(ModeCode mode) + internal + pure + returns ( + CallType _calltype, + ExecType _execType, + ModeSelector _modeSelector, + ModePayload _modePayload + ) + { + // solhint-disable-next-line no-inline-assembly + assembly { + _calltype := mode + _execType := shl(8, mode) + _modeSelector := shl(48, mode) + _modePayload := shl(80, mode) + } + } + + function encode( + CallType callType, + ExecType execType, + ModeSelector mode, + ModePayload payload + ) + internal + pure + returns (ModeCode) + { + return ModeCode.wrap( + bytes32( + abi.encodePacked(callType, execType, bytes4(0), ModeSelector.unwrap(mode), payload) + ) + ); + } + + function encodeSimpleBatch() internal pure returns (ModeCode mode) { + mode = encode(CALLTYPE_BATCH, EXECTYPE_DEFAULT, MODE_DEFAULT, ModePayload.wrap(0x00)); + } + + function encodeSimpleSingle() internal pure returns (ModeCode mode) { + mode = encode(CALLTYPE_SINGLE, EXECTYPE_DEFAULT, MODE_DEFAULT, ModePayload.wrap(0x00)); + } + + function getCallType(ModeCode mode) internal pure returns (CallType calltype) { + // solhint-disable-next-line no-inline-assembly + assembly { + calltype := mode + } + } +} + +using { eqModeSelector as == } for ModeSelector global; +using { eqCallType as == } for CallType global; +using { neqCallType as != } for CallType global; +using { eqExecType as == } for ExecType global; + +function eqCallType(CallType a, CallType b) pure returns (bool) { + return CallType.unwrap(a) == CallType.unwrap(b); +} + +function neqCallType(CallType a, CallType b) pure returns (bool) { + return CallType.unwrap(a) == CallType.unwrap(b); +} + +function eqExecType(ExecType a, ExecType b) pure returns (bool) { + return ExecType.unwrap(a) == ExecType.unwrap(b); +} + +function eqModeSelector(ModeSelector a, ModeSelector b) pure returns (bool) { + return ModeSelector.unwrap(a) == ModeSelector.unwrap(b); +} diff --git a/src/accounts/erc7579/ERC7579Factory.sol b/src/accounts/erc7579/ERC7579Factory.sol index 6b699118..12c50d59 100644 --- a/src/accounts/erc7579/ERC7579Factory.sol +++ b/src/accounts/erc7579/ERC7579Factory.sol @@ -1,28 +1,26 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; -import "../../external/ERC7579.sol"; import { IAccountFactory } from "src/accounts/interface/IAccountFactory.sol"; -import { IMSA } from "erc7579/interfaces/IMSA.sol"; -import { MSAProxy } from "erc7579/utils/MSAProxy.sol"; +import { IMSA } from "./interfaces/IMSA.sol"; +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; +import { + IERC7579Bootstrap, + BootstrapConfig as ERC7579BootstrapConfig +} from "src/accounts/erc7579/interfaces/IERC7579Bootstrap.sol"; +import { ERC7579Precompiles } from "src/test/precompiles/ERC7579Precompiles.sol"; -contract ERC7579Factory is IAccountFactory { - ERC7579Account internal implementation; - ERC7579Bootstrap internal bootstrapDefault; +contract ERC7579Factory is IAccountFactory, ERC7579Precompiles { + IERC7579Account internal implementation; + IERC7579Bootstrap internal bootstrapDefault; function init() public override { - implementation = new ERC7579Account(); - bootstrapDefault = new ERC7579Bootstrap(); + implementation = deployERC7579Account(); + bootstrapDefault = deployERC7579Bootstrap(); } function createAccount(bytes32 salt, bytes memory initCode) public override returns (address) { - address account = address( - new MSAProxy{ salt: salt }( - address(implementation), abi.encodeCall(IMSA.initializeAccount, initCode) - ) - ); - - return account; + return deployMSAPRoxy(salt, address(implementation), initCode); } function getAddress( @@ -41,7 +39,7 @@ contract ERC7579Factory is IAccountFactory { salt, keccak256( abi.encodePacked( - type(MSAProxy).creationCode, + MSAPROXY_BYTECODE, abi.encode( address(implementation), abi.encodeCall(IMSA.initializeAccount, initCode) @@ -73,7 +71,7 @@ contract ERC7579Factory is IAccountFactory { ERC7579BootstrapConfig[] memory _fallBacks = new ERC7579BootstrapConfig[](0); _init = abi.encode( address(bootstrapDefault), - abi.encodeCall(ERC7579Bootstrap.initMSA, (_validators, _executors, _hook, _fallBacks)) + abi.encodeCall(IERC7579Bootstrap.initMSA, (_validators, _executors, _hook, _fallBacks)) ); } diff --git a/src/accounts/erc7579/interfaces/IERC7579Bootstrap.sol b/src/accounts/erc7579/interfaces/IERC7579Bootstrap.sol new file mode 100644 index 00000000..14bbad7a --- /dev/null +++ b/src/accounts/erc7579/interfaces/IERC7579Bootstrap.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { IModule } from "../../common/interfaces/IERC7579Modules.sol"; + +struct BootstrapConfig { + address module; + bytes data; +} + +interface IERC7579Bootstrap { + function singleInitMSA(IModule validator, bytes calldata data) external; + + /** + * This function is intended to be called by the MSA with a delegatecall. + * Make sure that the MSA already initilazed the linked lists in the ModuleManager prior to + * calling this function + */ + function initMSA( + BootstrapConfig[] calldata $valdiators, + BootstrapConfig[] calldata $executors, + BootstrapConfig calldata _hook, + BootstrapConfig[] calldata _fallbacks + ) + external; + + function _getInitMSACalldata( + BootstrapConfig[] calldata $valdiators, + BootstrapConfig[] calldata $executors, + BootstrapConfig calldata _hook, + BootstrapConfig[] calldata _fallbacks + ) + external + view + returns (bytes memory init); +} diff --git a/src/accounts/erc7579/interfaces/IMSA.sol b/src/accounts/erc7579/interfaces/IMSA.sol new file mode 100644 index 00000000..90db12ca --- /dev/null +++ b/src/accounts/erc7579/interfaces/IMSA.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { IERC7579Account } from "../../common/interfaces/IERC7579Account.sol"; +import { IERC4337Account } from "../../common/interfaces/IERC4337Account.sol"; + +import { CallType, ExecType, ModeCode } from "../../common/lib/ModeLib.sol"; + +interface IMSA is IERC7579Account, IERC4337Account { + // Error thrown when an unsupported ModuleType is requested + error UnsupportedModuleType(uint256 moduleTypeId); + // Error thrown when an execution with an unsupported CallType was made + error UnsupportedCallType(CallType callType); + // Error thrown when an execution with an unsupported ExecType was made + error UnsupportedExecType(ExecType execType); + // Error thrown when account initialization fails + error AccountInitializationFailed(); + // Error thrown when account installs/unistalls module with mismatched input `moduleTypeId` + error MismatchModuleTypeId(uint256 moduleTypeId); + + /** + * @dev Initializes the account. Function might be called directly, or by a Factory + * @param data. encoded data that can be used during the initialization phase + */ + function initializeAccount(bytes calldata data) external payable; +} diff --git a/src/accounts/erc7579/lib/ExecutionLib.sol b/src/accounts/erc7579/lib/ExecutionLib.sol new file mode 100644 index 00000000..41e8b8d9 --- /dev/null +++ b/src/accounts/erc7579/lib/ExecutionLib.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { Execution } from "../../common/interfaces/IERC7579Account.sol"; + +/** + * Helper Library for decoding Execution calldata + * malloc for memory allocation is bad for gas. use this assembly instead + */ +library ExecutionLib { + function decodeBatch(bytes calldata callData) + internal + pure + returns (Execution[] calldata executionBatch) + { + /* + * Batch Call Calldata Layout + * Offset (in bytes) | Length (in bytes) | Contents + * 0x0 | 0x4 | bytes4 function selector + * 0x4 | - | + abi.encode(IERC7579Execution.Execution[]) + */ + // solhint-disable-next-line no-inline-assembly + assembly ("memory-safe") { + let dataPointer := add(callData.offset, calldataload(callData.offset)) + + // Extract the ERC7579 Executions + executionBatch.offset := add(dataPointer, 32) + executionBatch.length := calldataload(dataPointer) + } + } + + function encodeBatch(Execution[] memory executions) + internal + pure + returns (bytes memory callData) + { + callData = abi.encode(executions); + } + + function decodeSingle(bytes calldata executionCalldata) + internal + pure + returns (address target, uint256 value, bytes calldata callData) + { + target = address(bytes20(executionCalldata[0:20])); + value = uint256(bytes32(executionCalldata[20:52])); + callData = executionCalldata[52:]; + } + + function encodeSingle( + address target, + uint256 value, + bytes memory callData + ) + internal + pure + returns (bytes memory userOpCalldata) + { + userOpCalldata = abi.encodePacked(target, value, callData); + } +} diff --git a/src/accounts/interface/IAccountFactory.sol b/src/accounts/interface/IAccountFactory.sol index e6c54b01..1f3422d2 100644 --- a/src/accounts/interface/IAccountFactory.sol +++ b/src/accounts/interface/IAccountFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; interface IAccountFactory { function init() external; @@ -11,7 +11,7 @@ interface IAccountFactory { external returns (address account); - function getAddress(bytes32 salt, bytes memory initCode) external view returns (address); + function getAddress(bytes32 salt, bytes memory initCode) external returns (address); function getInitData( address validator, diff --git a/src/accounts/kernel/KernelFactory.sol b/src/accounts/kernel/KernelFactory.sol index 966e844d..cd759377 100644 --- a/src/accounts/kernel/KernelFactory.sol +++ b/src/accounts/kernel/KernelFactory.sol @@ -1,23 +1,27 @@ -pragma solidity >=0.8.0 <0.9.0; +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; -import { KernelFactory as KernelAccountFactory } from "kernel/factory/KernelFactory.sol"; -import { Kernel } from "kernel/Kernel.sol"; -import { IEntryPoint } from "kernel/interfaces/IEntryPoint.sol"; +import { IKernelFactory as IKernelAccountFactory } from + "src/accounts/kernel/interfaces/IKernelFactory.sol"; +import { IKernel } from "src/accounts/kernel/interfaces/IKernel.sol"; +import { IEntryPoint } from "@ERC4337/account-abstraction/contracts/interfaces/IEntryPoint.sol"; import { ENTRYPOINT_ADDR } from "../../test/predeploy/EntryPoint.sol"; -import { ValidatorLib } from "kernel/utils/ValidationTypeLib.sol"; -import { ValidationId } from "kernel/types/Types.sol"; -import { IValidator, IHook } from "kernel/interfaces/IERC7579Modules.sol"; +import { ValidatorLib } from "src/accounts/kernel/lib/ValidationTypeLib.sol"; +import { ValidationId } from "src/accounts/kernel/types/Types.sol"; +import { IValidator } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { IHook } from "src/accounts/kernel/interfaces/IERC7579Modules.sol"; import { IAccountFactory } from "src/accounts/interface/IAccountFactory.sol"; import { MockHookMultiPlexer } from "src/Mocks.sol"; +import { KernelPrecompiles } from "src/test/precompiles/KernelPrecompiles.sol"; -contract KernelFactory is IAccountFactory { - KernelAccountFactory internal factory; - Kernel internal kernalImpl; +contract KernelFactory is IAccountFactory, KernelPrecompiles { + IKernelAccountFactory internal factory; + IKernel internal kernelImpl; MockHookMultiPlexer public hookMultiPlexer; function init() public override { - kernalImpl = new Kernel(IEntryPoint(ENTRYPOINT_ADDR)); - factory = new KernelAccountFactory(address(kernalImpl)); + kernelImpl = deployKernel(ENTRYPOINT_ADDR); + factory = deployKernelFactory(address(kernelImpl)); hookMultiPlexer = new MockHookMultiPlexer(); } @@ -32,7 +36,7 @@ contract KernelFactory is IAccountFactory { account = factory.createAccount(data, salt); } - function getAddress(bytes32 salt, bytes memory data) public view override returns (address) { + function getAddress(bytes32 salt, bytes memory data) public override returns (address) { return factory.getAddress(data, salt); } @@ -48,7 +52,8 @@ contract KernelFactory is IAccountFactory { ValidationId rootValidator = ValidatorLib.validatorToIdentifier(IValidator(validator)); _init = abi.encodeCall( - Kernel.initialize, (rootValidator, IHook(address(hookMultiPlexer)), initData, hex"00") + IKernel.initialize, + (rootValidator, IHook(address(hookMultiPlexer)), initData, hex"00", new bytes[](0)) ); } diff --git a/src/accounts/kernel/interfaces/IAccount.sol b/src/accounts/kernel/interfaces/IAccount.sol new file mode 100644 index 00000000..5e1d5135 --- /dev/null +++ b/src/accounts/kernel/interfaces/IAccount.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; +import "../types/Types.sol"; + +interface IAccount { + /** + * Validate user's signature and nonce + * the entryPoint will make the call to the recipient only if this validation call returns + * successfully. + * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). + * This allows making a "simulation call" without a valid signature + * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to + * signal failure. + * + * @dev Must validate caller is the entryPoint. + * Must validate the signature and nonce + * @param userOp - The operation that is about to be executed. + * @param userOpHash - Hash of the user's request data. can be used as the basis for + * signature. + * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint. + * This is the minimum amount to transfer to the sender(entryPoint) + * to be + * able to make the call. The excess is left as a deposit in the + * entrypoint + * for future calls. Can be withdrawn anytime using + * "entryPoint.withdrawTo()". + * In case there is a paymaster in the request (or the current + * deposit is high + * enough), this value will be zero. + * @return validationData - Packaged ValidationData structure. use `_packValidationData` + * and + * `_unpackValidationData` to encode and decode. + * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark + * signature failure, + * otherwise, an address of an "authorizer" contract. + * <6-byte> validUntil - Last timestamp this operation is valid. 0 + * for "indefinite" + * <6-byte> validAfter - First timestamp this operation is valid + * If an account doesn't use time-range, it + * is enough to + * return SIG_VALIDATION_FAILED value (1) for + * signature failure. + * Note that the validation code cannot use block.timestamp (or + * block.number) directly. + */ + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) + external + payable + returns (ValidationData validationData); +} diff --git a/src/accounts/kernel/interfaces/IAccountExecute.sol b/src/accounts/kernel/interfaces/IAccountExecute.sol new file mode 100644 index 00000000..a77c257e --- /dev/null +++ b/src/accounts/kernel/interfaces/IAccountExecute.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; + +interface IAccountExecute { + /** + * Account may implement this execute method. + * passing this methodSig at the beginning of callData will cause the entryPoint to pass the + * full UserOp (and hash) + * to the account. + * The account should skip the methodSig, and use the callData (and optionally, other UserOp + * fields) + * + * @param userOp - The operation that was just validated. + * @param userOpHash - Hash of the user's request data. + */ + function executeUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + payable; +} diff --git a/src/accounts/kernel/interfaces/IERC7579Account.sol b/src/accounts/kernel/interfaces/IERC7579Account.sol new file mode 100644 index 00000000..0a779a16 --- /dev/null +++ b/src/accounts/kernel/interfaces/IERC7579Account.sol @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { CallType, ExecType, ExecMode } from "../lib/ExecLib.sol"; +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; + +struct Execution { + address target; + uint256 value; + bytes callData; +} + +interface IERC7579Account { + event ModuleInstalled(uint256 moduleTypeId, address module); + event ModuleUninstalled(uint256 moduleTypeId, address module); + + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by ERC-4337 EntryPoint.sol + * @dev Ensure adequate authorization control: i.e. onlyEntryPointOrSelf + * + * @dev MSA MUST implement this function signature. + * If a mode is requested that is not supported by the Account, it MUST revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function execute(ExecMode mode, bytes calldata executionCalldata) external payable; + + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by Executor Modules + * @dev Ensure adequate authorization control: i.e. onlyExecutorModule + * + * @dev MSA MUST implement this function signature. + * If a mode is requested that is not supported by the Account, it MUST revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function executeFromExecutor( + ExecMode mode, + bytes calldata executionCalldata + ) + external + payable + returns (bytes[] memory returnData); + + /** + * @dev ERC-1271 isValidSignature + * This function is intended to be used to validate a smart account signature + * and may forward the call to a validator module + * + * @param hash The hash of the data that is signed + * @param data The data that is signed + */ + function isValidSignature(bytes32 hash, bytes calldata data) external view returns (bytes4); + + /** + * @dev installs a Module of a certain type on the smart account + * @dev Implement Authorization control of your choosing + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param initData arbitrary data that may be required on the module during `onInstall` + * initialization. + */ + function installModule( + uint256 moduleTypeId, + address module, + bytes calldata initData + ) + external + payable; + + /** + * @dev uninstalls a Module of a certain type on the smart account + * @dev Implement Authorization control of your choosing + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param deInitData arbitrary data that may be required on the module during `onUninstall` + * de-initialization. + */ + function uninstallModule( + uint256 moduleTypeId, + address module, + bytes calldata deInitData + ) + external + payable; + + /** + * Function to check if the account supports a certain CallType or ExecType (see ModeLib.sol) + * @param encodedMode the encoded mode + */ + function supportsExecutionMode(ExecMode encodedMode) external view returns (bool); + + /** + * Function to check if the account supports installation of a certain module type Id + * @param moduleTypeId the module type ID according the ERC-7579 spec + */ + function supportsModule(uint256 moduleTypeId) external view returns (bool); + + /** + * Function to check if the account has a certain module installed + * @param moduleTypeId the module type ID according the ERC-7579 spec + * Note: keep in mind that some contracts can be multiple module types at the same time. It + * thus may be necessary to query multiple module types + * @param module the module address + * @param additionalContext additional context data that the smart account may interpret to + * identify conditions under which the module is installed. + * usually this is not necessary, but for some special hooks that + * are stored in mappings, this param might be needed + */ + function isModuleInstalled( + uint256 moduleTypeId, + address module, + bytes calldata additionalContext + ) + external + view + returns (bool); + + /** + * @dev Returns the account id of the smart account + * @return accountImplementationId the account id of the smart account + * the accountId should be structured like so: + * "vendorname.accountname.semver" + */ + function accountId() external view returns (string memory accountImplementationId); +} diff --git a/src/accounts/kernel/interfaces/IERC7579Modules.sol b/src/accounts/kernel/interfaces/IERC7579Modules.sol new file mode 100644 index 00000000..f1c89aeb --- /dev/null +++ b/src/accounts/kernel/interfaces/IERC7579Modules.sol @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; + +interface IModule { + error AlreadyInitialized(address smartAccount); + error NotInitialized(address smartAccount); + + /** + * @dev This function is called by the smart account during installation of the module + * @param data arbitrary data that may be required on the module during `onInstall` + * initialization + * + * MUST revert on error (i.e. if module is already enabled) + */ + function onInstall(bytes calldata data) external payable; + + /** + * @dev This function is called by the smart account during uninstallation of the module + * @param data arbitrary data that may be required on the module during `onUninstall` + * de-initialization + * + * MUST revert on error + */ + function onUninstall(bytes calldata data) external payable; + + /** + * @dev Returns boolean value if module is a certain type + * @param moduleTypeId the module type ID according the ERC-7579 spec + * + * MUST return true if the module is of the given type and false otherwise + */ + function isModuleType(uint256 moduleTypeId) external view returns (bool); + + /** + * @dev Returns if the module was already initialized for a provided smartaccount + */ + function isInitialized(address smartAccount) external view returns (bool); +} + +interface IValidator is IModule { + error InvalidTargetAddress(address target); + + /** + * @dev Validates a transaction on behalf of the account. + * This function is intended to be called by the MSA during the ERC-4337 validation + * phase + * Note: solely relying on bytes32 hash and signature is not sufficient for some + * validation implementations (i.e. SessionKeys often need access to userOp.calldata) + * @param userOp The user operation to be validated. The userOp MUST NOT contain any metadata. + * The MSA MUST clean up the userOp before sending it to the validator. + * @param userOpHash The hash of the user operation to be validated + * @return return value according to ERC-4337 + */ + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + payable + returns (uint256); + + /** + * Validator can be used for ERC-1271 validation + */ + function isValidSignatureWithSender( + address sender, + bytes32 hash, + bytes calldata data + ) + external + view + returns (bytes4); +} + +interface IExecutor is IModule { } + +interface IHook is IModule { + function preCheck( + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + external + payable + returns (bytes memory hookData); + + function postCheck(bytes calldata hookData) external payable; +} + +interface IFallback is IModule { } + +interface IPolicy is IModule { + function checkUserOpPolicy( + bytes32 id, + PackedUserOperation calldata userOp + ) + external + payable + returns (uint256); + function checkSignaturePolicy( + bytes32 id, + address sender, + bytes32 hash, + bytes calldata sig + ) + external + view + returns (uint256); +} + +interface ISigner is IModule { + function checkUserOpSignature( + bytes32 id, + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + payable + returns (uint256); + function checkSignature( + bytes32 id, + address sender, + bytes32 hash, + bytes calldata sig + ) + external + view + returns (bytes4); +} diff --git a/src/accounts/kernel/interfaces/IKernel.sol b/src/accounts/kernel/interfaces/IKernel.sol new file mode 100644 index 00000000..021c79ca --- /dev/null +++ b/src/accounts/kernel/interfaces/IKernel.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { IERC7579Account } from "./IERC7579Account.sol"; +import { IAccount, ValidationData } from "./IAccount.sol"; +import { IAccountExecute } from "./IAccountExecute.sol"; +import { ValidationId, ValidationConfig } from "../lib/ValidationTypeLib.sol"; +import { IHook } from "./IERC7579Modules.sol"; +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; +import { ExecMode } from "../lib/ExecLib.sol"; + +interface IKernel is IAccount, IAccountExecute, IERC7579Account { + function initialize( + ValidationId _rootValidator, + IHook hook, + bytes calldata validatorData, + bytes calldata hookData, + bytes[] calldata initConfig + ) + external; + + function upgradeTo(address _newImplementation) external payable; + + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) + external + pure + returns (bytes4); + + function onERC1155Received( + address, + address, + uint256, + uint256, + bytes calldata + ) + external + pure + returns (bytes4); + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) + external + pure + returns (bytes4); + + // validation part + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) + external + payable + returns (ValidationData validationData); + + // --- Execution --- + function executeUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + payable; + + function executeFromExecutor( + ExecMode execMode, + bytes calldata executionCalldata + ) + external + payable + returns (bytes[] memory returnData); + + function execute(ExecMode execMode, bytes calldata executionCalldata) external payable; + + function isValidSignature( + bytes32 hash, + bytes calldata signature + ) + external + view + returns (bytes4); + + function installModule( + uint256 moduleType, + address module, + bytes calldata initData + ) + external + payable; + + function installValidations( + ValidationId[] calldata vIds, + ValidationConfig[] memory configs, + bytes[] calldata validationData, + bytes[] calldata hookData + ) + external + payable; + + function uninstallValidation( + ValidationId vId, + bytes calldata deinitData, + bytes calldata hookDeinitData + ) + external + payable; + + function invalidateNonce(uint32 nonce) external payable; + + function uninstallModule( + uint256 moduleType, + address module, + bytes calldata deInitData + ) + external + payable; + + function supportsModule(uint256 moduleTypeId) external pure returns (bool); + + function isModuleInstalled( + uint256 moduleType, + address module, + bytes calldata additionalContext + ) + external + view + returns (bool); + + function accountId() external pure returns (string memory accountImplementationId); + + function supportsExecutionMode(ExecMode mode) external pure returns (bool); + + function isAllowedSelector(ValidationId vId, bytes4 selector) external view returns (bool); + + function _toWrappedHash(bytes32 hash) external view returns (bytes32); + + function validationConfig(ValidationId vId) external view returns (ValidationConfig memory); +} diff --git a/src/accounts/kernel/interfaces/IKernelFactory.sol b/src/accounts/kernel/interfaces/IKernelFactory.sol new file mode 100644 index 00000000..da577f2c --- /dev/null +++ b/src/accounts/kernel/interfaces/IKernelFactory.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { LibClone } from "solady/utils/LibClone.sol"; + +interface IKernelFactory { + function createAccount(bytes calldata data, bytes32 salt) external payable returns (address); + function getAddress(bytes calldata data, bytes32 salt) external returns (address); +} diff --git a/src/accounts/kernel/interfaces/IValidationManager.sol b/src/accounts/kernel/interfaces/IValidationManager.sol new file mode 100644 index 00000000..e45e7ae1 --- /dev/null +++ b/src/accounts/kernel/interfaces/IValidationManager.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { IHook, ISigner } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { PassFlag, PolicyData, ValidationId, PermissionId } from "../lib/ValidationTypeLib.sol"; + +// erc7579 plugins +struct ValidationConfig { + uint32 nonce; // 4 bytes + IHook hook; // 20 bytes address(1) : hook not required, address(0) : validator not installed +} + +struct PermissionConfig { + PassFlag permissionFlag; + ISigner signer; + PolicyData[] policyData; +} + +struct ValidationStorage { + ValidationId rootValidator; + uint32 currentNonce; + uint32 validNonceFrom; + mapping(ValidationId => ValidationConfig) validationConfig; + mapping(ValidationId => mapping(bytes4 => bool)) allowedSelectors; + // validation = validator | permission + // validator == 1 validator + // permission == 1 signer + N policies + mapping(PermissionId => PermissionConfig) permissionConfig; +} diff --git a/src/accounts/kernel/lib/ExecLib.sol b/src/accounts/kernel/lib/ExecLib.sol new file mode 100644 index 00000000..c5c3ed40 --- /dev/null +++ b/src/accounts/kernel/lib/ExecLib.sol @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { ExecMode, CallType, ExecType, ExecModeSelector, ExecModePayload } from "../types/Types.sol"; +import { + CALLTYPE_SINGLE, + CALLTYPE_BATCH, + EXECTYPE_DEFAULT, + EXEC_MODE_DEFAULT, + EXECTYPE_TRY, + CALLTYPE_DELEGATECALL +} from "../types/Constants.sol"; +import { Execution } from "../types/Structs.sol"; + +/** + * @dev ExecLib is a helper library for execution + */ +library ExecLib { + error ExecutionFailed(); + + event TryExecuteUnsuccessful(uint256 batchExecutionindex, bytes result); + + function execute( + ExecMode execMode, + bytes calldata executionCalldata + ) + internal + returns (bytes[] memory returnData) + { + (CallType callType, ExecType execType,,) = decode(execMode); + + // check if calltype is batch or single + if (callType == CALLTYPE_BATCH) { + // destructure executionCallData according to batched exec + Execution[] calldata executions = decodeBatch(executionCalldata); + // check if execType is revert or try + if (execType == EXECTYPE_DEFAULT) returnData = execute(executions); + else if (execType == EXECTYPE_TRY) returnData = tryExecute(executions); + else revert("Unsupported"); + } else if (callType == CALLTYPE_SINGLE) { + // destructure executionCallData according to single exec + (address target, uint256 value, bytes calldata callData) = + decodeSingle(executionCalldata); + returnData = new bytes[](1); + bool success; + // check if execType is revert or try + if (execType == EXECTYPE_DEFAULT) { + returnData[0] = execute(target, value, callData); + } else if (execType == EXECTYPE_TRY) { + (success, returnData[0]) = tryExecute(target, value, callData); + if (!success) emit TryExecuteUnsuccessful(0, returnData[0]); + } else { + revert("Unsupported"); + } + } else if (callType == CALLTYPE_DELEGATECALL) { + returnData = new bytes[](1); + address delegate = address(bytes20(executionCalldata[0:20])); + bytes calldata callData = executionCalldata[20:]; + bool success; + (success, returnData[0]) = executeDelegatecall(delegate, callData); + if (execType == EXECTYPE_TRY) { + if (!success) emit TryExecuteUnsuccessful(0, returnData[0]); + } else if (execType == EXECTYPE_DEFAULT) { + if (!success) revert("Delegatecall failed"); + } else { + revert("Unsupported"); + } + } else { + revert("Unsupported"); + } + } + + function execute(Execution[] calldata executions) internal returns (bytes[] memory result) { + uint256 length = executions.length; + result = new bytes[](length); + + for (uint256 i; i < length; i++) { + Execution calldata _exec = executions[i]; + result[i] = execute(_exec.target, _exec.value, _exec.callData); + } + } + + function tryExecute(Execution[] calldata executions) internal returns (bytes[] memory result) { + uint256 length = executions.length; + result = new bytes[](length); + + for (uint256 i; i < length; i++) { + Execution calldata _exec = executions[i]; + bool success; + (success, result[i]) = tryExecute(_exec.target, _exec.value, _exec.callData); + if (!success) emit TryExecuteUnsuccessful(i, result[i]); + } + } + + function execute( + address target, + uint256 value, + bytes calldata callData + ) + internal + returns (bytes memory result) + { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + calldatacopy(result, callData.offset, callData.length) + if iszero(call(gas(), target, value, result, callData.length, codesize(), 0x00)) { + // Bubble up the revert if the call reverts. + returndatacopy(result, 0x00, returndatasize()) + revert(result, returndatasize()) + } + mstore(result, returndatasize()) // Store the length. + let o := add(result, 0x20) + returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. + mstore(0x40, add(o, returndatasize())) // Allocate the memory. + } + } + + function tryExecute( + address target, + uint256 value, + bytes calldata callData + ) + internal + returns (bool success, bytes memory result) + { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + calldatacopy(result, callData.offset, callData.length) + success := call(gas(), target, value, result, callData.length, codesize(), 0x00) + mstore(result, returndatasize()) // Store the length. + let o := add(result, 0x20) + returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. + mstore(0x40, add(o, returndatasize())) // Allocate the memory. + } + } + + /// @dev Execute a delegatecall with `delegate` on this account. + function executeDelegatecall( + address delegate, + bytes calldata callData + ) + internal + returns (bool success, bytes memory result) + { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + calldatacopy(result, callData.offset, callData.length) + // Forwards the `data` to `delegate` via delegatecall. + success := delegatecall(gas(), delegate, result, callData.length, codesize(), 0x00) + mstore(result, returndatasize()) // Store the length. + let o := add(result, 0x20) + returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. + mstore(0x40, add(o, returndatasize())) // Allocate the memory. + } + } + + function decode(ExecMode mode) + internal + pure + returns ( + CallType _calltype, + ExecType _execType, + ExecModeSelector _modeSelector, + ExecModePayload _modePayload + ) + { + assembly { + _calltype := mode + _execType := shl(8, mode) + _modeSelector := shl(48, mode) + _modePayload := shl(80, mode) + } + } + + function encode( + CallType callType, + ExecType execType, + ExecModeSelector mode, + ExecModePayload payload + ) + internal + pure + returns (ExecMode) + { + return ExecMode.wrap( + bytes32( + abi.encodePacked( + callType, execType, bytes4(0), ExecModeSelector.unwrap(mode), payload + ) + ) + ); + } + + function encodeSimpleBatch() internal pure returns (ExecMode mode) { + mode = + encode(CALLTYPE_BATCH, EXECTYPE_DEFAULT, EXEC_MODE_DEFAULT, ExecModePayload.wrap(0x00)); + } + + function encodeSimpleSingle() internal pure returns (ExecMode mode) { + mode = + encode(CALLTYPE_SINGLE, EXECTYPE_DEFAULT, EXEC_MODE_DEFAULT, ExecModePayload.wrap(0x00)); + } + + function getCallType(ExecMode mode) internal pure returns (CallType calltype) { + assembly { + calltype := mode + } + } + + function decodeBatch(bytes calldata callData) + internal + pure + returns (Execution[] calldata executionBatch) + { + /* + * Batch Call Calldata Layout + * Offset (in bytes) | Length (in bytes) | Contents + * 0x0 | 0x4 | bytes4 function selector + * 0x4 | - | + abi.encode(IERC7579Execution.Execution[]) + */ + // solhint-disable-next-line no-inline-assembly + assembly ("memory-safe") { + let dataPointer := add(callData.offset, calldataload(callData.offset)) + + // Extract the ERC7579 Executions + executionBatch.offset := add(dataPointer, 32) + executionBatch.length := calldataload(dataPointer) + } + } + + function encodeBatch(Execution[] memory executions) + internal + pure + returns (bytes memory callData) + { + callData = abi.encode(executions); + } + + function decodeSingle(bytes calldata executionCalldata) + internal + pure + returns (address target, uint256 value, bytes calldata callData) + { + target = address(bytes20(executionCalldata[0:20])); + value = uint256(bytes32(executionCalldata[20:52])); + callData = executionCalldata[52:]; + } + + function encodeSingle( + address target, + uint256 value, + bytes memory callData + ) + internal + pure + returns (bytes memory userOpCalldata) + { + userOpCalldata = abi.encodePacked(target, value, callData); + } + + function doFallback2771Static(address fallbackHandler) + internal + view + returns (bool success, bytes memory result) + { + assembly { + function allocate(length) -> pos { + pos := mload(0x40) + mstore(0x40, add(pos, length)) + } + + let calldataPtr := allocate(calldatasize()) + calldatacopy(calldataPtr, 0, calldatasize()) + + // The msg.sender address is shifted to the left by 12 bytes to remove the padding + // Then the address without padding is stored right after the calldata + let senderPtr := allocate(20) + mstore(senderPtr, shl(96, caller())) + + // Add 20 bytes for the address appended add the end + success := + staticcall(gas(), fallbackHandler, calldataPtr, add(calldatasize(), 20), 0, 0) + + result := mload(0x40) + mstore(result, returndatasize()) // Store the length. + let o := add(result, 0x20) + returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. + mstore(0x40, add(o, returndatasize())) // Allocate the memory. + } + } + + function doFallback2771Call(address target) + internal + returns (bool success, bytes memory result) + { + assembly { + function allocate(length) -> pos { + pos := mload(0x40) + mstore(0x40, add(pos, length)) + } + + let calldataPtr := allocate(calldatasize()) + calldatacopy(calldataPtr, 0, calldatasize()) + + // The msg.sender address is shifted to the left by 12 bytes to remove the padding + // Then the address without padding is stored right after the calldata + let senderPtr := allocate(20) + mstore(senderPtr, shl(96, caller())) + + // Add 20 bytes for the address appended add the end + success := call(gas(), target, 0, calldataPtr, add(calldatasize(), 20), 0, 0) + + result := mload(0x40) + mstore(result, returndatasize()) // Store the length. + let o := add(result, 0x20) + returndatacopy(o, 0x00, returndatasize()) // Copy the returndata. + mstore(0x40, add(o, returndatasize())) // Allocate the memory. + } + } +} diff --git a/src/accounts/kernel/lib/ValidationTypeLib.sol b/src/accounts/kernel/lib/ValidationTypeLib.sol new file mode 100644 index 00000000..4cda97cf --- /dev/null +++ b/src/accounts/kernel/lib/ValidationTypeLib.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { + IValidator, IPolicy, IHook, ISigner +} from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { + PassFlag, + ValidationType, + ValidationId, + ValidationMode, + PolicyData, + PermissionId +} from "../types/Types.sol"; +import { VALIDATION_TYPE_PERMISSION } from "../types/Constants.sol"; + +// erc7579 plugins +struct ValidationConfig { + uint32 nonce; // 4 bytes + IHook hook; // 20 bytes address(1) : hook not required, address(0) : validator not installed +} + +struct PermissionConfig { + PassFlag permissionFlag; + ISigner signer; + PolicyData[] policyData; +} + +struct ValidationStorage { + ValidationId rootValidator; + uint32 currentNonce; + uint32 validNonceFrom; + mapping(ValidationId => ValidationConfig) validationConfig; + mapping(ValidationId => mapping(bytes4 => bool)) allowedSelectors; + // validation = validator | permission + // validator == 1 validator + // permission == 1 signer + N policies + mapping(PermissionId => PermissionConfig) permissionConfig; +} + +library ValidatorLib { + function encodeFlag( + bool skipUserOp, + bool skipSignature + ) + internal + pure + returns (PassFlag flag) + { + assembly { + if skipUserOp { + flag := 0x0001000000000000000000000000000000000000000000000000000000000000 + } + if skipSignature { + flag := or(flag, 0x0002000000000000000000000000000000000000000000000000000000000000) + } + } + } + + function encodePolicyData( + bool skipUserOp, + bool skipSig, + address policy + ) + internal + pure + returns (PolicyData data) + { + assembly { + if skipUserOp { + data := 0x0001000000000000000000000000000000000000000000000000000000000000 + } + if skipSig { + data := or(data, 0x0002000000000000000000000000000000000000000000000000000000000000) + } + data := or(data, shl(80, policy)) + } + } + + function encodePermissionAsNonce( + bytes1 mode, + bytes4 permissionId, + uint16 nonceKey, + uint64 nonce + ) + internal + pure + returns (uint256 res) + { + return encodeAsNonce( + mode, + ValidationType.unwrap(VALIDATION_TYPE_PERMISSION), + bytes20(permissionId), + nonceKey, + nonce + ); + } + + function encodeAsNonce( + bytes1 mode, + bytes1 vType, + bytes20 ValidationIdWithoutType, + uint16 nonceKey, + uint64 nonce + ) + internal + pure + returns (uint256 res) + { + assembly { + res := nonce + res := or(res, shl(64, nonceKey)) + res := or(res, shr(16, ValidationIdWithoutType)) + res := or(res, shr(8, vType)) + res := or(res, mode) + } + } + + function encodeAsNonceKey( + bytes1 mode, + bytes1 vType, + bytes20 ValidationIdWithoutType, + uint16 nonceKey + ) + internal + pure + returns (uint192 res) + { + assembly { + res := or(nonceKey, shr(80, ValidationIdWithoutType)) + res := or(res, shr(72, vType)) + res := or(res, shr(64, mode)) + } + } + + function decodeNonce(uint256 nonce) + internal + pure + returns (ValidationMode mode, ValidationType vType, ValidationId identifier) + { + // 2bytes mode (1byte currentMode, 1byte type) + // 21bytes identifier + // 1byte mode | 1byte type | 20bytes identifierWithoutType | 2byte nonceKey | 8byte nonce + // == 32bytes + assembly { + mode := nonce + vType := shl(8, nonce) + identifier := shl(8, nonce) + switch shr(248, identifier) + case 0x0000000000000000000000000000000000000000000000000000000000000002 { + identifier := + and(identifier, 0xffffffffff000000000000000000000000000000000000000000000000000000) + } + } + } + + function decodeSignature(bytes calldata signature) + internal + pure + returns (ValidationId vId, bytes calldata sig) + { + assembly { + vId := calldataload(signature.offset) + switch shr(248, vId) + case 0 { + // sudo mode + vId := 0x00 + sig.offset := add(signature.offset, 1) + sig.length := sub(signature.length, 1) + } + case 1 { + // validator mode + sig.offset := add(signature.offset, 21) + sig.length := sub(signature.length, 21) + } + case 2 { + vId := and(vId, 0xffffffffff000000000000000000000000000000000000000000000000000000) + sig.offset := add(signature.offset, 5) + sig.length := sub(signature.length, 5) + } + default { revert(0x00, 0x00) } + } + } + + function decodePolicyData(PolicyData data) + internal + pure + returns (PassFlag flag, IPolicy policy) + { + assembly { + flag := data + policy := shr(80, data) + } + } + + function validatorToIdentifier(IValidator validator) internal pure returns (ValidationId vId) { + assembly { + vId := 0x0100000000000000000000000000000000000000000000000000000000000000 + vId := or(vId, shl(88, validator)) + } + } + + function getType(ValidationId validator) internal pure returns (ValidationType vType) { + assembly { + vType := validator + } + } + + function getValidator(ValidationId validator) internal pure returns (IValidator v) { + assembly { + v := shr(88, validator) + } + } + + function getPermissionId(ValidationId validator) internal pure returns (PermissionId id) { + assembly { + id := shl(8, validator) + } + } + + function permissionToIdentifier(PermissionId permissionId) + internal + pure + returns (ValidationId vId) + { + assembly { + vId := 0x0200000000000000000000000000000000000000000000000000000000000000 + vId := or(vId, shr(8, permissionId)) + } + } + + function getPolicy(PolicyData data) internal pure returns (IPolicy vId) { + assembly { + vId := shr(80, data) + } + } + + function getPermissionSkip(PolicyData data) internal pure returns (PassFlag flag) { + assembly { + flag := data + } + } +} diff --git a/src/accounts/kernel/mock/MockFallback.sol b/src/accounts/kernel/mock/MockFallback.sol new file mode 100644 index 00000000..0cd3ff51 --- /dev/null +++ b/src/accounts/kernel/mock/MockFallback.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { IERC7579Account } from "../interfaces/IERC7579Account.sol"; +import { IFallback } from "../interfaces/IERC7579Modules.sol"; +import { CallType, ExecType, ExecMode, ExecLib } from "../lib/ExecLib.sol"; +import { EXEC_MODE_DEFAULT } from "../types/Constants.sol"; + +contract Callee { + address public lastCaller; + + function calleeTest() external { + lastCaller = msg.sender; + } +} + +contract MockFallback is IFallback { + mapping(address => bytes) public data; + + uint256 public valueStored; + + bool isExecutor; + + Callee public callee; + + constructor() { + callee = new Callee(); + } + + function setExecutorMode(bool _isExecutor) external payable { + isExecutor = _isExecutor; + } + + function onInstall(bytes calldata _data) external payable override { + data[msg.sender] = _data; + } + + function onUninstall(bytes calldata) external payable override { + delete data[msg.sender]; + } + + function isModuleType(uint256 moduleTypeId) external view override returns (bool) { + return moduleTypeId == 3 || (isExecutor && moduleTypeId == 2); + } + + function isInitialized(address smartAccount) external view override returns (bool) { + return data[smartAccount].length > 0; + } + + function fallbackFunction(uint256 v) external pure returns (uint256) { + return v * v; + } + + function getData() external view returns (bytes memory) { + return data[msg.sender]; + } + + function getCaller() external pure returns (address) { + return address(bytes20(msg.data[msg.data.length - 20:])); + } + + function setData(uint256 value) external { + valueStored = value; + if (isExecutor) { + IERC7579Account(msg.sender).executeFromExecutor( + ExecLib.encodeSimpleSingle(), + ExecLib.encodeSingle( + address(callee), 0, abi.encodeWithSelector(Callee.calleeTest.selector) + ) + ); + } + } +} diff --git a/src/accounts/kernel/types/Constants.sol b/src/accounts/kernel/types/Constants.sol new file mode 100644 index 00000000..607b736a --- /dev/null +++ b/src/accounts/kernel/types/Constants.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { CallType, ExecType, ExecModeSelector } from "./Types.sol"; +import { PassFlag, ValidationMode, ValidationType } from "./Types.sol"; +import { ValidationData } from "./Types.sol"; + +// --- ERC7579 calltypes --- +// Default CallType +CallType constant CALLTYPE_SINGLE = CallType.wrap(0x00); +// Batched CallType +CallType constant CALLTYPE_BATCH = CallType.wrap(0x01); +CallType constant CALLTYPE_STATIC = CallType.wrap(0xFE); +// @dev Implementing delegatecall is OPTIONAL! +// implement delegatecall with extreme care. +CallType constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF); + +// --- ERC7579 exectypes --- +// @dev default behavior is to revert on failure +// To allow very simple accounts to use mode encoding, the default behavior is to revert on failure +// Since this is value 0x00, no additional encoding is required for simple accounts +ExecType constant EXECTYPE_DEFAULT = ExecType.wrap(0x00); +// @dev account may elect to change execution behavior. For example "try exec" / "allow fail" +ExecType constant EXECTYPE_TRY = ExecType.wrap(0x01); + +// --- ERC7579 mode selector --- +ExecModeSelector constant EXEC_MODE_DEFAULT = ExecModeSelector.wrap(bytes4(0x00000000)); + +// --- Kernel permission skip flags --- +PassFlag constant SKIP_USEROP = PassFlag.wrap(0x0001); +PassFlag constant SKIP_SIGNATURE = PassFlag.wrap(0x0002); + +// --- Kernel validation modes --- +ValidationMode constant VALIDATION_MODE_DEFAULT = ValidationMode.wrap(0x00); +ValidationMode constant VALIDATION_MODE_ENABLE = ValidationMode.wrap(0x01); +ValidationMode constant VALIDATION_MODE_INSTALL = ValidationMode.wrap(0x02); + +// --- Kernel validation types --- +ValidationType constant VALIDATION_TYPE_ROOT = ValidationType.wrap(0x00); +ValidationType constant VALIDATION_TYPE_VALIDATOR = ValidationType.wrap(0x01); +ValidationType constant VALIDATION_TYPE_PERMISSION = ValidationType.wrap(0x02); + +// --- storage slots --- +// bytes32(uint256(keccak256('kernel.v3.selector')) - 1) +bytes32 constant SELECTOR_MANAGER_STORAGE_SLOT = + 0x7c341349a4360fdd5d5bc07e69f325dc6aaea3eb018b3e0ea7e53cc0bb0d6f3b; +// bytes32(uint256(keccak256('kernel.v3.executor')) - 1) +bytes32 constant EXECUTOR_MANAGER_STORAGE_SLOT = + 0x1bbee3173dbdc223633258c9f337a0fff8115f206d302bea0ed3eac003b68b86; +// bytes32(uint256(keccak256('kernel.v3.hook')) - 1) +bytes32 constant HOOK_MANAGER_STORAGE_SLOT = + 0x4605d5f70bb605094b2e761eccdc27bed9a362d8612792676bf3fb9b12832ffc; +// bytes32(uint256(keccak256('kernel.v3.validation')) - 1) +bytes32 constant VALIDATION_MANAGER_STORAGE_SLOT = + 0x7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f; +bytes32 constant ERC1967_IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + +// --- Kernel validation nonce incremental size limit --- +uint32 constant MAX_NONCE_INCREMENT_SIZE = 10; + +// -- EIP712 type hash --- +bytes32 constant ENABLE_TYPE_HASH = + 0xb17ab1224aca0d4255ef8161acaf2ac121b8faa32a4b2258c912cc5f8308c505; +bytes32 constant KERNEL_WRAPPER_TYPE_HASH = + 0x1547321c374afde8a591d972a084b071c594c275e36724931ff96c25f2999c83; + +// --- ERC constants --- +// ERC4337 constants +uint256 constant SIG_VALIDATION_FAILED_UINT = 1; +uint256 constant SIG_VALIDATION_SUCCESS_UINT = 0; +ValidationData constant SIG_VALIDATION_FAILED = ValidationData.wrap(SIG_VALIDATION_FAILED_UINT); + +// ERC-1271 constants +bytes4 constant ERC1271_MAGICVALUE = 0x1626ba7e; +bytes4 constant ERC1271_INVALID = 0xffffffff; + +uint256 constant MODULE_TYPE_VALIDATOR = 1; +uint256 constant MODULE_TYPE_EXECUTOR = 2; +uint256 constant MODULE_TYPE_FALLBACK = 3; +uint256 constant MODULE_TYPE_HOOK = 4; +uint256 constant MODULE_TYPE_POLICY = 5; +uint256 constant MODULE_TYPE_SIGNER = 6; diff --git a/src/accounts/kernel/types/Structs.sol b/src/accounts/kernel/types/Structs.sol new file mode 100644 index 00000000..edf9dbef --- /dev/null +++ b/src/accounts/kernel/types/Structs.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +struct Execution { + address target; + uint256 value; + bytes callData; +} diff --git a/src/accounts/kernel/types/Types.sol b/src/accounts/kernel/types/Types.sol new file mode 100644 index 00000000..f0e9b0a6 --- /dev/null +++ b/src/accounts/kernel/types/Types.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +// Custom type for improved developer experience +type ExecMode is bytes32; + +type CallType is bytes1; + +type ExecType is bytes1; + +type ExecModeSelector is bytes4; + +type ExecModePayload is bytes22; + +using { eqModeSelector as == } for ExecModeSelector global; +using { eqCallType as == } for CallType global; +using { notEqCallType as != } for CallType global; +using { eqExecType as == } for ExecType global; + +function eqCallType(CallType a, CallType b) pure returns (bool) { + return CallType.unwrap(a) == CallType.unwrap(b); +} + +function notEqCallType(CallType a, CallType b) pure returns (bool) { + return CallType.unwrap(a) != CallType.unwrap(b); +} + +function eqExecType(ExecType a, ExecType b) pure returns (bool) { + return ExecType.unwrap(a) == ExecType.unwrap(b); +} + +function eqModeSelector(ExecModeSelector a, ExecModeSelector b) pure returns (bool) { + return ExecModeSelector.unwrap(a) == ExecModeSelector.unwrap(b); +} + +type ValidationMode is bytes1; + +type ValidationId is bytes21; + +type ValidationType is bytes1; + +type PermissionId is bytes4; + +type PolicyData is bytes22; // 2bytes for flag on skip, 20 bytes for validator address + +type PassFlag is bytes2; + +using { vModeEqual as == } for ValidationMode global; +using { vTypeEqual as == } for ValidationType global; +using { vIdentifierEqual as == } for ValidationId global; +using { vModeNotEqual as != } for ValidationMode global; +using { vTypeNotEqual as != } for ValidationType global; +using { vIdentifierNotEqual as != } for ValidationId global; + +// nonce = uint192(key) + nonce +// key = mode + (vtype + validationDataWithoutType) + 2bytes parallelNonceKey +// key = 0x00 + 0x00 + 0x000 .. 00 + 0x0000 +// key = 0x00 + 0x01 + 0x1234...ff + 0x0000 +// key = 0x00 + 0x02 + ( ) + 0x000 + +function vModeEqual(ValidationMode a, ValidationMode b) pure returns (bool) { + return ValidationMode.unwrap(a) == ValidationMode.unwrap(b); +} + +function vModeNotEqual(ValidationMode a, ValidationMode b) pure returns (bool) { + return ValidationMode.unwrap(a) != ValidationMode.unwrap(b); +} + +function vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) { + return ValidationType.unwrap(a) == ValidationType.unwrap(b); +} + +function vTypeNotEqual(ValidationType a, ValidationType b) pure returns (bool) { + return ValidationType.unwrap(a) != ValidationType.unwrap(b); +} + +function vIdentifierEqual(ValidationId a, ValidationId b) pure returns (bool) { + return ValidationId.unwrap(a) == ValidationId.unwrap(b); +} + +function vIdentifierNotEqual(ValidationId a, ValidationId b) pure returns (bool) { + return ValidationId.unwrap(a) != ValidationId.unwrap(b); +} + +type ValidationData is uint256; + +type ValidAfter is uint48; + +type ValidUntil is uint48; + +function getValidationResult(ValidationData validationData) pure returns (address result) { + assembly { + result := validationData + } +} + +function packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure returns (uint256) { + return uint256(ValidAfter.unwrap(validAfter)) << 208 + | uint256(ValidUntil.unwrap(validUntil)) << 160; +} + +function parseValidationData(uint256 validationData) + pure + returns (ValidAfter validAfter, ValidUntil validUntil, address result) +{ + assembly { + result := validationData + validUntil := and(shr(160, validationData), 0xffffffffffff) + switch iszero(validUntil) + case 1 { validUntil := 0xffffffffffff } + validAfter := shr(208, validationData) + } +} diff --git a/src/accounts/nexus/NexusFactory.sol b/src/accounts/nexus/NexusFactory.sol index 393b92b9..95d8f515 100644 --- a/src/accounts/nexus/NexusFactory.sol +++ b/src/accounts/nexus/NexusFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; // Interfaces import { IAccountFactory } from "src/accounts/interface/IAccountFactory.sol"; diff --git a/src/accounts/nexus/interfaces/INexusAccountFactory.sol b/src/accounts/nexus/interfaces/INexusAccountFactory.sol index 23255fdb..00265ba1 100644 --- a/src/accounts/nexus/interfaces/INexusAccountFactory.sol +++ b/src/accounts/nexus/interfaces/INexusAccountFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; interface INexusAccountFactory { /// @notice Creates a new Nexus account with the provided initialization data. diff --git a/src/accounts/nexus/interfaces/INexusBootstrap.sol b/src/accounts/nexus/interfaces/INexusBootstrap.sol index baef9d2f..207b843f 100644 --- a/src/accounts/nexus/interfaces/INexusBootstrap.sol +++ b/src/accounts/nexus/interfaces/INexusBootstrap.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; -import { IERC7579Module } from "src/external/ERC7579.sol"; +import { IModule as IERC7579Module } from "src/accounts/common/interfaces/IERC7579Modules.sol"; import { IERC7484 } from "src/Interfaces.sol"; struct BootstrapConfig { diff --git a/src/accounts/safe/SafeFactory.sol b/src/accounts/safe/SafeFactory.sol index 28d9228c..d74102c8 100644 --- a/src/accounts/safe/SafeFactory.sol +++ b/src/accounts/safe/SafeFactory.sol @@ -1,29 +1,33 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; -import { Safe7579, ISafe7579 } from "safe7579/Safe7579.sol"; +import { ISafe7579 } from "src/accounts/safe/interfaces/ISafe7579.sol"; import { Safe } from "@safe-global/safe-contracts/contracts/Safe.sol"; import { SafeProxy } from "@safe-global/safe-contracts/contracts/proxies/SafeProxy.sol"; import { SafeProxyFactory } from "@safe-global/safe-contracts/contracts/proxies/SafeProxyFactory.sol"; -import { Safe7579Launchpad, IERC7484, ModuleInit } from "safe7579/Safe7579Launchpad.sol"; +import { + ISafe7579Launchpad, + IERC7484, + ModuleInit +} from "src/accounts/safe/interfaces/ISafe7579Launchpad.sol"; import { ENTRYPOINT_ADDR } from "src/test/predeploy/EntryPoint.sol"; import { REGISTRY_ADDR } from "src/test/predeploy/Registry.sol"; import { makeAddr } from "src/test/utils/Vm.sol"; import { Solarray } from "solarray/Solarray.sol"; import { IAccountFactory } from "src/accounts/interface/IAccountFactory.sol"; +import { Safe7579Precompiles } from "src/test/precompiles/Safe7579Precompiles.sol"; -contract SafeFactory is IAccountFactory { +contract SafeFactory is IAccountFactory, Safe7579Precompiles { // singletons - Safe7579 internal safe7579; - Safe7579Launchpad internal launchpad; + ISafe7579 internal safe7579; + ISafe7579Launchpad internal launchpad; Safe internal safeSingleton; SafeProxyFactory internal safeProxyFactory; function init() public override { - // Set up MSA and Factory - safe7579 = new Safe7579(); - launchpad = new Safe7579Launchpad(ENTRYPOINT_ADDR, IERC7484(address(REGISTRY_ADDR))); + safe7579 = deploySafe7579(); + launchpad = deploySafe7579Launchpad(ENTRYPOINT_ADDR, REGISTRY_ADDR); safeSingleton = new Safe(); safeProxyFactory = new SafeProxyFactory(); } @@ -36,12 +40,12 @@ contract SafeFactory is IAccountFactory { override returns (address safe) { - Safe7579Launchpad.InitData memory initData = - abi.decode(initCode, (Safe7579Launchpad.InitData)); + ISafe7579Launchpad.InitData memory initData = + abi.decode(initCode, (ISafe7579Launchpad.InitData)); bytes32 initHash = launchpad.hash(initData); bytes memory factoryInitializer = - abi.encodeCall(Safe7579Launchpad.preValidationSetup, (initHash, address(0), "")); + abi.encodeCall(ISafe7579Launchpad.preValidationSetup, (initHash, address(0), "")); safe = address( safeProxyFactory.createProxyWithNonce( @@ -59,12 +63,12 @@ contract SafeFactory is IAccountFactory { override returns (address) { - Safe7579Launchpad.InitData memory initData = - abi.decode(initCode, (Safe7579Launchpad.InitData)); + ISafe7579Launchpad.InitData memory initData = + abi.decode(initCode, (ISafe7579Launchpad.InitData)); bytes32 initHash = launchpad.hash(initData); bytes memory factoryInitializer = - abi.encodeCall(Safe7579Launchpad.preValidationSetup, (initHash, address(0), "")); + abi.encodeCall(ISafe7579Launchpad.preValidationSetup, (initHash, address(0), "")); return launchpad.predictSafeAddress({ singleton: address(launchpad), @@ -90,13 +94,13 @@ contract SafeFactory is IAccountFactory { ModuleInit[] memory fallbacks = new ModuleInit[](0); ModuleInit[] memory hooks = new ModuleInit[](0); - Safe7579Launchpad.InitData memory initDataSafe = Safe7579Launchpad.InitData({ + ISafe7579Launchpad.InitData memory initDataSafe = ISafe7579Launchpad.InitData({ singleton: address(safeSingleton), owners: Solarray.addresses(makeAddr("owner1")), threshold: 1, setupTo: address(launchpad), setupData: abi.encodeCall( - Safe7579Launchpad.initSafe7579, + ISafe7579Launchpad.initSafe7579, ( address(safe7579), executors, diff --git a/src/accounts/safe/interfaces/IERC7484.sol b/src/accounts/safe/interfaces/IERC7484.sol new file mode 100644 index 00000000..2c756f7d --- /dev/null +++ b/src/accounts/safe/interfaces/IERC7484.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +interface IERC7484 { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Check with Registry internal attesters */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function check(address module) external view; + + function checkForAccount(address smartAccount, address module) external view; + + function check(address module, uint256 moduleType) external view; + + function checkForAccount( + address smartAccount, + address module, + uint256 moduleType + ) + external + view; + + /** + * Allows Smart Accounts - the end users of the registry - to appoint + * one or many attesters as trusted. + * @dev this function reverts, if address(0), or duplicates are provided in attesters[] + * + * @param threshold The minimum number of attestations required for a module + * to be considered secure. + * @param attesters The addresses of the attesters to be trusted. + */ + function trustAttesters(uint8 threshold, address[] calldata attesters) external; + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Check with external attester(s) */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function check(address module, address[] calldata attesters, uint256 threshold) external view; + + function check( + address module, + uint256 moduleType, + address[] calldata attesters, + uint256 threshold + ) + external + view; +} diff --git a/src/accounts/safe/interfaces/IERC7579Account.sol b/src/accounts/safe/interfaces/IERC7579Account.sol new file mode 100644 index 00000000..d6c89d46 --- /dev/null +++ b/src/accounts/safe/interfaces/IERC7579Account.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { CallType, ExecType, ModeCode } from "../../common/lib/ModeLib.sol"; + +struct Execution { + address target; + uint256 value; + bytes callData; +} + +interface IERC7579AccountEvents { + event ModuleInstalled(uint256 moduleTypeId, address module); + event ModuleUninstalled(uint256 moduleTypeId, address module); +} + +interface IERC7579AccountView { + /** + * @dev Returns the account id of the smart account + * @return accountImplementationId the account id of the smart account + * the accountId should be structured like so: + * "vendorname.accountname.semver" + */ + function accountId() external view returns (string memory accountImplementationId); + + /** + * Function to check if the account supports a certain CallType or ExecType (see ModeLib.sol) + * @param encodedMode the encoded mode + */ + function supportsExecutionMode(ModeCode encodedMode) external view returns (bool); + + /** + * Function to check if the account supports installation of a certain module type Id + * @param moduleTypeId the module type ID according the ERC-7579 spec + */ + function supportsModule(uint256 moduleTypeId) external view returns (bool); +} + +interface IERC7579Account is IERC7579AccountEvents, IERC7579AccountView { + // Error thrown when an unsupported ModuleType is requested + error UnsupportedModuleType(uint256 moduleTypeId); + // Error thrown when an execution with an unsupported CallType was made + error UnsupportedCallType(CallType callType); + // Error thrown when an execution with an unsupported ExecType was made + error UnsupportedExecType(ExecType execType); + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by ERC-4337 EntryPoint.sol + * @dev Ensure adequate authorization control: i.e. onlyEntryPointOrSelf + * + * @dev MSA MUST implement this function signature. + * If a mode is requested that is not supported by the Account, it MUST revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + + function execute(ModeCode mode, bytes calldata executionCalldata) external; + + /** + * @dev Executes a transaction on behalf of the account. + * This function is intended to be called by Executor Modules + * @dev Ensure adequate authorization control: i.e. onlyExecutorModule + * + * @dev MSA MUST implement this function signature. + * If a mode is requested that is not supported by the Account, it MUST revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function executeFromExecutor( + ModeCode mode, + bytes calldata executionCalldata + ) + external + returns (bytes[] memory returnData); + + /** + * @dev ERC-1271 isValidSignature + * This function is intended to be used to validate a smart account signature + * and may forward the call to a validator module + * + * @param hash The hash of the data that is signed + * @param data The data that is signed + */ + function isValidSignature(bytes32 hash, bytes calldata data) external returns (bytes4); + + /** + * @dev installs a Module of a certain type on the smart account + * @dev Implement Authorization control of your chosing + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param initData arbitrary data that may be required on the module during `onInstall` + * initialization. + */ + function installModule( + uint256 moduleTypeId, + address module, + bytes calldata initData + ) + external; + + /** + * @dev uninstalls a Module of a certain type on the smart account + * @dev Implement Authorization control of your chosing + * @param moduleTypeId the module type ID according the ERC-7579 spec + * @param module the module address + * @param deInitData arbitrary data that may be required on the module during `onUninstall` + * de-initialization. + */ + function uninstallModule( + uint256 moduleTypeId, + address module, + bytes calldata deInitData + ) + external; + + /** + * Function to check if the account has a certain module installed + * @param moduleTypeId the module type ID according the ERC-7579 spec + * Note: keep in mind that some contracts can be multiple module types at the same time. It + * thus may be necessary to query multiple module types + * @param module the module address + * @param additionalContext additional context data that the smart account may interpret to + * identifiy conditions under which the module is installed. + * usually this is not necessary, but for some special hooks that + * are stored in mappings, this param might be needed + */ + function isModuleInstalled( + uint256 moduleTypeId, + address module, + bytes calldata additionalContext + ) + external + view + returns (bool); +} diff --git a/src/accounts/safe/interfaces/ISafe7579.sol b/src/accounts/safe/interfaces/ISafe7579.sol new file mode 100644 index 00000000..67130ef6 --- /dev/null +++ b/src/accounts/safe/interfaces/ISafe7579.sol @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import "../types/DataTypes.sol"; +import { IERC7579Account } from "./IERC7579Account.sol"; +import { ModeCode } from "../../common/lib/ModeLib.sol"; +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; +import { ISafeOp } from "./ISafeOp.sol"; + +/** + * @title ERC7579 Adapter for Safe accounts. + * creates full ERC7579 compliance to Safe accounts + * @author rhinestone | zeroknots.eth, Konrad Kopp (@kopy-kat) + */ +interface ISafe7579 is IERC7579Account, ISafeOp { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Validation */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * ERC4337 v0.7 validation function + * @dev expects that a ERC7579 validator module is encoded within the UserOp nonce. + * if no validator module is provided, it will fallback to validate the transaction with + * Safe's signers + */ + function validateUserOp( + PackedUserOperation memory userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) + external + returns (uint256 packedValidSig); + + /** + * Will use Safe's signed messages or checkSignatures features or ERC7579 validation modules + * if no signature is provided, it makes use of Safe's signedMessages + * if address(0) or a non-installed validator module is provided, it will use Safe's + * checkSignatures + * if a valid validator module is provided, it will use the module's validateUserOp function + * @param hash message hash of ERC1271 request + * @param data abi.encodePacked(address validationModule, bytes signatures) + */ + function isValidSignature( + bytes32 hash, + bytes memory data + ) + external + view + returns (bytes4 magicValue); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Executions */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @dev Executes a transaction on behalf of the Safe account. + * This function is intended to be called by ERC-4337 EntryPoint.sol + * @dev If a global hook and/or selector hook is set, it will be called + * @dev AccessControl: only Self of Entrypoint can install modules + * Safe7579 supports the following feature set: + * CallTypes: + * - CALLTYPE_SINGLE + * - CALLTYPE_BATCH + * - CALLTYPE_DELEGATECALL + * ExecTypes: + * - EXECTYPE_DEFAULT (revert if not successful) + * - EXECTYPE_TRY + * If a different mode is selected, this function will revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function execute(ModeCode mode, bytes memory executionCalldata) external; + + /** + * @dev Executes a transaction on behalf of the Safe account. + * This function is intended to be called by executor modules + * @dev If a global hook and/or selector hook is set, it will be called + * @dev AccessControl: only enabled executor modules + * Safe7579 supports the following feature set: + * CallTypes: + * - CALLTYPE_SINGLE + * - CALLTYPE_BATCH + * - CALLTYPE_DELEGATECALL + * ExecTypes: + * - EXECTYPE_DEFAULT (revert if not successful) + * - EXECTYPE_TRY + * If a different mode is selected, this function will revert + * @param mode The encoded execution mode of the transaction. See ModeLib.sol for details + * @param executionCalldata The encoded execution call data + */ + function executeFromExecutor( + ModeCode mode, + bytes memory executionCalldata + ) + external + returns (bytes[] memory returnDatas); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Manage Modules */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * Installs a 7579 Module of a certain type on the smart account + * @dev The module has to be initialized from msg.sender == SafeProxy, we thus use a + * delegatecall to DCUtil, which calls the onInstall/onUninstall function on the ERC7579 + * module and emits the ModuleInstall/ModuleUnintall events + * @dev AccessControl: only Self of Entrypoint can install modules + * @dev If the safe set a registry, ERC7484 registry will be queried before installing + * @dev If a global hook and/or selector hook is set, it will be called + * @param moduleType the module type ID according the ERC-7579 spec + * Note: MULTITYPE_MODULE (uint(0)) is a special type to install a module with + * multiple types + * @param module the module address + * @param initData arbitrary data that may be required on the module during `onInstall` + * initialization. + */ + function installModule(uint256 moduleType, address module, bytes memory initData) external; + + /** + * Uninstalls a Module of a certain type on the smart account. + * @dev The module has to be initialized from msg.sender == SafeProxy, we thus use a + * delegatecall to DCUtil, which calls the onInstall/onUninstall function on the ERC7579 + * module and emits the ModuleInstall/ModuleUnintall events + * @dev AccessControl: only Self of Entrypoint can install modules + * @dev If a global hook and/or selector hook is set, it will be called + * @param moduleType the module type ID according the ERC-7579 spec + * @param module the module address + * @param deInitData arbitrary data that may be required on the module during `onUninstall` + * de-initialization. + */ + function uninstallModule( + uint256 moduleType, + address module, + bytes memory deInitData + ) + external; + + /** + * Function to check if the account has a certain module installed + * @param moduleType the module type ID according the ERC-7579 spec + * Note: keep in mind that some contracts can be multiple module types at the same time. It + * thus may be necessary to query multiple module types + * @param module the module address + * @param additionalContext additional context data that the smart account may interpret to + * identifiy conditions under which the module is installed. + * usually this is not necessary, but for some special hooks that + * are stored in mappings, this param might be needed + */ + function isModuleInstalled( + uint256 moduleType, + address module, + bytes memory additionalContext + ) + external + view + returns (bool); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Initialize Safe7579 */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * This function can be called by the Launchpad.initSafe7579() or by already existing Safes that + * want to use Safe7579 + * if this is called by the Launchpad, it is expected that launchpadValidators() was called + * previously, and the param validators is empty + * @param validators validator modules and initData + * @param executors executor modules and initData + * @param executors executor modules and initData + * @param fallbacks fallback modules and initData + * @param hooks hook module and initData + * @param registryInit (OPTIONAL) registry, attesters and threshold for IERC7484 Registry + * If not provided, the registry will be set to the zero address, and no + * registry checks will be performed + */ + function initializeAccount( + ModuleInit[] memory validators, + ModuleInit[] memory executors, + ModuleInit[] memory fallbacks, + ModuleInit[] memory hooks, + RegistryInit memory registryInit + ) + external; + + /** + * This function is intended to be called by Launchpad.validateUserOp() + * @dev it will initialize the SentinelList4337 list for validators, and sstore all + * validators + * @dev Since this function has to be 4337 compliant (storage access), only validator storage is acccess + * @dev Note: this function DOES NOT call onInstall() on the validator modules or emit + * ModuleInstalled events. this has to be done by the launchpad + */ + function initializeAccountWithValidators(ModuleInit[] memory validators) external; + + /** + * Configure the Safe7579 with a IERC7484 registry + * @param registry IERC7484 registry + * @param attesters list of attesters + * @param threshold number of attesters required + */ + function setRegistry(IERC7484 registry, address[] memory attesters, uint8 threshold) external; + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Query Account Details */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + function getValidatorsPaginated( + address cursor, + uint256 pageSize + ) + external + view + returns (address[] memory array, address next); + + /** + * Get the current active global hook + */ + function getActiveHook() external view returns (address hook); + + /** + * Get the current active selector hook + */ + function getActiveHook(bytes4 selector) external view returns (address hook); + + function getExecutorsPaginated( + address cursor, + uint256 size + ) + external + view + returns (address[] memory array, address next); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Query Misc */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * Safe7579 is using validator selection encoding in the userop nonce. + * to make it easier for SDKs / devs to integrate, this function can be + * called to get the next nonce for a specific validator + * @param safe address of safe account + * @param validator ERC7579 validator to encode + */ + function getNonce(address safe, address validator) external view returns (uint256 nonce); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Custom Errors */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + error InvalidModule(address module); + error InvalidModuleType(address module, uint256 moduleType); + + // fallback handlers + error InvalidInput(); + error InvalidCallType(CallType callType); + error NoFallbackHandler(bytes4 msgSig); + error InvalidFallbackHandler(bytes4 msgSig); + error FallbackInstalled(bytes4 msgSig); + + // Hooks + error HookAlreadyInstalled(address currentHook); + error InvalidHookType(); + + // Registry Adapter + event ERC7484RegistryConfigured(address indexed smartAccount, IERC7484 indexed registry); +} diff --git a/src/accounts/safe/interfaces/ISafe7579Launchpad.sol b/src/accounts/safe/interfaces/ISafe7579Launchpad.sol new file mode 100644 index 00000000..a990c5dd --- /dev/null +++ b/src/accounts/safe/interfaces/ISafe7579Launchpad.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { + IAccount, + PackedUserOperation +} from "@ERC4337/account-abstraction/contracts/interfaces/IAccount.sol"; +import { ISafe7579 } from "./ISafe7579.sol"; +import { IERC7484 } from "./IERC7484.sol"; +import { ModuleInit } from "../types/DataTypes.sol"; + +interface ISafe7579Launchpad is IAccount { + /** + * @notice The keccak256 hash of the EIP-712 InitData struct, representing the structure + */ + struct InitData { + address singleton; + address[] owners; + uint256 threshold; + address setupTo; + bytes setupData; + ISafe7579 safe7579; + ModuleInit[] validators; + bytes callData; + } + + /** + * This function is intended to be delegatecalled by the ISafe.setup function. It configures the + * Safe7579 for the user for all module types except validators, which were initialized in the + * validateUserOp function. + */ + function initSafe7579( + address safe7579, + ModuleInit[] calldata executors, + ModuleInit[] calldata fallbacks, + ModuleInit[] calldata hooks, + address[] calldata attesters, + uint8 threshold + ) + external; + + /** + * This function allows existing safe accounts to add the Safe7579 adapter to their account + */ + function addSafe7579( + address safe7579, + ModuleInit[] calldata validators, + ModuleInit[] calldata executors, + ModuleInit[] calldata fallbacks, + ModuleInit[] calldata hooks, + address[] calldata attesters, + uint8 threshold + ) + external; + + /** + * SafeProxyFactory will create a SafeProxy and using this contract as the singleton + * implementation and call this function to initialize the account. + * will write initHash into SafeProxy storage + * @param initHash will be calculated offchain using this.hash(InitData) + * @param to optional parameter for a delegatecall + * @param preInit optional parameter for a delegatecall + */ + function preValidationSetup(bytes32 initHash, address to, bytes calldata preInit) external; + + /** + * Upon creation of SafeProxy by SafeProxyFactory, EntryPoint invokes this function to verify + * the transaction. It ensures that only this.setupSafe() can be called by EntryPoint during + * execution. The function validates the hash of InitData in userOp.callData against the hash + * stored in preValidationSetup. This function abides by ERC4337 storage restrictions, allowing + * Safe7579 adapter initialization only in Validation Modules compliant with 4337. It installs + * validators from InitData onto the Safe7579 adapter for the account. When called by EP, the + * SafeProxy singleton address remains unupgraded to SafeSingleton, preventing + * execTransactionFromModule by Safe7579 Adapter. Initialization of Validator Modules is + * achieved through a direct call to onInstall(). This delegatecalled function initializes the + * Validator Module with the correct msg.sender. Once all validator modules are set up, they can + * be used to validate the userOp. Parameters include userOp (EntryPoint v0.7 userOp), + * userOpHash, and missingAccountFunds representing the gas payment required. + * + * @param userOp EntryPoint v0.7 userOp. + * @param userOpHash hash of userOp + * @param missingAccountFunds amount of gas that has to be paid + * @return validationData 4337 packed validation data returned by the validator module + */ + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds + ) + external + returns (uint256 validationData); + + /** + * During the execution phase of ERC4337, this function upgrades the SafeProxy to the actual + * SafeSingleton implementation. Subsequently, it invokes the ISafe.setup() function to + * initialize the Safe Account. The setup() function should ensure the completion of Safe7579 + * Adapter initialization with InitData.setupTo as address(this) and InitData.setupData encoding + * the call to this.initSafe7579(). SafeProxy.setup() delegatecalls this function to install + * executors, fallbacks, hooks, and registry configurations on the Safe7579 adapter. As this + * occurs in the ERC4337 execution phase, storage restrictions are not applicable. + * + * @param initData initData to initialize the Safe and Safe7579 Adapter + */ + function setupSafe(InitData calldata initData) external; + + function getInitHash() external view returns (bytes32); + + /** + * Helper function that can be used offchain to predict the counterfactual Safe address. + * @dev factoryInitializer is expected to be: + * abi.encodeCall(Safe7579Launchpad.preValidationSetup, (initHash, to, callData)); + */ + function predictSafeAddress( + address singleton, + address safeProxyFactory, + bytes memory creationCode, + bytes32 salt, + bytes memory factoryInitializer + ) + external + pure + returns (address safeProxy); + + /** + * Create unique InitData hash. Using all params but excluding data.callData from hash + */ + function hash(InitData memory data) external pure returns (bytes32); +} diff --git a/src/accounts/safe/interfaces/ISafeOp.sol b/src/accounts/safe/interfaces/ISafeOp.sol new file mode 100644 index 00000000..fefc954f --- /dev/null +++ b/src/accounts/safe/interfaces/ISafeOp.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { PackedUserOperation } from "account-abstraction/interfaces/PackedUserOperation.sol"; + +bytes32 constant SAFE_OP_TYPEHASH = + 0xc03dfc11d8b10bf9cf703d558958c8c42777f785d998c62060d85a4f0ef6ea7f; + +interface ISafeOp { + /** + * @notice The EIP-712 type-hash for a SafeOp, representing the structure of a User Operation + * for + * the Safe. + * {address} safe - The address of the safe on which the operation is performed. + * {uint256} nonce - A unique number associated with the user operation, preventing replay + * attacks + * by ensuring each operation is unique. + * {bytes} initCode - The packed encoding of a factory address and its factory-specific data + * for + * creating a new Safe account. + * {bytes} callData - The bytes representing the data of the function call to be executed. + * {uint128} verificationGasLimit - The maximum amount of gas allowed for the verification + * process. + * {uint128} callGasLimit - The maximum amount of gas allowed for executing the function call. + * {uint256} preVerificationGas - The amount of gas allocated for pre-verification steps before + * executing the main operation. + * {uint128} maxPriorityFeePerGas - The maximum priority fee per gas that the user is willing + * to + * pay for the transaction. + * {uint128} maxFeePerGas - The maximum fee per gas that the user is willing to pay for the + * transaction. + * {bytes} paymasterAndData - The packed encoding of a paymaster address and its + * paymaster-specific + * data for sponsoring the user operation. + * {uint48} validAfter - A timestamp representing from when the user operation is valid. + * {uint48} validUntil - A timestamp representing until when the user operation is valid, or 0 + * to + * indicated "forever". + * {address} entryPoint - The address of the entry point that will execute the user operation. + * @dev When validating the user operation, the signature timestamps are pre-pended to the + * signature + * bytes. Equal to: + * keccak256( + * "SafeOp(address safe,uint256 nonce,bytes initCode,bytes callData,uint128 + * verificationGasLimit,uint128 callGasLimit,uint256 preVerificationGas,uint128 + * maxPriorityFeePerGas,uint128 maxFeePerGas,bytes paymasterAndData,uint48 validAfter,uint48 + * validUntil,address entryPoint)" + * ) = 0xc03dfc11d8b10bf9cf703d558958c8c42777f785d998c62060d85a4f0ef6ea7f + */ + struct EncodedSafeOpStruct { + bytes32 typeHash; + address safe; + uint256 nonce; + bytes32 initCodeHash; + bytes32 callDataHash; + uint128 verificationGasLimit; + uint128 callGasLimit; + uint256 preVerificationGas; + uint128 maxPriorityFeePerGas; + uint128 maxFeePerGas; + bytes32 paymasterAndDataHash; + uint48 validAfter; + uint48 validUntil; + address entryPoint; + } + + function domainSeparator() external view returns (bytes32); + + function getSafeOp( + PackedUserOperation calldata userOp, + address entryPoint + ) + external + view + returns ( + bytes memory operationData, + uint48 validAfter, + uint48 validUntil, + bytes calldata signatures + ); +} diff --git a/src/accounts/safe/types/DataTypes.sol b/src/accounts/safe/types/DataTypes.sol new file mode 100644 index 00000000..6ab8deef --- /dev/null +++ b/src/accounts/safe/types/DataTypes.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { IERC7484 } from "../interfaces/IERC7484.sol"; +import { CallType } from "../../common/lib/ModeLib.sol"; + +struct FallbackHandler { + address handler; + CallType calltype; +} + +enum HookType { + GLOBAL, + SIG +} + +struct ModuleInit { + address module; + bytes initData; +} + +struct RegistryInit { + IERC7484 registry; + address[] attesters; + uint8 threshold; +} diff --git a/src/accounts/template/FactoryTemplate.sol b/src/accounts/template/FactoryTemplate.sol index 2134d912..9a5d4ba4 100644 --- a/src/accounts/template/FactoryTemplate.sol +++ b/src/accounts/template/FactoryTemplate.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; abstract contract FactoryTemplate { constructor() { diff --git a/src/deployment/RegistryDeployer.sol b/src/deployment/RegistryDeployer.sol index 717cb88a..19090218 100644 --- a/src/deployment/RegistryDeployer.sol +++ b/src/deployment/RegistryDeployer.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; -import { IRegistry, IExternalResolver } from "registry/IRegistry.sol"; +import { IRegistry, IExternalResolver } from "src/deployment/registry/interfaces/IRegistry.sol"; import { ResolverRecord, ModuleRecord, @@ -11,8 +11,9 @@ import { ModuleType, SchemaUID, SchemaRecord -} from "registry/DataTypes.sol"; -import { IExternalSchemaValidator } from "registry/external/IExternalSchemaValidator.sol"; +} from "src/deployment/registry/types/DataTypes.sol"; +import { IExternalSchemaValidator } from + "src/deployment/registry/interfaces/IExternalSchemaValidator.sol"; address constant REGISTRY_ADDR = 0x000000000069E2a187AEFFb852bF3cCdC95151B2; diff --git a/src/deployment/registry/interfaces/IERC7484.sol b/src/deployment/registry/interfaces/IERC7484.sol new file mode 100644 index 00000000..b7bf16da --- /dev/null +++ b/src/deployment/registry/interfaces/IERC7484.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { ModuleType } from "src/deployment/registry/types/DataTypes.sol"; + +interface IERC7484 { + event NewTrustedAttesters(address indexed smartAccount); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Check with Registry internal attesters */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function check(address module) external view; + + function checkForAccount(address smartAccount, address module) external view; + + function check(address module, ModuleType moduleType) external view; + + function checkForAccount( + address smartAccount, + address module, + ModuleType moduleType + ) + external + view; + + /** + * Allows Smart Accounts - the end users of the registry - to appoint + * one or many attesters as trusted. + * @dev this function reverts, if address(0), or duplicates are provided in attesters[] + * + * @param threshold The minimum number of attestations required for a module + * to be considered secure. + * @param attesters The addresses of the attesters to be trusted. + */ + function trustAttesters(uint8 threshold, address[] calldata attesters) external; + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Check with external attester(s) */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function check(address module, address[] calldata attesters, uint256 threshold) external view; + + function check( + address module, + ModuleType moduleType, + address[] calldata attesters, + uint256 threshold + ) + external + view; +} diff --git a/src/deployment/registry/interfaces/IExternalResolver.sol b/src/deployment/registry/interfaces/IExternalResolver.sol new file mode 100644 index 00000000..65ce9e86 --- /dev/null +++ b/src/deployment/registry/interfaces/IExternalResolver.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { AttestationRecord, ModuleRecord } from "src/deployment/registry/types/DataTypes.sol"; +import { IERC165 } from "forge-std/interfaces/IERC165.sol"; + +/** + * @title The interface of an optional schema resolver. + * @dev The resolver is responsible for validating the schema and attestation data. + * @dev The resolver is also responsible for processing the attestation and revocation requests. + * + */ +interface IExternalResolver is IERC165 { + /** + * @dev Processes an attestation and verifies whether it's valid. + * + * @param attestation The new attestation. + * + * @return Whether the attestation is valid. + */ + function resolveAttestation(AttestationRecord calldata attestation) + external + payable + returns (bool); + + function resolveAttestation(AttestationRecord[] calldata attestation) + external + payable + returns (bool); + + /** + * @dev Processes an attestation revocation and verifies if it can be revoked. + * + * @param attestation The existing attestation to be revoked. + * + * @return Whether the attestation can be revoked. + */ + function resolveRevocation(AttestationRecord calldata attestation) + external + payable + returns (bool); + function resolveRevocation(AttestationRecord[] calldata attestation) + external + payable + returns (bool); + + /** + * @dev Processes a Module Registration + * + * @param sender The msg.sender of the module registration + * @param moduleAddress address of the module + * @param record Module registration artefact + * + * @return Whether the registration is valid + */ + function resolveModuleRegistration( + address sender, + address moduleAddress, + ModuleRecord calldata record, + bytes calldata resolverContext + ) + external + payable + returns (bool); +} diff --git a/src/deployment/registry/interfaces/IExternalSchemaValidator.sol b/src/deployment/registry/interfaces/IExternalSchemaValidator.sol new file mode 100644 index 00000000..5ec36149 --- /dev/null +++ b/src/deployment/registry/interfaces/IExternalSchemaValidator.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { AttestationRecord } from "src/deployment/registry/types/DataTypes.sol"; +import { IERC165 } from "forge-std/interfaces/IERC165.sol"; + +/** + * @title The interface of an optional schema resolver. + */ +interface IExternalSchemaValidator is IERC165 { + /** + * @notice Validates an attestation request. + */ + function validateSchema(AttestationRecord calldata attestation) external returns (bool); + + /** + * @notice Validates an array of attestation requests. + */ + function validateSchema(AttestationRecord[] calldata attestations) external returns (bool); +} diff --git a/src/deployment/registry/interfaces/IRegistry.sol b/src/deployment/registry/interfaces/IRegistry.sol new file mode 100644 index 00000000..7120f33e --- /dev/null +++ b/src/deployment/registry/interfaces/IRegistry.sol @@ -0,0 +1,418 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { + AttestationDataRef, + AttestationRecord, + AttestationRequest, + ModuleType, + ModuleRecord, + ResolverUID, + ResolverRecord, + RevocationRequest, + SchemaUID, + SchemaRecord +} from "src/deployment/registry/types/DataTypes.sol"; +import { IExternalSchemaValidator } from + "src/deployment/registry/interfaces/IExternalSchemaValidator.sol"; +import { IExternalResolver } from "src/deployment/registry/interfaces/IExternalResolver.sol"; +import { IERC7484 } from "src/deployment/registry/interfaces/IERC7484.sol"; + +/** + * Interface definition of all features of the registry: + * - Register Schemas + * - Register External Resolvers + * - Register Modules + * - Make Attestations + * - Make Revocations + * - Delegate Trust to Attester(s) + * + * @author rhinestone | zeroknots.eth, Konrad Kopp (@kopy-kat) + */ +interface IRegistry is IERC7484 { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Smart Account - Trust Management */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + error InvalidResolver(IExternalResolver resolver); + error InvalidResolverUID(ResolverUID uid); + error InvalidTrustedAttesterInput(); + error NoTrustedAttestersFound(); + error RevokedAttestation(address attester); + error InvalidModuleType(); + error AttestationNotFound(); + + error InsufficientAttestations(); + + /** + * Get trusted attester for a specific Smart Account + * @param smartAccount The address of the Smart Account + */ + function findTrustedAttesters(address smartAccount) + external + view + returns (address[] memory attesters); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Attestations */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + event Revoked(address indexed moduleAddress, address indexed revoker, SchemaUID schema); + event Attested( + address indexed moduleAddress, + address indexed attester, + SchemaUID schemaUID, + AttestationDataRef indexed sstore2Pointer + ); + + error AlreadyRevoked(); + error AlreadyAttested(); + error ModuleNotFoundInRegistry(address module); + error AccessDenied(); + error InvalidAttestation(); + error InvalidExpirationTime(); + error DifferentResolvers(); + error InvalidSignature(); + error InvalidModuleTypes(); + + /** + * Allows `msg.sender` to attest to multiple modules' security status. + * The `AttestationRequest.Data` provided should match the attestation + * schema defined by the Schema corresponding to the SchemaUID + * + * @dev This function will revert if the same module is attested twice by the same attester. + * If you want to re-attest, you have to revoke your attestation first, and then attest + * again. + * + * @param schemaUID The SchemaUID of the schema the attestation is based on. + * @param request a single AttestationRequest + */ + function attest(SchemaUID schemaUID, AttestationRequest calldata request) external; + + /** + * Allows `msg.sender` to attest to multiple modules' security status. + * The `AttestationRequest.Data` provided should match the attestation + * schema defined by the Schema corresponding to the SchemaUID + * + * @dev This function will revert if the same module is attested twice by the same attester. + * If you want to re-attest, you have to revoke your attestation first, and then attest + * again. + * + * @param schemaUID The SchemaUID of the schema the attestation is based on. + * @param requests An array of AttestationRequest + */ + function attest(SchemaUID schemaUID, AttestationRequest[] calldata requests) external; + + /** + * Allows attester to attest by signing an `AttestationRequest` (`ECDSA` or `ERC1271`) + * The `AttestationRequest.Data` provided should match the attestation + * schema defined by the Schema corresponding to the SchemaUID + * + * @dev This function will revert if the same module is attested twice by the same attester. + * If you want to re-attest, you have to revoke your attestation first, and then attest + * again. + * + * @param schemaUID The SchemaUID of the schema the attestation is based on. + * @param attester The address of the attester + * @param request An AttestationRequest + * @param signature The signature of the attester. ECDSA or ERC1271 + */ + function attest( + SchemaUID schemaUID, + address attester, + AttestationRequest calldata request, + bytes calldata signature + ) + external; + + /** + * Allows attester to attest by signing an `AttestationRequest` (`ECDSA` or `ERC1271`) + * The `AttestationRequest.Data` provided should match the attestation + * schema defined by the Schema corresponding to the SchemaUID + * + * @dev This function will revert if the same module is attested twice by the same attester. + * If you want to re-attest, you have to revoke your attestation first, and then attest + * again. + * + * @param schemaUID The SchemaUID of the schema the attestation is based on. + * @param attester The address of the attester + * @param requests An array of AttestationRequest + * @param signature The signature of the attester. ECDSA or ERC1271 + */ + function attest( + SchemaUID schemaUID, + address attester, + AttestationRequest[] calldata requests, + bytes calldata signature + ) + external; + + /** + * Getter function to get AttestationRequest made by one attester + */ + function findAttestation( + address module, + address attester + ) + external + view + returns (AttestationRecord memory attestation); + + /** + * Getter function to get AttestationRequest made by multiple attesters + */ + function findAttestations( + address module, + address[] calldata attesters + ) + external + view + returns (AttestationRecord[] memory attestations); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Revocations */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * Allows `msg.sender` to revoke an attestation made by the same `msg.sender` + * + * @dev this function will revert if the attestation is not found + * @dev this function will revert if the attestation is already revoked + * + * @param request single RevocationRequest + */ + function revoke(RevocationRequest calldata request) external; + + /** + * Allows msg.sender to revoke multiple attestation made by the same msg.sender + * + * @dev this function will revert if the attestation is not found + * @dev this function will revert if the attestation is already revoked + * + * @param requests the RevocationRequests + */ + function revoke(RevocationRequest[] calldata requests) external; + + /** + * Allows attester to revoke an attestation by signing an `RevocationRequest` (`ECDSA` or + * `ERC1271`) + * + * @param attester the signer / revoker + * @param request single RevocationRequest + * @param signature ECDSA or ERC1271 signature + */ + function revoke( + address attester, + RevocationRequest calldata request, + bytes calldata signature + ) + external; + + /** + * Allows attester to revoke an attestation by signing an `RevocationRequest` (`ECDSA` or + * `ERC1271`) + * @dev if you want to revoke multiple attestations, but from different attesters, call this + * function multiple times + * + * @param attester the signer / revoker + * @param requests array of RevocationRequests + * @param signature ECDSA or ERC1271 signature + */ + function revoke( + address attester, + RevocationRequest[] calldata requests, + bytes calldata signature + ) + external; + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Module Registration */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + // Event triggered when a module is deployed. + event ModuleRegistration(address indexed implementation); + + error AlreadyRegistered(address module); + error InvalidDeployment(); + error ModuleAddressIsNotContract(address moduleAddress); + error FactoryCallFailed(address factory); + + /** + * Module Developers can deploy their module Bytecode directly via the registry. + * This registry implements a `CREATE2` factory, that allows module developers to register and + * deploy module bytecode + * @param salt The salt to be used in the `CREATE2` factory. This adheres to + * Pr000xy/Create2Factory.sol salt formatting. + * The salt's first bytes20 should be the address of the sender + * or bytes20(0) to bypass the check (this will lose replay protection) + * @param resolverUID The resolverUID to be used in the `CREATE2` factory + * @param initCode The initCode to be used in the `CREATE2` factory + * @param metadata The metadata to be stored on the registry. + * This field is optional, and might be used by the module developer to store + * additional + * information about the module or facilitate business logic with the Resolver stub + * @param resolverContext bytes that will be passed to the resolver contract + */ + function deployModule( + bytes32 salt, + ResolverUID resolverUID, + bytes calldata initCode, + bytes calldata metadata, + bytes calldata resolverContext + ) + external + payable + returns (address moduleAddress); + + /** + * In order to make the integration into existing business logics possible, + * the Registry is able to utilize external factories that can be utilized to deploy the + * modules. + * @dev Registry can use other factories to deploy the module. + * @dev Note that this function will call the external factory via the FactoryTrampoline + * contract. + * Factory MUST not assume that msg.sender == registry + * @dev This function is used to deploy and register a module using a factory contract. + * Since one of the parameters of this function is a unique resolverUID and any + * registered module address can only be registered once, + * using this function is of risk for a frontrun attack + */ + function deployViaFactory( + address factory, + bytes calldata callOnFactory, + bytes calldata metadata, + ResolverUID resolverUID, + bytes calldata resolverContext + ) + external + payable + returns (address moduleAddress); + + /** + * Already deployed module addresses can be registered on the registry + * @dev This function is used to deploy and register an already deployed module. + * Since one of the parameters of this function is a unique resolverUID and any + * registered module address can only be registered once, + * using this function is of risk for a frontrun attack + * @dev the sender address of this registration is set to address(0) since anyone can invoke + * this function + * @param resolverUID The resolverUID to be used for the module + * @param moduleAddress The address of the module to be registered + * @param metadata The metadata to be stored on the registry. + * This field is optional, and might be used by the module developer to store + * additional + * information about the module or facilitate business logic with the Resolver stub + * @param resolverContext bytes that will be passed to the resolver contract + */ + function registerModule( + ResolverUID resolverUID, + address moduleAddress, + bytes calldata metadata, + bytes calldata resolverContext + ) + external; + + /** + * in conjunction with the deployModule() function, this function let's you + * predict the address of a CREATE2 module deployment + * @param salt CREATE2 salt + * @param initCode module initcode + * @return moduleAddress counterfactual address of the module deployment + */ + function calcModuleAddress( + bytes32 salt, + bytes calldata initCode + ) + external + view + returns (address); + + /** + * Getter function to get the stored ModuleRecord for a specific module address. + * @param moduleAddress The address of the module + */ + function findModule(address moduleAddress) + external + view + returns (ModuleRecord memory moduleRecord); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Manage Schemas */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + event SchemaRegistered(SchemaUID indexed uid, address indexed registerer); + + error SchemaAlreadyExists(SchemaUID uid); + + error InvalidSchema(); + error InvalidSchemaValidator(IExternalSchemaValidator validator); + + /** + * Register Schema and (optional) external `IExternalSchemaValidator` + * A Schema describe the structure of the data of attestations + * every attestation made on this registry, will reference a SchemaUID to + * make it possible to decode attestation data in human readable form + * overwriting a schema is not allowed, and will revert + * @param schema ABI schema used to encode attestations that are made with this schema + * @param validator (optional) external schema validator that will be used to validate + * attestations. + * use address(0), if you don't need an external validator + * @return uid SchemaUID of the registered schema + */ + function registerSchema( + string calldata schema, + IExternalSchemaValidator validator // OPTIONAL + ) + external + returns (SchemaUID uid); + + /** + * Getter function to retrieve SchemaRecord + */ + function findSchema(SchemaUID uid) external view returns (SchemaRecord memory record); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Manage Resolvers */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + event NewResolver(ResolverUID indexed uid, address indexed resolver); + event NewResolverOwner(ResolverUID indexed uid, address newOwner); + + error ResolverAlreadyExists(); + + /** + * Allows Marketplace Agents to register external resolvers. + * @param resolver external resolver contract + * @return uid ResolverUID of the registered resolver + */ + function registerResolver(IExternalResolver resolver) external returns (ResolverUID uid); + + /** + * Entities that previously registered an external resolver, may update the implementation + * address. + * @param uid The UID of the resolver. + * @param resolver The new resolver implementation address. + */ + function setResolver(ResolverUID uid, IExternalResolver resolver) external; + + /** + * Transfer ownership of resolverUID to a new address + * @param uid The UID of the resolver to transfer ownership for + * @param newOwner The address of the new owner + */ + function transferResolverOwnership(ResolverUID uid, address newOwner) external; + + /** + * Getter function to get the ResolverRecord of a registered resolver + * @param uid The UID of the resolver. + */ + function findResolver(ResolverUID uid) external view returns (ResolverRecord memory record); + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Stub Errors */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + error ExternalError_SchemaValidation(); + error ExternalError_ResolveAttestation(); + error ExternalError_ResolveRevocation(); + error ExternalError_ModuleRegistration(); +} diff --git a/src/deployment/registry/types/DataTypes.sol b/src/deployment/registry/types/DataTypes.sol new file mode 100644 index 00000000..fca9ac2b --- /dev/null +++ b/src/deployment/registry/types/DataTypes.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +import { IExternalSchemaValidator } from + "src/deployment/registry/interfaces/IExternalSchemaValidator.sol"; +import { IExternalResolver } from "src/deployment/registry/interfaces/IExternalResolver.sol"; + +/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ +/* Storage Structs */ +/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + +struct AttestationRecord { + uint48 time; // The time when the attestation was created (Unix timestamp). + uint48 expirationTime; // The time when the attestation expires (Unix timestamp). + uint48 revocationTime; // The time when the attestation was revoked (Unix timestamp). + PackedModuleTypes moduleTypes; // bit-wise encoded module types. See ModuleTypeLib + address moduleAddress; // The implementation address of the module that is being attested. + address attester; // The attesting account. + AttestationDataRef dataPointer; // SSTORE2 pointer to the attestation data. + SchemaUID schemaUID; // The unique identifier of the schema. +} + +struct ModuleRecord { + ResolverUID resolverUID; // The unique identifier of the resolver. + address sender; // The address of the sender who deployed the contract + bytes metadata; // Additional data related to the contract deployment +} + +struct SchemaRecord { + uint48 registeredAt; // The time when the schema was registered (Unix timestamp). + IExternalSchemaValidator validator; // Optional external schema validator. + string schema; // Custom specification of the schema (e.g., an ABI). +} + +struct ResolverRecord { + IExternalResolver resolver; // Optional resolver. + address resolverOwner; // The address of the account used to register the resolver. +} + +// Struct that represents a trusted attester. +struct TrustedAttesterRecord { + uint8 attesterCount; // number of attesters in the linked list + uint8 threshold; // minimum number of attesters required + address attester; // first attester in linked list. (packed to save gas) + mapping(address attester => mapping(address account => address linkedAttester)) linkedAttesters; +} + +/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ +/* Attestation / Revocation Requests */ +/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + +/** + * @dev A struct representing the arguments of the attestation request. + */ +struct AttestationRequest { + address moduleAddress; // The moduleAddress of the attestation. + uint48 expirationTime; // The time when the attestation expires (Unix timestamp). + bytes data; // Custom attestation data. + ModuleType[] moduleTypes; // optional: The type(s) of the module. +} + +/** + * @dev A struct representing the arguments of the revocation request. + */ +struct RevocationRequest { + address moduleAddress; // The module address. +} + +/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ +/* Custom Types */ +/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + +//---------------------- SchemaUID ------------------------------| +type SchemaUID is bytes32; + +using { schemaEq as == } for SchemaUID global; +using { schemaNotEq as != } for SchemaUID global; + +function schemaEq(SchemaUID uid1, SchemaUID uid2) pure returns (bool) { + return SchemaUID.unwrap(uid1) == SchemaUID.unwrap(uid2); +} + +function schemaNotEq(SchemaUID uid1, SchemaUID uid2) pure returns (bool) { + return SchemaUID.unwrap(uid1) != SchemaUID.unwrap(uid2); +} + +//--------------------- ResolverUID -----------------------------| +type ResolverUID is bytes32; + +using { resolverEq as == } for ResolverUID global; +using { resolverNotEq as != } for ResolverUID global; + +function resolverEq(ResolverUID uid1, ResolverUID uid2) pure returns (bool) { + return ResolverUID.unwrap(uid1) == ResolverUID.unwrap(uid2); +} + +function resolverNotEq(ResolverUID uid1, ResolverUID uid2) pure returns (bool) { + return ResolverUID.unwrap(uid1) != ResolverUID.unwrap(uid2); +} + +type AttestationDataRef is address; + +using { attestationDataRefEq as == } for AttestationDataRef global; + +function attestationDataRefEq( + AttestationDataRef uid1, + AttestationDataRef uid2 +) + pure + returns (bool) +{ + return AttestationDataRef.unwrap(uid1) == AttestationDataRef.unwrap(uid2); +} + +type PackedModuleTypes is uint32; + +type ModuleType is uint256; + +using { moduleTypeEq as == } for ModuleType global; +using { moduleTypeNeq as != } for ModuleType global; + +function moduleTypeEq(ModuleType uid1, ModuleType uid2) pure returns (bool) { + return ModuleType.unwrap(uid1) == ModuleType.unwrap(uid2); +} + +function moduleTypeNeq(ModuleType uid1, ModuleType uid2) pure returns (bool) { + return ModuleType.unwrap(uid1) != ModuleType.unwrap(uid2); +} diff --git a/src/external/ERC4337.sol b/src/external/ERC4337.sol index 6faf9777..f30e93f9 100644 --- a/src/external/ERC4337.sol +++ b/src/external/ERC4337.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-import */ import { PackedUserOperation } from diff --git a/src/external/ERC7579.sol b/src/external/ERC7579.sol deleted file mode 100644 index 863df1f5..00000000 --- a/src/external/ERC7579.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; - -/* solhint-disable no-unused-import */ -import { MSAFactory as ERC7579AccountFactory } from "erc7579/MSAFactory.sol"; -import { MSAAdvanced as ERC7579Account } from "erc7579/MSAAdvanced.sol"; -import { Execution, IERC7579Account } from "erc7579/interfaces/IERC7579Account.sol"; -import { IMSA } from "erc7579/interfaces/IMSA.sol"; -import { - IModule as IERC7579Module, - IValidator as IERC7579Validator, - IExecutor as IERC7579Executor, - IHook as IERC7579Hook, - IFallback as IERC7579Fallback, - MODULE_TYPE_VALIDATOR, - MODULE_TYPE_EXECUTOR, - MODULE_TYPE_HOOK, - MODULE_TYPE_FALLBACK -} from "erc7579/interfaces/IERC7579Module.sol"; - -import { - ModeLib as ERC7579ModeLib, - ModeCode, - CallType, - ExecType, - ModePayload, - CALLTYPE_SINGLE, - CALLTYPE_BATCH, - CALLTYPE_DELEGATECALL, - EXECTYPE_DEFAULT, - MODE_DEFAULT, - CALLTYPE_STATIC -} from "erc7579/lib/ModeLib.sol"; -import { Execution, ExecutionLib as ERC7579ExecutionLib } from "erc7579/lib/ExecutionLib.sol"; - -import { - Bootstrap as ERC7579Bootstrap, - BootstrapConfig as ERC7579BootstrapConfig -} from "erc7579/utils/Bootstrap.sol"; -/* solhint-enable no-unused-import */ diff --git a/src/integrations/ERC20.sol b/src/integrations/ERC20.sol index 47c6df33..ac27b52f 100644 --- a/src/integrations/ERC20.sol +++ b/src/integrations/ERC20.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { IERC20 } from "forge-std/interfaces/IERC20.sol"; import { Execution } from "../Accounts.sol"; diff --git a/src/integrations/ERC4626.sol b/src/integrations/ERC4626.sol index d52d7398..7599cc47 100644 --- a/src/integrations/ERC4626.sol +++ b/src/integrations/ERC4626.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { IERC4626 } from "forge-std/interfaces/IERC4626.sol"; import { Execution } from "../Accounts.sol"; diff --git a/src/integrations/ERC721.sol b/src/integrations/ERC721.sol index c5025f24..79bf4605 100644 --- a/src/integrations/ERC721.sol +++ b/src/integrations/ERC721.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { IERC721 } from "forge-std/interfaces/IERC721.sol"; import { Execution } from "../Accounts.sol"; diff --git a/src/integrations/ERC7579Exec.sol b/src/integrations/ERC7579Exec.sol index c34e36b6..c202f54f 100644 --- a/src/integrations/ERC7579Exec.sol +++ b/src/integrations/ERC7579Exec.sol @@ -1,7 +1,21 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; -import "../external/ERC7579.sol"; +import { + Execution, + ExecutionLib as ERC7579ExecutionLib +} from "src/accounts/erc7579/lib/ExecutionLib.sol"; +import { + ModeLib as ERC7579ModeLib, + CALLTYPE_SINGLE, + CALLTYPE_BATCH, + EXECTYPE_DEFAULT, + CALLTYPE_DELEGATECALL, + MODE_DEFAULT, + ModePayload, + ModeCode +} from "src/accounts/common/lib/ModeLib.sol"; +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; library ERC7579Exec { function exec7579( diff --git a/src/integrations/registry/ExampleFactory.sol b/src/integrations/registry/ExampleFactory.sol index b604b21f..56248117 100644 --- a/src/integrations/registry/ExampleFactory.sol +++ b/src/integrations/registry/ExampleFactory.sol @@ -1,12 +1,13 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; -import { IMSA, ERC7579Bootstrap, IERC7579Module } from "src/external/ERC7579.sol"; +import { IMSA } from "src/accounts/erc7579/interfaces/IMSA.sol"; import { FactoryBase } from "./FactoryBase.sol"; -import { IMSA } from "erc7579/interfaces/IMSA.sol"; -import { MSAProxy } from "erc7579/utils/MSAProxy.sol"; +import { IERC7579Bootstrap } from "src/accounts/erc7579/interfaces/IERC7579Bootstrap.sol"; +import { IModule as IERC7579Module } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { ERC7579Precompiles } from "src/test/precompiles/ERC7579Precompiles.sol"; -contract ExampleFactory is FactoryBase { +contract ExampleFactory is FactoryBase, ERC7579Precompiles { address public immutable IMPLEMENTATION; address public immutable BOOTSTRAP; @@ -38,15 +39,11 @@ contract ExampleFactory is FactoryBase { bytes memory initData = abi.encode( BOOTSTRAP, abi.encodeCall( - ERC7579Bootstrap.singleInitMSA, (IERC7579Module(validator), validatorInitData) + IERC7579Bootstrap.singleInitMSA, (IERC7579Module(validator), validatorInitData) ) ); - address account = address( - new MSAProxy{ salt: salt }( - IMPLEMENTATION, abi.encodeCall(IMSA.initializeAccount, initData) - ) - ); + address account = deployMSAPRoxy(salt, IMPLEMENTATION, initData); return account; } @@ -65,7 +62,7 @@ contract ExampleFactory is FactoryBase { bytes memory initData = abi.encode( BOOTSTRAP, abi.encodeCall( - ERC7579Bootstrap.singleInitMSA, (IERC7579Module(validator), validatorInitData) + IERC7579Bootstrap.singleInitMSA, (IERC7579Module(validator), validatorInitData) ) ); @@ -76,7 +73,7 @@ contract ExampleFactory is FactoryBase { salt, keccak256( abi.encodePacked( - type(MSAProxy).creationCode, + MSAPROXY_BYTECODE, abi.encode(IMPLEMENTATION, abi.encodeCall(IMSA.initializeAccount, initData)) ) ) diff --git a/src/integrations/registry/FactoryBase.sol b/src/integrations/registry/FactoryBase.sol index a8f45944..842fc1a9 100644 --- a/src/integrations/registry/FactoryBase.sol +++ b/src/integrations/registry/FactoryBase.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { IERC7484 } from "src/Interfaces.sol"; diff --git a/src/integrations/uniswap/MockUniswap.sol b/src/integrations/uniswap/MockUniswap.sol index a85fe535..449b6161 100644 --- a/src/integrations/uniswap/MockUniswap.sol +++ b/src/integrations/uniswap/MockUniswap.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import "../interfaces/uniswap/v3/ISwapRouter.sol"; diff --git a/src/integrations/uniswap/helpers/MainnetAddresses.sol b/src/integrations/uniswap/helpers/MainnetAddresses.sol index fa9a0db6..841d7c0a 100644 --- a/src/integrations/uniswap/helpers/MainnetAddresses.sol +++ b/src/integrations/uniswap/helpers/MainnetAddresses.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; address payable constant SWAPROUTER_ADDRESS = payable(0xE592427A0AEce92De3Edee1F18E0157C05861564); uint24 constant SWAPROUTER_DEFAULTFEE = 3000; diff --git a/src/integrations/uniswap/v3/Uniswap.sol b/src/integrations/uniswap/v3/Uniswap.sol index 9ee8daef..dfff9750 100644 --- a/src/integrations/uniswap/v3/Uniswap.sol +++ b/src/integrations/uniswap/v3/Uniswap.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { SWAPROUTER_ADDRESS, diff --git a/src/module-bases/ERC1271Policy.sol b/src/module-bases/ERC1271Policy.sol new file mode 100644 index 00000000..746ef485 --- /dev/null +++ b/src/module-bases/ERC1271Policy.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579PolicyBase } from "./ERC7579PolicyBase.sol"; +import { ConfigId, I1271Policy } from "./interfaces/IPolicy.sol"; + +abstract contract ERC1271Policy is ERC7579PolicyBase, I1271Policy { + function check1271SignedAction( + ConfigId id, + address requestSender, + address account, + bytes32 hash, + bytes calldata signature + ) + external + view + virtual + returns (bool); +} diff --git a/src/module-bases/ERC7484RegistryAdapter.sol b/src/module-bases/ERC7484RegistryAdapter.sol new file mode 100644 index 00000000..9893ce23 --- /dev/null +++ b/src/module-bases/ERC7484RegistryAdapter.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { IERC7484 } from "./interfaces/IERC7484.sol"; + +abstract contract ERC7484RegistryAdapter { + // registry address + IERC7484 public immutable REGISTRY; + + /** + * Contract constructor + * @dev sets the registry as an immutable variable + * + * @param _registry The registry address + */ + constructor(IERC7484 _registry) { + // set the registry + REGISTRY = _registry; + } +} diff --git a/src/module-bases/ERC7579ActionPolicy.sol b/src/module-bases/ERC7579ActionPolicy.sol new file mode 100644 index 00000000..4e0f684f --- /dev/null +++ b/src/module-bases/ERC7579ActionPolicy.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579PolicyBase } from "./ERC7579PolicyBase.sol"; +import { ConfigId, IActionPolicy } from "./interfaces/IPolicy.sol"; + +abstract contract ERC7579ActionPolicy is ERC7579PolicyBase, IActionPolicy { + function checkAction( + ConfigId id, + address account, + address target, + uint256 value, + bytes calldata data + ) + external + virtual + returns (uint256); +} diff --git a/src/module-bases/ERC7579ExecutorBase.sol b/src/module-bases/ERC7579ExecutorBase.sol new file mode 100644 index 00000000..e9833d3d --- /dev/null +++ b/src/module-bases/ERC7579ExecutorBase.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { IExecutor as IERC7579Executor } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; +import { + Execution, + ExecutionLib as ERC7579ExecutionLib +} from "src/accounts/erc7579/lib/ExecutionLib.sol"; +import { + ModeCode, + ModeLib as ERC7579ModeLib, + CALLTYPE_SINGLE, + EXECTYPE_DEFAULT, + MODE_DEFAULT, + ModePayload, + CALLTYPE_BATCH, + EXECTYPE_DEFAULT, + MODE_DEFAULT, + CALLTYPE_DELEGATECALL +} from "src/accounts/common/lib/ModeLib.sol"; +import { ERC7579ModuleBase } from "./ERC7579ModuleBase.sol"; + +abstract contract ERC7579ExecutorBase is IERC7579Executor, ERC7579ModuleBase { + function _execute( + address account, + address to, + uint256 value, + bytes memory data + ) + internal + returns (bytes memory result) + { + ModeCode modeCode = ERC7579ModeLib.encode({ + callType: CALLTYPE_SINGLE, + execType: EXECTYPE_DEFAULT, + mode: MODE_DEFAULT, + payload: ModePayload.wrap(bytes22(0)) + }); + + return IERC7579Account(account).executeFromExecutor( + modeCode, ERC7579ExecutionLib.encodeSingle(to, value, data) + )[0]; + } + + function _execute( + address to, + uint256 value, + bytes memory data + ) + internal + returns (bytes memory result) + { + return _execute(msg.sender, to, value, data); + } + + function _execute( + address account, + Execution[] memory execs + ) + internal + returns (bytes[] memory results) + { + ModeCode modeCode = ERC7579ModeLib.encode({ + callType: CALLTYPE_BATCH, + execType: EXECTYPE_DEFAULT, + mode: MODE_DEFAULT, + payload: ModePayload.wrap(bytes22(0)) + }); + results = IERC7579Account(account).executeFromExecutor( + modeCode, ERC7579ExecutionLib.encodeBatch(execs) + ); + } + + function _execute(Execution[] memory execs) internal returns (bytes[] memory results) { + return _execute(msg.sender, execs); + } + + // Note: Not every account will support delegatecalls + function _executeDelegateCall( + address account, + address delegateTarget, + bytes memory callData + ) + internal + returns (bytes[] memory results) + { + ModeCode modeCode = ERC7579ModeLib.encode({ + callType: CALLTYPE_DELEGATECALL, + execType: EXECTYPE_DEFAULT, + mode: MODE_DEFAULT, + payload: ModePayload.wrap(bytes22(0)) + }); + results = IERC7579Account(account).executeFromExecutor( + modeCode, abi.encodePacked(delegateTarget, callData) + ); + } + + // Note: Not every account will support delegatecalls + function _executeDelegateCall( + address delegateTarget, + bytes memory callData + ) + internal + returns (bytes[] memory results) + { + return _executeDelegateCall(msg.sender, delegateTarget, callData); + } +} diff --git a/src/module-bases/ERC7579FallbackBase.sol b/src/module-bases/ERC7579FallbackBase.sol new file mode 100644 index 00000000..b0b889ab --- /dev/null +++ b/src/module-bases/ERC7579FallbackBase.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { IFallback as IERC7579Fallback } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { ERC7579ModuleBase } from "./ERC7579ModuleBase.sol"; + +abstract contract ERC7579FallbackBase is IERC7579Fallback, ERC7579ModuleBase { + /** + * @notice Allows fetching the original caller address. + * @dev This is only reliable in combination with a FallbackManager that supports this (e.g. Safe + * contract >=1.3.0). + * When using this functionality make sure that the linked _manager (aka msg.sender) + * supports this. + * This function does not rely on a trusted forwarder. Use the returned value only to + * check information against the calling manager. + * @return sender Original caller address. + */ + function _msgSender() internal pure returns (address sender) { + // The assembly code is more direct than the Solidity version using `abi.decode`. + /* solhint-disable no-inline-assembly */ + /// @solidity memory-safe-assembly + assembly { + sender := shr(96, calldataload(sub(calldatasize(), 20))) + } + /* solhint-enable no-inline-assembly */ + } +} diff --git a/src/module-bases/ERC7579HookBase.sol b/src/module-bases/ERC7579HookBase.sol new file mode 100644 index 00000000..0c6a74fe --- /dev/null +++ b/src/module-bases/ERC7579HookBase.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { IHook as IERC7579Hook } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { ERC7579ModuleBase } from "./ERC7579ModuleBase.sol"; +import { TrustedForwarder } from "./utils/TrustedForwarder.sol"; + +abstract contract ERC7579HookBase is IERC7579Hook, ERC7579ModuleBase, TrustedForwarder { + /** + * Precheck hook + * + * @param msgSender sender of the transaction + * @param msgValue value of the transaction + * @param msgData data of the transaction + * + * @return hookData data for the postcheck hook + */ + function preCheck( + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + external + virtual + returns (bytes memory hookData) + { + // route to internal function + return _preCheck(_getAccount(), msgSender, msgValue, msgData); + } + + /** + * Postcheck hook + * + * @param hookData data from the precheck hook + */ + function postCheck(bytes calldata hookData) external virtual { + // route to internal function + _postCheck(_getAccount(), hookData); + } + + /** + * Precheck hook + * + * @param account account of the transaction + * @param msgSender sender of the transaction + * @param msgValue value of the transaction + * @param msgData data of the transaction + * + * @return hookData data for the postcheck hook + */ + function _preCheck( + address account, + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + internal + virtual + returns (bytes memory hookData); + + /** + * Postcheck hook + * + * @param account account of the transaction + * @param hookData data from the precheck hook + */ + function _postCheck(address account, bytes calldata hookData) internal virtual; +} diff --git a/src/module-bases/ERC7579HookDestruct.sol b/src/module-bases/ERC7579HookDestruct.sol new file mode 100644 index 00000000..ccc01a4f --- /dev/null +++ b/src/module-bases/ERC7579HookDestruct.sol @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; +import { IHook as IERC7579Hook } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { ExecutionLib, Execution } from "src/accounts/erc7579/lib/ExecutionLib.sol"; +import { + ModeLib, + CallType, + ModeCode, + CALLTYPE_SINGLE, + CALLTYPE_BATCH, + CALLTYPE_DELEGATECALL +} from "src/accounts/common/lib/ModeLib.sol"; +import { IAccountExecute } from "src/external/ERC4337.sol"; +import { ERC7579ModuleBase } from "./ERC7579ModuleBase.sol"; +import { TrustedForwarder } from "./utils/TrustedForwarder.sol"; + +uint256 constant EXECUSEROP_OFFSET = 164; +uint256 constant EXEC_OFFSET = 100; +uint256 constant INSTALL_OFFSET = 132; + +abstract contract ERC7579HookDestruct is IERC7579Hook, ERC7579ModuleBase, TrustedForwarder { + error HookInvalidSelector(); + error InvalidCallType(); + + /*////////////////////////////////////////////////////////////////////////// + CALLDATA DECODING + //////////////////////////////////////////////////////////////////////////*/ + + function preCheck( + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + external + virtual + override + returns (bytes memory hookData) + { + bytes4 selector = bytes4(msgData[0:4]); + + if (selector == IAccountExecute.executeUserOp.selector) { + uint256 offset = + uint256(bytes32(msgData[EXECUSEROP_OFFSET:EXECUSEROP_OFFSET + 32])) + 68; + uint256 paramLen = uint256(bytes32(msgData[offset:offset + 32])); + offset += 32; + bytes calldata _msgData = msgData[offset:offset + paramLen]; + return _decodeCallData(msgSender, msgValue, _msgData); + } else { + return _decodeCallData(msgSender, msgValue, msgData); + } + } + + function _decodeCallData( + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + internal + returns (bytes memory hookData) + { + bytes4 selector = bytes4(msgData[0:4]); + if (selector == IERC7579Account.execute.selector) { + return _handle4337Executions(msgSender, msgData); + } else if (selector == IERC7579Account.executeFromExecutor.selector) { + return _handleExecutorExecutions(msgSender, msgData); + } else if (selector == IERC7579Account.installModule.selector) { + uint256 paramLen = msgData.length > INSTALL_OFFSET + ? uint256(bytes32(msgData[INSTALL_OFFSET - 32:INSTALL_OFFSET])) + : uint256(0); + bytes calldata initData = msgData.length > INSTALL_OFFSET + ? msgData[INSTALL_OFFSET:INSTALL_OFFSET + paramLen] + : msgData[0:0]; + uint256 moduleType = uint256(bytes32(msgData[4:36])); + address module = address(bytes20((msgData[48:68]))); + return onInstallModule(_getAccount(), msgSender, moduleType, module, initData); + } else if (selector == IERC7579Account.uninstallModule.selector) { + uint256 paramLen = msgData.length > INSTALL_OFFSET + ? uint256(bytes32(msgData[INSTALL_OFFSET - 32:INSTALL_OFFSET])) + : uint256(0); + bytes calldata initData = msgData.length > INSTALL_OFFSET + ? msgData[INSTALL_OFFSET:INSTALL_OFFSET + paramLen] + : msgData[0:0]; + + uint256 moduleType = uint256(bytes32(msgData[4:36])); + address module = address(bytes20((msgData[48:68]))); + + return onUninstallModule(_getAccount(), msgSender, moduleType, module, initData); + } else { + return onUnknownFunction(_getAccount(), msgSender, msgValue, msgData); + } + } + + function _handle4337Executions( + address msgSender, + bytes calldata msgData + ) + internal + returns (bytes memory hookData) + { + uint256 paramLen = uint256(bytes32(msgData[EXEC_OFFSET - 32:EXEC_OFFSET])); + bytes calldata encodedExecutions = msgData[EXEC_OFFSET:EXEC_OFFSET + paramLen]; + + ModeCode mode = ModeCode.wrap(bytes32(msgData[4:36])); + CallType calltype = ModeLib.getCallType(mode); + + if (calltype == CALLTYPE_SINGLE) { + (address to, uint256 value, bytes calldata callData) = + ExecutionLib.decodeSingle(encodedExecutions); + return onExecute(_getAccount(), msgSender, to, value, callData); + } else if (calltype == CALLTYPE_BATCH) { + Execution[] calldata execs = ExecutionLib.decodeBatch(encodedExecutions); + return onExecuteBatch(_getAccount(), msgSender, execs); + } else if (calltype == CALLTYPE_DELEGATECALL) { + address to = address(bytes20(encodedExecutions[0:20])); + bytes calldata callData = encodedExecutions[20:]; + return onExecuteDelegateCall(_getAccount(), msgSender, to, callData); + } else { + revert InvalidCallType(); + } + } + + function _handleExecutorExecutions( + address msgSender, + bytes calldata msgData + ) + internal + returns (bytes memory hookData) + { + uint256 paramLen = uint256(bytes32(msgData[EXEC_OFFSET - 32:EXEC_OFFSET])); + bytes calldata encodedExecutions = msgData[EXEC_OFFSET:EXEC_OFFSET + paramLen]; + + ModeCode mode = ModeCode.wrap(bytes32(msgData[4:36])); + CallType calltype = ModeLib.getCallType(mode); + + if (calltype == CALLTYPE_SINGLE) { + (address to, uint256 value, bytes calldata callData) = + ExecutionLib.decodeSingle(encodedExecutions); + return onExecuteFromExecutor(_getAccount(), msgSender, to, value, callData); + } else if (calltype == CALLTYPE_BATCH) { + Execution[] calldata execs = ExecutionLib.decodeBatch(encodedExecutions); + return onExecuteBatchFromExecutor(_getAccount(), msgSender, execs); + } else if (calltype == CALLTYPE_DELEGATECALL) { + address to = address(bytes20(encodedExecutions[0:20])); + bytes calldata callData = encodedExecutions[20:]; + return onExecuteDelegateCallFromExecutor(_getAccount(), msgSender, to, callData); + } else { + revert InvalidCallType(); + } + } + + function postCheck(bytes calldata hookData) external virtual override { + onPostCheck(_getAccount(), hookData); + } + + /*////////////////////////////////////////////////////////////////////////// + EXECUTION + //////////////////////////////////////////////////////////////////////////*/ + + function onExecute( + address account, + address msgSender, + address target, + uint256 value, + bytes calldata callData + ) + internal + virtual + returns (bytes memory hookData) + { } + + function onExecuteBatch( + address account, + address msgSender, + Execution[] calldata + ) + internal + virtual + returns (bytes memory hookData) + { } + + function onExecuteDelegateCall( + address account, + address msgSender, + address target, + bytes calldata callData + ) + internal + virtual + returns (bytes memory hookData) + { } + + function onExecuteFromExecutor( + address account, + address msgSender, + address target, + uint256 value, + bytes calldata callData + ) + internal + virtual + returns (bytes memory hookData) + { } + + function onExecuteBatchFromExecutor( + address account, + address msgSender, + Execution[] calldata + ) + internal + virtual + returns (bytes memory hookData) + { } + + function onExecuteDelegateCallFromExecutor( + address account, + address msgSender, + address target, + bytes calldata callData + ) + internal + virtual + returns (bytes memory hookData) + { } + + /*////////////////////////////////////////////////////////////////////////// + CONFIG + //////////////////////////////////////////////////////////////////////////*/ + + function onInstallModule( + address account, + address msgSender, + uint256 moduleType, + address module, + bytes calldata initData + ) + internal + virtual + returns (bytes memory hookData) + { } + + function onUninstallModule( + address account, + address msgSender, + uint256 moduleType, + address module, + bytes calldata deInitData + ) + internal + virtual + returns (bytes memory hookData) + { } + + /*////////////////////////////////////////////////////////////////////////// + UNKNOWN FUNCTION + //////////////////////////////////////////////////////////////////////////*/ + + function onUnknownFunction( + address account, + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + internal + virtual + returns (bytes memory hookData) + { } + + /*////////////////////////////////////////////////////////////////////////// + POSTCHECK + //////////////////////////////////////////////////////////////////////////*/ + + function onPostCheck(address account, bytes calldata hookData) internal virtual { } +} diff --git a/src/module-bases/ERC7579HybridValidatorBase.sol b/src/module-bases/ERC7579HybridValidatorBase.sol new file mode 100644 index 00000000..ede9bb55 --- /dev/null +++ b/src/module-bases/ERC7579HybridValidatorBase.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { + PackedUserOperation, + _packValidationData as _packValidationData4337 +} from "src/external/ERC4337.sol"; +import { ERC7579ValidatorBase } from "./ERC7579ValidatorBase.sol"; +import { ERC7579StatelessValidatorBase } from "./ERC7579StatelessValidatorBase.sol"; + +/// @notice Base contract for hybrid validators, which are both stateful and stateless. +abstract contract ERC7579HybridValidatorBase is + ERC7579ValidatorBase, + ERC7579StatelessValidatorBase +{ } diff --git a/src/module-bases/ERC7579ModuleBase.sol b/src/module-bases/ERC7579ModuleBase.sol new file mode 100644 index 00000000..f9ae7172 --- /dev/null +++ b/src/module-bases/ERC7579ModuleBase.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { IModule as IERC7579Module } from "src/accounts/common/interfaces/IERC7579Modules.sol"; + +abstract contract ERC7579ModuleBase is IERC7579Module { + uint256 internal constant TYPE_VALIDATOR = 1; + uint256 internal constant TYPE_EXECUTOR = 2; + uint256 internal constant TYPE_FALLBACK = 3; + uint256 internal constant TYPE_HOOK = 4; + uint256 internal constant TYPE_POLICY = 7; +} diff --git a/src/module-bases/ERC7579PolicyBase.sol b/src/module-bases/ERC7579PolicyBase.sol new file mode 100644 index 00000000..df6c98f7 --- /dev/null +++ b/src/module-bases/ERC7579PolicyBase.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579ModuleBase } from "./ERC7579ModuleBase.sol"; +import { IPolicy, ConfigId } from "./interfaces/IPolicy.sol"; + +abstract contract ERC7579PolicyBase is ERC7579ModuleBase, IPolicy { + function initializeWithMultiplexer( + address account, + ConfigId configId, + bytes calldata initData + ) + external + virtual; +} diff --git a/src/module-bases/ERC7579StatelessValidatorBase.sol b/src/module-bases/ERC7579StatelessValidatorBase.sol new file mode 100644 index 00000000..272d28a9 --- /dev/null +++ b/src/module-bases/ERC7579StatelessValidatorBase.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579ModuleBase } from "./ERC7579ModuleBase.sol"; +import { IStatelessValidator } from "./interfaces/IStatelessValidator.sol"; + +abstract contract ERC7579StatelessValidatorBase is ERC7579ModuleBase, IStatelessValidator { + function validateSignatureWithData( + bytes32, + bytes calldata, + bytes calldata + ) + external + view + virtual + returns (bool validSig); +} diff --git a/src/module-bases/ERC7579UserOpPolicy.sol b/src/module-bases/ERC7579UserOpPolicy.sol new file mode 100644 index 00000000..4ad9ff64 --- /dev/null +++ b/src/module-bases/ERC7579UserOpPolicy.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579PolicyBase } from "./ERC7579PolicyBase.sol"; +import { ConfigId, IUserOpPolicy } from "./interfaces/IPolicy.sol"; +import { PackedUserOperation } from "src/external/ERC4337.sol"; + +abstract contract ERC7579UserOpPolicy is ERC7579PolicyBase, IUserOpPolicy { + function checkUserOp( + ConfigId id, + PackedUserOperation calldata userOp + ) + external + virtual + returns (uint256); +} diff --git a/src/module-bases/ERC7579ValidatorBase.sol b/src/module-bases/ERC7579ValidatorBase.sol new file mode 100644 index 00000000..a6c259b1 --- /dev/null +++ b/src/module-bases/ERC7579ValidatorBase.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { + PackedUserOperation, + _packValidationData as _packValidationData4337 +} from "src/external/ERC4337.sol"; +import { ERC7579ModuleBase } from "./ERC7579ModuleBase.sol"; + +abstract contract ERC7579ValidatorBase is ERC7579ModuleBase { + type ValidationData is uint256; + + ValidationData internal constant VALIDATION_SUCCESS = ValidationData.wrap(0); + ValidationData internal constant VALIDATION_FAILED = ValidationData.wrap(1); + bytes4 internal constant EIP1271_SUCCESS = 0x1626ba7e; + bytes4 internal constant EIP1271_FAILED = 0xFFFFFFFF; + + /** + * Helper to pack the return value for validateUserOp, when not using an aggregator. + * @param sigFailed - True for signature failure, false for success. + * @param validUntil - Last timestamp this UserOperation is valid (or zero for + * infinite). + * @param validAfter - First timestamp this UserOperation is valid. + */ + function _packValidationData( + bool sigFailed, + uint48 validUntil, + uint48 validAfter + ) + internal + pure + returns (ValidationData) + { + return ValidationData.wrap(_packValidationData4337(sigFailed, validUntil, validAfter)); + } + + function _unpackValidationData(ValidationData _packedData) + internal + pure + returns (bool sigFailed, uint48 validUntil, uint48 validAfter) + { + uint256 packedData = ValidationData.unwrap(_packedData); + sigFailed = (packedData & 1) == 1; + validUntil = uint48((packedData >> 160) & ((1 << 48) - 1)); + validAfter = uint48((packedData >> (160 + 48)) & ((1 << 48) - 1)); + } + + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + virtual + returns (ValidationData); + + function isValidSignatureWithSender( + address sender, + bytes32 hash, + bytes calldata data + ) + external + view + virtual + returns (bytes4); +} diff --git a/src/module-bases/ERC7579ValidatorMaster.sol b/src/module-bases/ERC7579ValidatorMaster.sol new file mode 100644 index 00000000..32d7c6de --- /dev/null +++ b/src/module-bases/ERC7579ValidatorMaster.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { + PackedUserOperation, + _packValidationData as _packValidationData4337 +} from "src/external/ERC4337.sol"; +import { ERC7579ModuleBase } from "./ERC7579ModuleBase.sol"; + +abstract contract ERC7579ValidatorBase is ERC7579ModuleBase { + type ValidationData is uint256; + + ValidationData internal constant VALIDATION_FAILED = ValidationData.wrap(1); + bytes4 internal constant EIP1271_SUCCESS = 0x1626ba7e; + bytes4 internal constant EIP1271_FAILED = 0xFFFFFFFF; + + modifier notInitialized() virtual; + modifier alreadyInitialized() virtual; + + // Modules may be intalled without being added to the account + function onInstall(bytes calldata data) external virtual override notInitialized { + _onInstall(data); + } + + function onUninstall(bytes calldata data) external virtual override alreadyInitialized { + _onUninstall(data); + } + + function _onInstall(bytes calldata data) internal virtual; + function _onUninstall(bytes calldata data) internal virtual; + + /** + * Helper to pack the return value for validateUserOp, when not using an aggregator. + * @param sigFailed - True for signature failure, false for success. + * @param validUntil - Last timestamp this UserOperation is valid (or zero for + * infinite). + * @param validAfter - First timestamp this UserOperation is valid. + */ + function _packValidationData( + bool sigFailed, + uint48 validUntil, + uint48 validAfter + ) + internal + pure + returns (ValidationData) + { + return ValidationData.wrap(_packValidationData4337(sigFailed, validUntil, validAfter)); + } + + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + virtual + returns (ValidationData); + + function isValidSignatureWithSender( + address sender, + bytes32 hash, + bytes calldata data + ) + external + view + virtual + returns (bytes4); +} diff --git a/src/module-bases/SchedulingBase.sol b/src/module-bases/SchedulingBase.sol new file mode 100644 index 00000000..5dbea593 --- /dev/null +++ b/src/module-bases/SchedulingBase.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579ExecutorBase } from "./ERC7579ExecutorBase.sol"; + +abstract contract SchedulingBase is ERC7579ExecutorBase { + /*////////////////////////////////////////////////////////////////////////// + CONSTANTS & STORAGE + //////////////////////////////////////////////////////////////////////////*/ + + error InvalidExecution(); + + event ExecutionAdded(address indexed smartAccount, uint256 indexed jobId); + event ExecutionTriggered(address indexed smartAccount, uint256 indexed jobId); + event ExecutionStatusUpdated(address indexed smartAccount, uint256 indexed jobId); + event ExecutionsCancelled(address indexed smartAccount); + + mapping(address smartAccount => mapping(uint256 jobId => ExecutionConfig)) public executionLog; + + mapping(address smartAccount => uint256 jobCount) public accountJobCount; + + struct ExecutionConfig { + uint48 executeInterval; + uint16 numberOfExecutions; + uint16 numberOfExecutionsCompleted; + uint48 startDate; + bool isEnabled; + uint48 lastExecutionTime; + bytes executionData; + } + + struct ExecutorAccess { + uint256 jobId; + } + + /*////////////////////////////////////////////////////////////////////////// + CONFIG + //////////////////////////////////////////////////////////////////////////*/ + + function _onInstall(bytes calldata packedSchedulingData) internal { + address account = msg.sender; + if (isInitialized(account)) { + revert AlreadyInitialized(account); + } + + _createExecution({ orderData: packedSchedulingData }); + } + + function _onUninstall() internal { + address account = msg.sender; + + uint256 count = accountJobCount[account]; + for (uint256 i = 1; i <= count; i++) { + delete executionLog[account][i]; + } + accountJobCount[account] = 0; + + emit ExecutionsCancelled(account); + } + + function isInitialized(address smartAccount) public view returns (bool) { + return accountJobCount[smartAccount] != 0; + } + + function addOrder(bytes calldata orderData) external { + address account = msg.sender; + if (!isInitialized(account)) revert NotInitialized(account); + + _createExecution({ orderData: orderData }); + } + + function toggleOrder(uint256 jobId) external { + address account = msg.sender; + + ExecutionConfig storage executionConfig = executionLog[account][jobId]; + + if (executionConfig.numberOfExecutions == 0) { + revert InvalidExecution(); + } + + executionConfig.isEnabled = !executionConfig.isEnabled; + + emit ExecutionStatusUpdated(account, jobId); + } + + /*////////////////////////////////////////////////////////////////////////// + INTERNAL + //////////////////////////////////////////////////////////////////////////*/ + + function _createExecution(bytes calldata orderData) internal { + address account = msg.sender; + + uint256 jobId = accountJobCount[account] + 1; + accountJobCount[account]++; + + // prevent user from supplying an invalid number of execution (0) + uint16 nrOfExecutions = uint16(bytes2(orderData[6:8])); + if (nrOfExecutions == 0) revert InvalidExecution(); + + executionLog[account][jobId] = ExecutionConfig({ + numberOfExecutionsCompleted: 0, + isEnabled: true, + lastExecutionTime: 0, + executeInterval: uint48(bytes6(orderData[0:6])), + numberOfExecutions: nrOfExecutions, + startDate: uint48(bytes6(orderData[8:14])), + executionData: orderData[14:] + }); + + emit ExecutionAdded(account, jobId); + } + + function _isExecutionValid(uint256 jobId) internal view { + ExecutionConfig storage executionConfig = executionLog[msg.sender][jobId]; + + if (!executionConfig.isEnabled) { + revert InvalidExecution(); + } + + if (executionConfig.lastExecutionTime + executionConfig.executeInterval > block.timestamp) { + revert InvalidExecution(); + } + + if (executionConfig.numberOfExecutionsCompleted >= executionConfig.numberOfExecutions) { + revert InvalidExecution(); + } + + if (executionConfig.startDate > block.timestamp) { + revert InvalidExecution(); + } + } + + modifier canExecute(uint256 jobId) { + _isExecutionValid(jobId); + _; + } + + /*////////////////////////////////////////////////////////////////////////// + METADATA + //////////////////////////////////////////////////////////////////////////*/ + + function isModuleType(uint256 typeID) external pure override returns (bool) { + return typeID == TYPE_EXECUTOR; + } +} diff --git a/src/module-bases/interfaces/Flashloan.sol b/src/module-bases/interfaces/Flashloan.sol new file mode 100644 index 00000000..e52e59d9 --- /dev/null +++ b/src/module-bases/interfaces/Flashloan.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +enum FlashLoanType { + ERC20, + ERC721 +} + +interface IERC6682 { + function flashFeeToken() external view returns (address); + function flashFee(address token, uint256 tokenId) external view returns (uint256); + function availableForFlashLoan(address token, uint256 tokenId) external view returns (bool); +} + +/** + * @dev Interface of the ERC3156 FlashLender, as defined in + * https://eips.ethereum.org/EIPS/eip-3156. + */ +interface IERC3156FlashLender { + /** + * @dev The amount of currency available to be lended. + * @param token The loan currency. + * @return The amount of `token` that can be borrowed. + */ + function maxFlashLoan(address token) external view returns (uint256); + + /** + * @dev The fee to be charged for a given loan. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @return The amount of `token` to be charged for the loan, on top of the returned principal. + */ + function flashFee(address token, uint256 amount) external view returns (uint256); + + /** + * @dev Initiate a flash loan. + * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @param data Arbitrary data structure, intended to contain user-defined parameters. + */ + function flashLoan( + IERC3156FlashBorrower receiver, + address token, + uint256 amount, + bytes calldata data + ) + external + returns (bool); +} + +/** + * @dev Interface of the ERC3156 FlashBorrower, as defined in + * https://eips.ethereum.org/EIPS/eip-3156. + */ +interface IERC3156FlashBorrower { + /** + * @dev Receive a flash loan. + * @param initiator The initiator of the loan. + * @param token The loan currency. + * @param amount The amount of tokens lent. + * @param fee The additional amount of tokens to repay. + * @param data Arbitrary data structure, intended to contain user-defined parameters. + * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" + */ + function onFlashLoan( + address initiator, + address token, + uint256 amount, + uint256 fee, + bytes calldata data + ) + external + returns (bytes32); +} diff --git a/src/module-bases/interfaces/IERC1271.sol b/src/module-bases/interfaces/IERC1271.sol new file mode 100644 index 00000000..2bce20b9 --- /dev/null +++ b/src/module-bases/interfaces/IERC1271.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +// bytes4(keccak256("isValidSignature(bytes32,bytes)") +bytes4 constant EIP1271_MAGIC_VALUE = 0x1626ba7e; + +interface IERC1271 { + /** + * @dev Should return whether the signature provided is valid for the provided data + * @param _dataHash Arbitrary length data signed on behalf of address(this) + * @param _signature Signature byte array associated with _data + * + * MUST return the bytes4 magic value 0x1626ba7e when function passes. + * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > + * 0.5) + * MUST allow external calls + */ + function isValidSignature( + bytes32 _dataHash, + bytes calldata _signature + ) + external + view + returns (bytes4); +} diff --git a/src/module-bases/interfaces/IERC7484.sol b/src/module-bases/interfaces/IERC7484.sol new file mode 100644 index 00000000..bc070193 --- /dev/null +++ b/src/module-bases/interfaces/IERC7484.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IERC7484 { + event NewTrustedAttesters(); + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Check with Registry internal attesters */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function check(address module) external view; + + function checkForAccount(address smartAccount, address module) external view; + + function check(address module, uint256 moduleType) external view; + + function checkForAccount( + address smartAccount, + address module, + uint256 moduleType + ) + external + view; + + /** + * Allows Smart Accounts - the end users of the registry - to appoint + * one or many attesters as trusted. + * @dev this function reverts, if address(0), or duplicates are provided in attesters[] + * + * @param threshold The minimum number of attestations required for a module + * to be considered secure. + * @param attesters The addresses of the attesters to be trusted. + */ + function trustAttesters(uint8 threshold, address[] calldata attesters) external; + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Check with external attester(s) */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function check(address module, address[] calldata attesters, uint256 threshold) external view; + + function check( + address module, + uint256 moduleType, + address[] calldata attesters, + uint256 threshold + ) + external + view; +} diff --git a/src/module-bases/interfaces/IPolicy.sol b/src/module-bases/interfaces/IPolicy.sol new file mode 100644 index 00000000..675f1c7e --- /dev/null +++ b/src/module-bases/interfaces/IPolicy.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +// solhint-disable no-unused-import +import { PackedUserOperation, _packValidationData } from "src/external/ERC4337.sol"; +import { + IModule as IERC7579Module, + VALIDATION_SUCCESS, + VALIDATION_FAILED +} from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { IERC165 } from "forge-std/interfaces/IERC165.sol"; + +type ConfigId is bytes32; + +/** + * IPolicy are external contracts that enforce policies / permission on 4337/7579 executions + * Since it's not the account calling into this contract, and check functions are called during the + * ERC4337 validation + * phase, IPolicy implementations MUST follow ERC4337 storage and opcode restrictions + * A recommend storage layout to store policy related data: + * mapping(id => msg.sender => userOp.sender(account) => state) + * ^ smartSession ^ smart account (associated storage) + */ +interface IPolicy is IERC165, IERC7579Module { + function isInitialized(address account, ConfigId configId) external view returns (bool); + function isInitialized( + address account, + address mulitplexer, + ConfigId configId + ) + external + view + returns (bool); + + /** + * This function may be called by the multiplexer (SmartSessions) without deinitializing first. + * Policies MUST overwrite the current state when this happens + */ + function initializeWithMultiplexer( + address account, + ConfigId configId, + bytes calldata initData + ) + external; +} + +/** + * IUserOpPolicy is a policy that enforces restrictions on user operations. It is called during the + * validation phase + * of the ERC4337 execution. + * Use this policy to enforce restrictions on user operations (userOp.gas, Time based restrictions). + * The checkUserOpPolicy function should return a uint256 value that represents the policy's + * decision. + * The policy's decision should be one of the following: + * - VALIDATION_SUCCESS: The user operation is allowed. + * - VALIDATION_FAILED: The user operation is not allowed. + */ +interface IUserOpPolicy is IPolicy { + function checkUserOpPolicy( + ConfigId id, + PackedUserOperation calldata userOp + ) + external + returns (uint256); +} + +/** + * IActionPolicy is a policy that enforces restrictions on actions. It is called during the + * validation phase + * of the ERC4337 execution. + * ERC7579 accounts natively support batched executions. So in one userOp, multiple actions can be + * executed. + * SmartSession will destruct the execution batch, and call the policy for each action, if the + * policy is installed for + * the actionId for the account. + * Use this policy to enforce restrictions on individual actions (i.e. transfers, approvals, etc). + * The checkAction function should return a uint256 value that represents the policy's decision. + * The policy's decision should be one of the following: + * - VALIDATION_SUCCESS: The action is allowed. + * - VALIDATION_FAILED: The action is not allowed. + */ +interface IActionPolicy is IPolicy { + function checkAction( + ConfigId id, + address account, + address target, + uint256 value, + bytes calldata data + ) + external + returns (uint256); +} + +/** + * I1271Policy is a policy that enforces restrictions on 1271 signed actions. It is called during an + * ERC1271 signature + * validation + */ +interface I1271Policy is IPolicy { + // request sender is probably protocol, so can introduce policies based on it. + function check1271SignedAction( + ConfigId id, + address requestSender, + address account, + bytes32 hash, + bytes calldata signature + ) + external + view + returns (bool); +} diff --git a/src/module-bases/interfaces/IStatelessValidator.sol b/src/module-bases/interfaces/IStatelessValidator.sol new file mode 100644 index 00000000..59c367e1 --- /dev/null +++ b/src/module-bases/interfaces/IStatelessValidator.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +interface IStatelessValidator { + function validateSignatureWithData( + bytes32 hash, + bytes calldata signature, + bytes calldata data + ) + external + view + returns (bool); +} diff --git a/src/module-bases/mocks/MockExecutor.sol b/src/module-bases/mocks/MockExecutor.sol new file mode 100644 index 00000000..005c190e --- /dev/null +++ b/src/module-bases/mocks/MockExecutor.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579ExecutorBase } from "../ERC7579ExecutorBase.sol"; +// solhint-disable-next-line no-unused-import +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; + +contract MockExecutor is ERC7579ExecutorBase { + function onInstall(bytes calldata data) external override { } + + function onUninstall(bytes calldata data) external override { } + + function exec( + address account, + address to, + uint256 value, + bytes calldata callData + ) + external + returns (bytes memory) + { + return _execute(account, to, value, callData); + } + + function isModuleType(uint256 typeID) external pure override returns (bool) { + return typeID == TYPE_EXECUTOR; + } + + function isInitialized( + address // smartAccount + ) + external + pure + returns (bool) + { + return false; + } +} diff --git a/src/module-bases/mocks/MockFallback.sol b/src/module-bases/mocks/MockFallback.sol new file mode 100644 index 00000000..d1400191 --- /dev/null +++ b/src/module-bases/mocks/MockFallback.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579FallbackBase } from "../ERC7579FallbackBase.sol"; + +contract MockFallback is ERC7579FallbackBase { + function onInstall(bytes calldata data) external override { } + + function onUninstall(bytes calldata data) external override { } + + function targetFunction() external pure returns (bool) { + return true; + } + + function isModuleType(uint256 typeID) external pure returns (bool) { + return typeID == TYPE_FALLBACK; + } + + function isInitialized( + address // smartAccount + ) + external + pure + returns (bool) + { + return false; + } +} diff --git a/src/module-bases/mocks/MockHook.sol b/src/module-bases/mocks/MockHook.sol new file mode 100644 index 00000000..6906f9ed --- /dev/null +++ b/src/module-bases/mocks/MockHook.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579HookBase } from "../ERC7579HookBase.sol"; + +contract MockHook is ERC7579HookBase { + function onInstall(bytes calldata data) external override { } + + function onUninstall(bytes calldata data) external override { } + + function _preCheck( + address account, + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + internal + override + returns (bytes memory hookData) + { } + function _postCheck(address account, bytes calldata hookData) internal override { } + + function isInitialized( + address // smartAccount + ) + external + pure + returns (bool) + { + return false; + } + + function isModuleType(uint256 typeID) external pure returns (bool) { + return typeID == TYPE_HOOK; + } +} diff --git a/src/module-bases/mocks/MockHookMultiPlexer.sol b/src/module-bases/mocks/MockHookMultiPlexer.sol new file mode 100644 index 00000000..0362dd0f --- /dev/null +++ b/src/module-bases/mocks/MockHookMultiPlexer.sol @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579HookBase } from "../ERC7579HookBase.sol"; + +contract MockHookMultiPlexer is ERC7579HookBase { + error PreCheckFailed(address hook); + error PostCheckFailed(address hook); + + struct Hook { + address hook; + bool isInitialized; + } + + mapping(address account => Hook[] hookData) public hooks; + + function onInstall(bytes calldata data) external override { + if (data.length == 0) return; + (address[] memory _hooks) = abi.decode(data, (address[])); + for (uint256 i = 0; i < _hooks.length; i++) { + Hook memory _hook = Hook(_hooks[i], true); + hooks[msg.sender].push(_hook); + } + } + + function onUninstall(bytes calldata) external override { + delete hooks[msg.sender]; + } + + function addHook(address hook) external { + Hook memory _hook = Hook(hook, false); + hooks[msg.sender].push(_hook); + } + + function removeHook(address hook) external { + Hook[] storage _hooks = hooks[msg.sender]; + for (uint256 i = 0; i < _hooks.length; i++) { + if (_hooks[i].hook == hook) { + _hooks[i] = _hooks[_hooks.length - 1]; + _hooks.pop(); + break; + } + } + } + + function isHookInstalled(address account, address hook) external view returns (bool) { + Hook[] memory _hooks = hooks[account]; + for (uint256 i = 0; i < _hooks.length; i++) { + if (_hooks[i].hook == hook) return true; + } + return false; + } + + function _preCheck( + address account, + address msgSender, + uint256 msgValue, + bytes calldata msgData + ) + internal + override + returns (bytes memory hookData) + { + uint256 length = hooks[account].length; + if (length == 0) return hookData; + + bytes[] memory _hookData = new bytes[](length); + for (uint256 i = 0; i < length; i++) { + Hook storage _hook = hooks[account][i]; + if (!_hook.isInitialized) { + _hook.isInitialized = true; + } + (bool success, bytes memory _ret) = _hook.hook.call( + abi.encodePacked( + abi.encodeCall(ERC7579HookBase.preCheck, (msgSender, msgValue, msgData)), + address(this), + msg.sender + ) + ); + if (!success) revert PreCheckFailed(_hook.hook); + _hookData[i] = abi.decode(_ret, (bytes)); + } + hookData = abi.encode(_hookData); + } + + function _postCheck(address account, bytes calldata hookData) internal override { + uint256 length = hooks[account].length; + if (length == 0) return; + + bytes[] memory _hookData = new bytes[](length); + if (hookData.length != 0) { + _hookData = abi.decode(hookData, (bytes[])); + } + for (uint256 i = 0; i < length; i++) { + Hook storage _hook = hooks[account][i]; + if (_hook.isInitialized) { + (bool success,) = _hook.hook.call( + abi.encodePacked( + abi.encodeCall(ERC7579HookBase.postCheck, (_hookData[i])), + address(this), + msg.sender + ) + ); + if (!success) revert PostCheckFailed(_hook.hook); + } + } + } + + function isInitialized(address smartAccount) external view returns (bool) { + return hooks[smartAccount].length > 0; + } + + function isModuleType(uint256 typeID) external pure returns (bool) { + return typeID == TYPE_HOOK; + } +} diff --git a/src/module-bases/mocks/MockHybridValidator.sol b/src/module-bases/mocks/MockHybridValidator.sol new file mode 100644 index 00000000..1af9799f --- /dev/null +++ b/src/module-bases/mocks/MockHybridValidator.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579HybridValidatorBase } from "../ERC7579HybridValidatorBase.sol"; +import { PackedUserOperation } from "src/external/ERC4337.sol"; + +contract MockHybridValidator is ERC7579HybridValidatorBase { + function onInstall(bytes calldata data) external virtual override { } + + function onUninstall(bytes calldata data) external virtual override { } + + function validateUserOp( + PackedUserOperation calldata, // userOp + bytes32 // userOpHash + ) + external + virtual + override + returns (ValidationData) + { + return + _packValidationData({ sigFailed: false, validUntil: type(uint48).max, validAfter: 0 }); + } + + function isValidSignatureWithSender( + address, // sender + bytes32, // hash + bytes calldata // data + ) + external + view + virtual + override + returns (bytes4) + { + return EIP1271_SUCCESS; + } + + function isModuleType(uint256 typeID) external pure override returns (bool) { + return typeID == TYPE_VALIDATOR || typeID == 7; + } + + function isInitialized( + address // smartAccount + ) + external + pure + returns (bool) + { + return false; + } + + function validateSignatureWithData( + bytes32, + bytes calldata, + bytes calldata + ) + external + pure + override + returns (bool validSig) + { + return true; + } +} diff --git a/src/module-bases/mocks/MockPolicy.sol b/src/module-bases/mocks/MockPolicy.sol new file mode 100644 index 00000000..398da157 --- /dev/null +++ b/src/module-bases/mocks/MockPolicy.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import { PackedUserOperation } from + "@ERC4337/account-abstraction/contracts/interfaces/PackedUserOperation.sol"; + +contract MockPolicy { + mapping(address account => uint256 validation) public validationData; + mapping( + bytes32 id => mapping(address msgSender => mapping(address userOpSender => uint256 calls)) + ) public userOpState; + mapping( + bytes32 id => mapping(address msgSender => mapping(address userOpSender => uint256 calls)) + ) public actionState; + + function setValidationData(address account, uint256 validation) external { + validationData[account] = validation; + } + + function initializeWithMultiplexer( + address account, + bytes32 configId, + bytes calldata + ) + external + { + userOpState[configId][msg.sender][account] = 1; + } + + function checkUserOpPolicy( + bytes32 id, + PackedUserOperation calldata userOp + ) + external + returns (uint256) + { + userOpState[id][msg.sender][userOp.sender] += 1; + return validationData[userOp.sender]; + } + + function checkAction( + bytes32 id, + address account, + address, + uint256, + bytes calldata + ) + external + returns (uint256) + { + actionState[id][msg.sender][account] += 1; + return validationData[account]; + } + + function supportsInterface(bytes4) external pure returns (bool) { + return true; + } + + function check1271SignedAction( + bytes32, + address, + address, + bytes32, + bytes calldata + ) + external + pure + returns (bool) + { + return true; + } +} diff --git a/src/module-bases/mocks/MockRegistry.sol b/src/module-bases/mocks/MockRegistry.sol new file mode 100644 index 00000000..4f1c0926 --- /dev/null +++ b/src/module-bases/mocks/MockRegistry.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import { IERC7484 } from "../interfaces/IERC7484.sol"; + +/// @title MockRegistry +/// @author zeroknots +contract MockRegistry is IERC7484 { + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Check with Registry internal attesters */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + function check(address module) external view { } + + function checkForAccount(address smartAccount, address module) external view { } + + function check(address module, uint256 moduleType) external view { } + + function checkForAccount( + address smartAccount, + address module, + uint256 moduleType + ) + external + view + { } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Check with external attester(s) */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + function check(address module, address[] calldata attesters, uint256 threshold) external view { } + + function check( + address module, + uint256 moduleType, + address[] calldata attesters, + uint256 threshold + ) + external + view + { } + + function trustAttesters(uint8 threshold, address[] calldata attesters) external { } +} diff --git a/src/module-bases/mocks/MockStatelessValidator.sol b/src/module-bases/mocks/MockStatelessValidator.sol new file mode 100644 index 00000000..835469e9 --- /dev/null +++ b/src/module-bases/mocks/MockStatelessValidator.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +import { ERC7579StatelessValidatorBase } from "../ERC7579StatelessValidatorBase.sol"; + +contract MockStatelessValidator is ERC7579StatelessValidatorBase { + function onInstall(bytes calldata data) external virtual { } + + function onUninstall(bytes calldata data) external virtual { } + + function isModuleType(uint256 typeID) external pure returns (bool) { + return typeID == 7; + } + + function isInitialized(address) external pure returns (bool) { + return true; + } + + function validateSignatureWithData( + bytes32, + bytes calldata, + bytes calldata + ) + external + pure + override + returns (bool validSig) + { + return true; + } +} diff --git a/src/module-bases/mocks/MockTarget.sol b/src/module-bases/mocks/MockTarget.sol new file mode 100644 index 00000000..12a3ef5a --- /dev/null +++ b/src/module-bases/mocks/MockTarget.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +contract MockTarget { + error Unauthorized(); + + uint256 public value; + + function set(uint256 _value) public payable returns (uint256) { + value = _value; + return _value; + } + + function setAccessControl(uint256 _value) public returns (uint256) { + if (msg.sender != address(this)) { + revert Unauthorized(); + } + value = _value; + return _value; + } +} diff --git a/src/module-bases/mocks/MockValidator.sol b/src/module-bases/mocks/MockValidator.sol new file mode 100644 index 00000000..4965888f --- /dev/null +++ b/src/module-bases/mocks/MockValidator.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +/* solhint-disable no-unused-vars */ +import { ERC7579ValidatorBase } from "../ERC7579ValidatorBase.sol"; +import { PackedUserOperation } from "src/external/ERC4337.sol"; + +contract MockValidator is ERC7579ValidatorBase { + function onInstall(bytes calldata data) external virtual override { } + + function onUninstall(bytes calldata data) external virtual override { } + + function validateUserOp( + PackedUserOperation calldata, // userOp + bytes32 // userOpHash + ) + external + virtual + override + returns (ValidationData) + { + return + _packValidationData({ sigFailed: false, validUntil: type(uint48).max, validAfter: 0 }); + } + + function isValidSignatureWithSender( + address, // sender + bytes32, // hash + bytes calldata // data + ) + external + view + virtual + override + returns (bytes4) + { + return EIP1271_SUCCESS; + } + + function isModuleType(uint256 typeID) external pure override returns (bool) { + return typeID == TYPE_VALIDATOR || typeID == 7; + } + + function isInitialized( + address // smartAccount + ) + external + pure + returns (bool) + { + return false; + } +} diff --git a/src/module-bases/utils/ERC7579ValidatorLib.sol b/src/module-bases/utils/ERC7579ValidatorLib.sol new file mode 100644 index 00000000..b5437862 --- /dev/null +++ b/src/module-bases/utils/ERC7579ValidatorLib.sol @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +// solhint-disable-next-line no-unused-import +import { IERC7579Account, Execution } from "src/accounts/common/interfaces/IERC7579Account.sol"; +import { PackedUserOperation, UserOperationLib } from "src/external/ERC4337.sol"; + +enum ACCOUNT_EXEC_TYPE { + EXEC_SINGLE, + EXEC_BATCH, + EXEC_SINGLE_FROM_EXECUTOR, + EXEC_BATCH_FROM_EXECUTOR, + UNINSTALL_HOOK, + INSTALL_VALIDATOR, + INSTALL_EXECUTOR, + ERROR +} + +library ERC7579ValidatorLib { + error InvalidExecutionType(); + + function decodeExecType(PackedUserOperation calldata _ops) + internal + pure + returns (ACCOUNT_EXEC_TYPE _type) + { + return decodeExecType(_ops.callData); + } + + function decodeExecType(bytes calldata userOpCalldata) + internal + pure + returns (ACCOUNT_EXEC_TYPE _type) + { + // bytes4 functionSig = bytes4(userOpCalldata[:4]); + + // if (IERC7579Account.execute.selector == functionSig) { + // _type = ACCOUNT_EXEC_TYPE.EXEC_SINGLE; + // } else if (IERC7579Account.executeBatch.selector == functionSig) { + // _type = ACCOUNT_EXEC_TYPE.EXEC_BATCH; + // } else if (IERC7579Account.executeFromExecutor.selector == functionSig) { + // _type = ACCOUNT_EXEC_TYPE.EXEC_SINGLE_FROM_EXECUTOR; + // } else if (IERC7579Account.executeBatchFromExecutor.selector == functionSig) { + // _type = ACCOUNT_EXEC_TYPE.EXEC_BATCH_FROM_EXECUTOR; + // } else if (IERC7579Account.installValidator.selector == functionSig) { + // _type = ACCOUNT_EXEC_TYPE.INSTALL_VALIDATOR; + // } else if (IERC7579Account.installExecutor.selector == functionSig) { + // _type = ACCOUNT_EXEC_TYPE.INSTALL_EXECUTOR; + // } else if (IERC7579Account.uninstallHook.selector == functionSig) { + // _type = ACCOUNT_EXEC_TYPE.UNINSTALL_HOOK; + // } else { + // _type = ACCOUNT_EXEC_TYPE.ERROR; + // } + } + + function decodeCalldataBatch(bytes calldata userOpCalldata) + internal + pure + returns (Execution[] calldata executionBatch) + { + /* + * Batch Call Calldata Layout + * Offset (in bytes) | Length (in bytes) | Contents + * 0x0 | 0x4 | bytes4 function selector + * 0x4 | - | + abi.encode(Execution[]) + */ + // solhint-disable-next-line no-inline-assembly + assembly ("memory-safe") { + let offset := add(userOpCalldata.offset, 0x4) + let baseOffset := offset + + let dataPointer := add(baseOffset, calldataload(offset)) + + // Extract the ERC7579 Executions + executionBatch.offset := add(dataPointer, 32) + executionBatch.length := calldataload(dataPointer) + } + } + + function decodeCalldataSingle(bytes calldata userOpCalldata) + internal + pure + returns (address destination, uint256 value, bytes calldata callData) + { + bytes calldata accountExecCallData = userOpCalldata[4:]; + destination = address(bytes20(accountExecCallData[12:32])); + value = uint256(bytes32(accountExecCallData[32:64])); + callData = accountExecCallData[128:userOpCalldata.length - 32]; + } + + function decodeConfig(bytes calldata callData) + internal + pure + returns (address module, bytes calldata _callData) + { + module = address(bytes20(callData[12:32])); + _callData = callData[32:]; + } + + function validateWith( + PackedUserOperation calldata userOp, + function(PackedUserOperation calldata,address,uint256,bytes calldata) internal returns(uint48,uint48) + validationFunction + ) + internal + returns (uint48 validUntil, uint48 validAfter) + { + ACCOUNT_EXEC_TYPE _type = decodeExecType(userOp); + + address target; + uint256 value; + bytes calldata callData; + if (ACCOUNT_EXEC_TYPE.EXEC_SINGLE == _type) { + (target, value, callData) = decodeCalldataSingle(userOp.callData); + (validUntil, validAfter) = validationFunction(userOp, target, value, callData); + } else if (ACCOUNT_EXEC_TYPE.EXEC_BATCH == _type) { + Execution[] calldata executionBatch = decodeCalldataBatch(userOp.callData); + uint256 length = executionBatch.length; + for (uint256 i; i < length; i++) { + Execution calldata execution = executionBatch[i]; + (target, value, callData) = (execution.target, execution.value, execution.callData); + (uint256 _newValidUntil, uint256 _newValidAfter) = + validationFunction(userOp, target, value, callData); + (validUntil, validAfter) = + getValidUntil(validUntil, validAfter, _newValidUntil, _newValidAfter); + } + } else { + revert InvalidExecutionType(); + } + } +} + +abstract contract Decoder { + using ERC7579ValidatorLib for *; + using UserOperationLib for *; + + function validate(PackedUserOperation calldata userOp) internal { + ACCOUNT_EXEC_TYPE accountExecType = userOp.callData.decodeExecType(); + address smartAccount = userOp.getSender(); + + if (ACCOUNT_EXEC_TYPE.EXEC_SINGLE == accountExecType) { + (address target, uint256 value, bytes calldata data) = + ERC7579ValidatorLib.decodeCalldataSingle(userOp.callData); + onValidate(smartAccount, target, value, data); + } else if (ACCOUNT_EXEC_TYPE.EXEC_BATCH == accountExecType) { + Execution[] calldata executionBatch = + ERC7579ValidatorLib.decodeCalldataBatch(userOp.callData); + uint256 length; + for (uint256 i; i < length; i++) { + Execution calldata execution = executionBatch[i]; + onValidate(smartAccount, execution.target, execution.value, execution.callData); + } + } else { + revert ERC7579ValidatorLib.InvalidExecutionType(); + } + } + + function onValidate( + address smartAccount, + address target, + uint256 value, + bytes calldata data + ) + internal + virtual + returns (bytes[] memory); +} + +function getValidUntil( + uint256 maxValidUntil, + uint256 minValidAfter, + uint256 newValidUntil, + uint256 newValidAfter +) + pure + returns (uint48 _maxValidUntil, uint48 _minValidAfter) +{ + if (newValidUntil > maxValidUntil) { + _maxValidUntil = uint48(newValidUntil); + } else { + _maxValidUntil = uint48(maxValidUntil); + } + + if (newValidAfter > minValidAfter) { + _minValidAfter = uint48(newValidAfter); + } else { + _minValidAfter = uint48(minValidAfter); + } +} diff --git a/src/module-bases/utils/TrustedForwarder.sol b/src/module-bases/utils/TrustedForwarder.sol new file mode 100644 index 00000000..13533710 --- /dev/null +++ b/src/module-bases/utils/TrustedForwarder.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0 <0.9.0; + +abstract contract TrustedForwarder { + // account => trustedForwarder + mapping(address account => address trustedForwarder) public trustedForwarder; + + /** + * Set the trusted forwarder for an account + * + * @param forwarder The address of the trusted forwarder + */ + function setTrustedForwarder(address forwarder) external { + trustedForwarder[msg.sender] = forwarder; + } + + /** + * Clear the trusted forwarder for an account + */ + function clearTrustedForwarder() public { + trustedForwarder[msg.sender] = address(0); + } + + /** + * Check if a forwarder is trusted for an account + * + * @param forwarder The address of the forwarder + * @param account The address of the account + * + * @return true if the forwarder is trusted for the account + */ + function isTrustedForwarder(address forwarder, address account) public view returns (bool) { + return forwarder == trustedForwarder[account]; + } + + /** + * Get the sender of the transaction + * + * @return account the sender of the transaction + */ + function _getAccount() internal view returns (address account) { + account = msg.sender; + address _account; + address forwarder; + if (msg.data.length >= 40) { + assembly { + _account := shr(96, calldataload(sub(calldatasize(), 20))) + forwarder := shr(96, calldataload(sub(calldatasize(), 40))) + } + if (forwarder == msg.sender && isTrustedForwarder(forwarder, _account)) { + account = _account; + } + } + } +} diff --git a/src/test/Auxiliary.sol b/src/test/Auxiliary.sol index 9cea327e..9b8bc05e 100644 --- a/src/test/Auxiliary.sol +++ b/src/test/Auxiliary.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { IEntryPoint, PackedUserOperation } from "../external/ERC4337.sol"; -import { ERC7579Bootstrap } from "../external/ERC7579.sol"; +import { IERC7579Bootstrap } from "src/accounts/erc7579/interfaces/IERC7579Bootstrap.sol"; import { IERC7484 } from "src/Interfaces.sol"; import { etchEntrypoint } from "./predeploy/EntryPoint.sol"; import { etchSmartSessions } from "./precompiles/SmartSessions.sol"; diff --git a/src/test/ModuleKitHelpers.sol b/src/test/ModuleKitHelpers.sol index 5f598e97..8657703a 100644 --- a/src/test/ModuleKitHelpers.sol +++ b/src/test/ModuleKitHelpers.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { AccountInstance, @@ -14,7 +14,8 @@ import { import { PackedUserOperation } from "../external/ERC4337.sol"; import { ERC4337Helpers } from "./utils/ERC4337Helpers.sol"; import { HelperBase } from "./helpers/HelperBase.sol"; -import { Execution, MODULE_TYPE_HOOK } from "../external/ERC7579.sol"; +import { MODULE_TYPE_HOOK } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { Execution } from "src/accounts/erc7579/lib/ExecutionLib.sol"; import { prank, VmSafe, diff --git a/src/test/ModuleKitUserOp.sol b/src/test/ModuleKitUserOp.sol index b951a8a7..6388918c 100644 --- a/src/test/ModuleKitUserOp.sol +++ b/src/test/ModuleKitUserOp.sol @@ -1,4 +1,4 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; library ModuleKitUserOp { } diff --git a/src/test/RhinestoneModuleKit.sol b/src/test/RhinestoneModuleKit.sol index 72331fc0..920e6f3c 100644 --- a/src/test/RhinestoneModuleKit.sol +++ b/src/test/RhinestoneModuleKit.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { SafeFactory } from "src/accounts/safe/SafeFactory.sol"; import { ERC7579Factory } from "src/accounts/erc7579/ERC7579Factory.sol"; @@ -17,8 +17,8 @@ import { PackedUserOperation, IStakeManager, IEntryPoint } from "../external/ERC import { ENTRYPOINT_ADDR } from "./predeploy/EntryPoint.sol"; import { SMARTSESSION_ADDR } from "./precompiles/SmartSessions.sol"; import { ISmartSession, ISessionValidator } from "src/test/helpers/interfaces/ISmartSession.sol"; -import { IERC7579Validator } from "../external/ERC7579.sol"; -import { MockValidator } from "../Mocks.sol"; +import { IValidator as IERC7579Validator } from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { MockValidator, MockStatelessValidator } from "../Mocks.sol"; import { getAccountEnv, getHelper, @@ -76,7 +76,7 @@ contract RhinestoneModuleKit is AuxiliaryFactory { //////////////////////////////////////////////////////////////////////////*/ MockValidator public _defaultValidator; - MockValidator public _defaultSessionValidator; + MockStatelessValidator public _defaultSessionValidator; bool public isInit; /*////////////////////////////////////////////////////////////////////////// @@ -301,7 +301,7 @@ contract RhinestoneModuleKit is AuxiliaryFactory { label(address(_defaultValidator), "DefaultValidator"); // Set session validator - _defaultSessionValidator = new MockValidator(); + _defaultSessionValidator = new MockStatelessValidator(); label(address(_defaultSessionValidator), "SessionValidator"); } diff --git a/src/test/helpers/ERC7579Helpers.sol b/src/test/helpers/ERC7579Helpers.sol index 7cca84e6..62b29981 100644 --- a/src/test/helpers/ERC7579Helpers.sol +++ b/src/test/helpers/ERC7579Helpers.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; // note: removing the first import will cause a build error import { AccountInstance } from "../RhinestoneModuleKit.sol"; import { HelperBase } from "./HelperBase.sol"; import { IAccountModulesPaginated } from "./interfaces/IAccountModulesPaginated.sol"; import { IERC1271, EIP1271_MAGIC_VALUE } from "src/Interfaces.sol"; -import { CallType } from "src/external/ERC7579.sol"; +import { CallType } from "src/accounts/common/lib/ModeLib.sol"; contract ERC7579Helpers is HelperBase { /*////////////////////////////////////////////////////////////////////////// diff --git a/src/test/helpers/HelperBase.sol b/src/test/helpers/HelperBase.sol index 105ad731..27d3728b 100644 --- a/src/test/helpers/HelperBase.sol +++ b/src/test/helpers/HelperBase.sol @@ -1,13 +1,29 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; - -import { Execution, IERC7579Account } from "../../external/ERC7579.sol"; -import "erc7579/lib/ModeLib.sol"; -import "erc7579/interfaces/IERC7579Module.sol"; +pragma solidity >=0.8.23 <0.9.0; + +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; +import { + ModeLib, + ModeCode, + CALLTYPE_SINGLE, + CALLTYPE_BATCH, + MODE_DEFAULT, + EXECTYPE_DEFAULT, + CALLTYPE_BATCH, + ModePayload +} from "src/accounts/common/lib/ModeLib.sol"; +import { + IModule as IERC7579Module, + MODULE_TYPE_VALIDATOR, + MODULE_TYPE_EXECUTOR, + MODULE_TYPE_HOOK, + MODULE_TYPE_FALLBACK +} from "src/accounts/common/interfaces/IERC7579Modules.sol"; import { PackedUserOperation } from "../../external/ERC4337.sol"; import { AccountInstance } from "../RhinestoneModuleKit.sol"; import "../utils/Vm.sol"; import { IERC1271, EIP1271_MAGIC_VALUE } from "src/Interfaces.sol"; +import { Execution } from "src/accounts/erc7579/lib/ExecutionLib.sol"; abstract contract HelperBase { /*////////////////////////////////////////////////////////////////////////// diff --git a/src/test/helpers/KernelHelpers.sol b/src/test/helpers/KernelHelpers.sol index 0eeadf5a..91eb22c7 100644 --- a/src/test/helpers/KernelHelpers.sol +++ b/src/test/helpers/KernelHelpers.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { AccountInstance } from "../RhinestoneModuleKit.sol"; -import { ValidatorLib } from "kernel/utils/ValidationTypeLib.sol"; -import { ValidationType, ValidationMode, ValidationId } from "kernel/types/Types.sol"; +import { ValidatorLib, ValidationConfig } from "src/accounts/kernel/lib/ValidationTypeLib.sol"; +import { ValidationType, ValidationMode, ValidationId } from "src/accounts/kernel/types/Types.sol"; import { VALIDATION_TYPE_PERMISSION, VALIDATION_TYPE_ROOT, @@ -14,33 +14,26 @@ import { MODULE_TYPE_HOOK, MODULE_TYPE_VALIDATOR, KERNEL_WRAPPER_TYPE_HASH -} from "kernel/types/Constants.sol"; +} from "src/accounts/kernel/types/Constants.sol"; import { ENTRYPOINT_ADDR } from "../predeploy/EntryPoint.sol"; -import { IEntryPoint } from "kernel/interfaces/IEntryPoint.sol"; -import { IERC7579Account } from "erc7579/interfaces/IERC7579Account.sol"; -import { MockFallback } from "kernel/mock/MockFallback.sol"; +import { IEntryPoint } from "@ERC4337/account-abstraction/contracts/interfaces/IEntryPoint.sol"; +import { IERC7579Account } from "src/accounts/kernel/interfaces/IERC7579Account.sol"; +import { MockFallback } from "src/accounts/kernel/mock/MockFallback.sol"; import { HelperBase } from "./HelperBase.sol"; -import { Kernel } from "kernel/Kernel.sol"; +import { IKernel } from "src/accounts/kernel/interfaces/IKernel.sol"; import { etch } from "../utils/Vm.sol"; -import { IValidator, IModule } from "kernel/interfaces/IERC7579Modules.sol"; +import { IValidator, IModule } from "src/accounts/common/interfaces/IERC7579Modules.sol"; import { IERC1271, EIP1271_MAGIC_VALUE } from "src/Interfaces.sol"; -import { CallType, Execution } from "src/external/ERC7579.sol"; +import { CallType } from "src/accounts/common/lib/ModeLib.sol"; +import { Execution } from "src/accounts/erc7579/lib/ExecutionLib.sol"; import { MockHookMultiPlexer } from "src/Mocks.sol"; import { TrustedForwarder } from "src/Modules.sol"; import { PackedUserOperation } from "src/external/ERC4337.sol"; -import { ValidationManager } from "kernel/core/ValidationManager.sol"; import { KernelFactory } from "src/accounts/kernel/KernelFactory.sol"; import { EIP712 } from "solady/utils/EIP712.sol"; +import { KernelPrecompiles, ISetSelector } from "src/test/precompiles/KernelPrecompiles.sol"; -contract SetSelector is Kernel { - constructor(IEntryPoint _entrypoint) Kernel(_entrypoint) { } - - function setSelector(ValidationId vId, bytes4 selector, bool allowed) external { - _setSelector(vId, selector, allowed); - } -} - -contract KernelHelpers is HelperBase { +contract KernelHelpers is HelperBase, KernelPrecompiles { /*////////////////////////////////////////////////////////////////////////// EXECUTIONS //////////////////////////////////////////////////////////////////////////*/ @@ -64,7 +57,7 @@ contract KernelHelpers is HelperBase { address execHook = getExecHook(instance, txValidator); if (execHook != address(0) && execHook != address(1)) { - callData = abi.encodePacked(Kernel.executeUserOp.selector, callData); + callData = abi.encodePacked(IKernel.executeUserOp.selector, callData); } userOp = PackedUserOperation({ @@ -188,7 +181,7 @@ contract KernelHelpers is HelperBase { address execHook = getExecHook(instance, txValidator); if (execHook != address(0) && execHook != address(1)) { - callData = abi.encodePacked(Kernel.executeUserOp.selector, callData); + callData = abi.encodePacked(IKernel.executeUserOp.selector, callData); } userOp = PackedUserOperation({ @@ -219,12 +212,12 @@ contract KernelHelpers is HelperBase { assembly { selector := mload(add(callData, 32)) } - bool isAllowedSelector = Kernel(payable(instance.account)).isAllowedSelector(vId, selector); + bool isAllowedSelector = IKernel(payable(instance.account)).isAllowedSelector(vId, selector); if (!isAllowedSelector) { bytes memory accountCode = instance.account.code; - address _setSelector = address(new SetSelector(IEntryPoint(ENTRYPOINT_ADDR))); + address _setSelector = address(deployKernelWithSetSelector(ENTRYPOINT_ADDR)); etch(instance.account, _setSelector.code); - SetSelector(payable(instance.account)).setSelector(vId, selector, true); + ISetSelector(payable(instance.account)).setSelector(vId, selector, true); etch(instance.account, accountCode); } } @@ -439,7 +432,7 @@ contract KernelHelpers is HelperBase { deployAccountForAction(instance) returns (bytes32) { - return Kernel(payable(instance.account))._toWrappedHash(hash); + return IKernel(payable(instance.account))._toWrappedHash(hash); } function formatERC1271Signature( @@ -484,8 +477,8 @@ contract KernelHelpers is HelperBase { returns (address) { ValidationId vId = ValidatorLib.validatorToIdentifier(IValidator(txValidator)); - ValidationManager.ValidationConfig memory validationConfig = - Kernel(payable(instance.account)).validationConfig(vId); + ValidationConfig memory validationConfig = + IKernel(payable(instance.account)).validationConfig(vId); return address(validationConfig.hook); } } diff --git a/src/test/helpers/NexusHelpers.sol b/src/test/helpers/NexusHelpers.sol index fecbec94..bf9cfb16 100644 --- a/src/test/helpers/NexusHelpers.sol +++ b/src/test/helpers/NexusHelpers.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { PackedUserOperation } from "../../external/ERC4337.sol"; import { AccountInstance } from "../RhinestoneModuleKit.sol"; import { HelperBase } from "./HelperBase.sol"; import { IAccountModulesPaginated } from "./interfaces/IAccountModulesPaginated.sol"; import { IERC1271, EIP1271_MAGIC_VALUE } from "src/Interfaces.sol"; -import { CallType } from "src/external/ERC7579.sol"; +import { CallType } from "src/accounts/common/lib/ModeLib.sol"; contract NexusHelpers is HelperBase { /*////////////////////////////////////////////////////////////////////////// diff --git a/src/test/helpers/SafeHelpers.sol b/src/test/helpers/SafeHelpers.sol index ffcb5d74..7a3d55d3 100644 --- a/src/test/helpers/SafeHelpers.sol +++ b/src/test/helpers/SafeHelpers.sol @@ -1,25 +1,25 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { HelperBase } from "./HelperBase.sol"; import { AccountInstance } from "../RhinestoneModuleKit.sol"; -import { Safe7579Launchpad } from "safe7579/Safe7579Launchpad.sol"; +import { ISafe7579Launchpad } from "src/accounts/safe/interfaces/ISafe7579Launchpad.sol"; import { SafeFactory } from "src/accounts/safe/SafeFactory.sol"; import { PackedUserOperation } from "../../external/ERC4337.sol"; import { - IERC7579Account, MODULE_TYPE_HOOK, MODULE_TYPE_VALIDATOR, MODULE_TYPE_EXECUTOR, MODULE_TYPE_FALLBACK -} from "../../external/ERC7579.sol"; -import { HookType } from "safe7579/DataTypes.sol"; +} from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; +import { HookType } from "src/accounts/safe/types/DataTypes.sol"; import { IAccountFactory } from "src/accounts/interface/IAccountFactory.sol"; import { IAccountModulesPaginated } from "./interfaces/IAccountModulesPaginated.sol"; -import { CALLTYPE_STATIC } from "safe7579/lib/ModeLib.sol"; +import { CALLTYPE_STATIC } from "src/accounts/common/lib/ModeLib.sol"; import { IERC1271, EIP1271_MAGIC_VALUE } from "src/Interfaces.sol"; import { startPrank, stopPrank } from "../utils/Vm.sol"; -import { CallType } from "src/external/ERC7579.sol"; +import { CallType } from "src/accounts/common/lib/ModeLib.sol"; contract SafeHelpers is HelperBase { /*////////////////////////////////////////////////////////////////////////// @@ -324,7 +324,7 @@ contract SafeHelpers is HelperBase { }); bytes32 userOpHash = instance.aux.entrypoint.getUserOpHash(userOp); bytes memory userOpValidationCallData = - abi.encodeCall(Safe7579Launchpad.validateUserOp, (userOp, userOpHash, 0)); + abi.encodeCall(ISafe7579Launchpad.validateUserOp, (userOp, userOpHash, 0)); startPrank(address(instance.aux.entrypoint)); (bool success,) = instance.account.call(userOpValidationCallData); if (!success) { @@ -359,13 +359,13 @@ contract SafeHelpers is HelperBase { assembly { factory := mload(add(originalInitCode, 20)) } - Safe7579Launchpad.InitData memory initData = abi.decode( - IAccountFactory(factory).getInitData(txValidator, ""), (Safe7579Launchpad.InitData) + ISafe7579Launchpad.InitData memory initData = abi.decode( + IAccountFactory(factory).getInitData(txValidator, ""), (ISafe7579Launchpad.InitData) ); initData.callData = erc4337CallData; initCode = abi.encodePacked( factory, abi.encodeCall(SafeFactory.createAccount, (salt, abi.encode(initData))) ); - callData = abi.encodeCall(Safe7579Launchpad.setupSafe, (initData)); + callData = abi.encodeCall(ISafe7579Launchpad.setupSafe, (initData)); } } diff --git a/src/test/helpers/SmartSessionHelpers.sol b/src/test/helpers/SmartSessionHelpers.sol index 5bfae395..4da17ab0 100644 --- a/src/test/helpers/SmartSessionHelpers.sol +++ b/src/test/helpers/SmartSessionHelpers.sol @@ -12,7 +12,7 @@ import { ERC7739Data } from "src/test/helpers/interfaces/ISmartSession.sol"; import { LibZip } from "solady/utils/LibZip.sol"; -import { ModeCode as ExecutionMode } from "erc7579/lib/ModeLib.sol"; +import { ModeCode as ExecutionMode } from "src/accounts/common/lib/ModeLib.sol"; import { EfficientHashLib } from "solady/utils/EfficientHashLib.sol"; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; diff --git a/src/test/helpers/interfaces/IAccountModulesPaginated.sol b/src/test/helpers/interfaces/IAccountModulesPaginated.sol index 109905d9..1d9c50cf 100644 --- a/src/test/helpers/interfaces/IAccountModulesPaginated.sol +++ b/src/test/helpers/interfaces/IAccountModulesPaginated.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; interface IAccountModulesPaginated { function getValidatorsPaginated( diff --git a/src/test/helpers/interfaces/ISmartSession.sol b/src/test/helpers/interfaces/ISmartSession.sol index 4f14ba8e..b97adac1 100644 --- a/src/test/helpers/interfaces/ISmartSession.sol +++ b/src/test/helpers/interfaces/ISmartSession.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; -import { IModule } from "erc7579/interfaces/IERC7579Module.sol"; +import { IModule } from "src/accounts/common/interfaces/IERC7579Modules.sol"; import { PackedUserOperation } from "src/external/ERC4337.sol"; diff --git a/src/test/precompiles/BytecodeDeployer.sol b/src/test/precompiles/BytecodeDeployer.sol new file mode 100644 index 00000000..9e002174 --- /dev/null +++ b/src/test/precompiles/BytecodeDeployer.sol @@ -0,0 +1,27 @@ +// // SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +contract BytecodeDeployer { + /// @notice Deploys a contract using CREATE, reverts on failure + function _deploy(bytes memory creationBytecode) internal returns (address contractAddress) { + assembly { + contractAddress := create(0, add(creationBytecode, 0x20), mload(creationBytecode)) + } + require(contractAddress != address(0), "Deployer: deployment failed"); + } + + /// @notice Deploys a contract using CREATE2, reverts on failure + function _deploy2( + bytes memory creationBytecode, + bytes32 salt + ) + internal + returns (address contractAddress) + { + assembly { + contractAddress := + create2(0, add(creationBytecode, 0x20), mload(creationBytecode), salt) + } + require(contractAddress != address(0), "Deployer: deployment failed"); + } +} diff --git a/src/test/precompiles/ERC7579Precompiles.sol b/src/test/precompiles/ERC7579Precompiles.sol new file mode 100644 index 00000000..556b15aa --- /dev/null +++ b/src/test/precompiles/ERC7579Precompiles.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +// Interfaces +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; +import { IERC7579Bootstrap } from "src/accounts/erc7579/interfaces/IERC7579Bootstrap.sol"; +import { IMSA } from "src/accounts/erc7579/interfaces/IMSA.sol"; + +// Utils +import { label } from "src/test/utils/Vm.sol"; +import { BytecodeDeployer } from "./BytecodeDeployer.sol"; + +interface RhinestoneBootstrap { + function init() external; +} + +contract ERC7579Precompiles is BytecodeDeployer { + /*////////////////////////////////////////////////////////////// + DEPLOY + //////////////////////////////////////////////////////////////*/ + + function deployERC7579Account() internal returns (IERC7579Account) { + return IERC7579Account(_deploy(ERC7579_BYTECODE)); + } + + function deployMSAPRoxy( + bytes32 salt, + address implementation, + bytes memory initCode + ) + internal + returns (address) + { + return _deploy2( + bytes.concat( + MSAPROXY_BYTECODE, + abi.encode( + implementation, + abi.encodeWithSelector(IMSA.initializeAccount.selector, initCode) + ) + ), + salt + ); + } + + function deployERC7579Bootstrap() internal returns (IERC7579Bootstrap) { + return IERC7579Bootstrap(_deploy(ERC7579_BOOTSTRAP_BYTECODE)); + } + + function deployRhinestoneBootstrap() internal returns (RhinestoneBootstrap) { + return RhinestoneBootstrap(_deploy(ERC7579_RHINESTONE_TRAMPOLOINE_BYTECODE)); + } + + /*////////////////////////////////////////////////////////////// + BYTECODES + //////////////////////////////////////////////////////////////*/ + + bytes constant ERC7579_BYTECODE = + hex"6080604052348015600e575f5ffd5b5061387a8061001c5f395ff3fe60806040526004361061010c575f3560e01c8063a71763a811610094578063e9ae5c5311610063578063e9ae5c5314610438578063ea5f61d01461044b578063eab77e171461046a578063eac9b20d14610489578063f2dc691d146104d657610113565b8063a71763a8146103c4578063b0d691fe146103d7578063d03c7914146103f9578063d691c9641461041857610113565b80634b6a1419116100db5780634b6a1419146103135780635faac46b146103265780638dd7712f146103535780639517e29f146103665780639cfd7cff1461037957610113565b80630a664dba1461025a578063112d3a7d1461028b5780631626ba7e146102ba57806319822f7c146102f257610113565b3661011357005b5f3560e01c63bc197c81811463f23a6e6182141763150b7a028214171561013e57806020526020603cf35b505f6101486104f5565b5f80356001600160e01b03191681526002919091016020526040902080549091506001600160a01b03811690600160a01b900460f81b816101ae57604051632464e76d60e11b81526001600160e01b03195f351660048201526024015b60405180910390fd5b6101bc81607f60f91b610519565b1561020d5760408051368101909152365f823760408051601481019091523360601b90525f803660140183865afa90506101fc3d60408051918201905290565b3d5f823e81610209573d81fd5b3d81f35b610217815f610519565b156102585760408051368101909152365f823760408051601481019091523360601b90525f80366014018382875af190506101fc3d60408051918201905290565b005b348015610265575f5ffd5b5061026e610530565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610296575f5ffd5b506102aa6102a5366004612d4c565b61054b565b6040519015158152602001610282565b3480156102c5575f5ffd5b506102d96102d4366004612da3565b6105ae565b6040516001600160e01b03199091168152602001610282565b610305610300366004612ecf565b610681565b604051908152602001610282565b610258610321366004613003565b610891565b348015610331575f5ffd5b50610345610340366004613041565b61091d565b60405161028292919061306b565b6102586103613660046130cd565b610943565b610258610374366004612d4c565b610a0e565b348015610384575f5ffd5b50604080518082018252601b81527f754d53412e616476616e6365642f77697468486f6f6b2e76302e310000000000602082015290516102829190613133565b6102586103d2366004612d4c565b610ea1565b3480156103e2575f5ffd5b506f71727de22e5e9d8baf0edac6f37da03261026e565b348015610404575f5ffd5b506102aa610413366004613145565b611106565b61042b610426366004612da3565b6111a1565b604051610282919061315c565b610258610446366004612da3565b61189f565b348015610456575f5ffd5b50610345610465366004613041565b611ccc565b348015610475575f5ffd5b506102586104843660046131bf565b611ce8565b348015610494575f5ffd5b506104a86104a336600461326d565b611da5565b6040805182516001600160a01b031681526020928301516001600160f81b0319169281019290925201610282565b3480156104e1575f5ffd5b506102aa6104f0366004613145565b611e12565b7ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea0290565b6001600160f81b0319828116908216145b92915050565b5f6105465f5160206137f45f395f51905f525490565b905090565b5f600185036105645761055d84611e5f565b90506105a6565b600285036105755761055d84611e7c565b600385036105925761055d61058c8385018561326d565b85611e95565b600485036105a35761055d84611ed1565b505f5b949350505050565b5f806105bd6014828587613288565b6105c6916132af565b60601c90506105d481611e5f565b6105fc57604051635c93ff2f60e11b81526001600160a01b03821660048201526024016101a5565b6001600160a01b03811663f551e2ee338761061a876014818b613288565b6040518563ffffffff1660e01b81526004016106399493929190613324565b602060405180830381865afa158015610654573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106789190613355565b95945050505050565b5f336f71727de22e5e9d8baf0edac6f37da032146106b257604051635629665f60e11b815260040160405180910390fd5b60208401518290606081901c906106c882611e5f565b610806576106d4611f01565b6107fb575f5f5f8961010001518060200190518101906106f491906133bd565b9250925092505f5f848060200190518101906107109190613448565b915091505f61071f8383611f2d565b90505f610759610753836020527b19457468657265756d205369676e6564204d6573736167653a0a33325f52603c60042090565b87611fb0565b90506001600160a01b038116301461077d5760019a50505050505050505050610879565b61078561203b565b5f846001600160a01b03168460405161079e91906134ac565b5f60405180830381855af49150503d805f81146107d6576040519150601f19603f3d011682016040523d82523d5f602084013e6107db565b606091505b50509050806107e8575f5ffd5b50505050506101008a0152506108069050565b600193505050610879565b604051639700320360e01b81526001600160a01b03831690639700320390610834908a908a906004016134b7565b6020604051808303815f875af1158015610850573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108749190613583565b935050505b8015610889575f385f3884335af1505b509392505050565b61089961205e565b6108a161203b565b5f806108af8385018561359a565b915091505f826001600160a01b0316826040516108cc91906134ac565b5f60405180830381855af49150503d805f8114610904576040519150601f19603f3d011682016040523d82523d5f602084013e610909565b606091505b5050905080610916575f5ffd5b5050505050565b60605f5f6109296104f5565b90506109368186866120a3565b92509250505b9250929050565b336f71727de22e5e9d8baf0edac6f37da0321461097357604051635629665f60e11b815260040160405180910390fd5b365f61098260608501856135dc565b610990916004908290613288565b915091505f306001600160a01b031683836040516109af92919061361e565b5f60405180830381855af49150503d805f81146109e7576040519150601f19603f3d011682016040523d82523d5f602084013e6109ec565b606091505b505090508061091657604051632b3f6d1160e21b815260040160405180910390fd5b336f71727de22e5e9d8baf0edac6f37da0321480610a2b57503330145b610a4857604051635629665f60e11b815260040160405180910390fd5b5f610a5e5f5160206137f45f395f51905f525490565b90506001600160a01b038116610c1d575f54849086906001600160a01b03168015610ae0576040516396fb721760e01b81526001600160a01b038481166004830152602482018490528216906396fb7217906044015f6040518083038186803b158015610ac9575f5ffd5b505afa158015610adb573d5f5f3e3d5ffd5b505050505b60405163ecd0596160e01b8152600481018990526001600160a01b0388169063ecd0596190602401602060405180830381865afa158015610b23573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b47919061362d565b610b67576040516369c9a24560e11b8152600481018990526024016101a5565b60018803610b7f57610b7a87878761224a565b610bd4565b60028803610b9257610b7a87878761228d565b60038803610ba557610b7a8787876122a5565b60048803610bb857610b7a878787612423565b60405163041c38b360e41b8152600481018990526024016101a5565b604080518981526001600160a01b03891660208201527fd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123910160405180910390a1505050610916565b60405163d68f602560e01b81525f906001600160a01b0383169063d68f602590610c51903390349086903690600401613324565b5f604051808303815f875af1158015610c6c573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610c93919081019061364c565b5f54909150859087906001600160a01b03168015610d08576040516396fb721760e01b81526001600160a01b038481166004830152602482018490528216906396fb7217906044015f6040518083038186803b158015610cf1575f5ffd5b505afa158015610d03573d5f5f3e3d5ffd5b505050505b60405163ecd0596160e01b8152600481018a90526001600160a01b0389169063ecd0596190602401602060405180830381865afa158015610d4b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d6f919061362d565b610d8f576040516369c9a24560e11b8152600481018a90526024016101a5565b60018903610da757610da288888861224a565b610dfc565b60028903610dba57610da288888861228d565b60038903610dcd57610da28888886122a5565b60048903610de057610da2888888612423565b60405163041c38b360e41b8152600481018a90526024016101a5565b604080518a81526001600160a01b038a1660208201527fd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123910160405180910390a15050604051630b9dfbed60e11b81526001600160a01b038416915063173bf7da90610e6c908490600401613133565b5f604051808303815f87803b158015610e83575f5ffd5b505af1158015610e95573d5f5f3e3d5ffd5b50505050505050505050565b336f71727de22e5e9d8baf0edac6f37da0321480610ebe57503330145b610edb57604051635629665f60e11b815260040160405180910390fd5b5f610ef15f5160206137f45f395f51905f525490565b90506001600160a01b038116610fb45760018503610f1957610f14848484612483565b610f6e565b60028503610f2c57610f148484846124d8565b60038503610f3f57610f148484846124f4565b60048503610f5257610f148484846126f9565b60405163041c38b360e41b8152600481018690526024016101a5565b604080518681526001600160a01b03861660208201527f341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e910160405180910390a1610916565b60405163d68f602560e01b81525f906001600160a01b0383169063d68f602590610fe8903390349086903690600401613324565b5f604051808303815f875af1158015611003573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261102a919081019061364c565b9050600186036110445761103f858585612483565b611099565b600286036110575761103f8585856124d8565b6003860361106a5761103f8585856124f4565b6004860361107d5761103f8585856126f9565b60405163041c38b360e41b8152600481018790526024016101a5565b604080518781526001600160a01b03871660208201527f341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e910160405180910390a1604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da90610e6c908490600401613133565b5f81600881901b61111b82600160f81b610519565b15611129576001925061116a565b611133825f610519565b15611141576001925061116a565b611153826001600160f81b0319610519565b15611161576001925061116a565b505f9392505050565b611174815f610519565b15611182576001925061119a565b61119081600160f81b610519565b1561116157600192505b5050919050565b60605f6111ac6104f5565b60010190506111bb813361276e565b6111da57604051635c93ff2f60e11b81523360048201526024016101a5565b5f6111f05f5160206137f45f395f51905f525490565b90506001600160a01b038116611520575f5433906002906001600160a01b03168015611273576040516396fb721760e01b81526001600160a01b038481166004830152602482018490528216906396fb7217906044015f6040518083038186803b15801561125c575f5ffd5b505afa15801561126e573d5f5f3e3d5ffd5b505050505b88600881901b61128782600160f81b610519565b156112f55789358a016020810190356112a0835f610519565b156112b6576112af82826127a6565b99506112ee565b6112c483600160f81b610519565b156112d3576112af828261287d565b826040516308c3ee0360e11b81526004016101a5919061367d565b5050611516565b6112ff825f610519565b15611446575f5f365f6113128e8e6129a8565b6040805160018082528183019092529498509296509094509250816020015b6060815260200190600190039081611331579050509b505f6113538682610519565b1561138657611364858585856129f8565b8d5f8151811061137657611376613692565b602002602001018190525061143c565b61139486600160f81b610519565b15611421576113a585858585612a2b565b8e5f815181106113b7576113b7613692565b602090810291909101015290508061141c577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb75f8e5f815181106113fd576113fd613692565b60200260200101516040516114139291906136a6565b60405180910390a15b61143c565b856040516308c3ee0360e11b81526004016101a5919061367d565b5050505050611516565b611458826001600160f81b0319610519565b156114fb575f61146b6014828c8e613288565b611474916132af565b60601c9050365f8c8c601490809261148e93929190613288565b909250905061149d845f610519565b156114b3576114ad838383612a59565b506114f3565b6114c184600160f81b610519565b156114d8576114d1838383612a8a565b50506114f3565b836040516308c3ee0360e11b81526004016101a5919061367d565b505050611516565b81604051632e5bf3f960e21b81526004016101a5919061367d565b5050505050611896565b60405163d68f602560e01b81525f906001600160a01b0383169063d68f602590611554903390349086903690600401613324565b5f604051808303815f875af115801561156f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611596919081019061364c565b5f5490915033906002906001600160a01b0316801561160c576040516396fb721760e01b81526001600160a01b038481166004830152602482018490528216906396fb7217906044015f6040518083038186803b1580156115f5575f5ffd5b505afa158015611607573d5f5f3e3d5ffd5b505050505b89600881901b61162082600160f81b610519565b15611673578a358b01602081019035611639835f610519565b1561164f5761164882826127a6565b9a5061166c565b61165d83600160f81b610519565b156112d357611648828261287d565b5050611836565b61167d825f610519565b156117a4575f5f365f6116908f8f6129a8565b6040805160018082528183019092529498509296509094509250816020015b60608152602001906001900390816116af579050509c505f6116d18682610519565b15611704576116e2858585856129f8565b8e5f815181106116f4576116f4613692565b602002602001018190525061179a565b61171286600160f81b610519565b156114215761172385858585612a2b565b8f5f8151811061173557611735613692565b602090810291909101015290508061179a577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb75f8f5f8151811061177b5761177b613692565b60200260200101516040516117919291906136a6565b60405180910390a15b5050505050611836565b6117b6826001600160f81b0319610519565b156114fb575f6117c96014828d8f613288565b6117d2916132af565b60601c9050365f8d8d60149080926117ec93929190613288565b90925090506117fb845f610519565b156118115761180b838383612a59565b50611832565b61181f84600160f81b610519565b156114d85761182f838383612a8a565b50505b5050505b5050604051630b9dfbed60e11b81526001600160a01b038616935063173bf7da925061186791508490600401613133565b5f604051808303815f87803b15801561187e575f5ffd5b505af1158015611890573d5f5f3e3d5ffd5b50505050505b50509392505050565b336f71727de22e5e9d8baf0edac6f37da03214806118bc57503330145b6118d957604051635629665f60e11b815260040160405180910390fd5b5f6118ef5f5160206137f45f395f51905f525490565b90506001600160a01b038116611a8b5783600881901b61191382600160f81b610519565b15611965578435850160208101903561192c835f610519565b156119415761193b82826127a6565b5061195e565b61194f83600160f81b610519565b156112d35761193b828261287d565b5050611a84565b61196f825f610519565b156119f8575f5f365f61198289896129a8565b9350935093509350611997855f60f81b610519565b156119ae576119a8848484846129f8565b506119ef565b6119bc85600160f81b610519565b156119d4576119cd84848484612a2b565b50506119ef565b846040516308c3ee0360e11b81526004016101a5919061367d565b50505050611a84565b611a0a826001600160f81b0319610519565b156114fb575f611a1d6014828789613288565b611a26916132af565b60601c9050365f611a3a876014818b613288565b9092509050611a49845f610519565b15611a5f57611a59838383612a59565b50611a80565b611a6d84600160f81b610519565b156114d857611a7d838383612a8a565b50505b5050505b5050611cc6565b60405163d68f602560e01b81525f906001600160a01b0383169063d68f602590611abf903390349086903690600401613324565b5f604051808303815f875af1158015611ada573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611b01919081019061364c565b905084600881901b611b1782600160f81b610519565b15611b695785358601602081019035611b30835f610519565b15611b4557611b3f82826127a6565b50611b62565b611b5383600160f81b610519565b156112d357611b3f828261287d565b5050611c69565b611b73825f610519565b15611bdd575f5f365f611b868a8a6129a8565b9350935093509350611b9b855f60f81b610519565b15611bb257611bac848484846129f8565b50611bd4565b611bc085600160f81b610519565b156119d457611bd184848484612a2b565b50505b50505050611c69565b611bef826001600160f81b0319610519565b156114fb575f611c02601482888a613288565b611c0b916132af565b60601c9050365f611c1f886014818c613288565b9092509050611c2e845f610519565b15611c4457611c3e838383612a59565b50611c65565b611c5284600160f81b610519565b156114d857611c62838383612a8a565b50505b5050505b5050604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da90611c97908490600401613133565b5f604051808303815f87803b158015611cae575f5ffd5b505af1158015611cc0573d5f5f3e3d5ffd5b50505050505b50505050565b60605f5f611cd86104f5565b60010190506109368186866120a3565b336f71727de22e5e9d8baf0edac6f37da0321480611d0557503330145b611d2257604051635629665f60e11b815260040160405180910390fd5b5f80546001600160a01b0319166001600160a01b0386161790558115611cc65760405163f05c04e160e01b81526001600160a01b0385169063f05c04e190611d72908490879087906004016136be565b5f604051808303815f87803b158015611d89575f5ffd5b505af1158015611d9b573d5f5f3e3d5ffd5b5050505050505050565b604080518082019091525f8082526020820152611dc06104f5565b6001600160e01b0319929092165f908152600290920160209081526040928390208351808501909452546001600160a01b0381168452600160a01b900460f81b6001600160f81b031916908301525090565b5f60018203611e2357506001919050565b60028203611e3357506001919050565b60038203611e4357506001919050565b60048203611e5357506001919050565b505f919050565b919050565b5f5f611e696104f5565b9050611e75818461276e565b9392505050565b5f5f611e866104f5565b6001019050611e75818461276e565b5f5f611e9f6104f5565b6001600160e01b0319949094165f908152600290940160205250506040909120546001600160a01b0390811691161490565b5f816001600160a01b0316611ef15f5160206137f45f395f51905f525490565b6001600160a01b03161492915050565b5f5f611f0b6104f5565b60015f90815260209190915260409020546001600160a01b0316151592915050565b5f60405180606001604052806031815260200161381460319139604051602001611f5791906134ac565b60408051808303601f190181528282528051602091820120855186830120918401526001600160a01b03861691830191909152606082015260800160405160208183030381529060405280519060200120905092915050565b604051600190835f5260208301516040526040835103611feb57604083015160ff81901c601b016020526001600160ff1b031660605261200f565b604183510361200b5760608301515f1a602052604083015160605261200f565b5f91505b6020600160805f855afa5191503d61202e57638baa579f5f526004601cfd5b5f60605260405292915050565b5f6120446104f5565b905061205281600101612ab6565b61205b81612ab6565b50565b7f15839c8259ca8706cafa7ed5f198b3de1472c96ca2900b32a679090cc8a614de805c8061209f5760405163aed5959560e01b815260040160405180910390fd5b5050565b60605f6001600160a01b0384166001148015906120c757506120c5858561276e565b155b156120f057604051637c84ecfb60e01b81526001600160a01b03851660048201526024016101a5565b825f036121105760405163f725081760e01b815260040160405180910390fd5b826001600160401b0381111561212857612128612dea565b604051908082528060200260200182016040528015612151578160200160208202803683370190505b506001600160a01b038086165f90815260208890526040812054929450911691505b6001600160a01b0382161580159061219557506001600160a01b038216600114155b80156121a057508381105b156121f957818382815181106121b8576121b8613692565b6001600160a01b039283166020918202929092018101919091529281165f9081529287905260409092205490911690806121f181613729565b915050612173565b6001600160a01b03821660011480159061221257505f81115b1561223e5782612223600183613741565b8151811061223357612233613692565b602002602001015191505b80835250935093915050565b5f6122536104f5565b905061225f8185612b11565b6040516306d61fe760e41b81526001600160a01b03851690636d61fe7090611d729086908690600401613754565b5f6122966104f5565b600101905061225f8185612b11565b5f6122b36004828486613288565b6122bc91613767565b90505f838360048181106122d2576122d2613692565b909101356001600160f81b03191691505f90506122f28460058188613288565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152509293506123349250859150612be59050565b156123815760405162461bcd60e51b815260206004820152601e60248201527f46756e6374696f6e2073656c6563746f7220616c72656164792075736564000060448201526064016101a5565b604080518082019091526001600160a01b03871681526001600160f81b0319831660208201526123af6104f5565b6001600160e01b031985165f908152600291909101602090815260409182902083518154949092015160f81c600160a01b026001600160a81b03199094166001600160a01b039283161793909317909255516306d61fe760e41b815290871690636d61fe7090610e6c908490600401613133565b5f6124395f5160206137f45f395f51905f525490565b90506001600160a01b0381161561246e5760405163741cbe0360e01b81526001600160a01b03821660048201526024016101a5565b61225f845f5160206137f45f395f51905f5255565b5f61248c6104f5565b90505f8061249c8486018661359a565b90925090506124ac838388612c1d565b604051638a91b0e360e01b81526001600160a01b03871690638a91b0e390610e6c908490600401613133565b5f6124e16104f5565b60010190505f8061249c8486018661359a565b5f6125026004828486613288565b61250b91613767565b90505f61251b8360048187613288565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525092935061255d9250849150612be59050565b6125a95760405162461bcd60e51b815260206004820152601a60248201527f46756e6374696f6e2073656c6563746f72206e6f74207573656400000000000060448201526064016101a5565b5f6125b26104f5565b6001600160e01b031984165f90815260029190910160209081526040918290208251808401909352546001600160a01b03808216808552600160a01b90920460f81b6001600160f81b0319169284019290925291925087161461266a5760405162461bcd60e51b815260206004820152602a60248201527f46756e6374696f6e2073656c6563746f72206e6f74207573656420627920746860448201526934b9903430b7323632b960b11b60648201526084016101a5565b604080518082019091525f80825260208201526126856104f5565b6001600160e01b031985165f908152600291909101602090815260409182902083518154949092015160f81c600160a01b026001600160a81b03199094166001600160a01b03928316179390931790925551638a91b0e360e01b815290871690638a91b0e390610e6c908590600401613133565b61270e5f5f5160206137f45f395f51905f5255565b604051638a91b0e360e01b81526001600160a01b03841690638a91b0e39061273c9085908590600401613754565b5f604051808303815f87803b158015612753575f5ffd5b505af1158015612765573d5f5f3e3d5ffd5b50505050505050565b5f60016001600160a01b03831614801590611e755750506001600160a01b039081165f90815260209290925260409091205416151590565b606081806001600160401b038111156127c1576127c1612dea565b6040519080825280602002602001820160405280156127f457816020015b60608152602001906001900390816127df5790505b5091505f5b81811015612875573685858381811061281457612814613692565b9050602002810190612826919061379d565b905061284f61283860208301836137bb565b602083013561284a60408501856135dc565b6129f8565b84838151811061286157612861613692565b6020908102919091010152506001016127f9565b505092915050565b606081806001600160401b0381111561289857612898612dea565b6040519080825280602002602001820160405280156128cb57816020015b60608152602001906001900390816128b65790505b5091505f5b8181101561287557368585838181106128eb576128eb613692565b90506020028101906128fd919061379d565b90505f61292761291060208401846137bb565b602084013561292260408601866135dc565b612a2b565b86858151811061293957612939613692565b602090810291909101015290508061299e577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb78386858151811061297f5761297f613692565b60200260200101516040516129959291906136a6565b60405180910390a15b50506001016128d0565b5f8036816129b96014828789613288565b6129c2916132af565b60601c93506129d5603460148789613288565b6129de916137d6565b92506129ed8560348189613288565b949793965094505050565b604051818382375f38838387895af1612a13573d5f823e3d81fd5b3d8152602081013d5f823e3d01604052949350505050565b6040515f90828482375f388483888a5af191503d8152602081013d5f823e3d81016040525094509492505050565b604051818382375f388383875af4612a73573d5f823e3d81fd5b3d8152602081013d5f823e3d016040529392505050565b6040515f90828482375f388483885af491503d8152602081013d5f823e3d810160405250935093915050565b60015f908152602082905260409020546001600160a01b031615612aed576040516329e42f3360e11b815260040160405180910390fd5b60015f818152602092909252604090912080546001600160a01b0319169091179055565b6001600160a01b0381161580612b3057506001600160a01b0381166001145b15612b5957604051637c84ecfb60e01b81526001600160a01b03821660048201526024016101a5565b6001600160a01b038181165f908152602084905260409020541615612b9c57604051631034f46960e21b81526001600160a01b03821660048201526024016101a5565b60015f818152602093909352604080842080546001600160a01b039485168087529286208054959091166001600160a01b03199586161790559190935280549091169091179055565b5f5f612bef6104f5565b6001600160e01b03199093165f908152600293909301602052505060409020546001600160a01b0316151590565b6001600160a01b0381161580612c3c57506001600160a01b0381166001145b15612c6557604051637c84ecfb60e01b81526001600160a01b03831660048201526024016101a5565b6001600160a01b038281165f90815260208590526040902054811690821614612cac57604051637c84ecfb60e01b81526001600160a01b03821660048201526024016101a5565b6001600160a01b039081165f8181526020949094526040808520805494841686529085208054949093166001600160a01b0319948516179092559092528154169055565b6001600160a01b038116811461205b575f5ffd5b8035611e5a81612cf0565b5f5f83601f840112612d1f575f5ffd5b5081356001600160401b03811115612d35575f5ffd5b60208301915083602082850101111561093c575f5ffd5b5f5f5f5f60608587031215612d5f575f5ffd5b843593506020850135612d7181612cf0565b925060408501356001600160401b03811115612d8b575f5ffd5b612d9787828801612d0f565b95989497509550505050565b5f5f5f60408486031215612db5575f5ffd5b8335925060208401356001600160401b03811115612dd1575f5ffd5b612ddd86828701612d0f565b9497909650939450505050565b634e487b7160e01b5f52604160045260245ffd5b60405161012081016001600160401b0381118282101715612e2157612e21612dea565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612e4f57612e4f612dea565b604052919050565b5f6001600160401b03821115612e6f57612e6f612dea565b50601f01601f191660200190565b5f82601f830112612e8c575f5ffd5b8135612e9f612e9a82612e57565b612e27565b818152846020838601011115612eb3575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f60608486031215612ee1575f5ffd5b83356001600160401b03811115612ef6575f5ffd5b84016101208187031215612f08575f5ffd5b612f10612dfe565b612f1982612d04565b81526020828101359082015260408201356001600160401b03811115612f3d575f5ffd5b612f4988828501612e7d565b60408301525060608201356001600160401b03811115612f67575f5ffd5b612f7388828501612e7d565b6060830152506080828101359082015260a0808301359082015260c0808301359082015260e08201356001600160401b03811115612faf575f5ffd5b612fbb88828501612e7d565b60e0830152506101008201356001600160401b03811115612fda575f5ffd5b612fe688828501612e7d565b610100830152509660208601359650604090950135949350505050565b5f5f60208385031215613014575f5ffd5b82356001600160401b03811115613029575f5ffd5b61303585828601612d0f565b90969095509350505050565b5f5f60408385031215613052575f5ffd5b823561305d81612cf0565b946020939093013593505050565b604080825283519082018190525f9060208501906060840190835b818110156130ad5783516001600160a01b0316835260209384019390920191600101613086565b50506001600160a01b039490941660209390930192909252509092915050565b5f5f604083850312156130de575f5ffd5b82356001600160401b038111156130f3575f5ffd5b8301610120818603121561305d575f5ffd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611e756020830184613105565b5f60208284031215613155575f5ffd5b5035919050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156131b357603f1987860301845261319e858351613105565b94506020938401939190910190600101613182565b50929695505050505050565b5f5f5f5f606085870312156131d2575f5ffd5b84356131dd81612cf0565b935060208501356001600160401b038111156131f7575f5ffd5b8501601f81018713613207575f5ffd5b80356001600160401b0381111561321c575f5ffd5b8760208260051b8401011115613230575f5ffd5b60209190910193509150604085013560ff8116811461324d575f5ffd5b939692955090935050565b6001600160e01b03198116811461205b575f5ffd5b5f6020828403121561327d575f5ffd5b8135611e7581613258565b5f5f85851115613296575f5ffd5b838611156132a2575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156132f5576bffffffffffffffffffffffff196bffffffffffffffffffffffff198560140360031b1b82161691505b5092915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b0385168152836020820152606060408201525f61334b6060830184866132fc565b9695505050505050565b5f60208284031215613365575f5ffd5b8151611e7581613258565b5f82601f83011261337f575f5ffd5b815161338d612e9a82612e57565b8181528460208386010111156133a1575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f5f606084860312156133cf575f5ffd5b83516001600160401b038111156133e4575f5ffd5b6133f086828701613370565b93505060208401516001600160401b0381111561340b575f5ffd5b61341786828701613370565b92505060408401516001600160401b03811115613432575f5ffd5b61343e86828701613370565b9150509250925092565b5f5f60408385031215613459575f5ffd5b825161346481612cf0565b60208401519092506001600160401b0381111561347f575f5ffd5b61348b85828601613370565b9150509250929050565b5f81518060208401855e5f93019283525090919050565b5f611e758284613495565b604081526134d16040820184516001600160a01b03169052565b602083015160608201525f604084015161012060808401526134f7610160840182613105565b90506060850151603f198483030160a08501526135148282613105565b915050608085015160c084015260a085015160e084015260c085015161010084015260e0850151603f19848303016101208501526135528282613105565b915050610100850151603f19848303016101408501526135728282613105565b925050508260208301529392505050565b5f60208284031215613593575f5ffd5b5051919050565b5f5f604083850312156135ab575f5ffd5b82356135b681612cf0565b915060208301356001600160401b038111156135d0575f5ffd5b61348b85828601612e7d565b5f5f8335601e198436030181126135f1575f5ffd5b8301803591506001600160401b0382111561360a575f5ffd5b60200191503681900382131561093c575f5ffd5b818382375f9101908152919050565b5f6020828403121561363d575f5ffd5b81518015158114611e75575f5ffd5b5f6020828403121561365c575f5ffd5b81516001600160401b03811115613671575f5ffd5b6105a684828501613370565b6001600160f81b031991909116815260200190565b634e487b7160e01b5f52603260045260245ffd5b828152604060208201525f6105a66040830184613105565b60ff8416815260406020820181905281018290525f8360608301825b8581101561370a5782356136ed81612cf0565b6001600160a01b03168252602092830192909101906001016136da565b509695505050505050565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161373a5761373a613715565b5060010190565b8181038181111561052a5761052a613715565b602081525f6105a66020830184866132fc565b80356001600160e01b031981169060048410156132f5576001600160e01b031960049490940360031b84901b1690921692915050565b5f8235605e198336030181126137b1575f5ffd5b9190910192915050565b5f602082840312156137cb575f5ffd5b8135611e7581612cf0565b8035602083101561052a575f19602084900360031b1b169291505056fe36e05829dd1b9a4411d96a3549582172d7f071c1c0db5c573fcf94eb284316085369676e6564496e6974286164647265737320626f6f7473747261702c627974657320626f6f747374726170496e697429a2646970667358221220e83e3381e4a3a01b6e4061c5e74a9174afdce384fd5b72cbf6e35c1dd5e9d02564736f6c634300081b0033"; + bytes constant ERC7579_BOOTSTRAP_BYTECODE = + hex"6080604052348015600e575f5ffd5b506112a48061001c5f395ff3fe60806040526004361061007e575f3560e01c80636b0d5cc41161004d5780636b0d5cc414610271578063b0d691fe14610290578063ea5f61d0146102b2578063eac9b20d146102d157610085565b80630a664dba146101c85780635e87556d146101f95780635faac46b14610225578063642219af1461025257610085565b3661008557005b5f3560e01c63bc197c81811463f23a6e6182141763150b7a02821417156100b057806020526020603cf35b505f80356001600160e01b03191681525f51602061124f5f395f51905f526020526040902080546001600160a01b03811690600160a01b900460f81b8161011c57604051632464e76d60e11b81526001600160e01b03195f351660048201526024015b60405180910390fd5b61012a81607f60f91b610384565b1561017b5760408051368101909152365f823760408051601481019091523360601b90525f803660140183865afa905061016a3d60408051918201905290565b3d5f823e81610177573d81fd5b3d81f35b610185815f610384565b156101c65760408051368101909152365f823760408051601481019091523360601b90525f80366014018382875af1905061016a3d60408051918201905290565b005b3480156101d3575f5ffd5b506101dc61039b565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610204575f5ffd5b50610218610213366004610d11565b6103c9565b6040516101f09190610e0c565b348015610230575f5ffd5b5061024461023f366004610e35565b610452565b6040516101f0929190610e5f565b34801561025d575f5ffd5b506101c661026c366004610d11565b61048e565b34801561027c575f5ffd5b506101c661028b366004610ec1565b6106d4565b34801561029b575f5ffd5b506f71727de22e5e9d8baf0edac6f37da0326101dc565b3480156102bd575f5ffd5b506102446102cc366004610e35565b6106e4565b3480156102dc575f5ffd5b506103566102eb366004610f41565b6040805180820182525f80825260209182018190526001600160e01b03199390931683525f51602061124f5f395f51905f528152918190208151808301909252546001600160a01b0381168252600160a01b900460f81b6001600160f81b0319169181019190915290565b6040805182516001600160a01b031681526020928301516001600160f81b03191692810192909252016101f0565b6001600160f81b0319828116908216145b92915050565b5f6103c47f36e05829dd1b9a4411d96a3549582172d7f071c1c0db5c573fcf94eb284316085490565b905090565b606030306001600160a01b031663642219af8a8a8a8a8a8a8a6040516024016103f89796959493929190611071565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506040516020016104369291906110ce565b6040516020818303038152906040529050979650505050505050565b60605f7ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea0261048181868661070f565b92509250505b9250929050565b5f5b8681101561050c576105048888838181106104ad576104ad6110f9565b90506020028101906104bf919061110d565b6104cd90602081019061112b565b8989848181106104df576104df6110f9565b90506020028101906104f1919061110d565b6104ff906020810190611146565b6108b7565b600101610490565b505f5b848110156105cc575f86868381811061052a5761052a6110f9565b905060200281019061053c919061110d565b61054a90602081019061112b565b6001600160a01b0316146105c4576105c486868381811061056d5761056d6110f9565b905060200281019061057f919061110d565b61058d90602081019061112b565b87878481811061059f5761059f6110f9565b90506020028101906105b1919061110d565b6105bf906020810190611146565b610939565b60010161050f565b505f6105db602085018561112b565b6001600160a01b03161461060b5761060b6105f9602085018561112b565b6106066020860186611146565b610964565b5f5b818110156106ca575f838383818110610628576106286110f9565b905060200281019061063a919061110d565b61064890602081019061112b565b6001600160a01b0316146106c2576106c283838381811061066b5761066b6110f9565b905060200281019061067d919061110d565b61068b90602081019061112b565b84848481811061069d5761069d6110f9565b90506020028101906106af919061110d565b6106bd906020810190611146565b6109ea565b60010161060d565b5050505050505050565b6106df8383836108b7565b505050565b60605f7ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea036104818186865b60605f6001600160a01b03841660011480159061073357506107318585610b90565b155b1561075c57604051637c84ecfb60e01b81526001600160a01b0385166004820152602401610113565b825f0361077c5760405163f725081760e01b815260040160405180910390fd5b8267ffffffffffffffff81111561079557610795611189565b6040519080825280602002602001820160405280156107be578160200160208202803683370190505b506001600160a01b038086165f90815260208890526040812054929450911691505b6001600160a01b0382161580159061080257506001600160a01b038216600114155b801561080d57508381105b156108665781838281518110610825576108256110f9565b6001600160a01b039283166020918202929092018101919091529281165f90815292879052604090922054909116908061085e816111b1565b9150506107e0565b6001600160a01b03821660011480159061087f57505f81115b156108ab57826108906001836111c9565b815181106108a0576108a06110f9565b602002602001015191505b80835250935093915050565b7ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea026108e28185610bca565b6040516306d61fe760e41b81526001600160a01b03851690636d61fe709061091090869086906004016111dc565b5f604051808303815f87803b158015610927575f5ffd5b505af11580156106ca573d5f5f3e3d5ffd5b7ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea036108e28185610bca565b5f61098d7f36e05829dd1b9a4411d96a3549582172d7f071c1c0db5c573fcf94eb284316085490565b90506001600160a01b038116156109c25760405163741cbe0360e01b81526001600160a01b0382166004820152602401610113565b6108e2847f36e05829dd1b9a4411d96a3549582172d7f071c1c0db5c573fcf94eb2843160855565b5f6109f860048284866111ef565b610a0191611216565b90505f83836004818110610a1757610a176110f9565b909101356001600160f81b03191691505f9050610a3784600581886111ef565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929350610a799250859150610c9e9050565b15610ac65760405162461bcd60e51b815260206004820152601e60248201527f46756e6374696f6e2073656c6563746f7220616c7265616479207573656400006044820152606401610113565b6040805180820182526001600160a01b038881168083526001600160f81b0319861660208085019182526001600160e01b031989165f9081525f51602061124f5f395f51905f5290915285902093518454915160f81c600160a01b026001600160a81b03199092169316929092179190911790915590516306d61fe760e41b8152636d61fe7090610b5b908490600401610e0c565b5f604051808303815f87803b158015610b72575f5ffd5b505af1158015610b84573d5f5f3e3d5ffd5b50505050505050505050565b5f60016001600160a01b03831614801590610bc357506001600160a01b038281165f908152602085905260409020541615155b9392505050565b6001600160a01b0381161580610be957506001600160a01b0381166001145b15610c1257604051637c84ecfb60e01b81526001600160a01b0382166004820152602401610113565b6001600160a01b038181165f908152602084905260409020541615610c5557604051631034f46960e21b81526001600160a01b0382166004820152602401610113565b60015f818152602093909352604080842080546001600160a01b039485168087529286208054959091166001600160a01b03199586161790559190935280549091169091179055565b6001600160e01b0319165f9081525f51602061124f5f395f51905f5260205260409020546001600160a01b0316151590565b5f5f83601f840112610ce0575f5ffd5b50813567ffffffffffffffff811115610cf7575f5ffd5b6020830191508360208260051b8501011115610487575f5ffd5b5f5f5f5f5f5f5f6080888a031215610d27575f5ffd5b873567ffffffffffffffff811115610d3d575f5ffd5b610d498a828b01610cd0565b909850965050602088013567ffffffffffffffff811115610d68575f5ffd5b610d748a828b01610cd0565b909650945050604088013567ffffffffffffffff811115610d93575f5ffd5b88016040818b031215610da4575f5ffd5b9250606088013567ffffffffffffffff811115610dbf575f5ffd5b610dcb8a828b01610cd0565b989b979a50959850939692959293505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610bc36020830184610dde565b6001600160a01b0381168114610e32575f5ffd5b50565b5f5f60408385031215610e46575f5ffd5b8235610e5181610e1e565b946020939093013593505050565b604080825283519082018190525f9060208501906060840190835b81811015610ea15783516001600160a01b0316835260209384019390920191600101610e7a565b50506001600160a01b039490941660209390930192909252509092915050565b5f5f5f60408486031215610ed3575f5ffd5b8335610ede81610e1e565b9250602084013567ffffffffffffffff811115610ef9575f5ffd5b8401601f81018613610f09575f5ffd5b803567ffffffffffffffff811115610f1f575f5ffd5b866020828401011115610f30575f5ffd5b939660209190910195509293505050565b5f60208284031215610f51575f5ffd5b81356001600160e01b031981168114610bc3575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f8135610f9c81610e1e565b6001600160a01b03168352602082013536839003601e19018112610fbe575f5ffd5b820160208101903567ffffffffffffffff811115610fda575f5ffd5b803603821315610fe8575f5ffd5b60406020860152610ffd604086018284610f68565b95945050505050565b5f8383855260208501945060208460051b820101835f5b8681101561106557838303601f19018852813536879003603e19018112611042575f5ffd5b61104e84888301610f90565b6020998a019990945092909201915060010161101d565b50909695505050505050565b608081525f61108460808301898b611006565b828103602084015261109781888a611006565b905082810360408401526110ab8187610f90565b905082810360608401526110c0818587611006565b9a9950505050505050505050565b6001600160a01b03831681526040602082018190525f906110f190830184610dde565b949350505050565b634e487b7160e01b5f52603260045260245ffd5b5f8235603e19833603018112611121575f5ffd5b9190910192915050565b5f6020828403121561113b575f5ffd5b8135610bc381610e1e565b5f5f8335601e1984360301811261115b575f5ffd5b83018035915067ffffffffffffffff821115611175575f5ffd5b602001915036819003821315610487575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016111c2576111c261119d565b5060010190565b818103818111156103955761039561119d565b602081525f6110f1602083018486610f68565b5f5f858511156111fd575f5ffd5b83861115611209575f5ffd5b5050820193919092039150565b80356001600160e01b03198116906004841015611247576001600160e01b0319600485900360031b81901b82161691505b509291505056fef88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea04a26469706673582212207f8df2c19a2c8e169be0659188dfe64559741fb2ca38b30f93836a17f2cbc4e764736f6c634300081b0033"; + bytes constant ERC7579_RHINESTONE_TRAMPOLOINE_BYTECODE = + hex"6080604052348015600e575f5ffd5b5061081d8061001c5f395ff3fe608060405260043610610058575f3560e01c80630a664dba146101b55780635faac46b146101e6578063b0d691fe14610213578063e1c7392a14610235578063ea5f61d014610249578063eac9b20d146102685761005f565b3661005f57005b5f3560e01c63bc197c81811463f23a6e6182141763150b7a028214171561008a57806020526020603cf35b505f80356001600160e01b03191681527ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea046020526040902080546001600160a01b03811690600160a01b900460f81b8161010957604051632464e76d60e11b81526001600160e01b03195f351660048201526024015b60405180910390fd5b61011781607f60f91b61032e565b156101685760408051368101909152365f823760408051601481019091523360601b90525f803660140183865afa90506101573d60408051918201905290565b3d5f823e81610164573d81fd5b3d81f35b610172815f61032e565b156101b35760408051368101909152365f823760408051601481019091523360601b90525f80366014018382875af190506101573d60408051918201905290565b005b3480156101c0575f5ffd5b506101c9610345565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101f1575f5ffd5b5061020561020036600461068d565b610373565b6040516101dd9291906106c2565b34801561021e575f5ffd5b506f71727de22e5e9d8baf0edac6f37da0326101c9565b348015610240575f5ffd5b506101b36103ae565b348015610254575f5ffd5b5061020561026336600461068d565b610480565b348015610273575f5ffd5b50610300610282366004610724565b6040805180820182525f80825260209182018190526001600160e01b03199390931683527ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea048152918190208151808301909252546001600160a01b0381168252600160a01b900460f81b6001600160f81b0319169181019190915290565b6040805182516001600160a01b031681526020928301516001600160f81b03191692810192909252016101dd565b6001600160f81b0319828116908216145b92915050565b5f61036e7f36e05829dd1b9a4411d96a3549582172d7f071c1c0db5c573fcf94eb284316085490565b905090565b60605f7ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea026103a28186866104ab565b92509250509250929050565b6103ea7334dedac925c00d63bd91800ff821e535fe59d6f57f36e05829dd1b9a4411d96a3549582172d7f071c1c0db5c573fcf94eb2843160855565b60408051737066f491ce8b5f782f315dfbd549f2107a32641360611b60208201528151601481830301815260348201928390526306d61fe760e41b9092527334dedac925c00d63bd91800ff821e535fe59d6f591636d61fe7091610451919060380161074b565b5f604051808303815f87803b158015610468575f5ffd5b505af115801561047a573d5f5f3e3d5ffd5b50505050565b60605f7ff88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea036103a28186865b60605f6001600160a01b0384166001148015906104cf57506104cd8585610653565b155b156104f857604051637c84ecfb60e01b81526001600160a01b0385166004820152602401610100565b825f036105185760405163f725081760e01b815260040160405180910390fd5b8267ffffffffffffffff81111561053157610531610780565b60405190808252806020026020018201604052801561055a578160200160208202803683370190505b506001600160a01b038086165f90815260208890526040812054929450911691505b6001600160a01b0382161580159061059e57506001600160a01b038216600114155b80156105a957508381105b1561060257818382815181106105c1576105c1610794565b6001600160a01b039283166020918202929092018101919091529281165f9081529287905260409092205490911690806105fa816107bc565b91505061057c565b6001600160a01b03821660011480159061061b57505f81115b15610647578261062c6001836107d4565b8151811061063c5761063c610794565b602002602001015191505b80835250935093915050565b5f60016001600160a01b0383161480159061068657506001600160a01b038281165f908152602085905260409020541615155b9392505050565b5f5f6040838503121561069e575f5ffd5b82356001600160a01b03811681146106b4575f5ffd5b946020939093013593505050565b604080825283519082018190525f9060208501906060840190835b818110156107045783516001600160a01b03168352602093840193909201916001016106dd565b50506001600160a01b039490941660209390930192909252509092915050565b5f60208284031215610734575f5ffd5b81356001600160e01b031981168114610686575f5ffd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016107cd576107cd6107a8565b5060010190565b8181038181111561033f5761033f6107a856fea26469706673582212208b8d179eb9f1d514092184d86650903af803b01f367d0d2440620538d93230ac64736f6c634300081b0033"; + bytes constant MSAPROXY_BYTECODE = + hex"60806040526040516104003803806104008339810160408190526100229161026c565b61002a61003b565b6100348282610063565b5050610351565b7f15839c8259ca8706cafa7ed5f198b3de1472c96ca2900b32a679090cc8a614de6001815d50565b61006c826100c1565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100b5576100b0828261013c565b505050565b6100bd6101af565b5050565b806001600160a01b03163b5f036100fb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b031684604051610158919061033b565b5f60405180830381855af49150503d805f8114610190576040519150601f19603f3d011682016040523d82523d5f602084013e610195565b606091505b5090925090506101a68583836101d0565b95945050505050565b34156101ce5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101e5576101e08261022f565b610228565b81511580156101fc57506001600160a01b0384163b155b1561022557604051639996b31560e01b81526001600160a01b03851660048201526024016100f2565b50805b9392505050565b80511561023f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561027d575f80fd5b82516001600160a01b0381168114610293575f80fd5b60208401519092506001600160401b038111156102ae575f80fd5b8301601f810185136102be575f80fd5b80516001600160401b038111156102d7576102d7610258565b604051601f8201601f19908116603f011681016001600160401b038111828210171561030557610305610258565b60405281815282820160200187101561031c575f80fd5b8160208401602083015e5f602083830101528093505050509250929050565b5f82518060208501845e5f920191825250919050565b60a38061035d5f395ff3fe6080604052600a600c565b005b60186014601a565b6050565b565b5f604b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e8080156069573d5ff35b3d5ffdfea2646970667358221220e3c8c97d834e82a83c1185c7042bb7bd31705d6e60df591502afb5b12fe921b464736f6c634300081a0033"; +} diff --git a/src/test/precompiles/KernelPrecompiles.sol b/src/test/precompiles/KernelPrecompiles.sol new file mode 100644 index 00000000..97cc6b73 --- /dev/null +++ b/src/test/precompiles/KernelPrecompiles.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +// Interfaces +import { IKernel } from "src/accounts/kernel/interfaces/IKernel.sol"; +import { IKernelFactory } from "src/accounts/kernel/interfaces/IKernelFactory.sol"; + +// Types +import { ValidationId } from "src/accounts/kernel/types/Types.sol"; + +// Utils +import { label } from "src/test/utils/Vm.sol"; +import { BytecodeDeployer } from "./BytecodeDeployer.sol"; + +interface ISetSelector is IKernel { + function setSelector(ValidationId vId, bytes4 selector, bool allowed) external; +} + +contract KernelPrecompiles is BytecodeDeployer { + /*////////////////////////////////////////////////////////////// + DEPLOY + //////////////////////////////////////////////////////////////*/ + + function deployKernel(address entrypoint) internal returns (IKernel kernel) { + // Concat constructor params to bytecode + bytes memory creationBytecode = bytes.concat(KERNEL_BYTECODE, abi.encode(entrypoint)); + kernel = IKernel(_deploy(creationBytecode)); + label(address(kernel), "Kernel"); + } + + function deployKernelWithSetSelector(address entrypoint) + internal + returns (ISetSelector kernel) + { + // Concat constructor params to bytecode + bytes memory creationBytecode = + bytes.concat(KERNEL_WITH_SETSELECTOR_BYTECODE, abi.encode(entrypoint)); + kernel = ISetSelector(_deploy(creationBytecode)); + label(address(kernel), "SetSelector"); + } + + function deployKernelFactory(address kernelImpl) + internal + returns (IKernelFactory kernelFactory) + { + // Concat constructor params to bytecode + bytes memory creationBytecode = + bytes.concat(KERNEL_FACTORY_BYTECODE, abi.encode(kernelImpl)); + kernelFactory = IKernelFactory(_deploy(creationBytecode)); + label(address(kernelFactory), "KernelFactory"); + } + + /*////////////////////////////////////////////////////////////// + BYTECODES + //////////////////////////////////////////////////////////////*/ + + bytes constant KERNEL_BYTECODE = + hex"61014060405234801561001157600080fd5b506040516172093803806172098339810160408190526100309161015a565b306080524660a05260608061007a604080518082018252600681526512d95c9b995b60d21b60208083019190915282518084019093526005835264302e332e3160d81b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152808501939093528281019190915246606083015230608083015260a0909120610100526001600160a01b03851661012052805163deadbeef60e01b92810192909252805160048184030181526024909201905261011b9250905061018a565b7f7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f80546001600160a81b03191660589290921c919091179055506101c8565b60006020828403121561016c57600080fd5b81516001600160a01b038116811461018357600080fd5b9392505050565b805160208201516001600160581b03198116919060158210156101c1576001600160581b0319601583900360031b81901b82161692505b5050919050565b60805160a05160c05160e0516101005161012051616fa5610264600039600081816102ef0152818161069401528181610cb701528181610fec015281816111b6015281816115a301528181611a7101528181611b9501528181611d590152818161253901528181612e6b015261303c0152600061465b01526000614715015260006146ef0152600061469f0152600061467c0152616fa56000f3fe6080604052600436106101d15760003560e01c80639517e29f116100f7578063c3e5897811610095578063e9ae5c5311610064578063e9ae5c53146107ef578063f1f7f0f914610802578063f23a6e6114610830578063f2dc691d1461085d57610210565b8063c3e589781461076f578063d03c79141461079c578063d691c964146107bc578063e6f3d50a146107dc57610210565b8063a71763a8116100d1578063a71763a8146106ce578063adb610a3146106e1578063b8afe17d146106f6578063bc197c811461074057610210565b80639517e29f1461062a5780639cfd7cff1461063d578063a65d69d41461068257610210565b806352141cd91161016f57806384b0196e1161013e57806384b0196e146105b25780638dd7712f146105da57806390ef8862146105ed5780639198bdf51461061757610210565b806352141cd9146104ed57806357b3a5f4146105005780636e6fa0c61461055a578063721e67f41461057a57610210565b806319822f7c116101ab57806319822f7c146104845780631f1b92e3146104a55780633659cfe6146104ba5780633c3b752b146104cd57610210565b8063112d3a7d146103ea578063150b7a021461041f5780631626ba7e1461046457610210565b3661021057604080513381523460208201527f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f88525874910160405180910390a1005b60006102276000356001600160e01b03191661087d565b604080516060808201835283546001600160a01b039081168084526001909501549081166020840152600160a01b900460f81b6001600160f81b03191692820192909252925060009161028d57604051631cd4b64760e21b815260040160405180910390fd5b82516060906001600160a01b03166001148015906102b6575083516001600160a01b0390811614155b156102d15783516102ca90346000366108b7565b905061032d565b83516001600160a01b03908116900361032d57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461032d576040516348f5c3ed60e01b815260040160405180910390fd5b604084015161033d90600061093c565b156103595761034f8460200151610953565b909350915061039e565b6040840151610370906001600160f81b031961093c565b156103855761034f84602001516000366109a3565b604051632d6a6bb760e01b815260040160405180910390fd5b826103ab57815160208301fd5b83516001600160a01b03166001148015906103d1575083516001600160a01b0390811614155b156103e25783516103e290826109d2565b815160208301f35b3480156103f657600080fd5b5061040a610405366004615f19565b610a34565b60405190151581526020015b60405180910390f35b34801561042b57600080fd5b5061044b61043a366004615f74565b630a85bd0160e11b95945050505050565b6040516001600160e01b03199091168152602001610416565b34801561047057600080fd5b5061044b61047f366004615fe6565b610b09565b61049761049236600461604a565b610caa565b604051908152602001610416565b6104b86104b33660046160ab565b610fc5565b005b6104b86104c83660046160c6565b61119c565b3480156104d957600080fd5b506104b86104e836600461613f565b6113b5565b6104b86104fb366004616205565b611589565b34801561050c57600080fd5b5061052061051b3660046162b1565b61191e565b6040805182516001600160a01b03908116825260208085015190911690820152918101516001600160f81b03191690820152606001610416565b34801561056657600080fd5b5061040a6105753660046162ce565b61198a565b34801561058657600080fd5b5061059a6105953660046160c6565b6119d2565b60405190516001600160a01b03168152602001610416565b3480156105be57600080fd5b506105c7611a08565b6040516104169796959493929190616355565b6104b86105e83660046163ed565b611a66565b3480156105f957600080fd5b50610602611b5e565b60405163ffffffff9091168152602001610416565b6104b86106253660046164c2565b611b7b565b6104b8610638366004615f19565b611d3f565b34801561064957600080fd5b5060408051808201825260168152756b65726e656c2e616476616e6365642e76302e332e3160501b60208201529051610416919061663d565b34801561068e57600080fd5b506106b67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610416565b6104b86106dc366004615f19565b61251f565b3480156106ed57600080fd5b50610602612b78565b34801561070257600080fd5b50610716610711366004616650565b612b95565b60408051825163ffffffff1681526020928301516001600160a01b03169281019290925201610416565b34801561074c57600080fd5b5061044b61075b36600461666b565b63bc197c8160e01b98975050505050505050565b34801561077b57600080fd5b5061078f61078a3660046162b1565b612bfd565b604051610416919061671f565b3480156107a857600080fd5b5061040a6107b73660046167a2565b612cd9565b6107cf6107ca366004615fe6565b612dc6565b60405161041691906167bb565b6104b86107ea366004616820565b612e51565b6104b86107fd366004615fe6565b613022565b34801561080e57600080fd5b506108176131db565b6040516001600160581b03199091168152602001610416565b34801561083c57600080fd5b5061044b61084b366004616887565b63f23a6e6160e01b9695505050505050565b34801561086957600080fd5b5061040a6108783660046167a2565b6131ee565b6001600160e01b03191660009081527f7c341349a4360fdd5d5bc07e69f325dc6aaea3eb018b3e0ea7e53cc0bb0d6f3b6020526040902090565b60405163d68f602560e01b81526060906001600160a01b0386169063d68f6025906108ec90339088908890889060040161690d565b6000604051808303816000875af115801561090b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109339190810190616966565b95945050505050565b6001600160f81b0319828116908216145b92915050565b6000606060408051368101909152366000823760408051601481019091523360601b9052600080366014018382885af192505060405190503d8152602081013d6000823e3d810160405250915091565b604051600090828482376000388483885af491503d8152602081013d6000823e3d810160405250935093915050565b604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da906109fe90849060040161663d565b600060405180830381600087803b158015610a1857600080fd5b505af1158015610a2c573d6000803e3d6000fd5b505050505050565b600060018503610a91576000610a4861320e565b6001016000610a5d8760581b600160f81b1790565b6001600160581b0319168152602081019190915260400160002054600160201b90046001600160a01b031614159050610b01565b60028503610ab7576000610aa485613232565b546001600160a01b031614159050610b01565b60038503610afd576001600160a01b038416610ae8610ada6004600086886169d8565b610ae391616a02565b61087d565b600101546001600160a01b0316149050610b01565b5060005b949350505050565b600080610b1461320e565b90506000366000610b25878761326b565b925092509250610b3c610b358490565b600061093c565b15610b4957835460581b92505b6001600160581b031983166000908152600185016020526040902054600160201b90046001600160a01b0316610b9257604051631a0a9b9f60e21b815260040160405180910390fd5b610ba083600160f81b61093c565b15610c3a576000610bb18460581c90565b9050806001600160a01b031663f551e2ee33610bcc8c6132d8565b86866040518563ffffffff1660e01b8152600401610bed949392919061690d565b602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190616a3a565b95505050505050610ca3565b6000610c468460081b90565b6001600160e01b03198116600090815260038701602052604090205490915060f01b600160f11b811615610c8d57604051635b71057960e01b815260040160405180910390fd5b610c9a82338c878761332e565b96505050505050505b9392505050565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cf5576040516348f5c3ed60e01b815260040160405180910390fd5b6000610cff61320e565b90506000806000610d13886020013561342c565b91945092509050610d2582600061093c565b15610d315750825460581b5b610d3d83828a8a61345a565b6001600160581b031982166000908152600186016020908152604080832081518083019092525463ffffffff81168252600160201b90046001600160a01b031691810191909152919650610d92908490613656565b8015610db057508454815163ffffffff600160c81b90920482169116105b15610dce57604051633ab3447f60e11b815260040160405180910390fd5b60208101516001600160a01b038116610dfa57604051631a0a9b9f60e21b815260040160405180910390fd5b600089815260208190526040902080546001600160a01b0319166001600160a01b03831690811790915560001901610ec257610e37846000613656565b8015610e9f57506001600160581b031983166000908152600287016020526040812090610e6760608d018d616a57565b610e76916004916000916169d8565b610e7f91616a02565b6001600160e01b031916815260208101919091526040016000205460ff16155b15610ebd57604051631a0a9b9f60e21b815260040160405180910390fd5b610fa8565b610ecd846000613656565b8015610f3557506001600160581b031983166000908152600287016020526040812090610efd60608d018d616a57565b610f0c916008916004916169d8565b610f1591616a02565b6001600160e01b031916815260208101919091526040016000205460ff16155b15610f5357604051631a0a9b9f60e21b815260040160405180910390fd5b638dd7712f60e01b610f6860608c018c616a57565b610f77916004916000916169d8565b610f8091616a02565b6001600160e01b03191614610fa85760405163dbbb044b60e01b815260040160405180910390fd5b8715610fb857343434348b335af1505b5050505050509392505050565b6000610fdf610fd261320e565b546001600160a81b031690565b9050336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480159061101a5750333014155b1561118f5760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110879190616a9d565b156111765760405163d68f602560e01b81526000906001600160a01b0383169063d68f6025906110c190339034908690369060040161690d565b6000604051808303816000875af11580156110e0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111089190810190616966565b905061111383613669565b604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da9061113f90849060040161663d565b600060405180830381600087803b15801561115957600080fd5b505af115801561116d573d6000803e3d6000fd5b50505050505050565b6040516348f5c3ed60e01b815260040160405180910390fd5b61119882613669565b5050565b60006111a9610fd261320e565b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906111e45750333014155b156113595760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa15801561122d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112519190616a9d565b156111765760405163d68f602560e01b81526000906001600160a01b0383169063d68f60259061128b90339034908690369060040161690d565b6000604051808303816000875af11580156112aa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112d29190810190616966565b9050827f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55826001600160a01b03167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a2604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da9061113f90849060040161663d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8290556040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006113bf61320e565b805490915060581b6001600160581b031916156114195760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b60448201526064015b60405180910390fd5b6001600160581b0319891661144157604051631a0a9b9f60e21b815260040160405180910390fd5b8861145081600160f81b613656565b8015611465575061146581600160f91b613656565b15611483576040516361c4e91b60e11b815260040160405180910390fd5b61148c8a61374b565b60408051808201909152600181526001600160a01b038a166020820152825463ffffffff60a81b1916600160a81b1783556114cb8b828b8b8b8b6137ad565b60005b8481101561157b576000308787848181106114eb576114eb616abf565b90506020028101906114fd9190616a57565b60405161150b929190616ad5565b6000604051808303816000865af19150503d8060008114611548576040519150601f19603f3d011682016040523d82523d6000602084013e61154d565b606091505b505090508061157257604051636534eae560e11b815260048101839052602401611410565b506001016114ce565b505050505050505050505050565b6000611596610fd261320e565b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906115d15750333014155b1561181d5760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa15801561161a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163e9190616a9d565b156111765760405163d68f602560e01b81526000906001600160a01b0383169063d68f60259061167890339034908690369060040161690d565b6000604051808303816000875af1158015611697573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116bf9190810190616966565b905060006116cb61320e565b90506001600160581b031989166116f557604051631a0a9b9f60e21b815260040160405180910390fd5b8861170481600160f81b613656565b8015611719575061171981600160f91b613656565b15611737576040516361c4e91b60e11b815260040160405180910390fd5b6117408a61374b565b600061174a61320e565b6001600160581b03198c1660009081526001919091016020526040902054600160201b90046001600160a01b0316036117b757604080518082019091528254600160a81b900463ffffffff1681526001600160a01b038a1660208201526117b58b828b8b8b8b6137ad565b505b5050604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da906117e590849060040161663d565b600060405180830381600087803b1580156117ff57600080fd5b505af1158015611813573d6000803e3d6000fd5b505050505061116d565b600061182761320e565b90506001600160581b0319881661185157604051631a0a9b9f60e21b815260040160405180910390fd5b8761186081600160f81b613656565b8015611875575061187581600160f91b613656565b15611893576040516361c4e91b60e11b815260040160405180910390fd5b61189c8961374b565b60006118a661320e565b6001600160581b03198b1660009081526001919091016020526040902054600160201b90046001600160a01b03160361191357604080518082019091528254600160a81b900463ffffffff1681526001600160a01b03891660208201526119118a828a8a8a8a6137ad565b505b505050505050505050565b60408051606081018252600080825260208201819052918101919091526119448261087d565b6040805160608101825282546001600160a01b0390811682526001909301549283166020820152600160a01b90920460f81b6001600160f81b0319169082015292915050565b600061199461320e565b6001600160581b031984166000908152600291909101602090815260408083206001600160e01b03198616845290915290205460ff16905092915050565b6040805160208101909152600081526119ea82613232565b604080516020810190915290546001600160a01b0316815292915050565b600f60f81b6060806000808083611a54604080518082018252600681526512d95c9b995b60d21b60208083019190915282518084019093526005835264302e332e3160d81b9083015291565b97989097965046955030945091925090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611aaf576040516348f5c3ed60e01b815260040160405180910390fd5b6000818152602081905260409020546060906001600160a01b031660018114611afa57611af78134611ae46060880188616a57565b611af29160049082906169d8565b6108b7565b91505b600080611b2130611b0e6060890189616a57565b611b1c9160049082906169d8565b6109a3565b9150915081611b435760405163f21e646b60e01b815260040160405180910390fd5b6001600160a01b038316600114610a2c57610a2c83856109d2565b6000611b6861320e565b54600160c81b900463ffffffff16919050565b6000611b88610fd261320e565b9050336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590611bc35750333014155b15611d265760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015611c0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c309190616a9d565b156111765760405163d68f602560e01b81526000906001600160a01b0383169063d68f602590611c6a90339034908690369060040161690d565b6000604051808303816000875af1158015611c89573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cb19190810190616966565b9050611cc2898989898989896139fc565b604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da90611cee90849060040161663d565b600060405180830381600087803b158015611d0857600080fd5b505af1158015611d1c573d6000803e3d6000fd5b5050505050611d35565b611d35888888888888886139fc565b5050505050505050565b6000611d4c610fd261320e565b9050336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590611d875750333014155b156122265760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015611dd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df49190616a9d565b156111765760405163d68f602560e01b81526000906001600160a01b0383169063d68f602590611e2e90339034908690369060040161690d565b6000604051808303816000875af1158015611e4d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e759190810190616966565b905060018603611fb2576000611e8961320e565b90506000611e9d8760581b600160f81b1790565b82546001600160581b03198216600090815260018501602052604090205491925063ffffffff600160a81b9091048116911603611efd578154600163ffffffff600160a81b808404821692909201160263ffffffff60a81b199091161782555b604080518082019091528254600160a81b900463ffffffff16815260009060208101611f2c6014848a8c6169d8565b611f3591616ae5565b60601c9052905060148781013588016034818101929182013591818b01358b0180830192908201359160548d01358d01918201910135611f798888888888886137ad565b6004819003611fa457611fa488611f946004600085876169d8565b611f9d91616a02565b6001613aa0565b5050505050505050506121c2565b6002860361201957601484810135850160348181019291820135918188013588019182019181013590600090611fea90828a8c6169d8565b611ff391616ae5565b60601c90506120048a868684613b33565b61200f818484613b99565b50505050506121c2565b600386036120a9576018848101358501603881810192918201359181880135880191820191013561207c612051600460008a8c6169d8565b61205a91616a02565b8a612069601860048c8e6169d8565b61207291616ae5565b60601c8787613d6a565b6120a061208d601860048a8c6169d8565b61209691616ae5565b60601c8383613b99565b505050506121c2565b6004860361213d576040516306d61fe760e41b81526001600160a01b03861690636d61fe70906120df9087908790600401616b25565b600060405180830381600087803b1580156120f957600080fd5b505af115801561210d573d6000803e3d6000fd5b50505050600080516020616f658339815191528686604051612130929190616b39565b60405180910390a16121c2565b60058603612173576040516306d61fe760e41b81526001600160a01b03861690636d61fe70906120df9087908790600401616b25565b600686036121a9576040516306d61fe760e41b81526001600160a01b03861690636d61fe70906120df9087908790600401616b25565b604051631092ef5760e11b815260040160405180910390fd5b604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da906121ee90849060040161663d565b600060405180830381600087803b15801561220857600080fd5b505af115801561221c573d6000803e3d6000fd5b5050505050612518565b6001850361235157600061223861320e565b9050600061224c8660581b600160f81b1790565b82546001600160581b03198216600090815260018501602052604090205491925063ffffffff600160a81b90910481169116036122ac578154600163ffffffff600160a81b808404821692909201160263ffffffff60a81b199091161782555b604080518082019091528254600160a81b900463ffffffff168152600090602081016122db601484898b6169d8565b6122e491616ae5565b60601c9052905060148681013587016034818101929182013591818a01358a0180830192908201359160548c01358c019182019101356123288888888888886137ad565b60048190036123435761234388611f946004600085876169d8565b505050505050505050612518565b600285036123ae576014838101358401603481810192918201359181870135870191820191810135906000906123899082898b6169d8565b61239291616ae5565b60601c90506123a389868684613b33565b61221c818484613b99565b6003850361241857601883810135840160388181019291820135918187013587019182019101356123fe6123e660046000898b6169d8565b6123ef91616a02565b89612069601860048b8d6169d8565b61240f61208d60186004898b6169d8565b50505050612518565b600485036124ac576040516306d61fe760e41b81526001600160a01b03851690636d61fe709061244e9086908690600401616b25565b600060405180830381600087803b15801561246857600080fd5b505af115801561247c573d6000803e3d6000fd5b50505050600080516020616f65833981519152858560405161249f929190616b39565b60405180910390a1612518565b600585036124e2576040516306d61fe760e41b81526001600160a01b03851690636d61fe709061244e9086908690600401616b25565b600685036121a9576040516306d61fe760e41b81526001600160a01b03851690636d61fe709061244e9086908690600401616b25565b5050505050565b600061252c610fd261320e565b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906125675750333014155b156128ed5760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa1580156125b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d49190616a9d565b156111765760405163d68f602560e01b81526000906001600160a01b0383169063d68f60259061260e90339034908690369060040161690d565b6000604051808303816000875af115801561262d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126559190810190616966565b9050856001036126855760006126718660581b600160f81b1790565b905061267e818686613edb565b50506121c2565b8560020361269e5761269885858561401f565b506121c2565b856003036126d65760006126b560048286886169d8565b6126be91616a02565b905061267e816126d1866004818a6169d8565b6140bb565b856004036127f35760006126e861320e565b5460581b90506001600160a01b03861661270061320e565b6001600160581b0319831660009081526001919091016020526040902054600160201b90046001600160a01b03160361278557600161273d61320e565b6001600160581b0319831660009081526001919091016020526040902080546001600160a01b0392909216600160201b02640100000000600160c01b03199092169190911790555b6127c58686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141a192505050565b50600080516020616f8583398151915287876040516127e5929190616b39565b60405180910390a1506121c2565b856005036128db57600061280561320e565b5460581b9050600061281a60208287896169d8565b61282391616b50565b9050612834825b600160f91b61093c565b1561286c576128438260081b90565b6001600160e01b031916810361286c576040516313002bdd60e31b815260040160405180910390fd5b6128ac8787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141a192505050565b50600080516020616f8583398151915288886040516128cc929190616b39565b60405180910390a150506121c2565b856006036121a957600061280561320e565b8460010361291b5760006129078560581b600160f81b1790565b9050612914818585613edb565b5050612518565b846002036129345761292e84848461401f565b50612518565b8460030361296757600061294b60048285876169d8565b61295491616a02565b9050612914816126d185600481896169d8565b84600403612a8457600061297961320e565b5460581b90506001600160a01b03851661299161320e565b6001600160581b0319831660009081526001919091016020526040902054600160201b90046001600160a01b031603612a165760016129ce61320e565b6001600160581b0319831660009081526001919091016020526040902080546001600160a01b0392909216600160201b02640100000000600160c01b03199092169190911790555b612a568585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141a192505050565b50600080516020616f858339815191528686604051612a76929190616b39565b60405180910390a150612518565b84600503612b66576000612a9661320e565b5460581b90506000612aab60208286886169d8565b612ab491616b50565b9050612abf8261282a565b15612af757612ace8260081b90565b6001600160e01b0319168103612af7576040516313002bdd60e31b815260040160405180910390fd5b612b378686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141a192505050565b50600080516020616f858339815191528787604051612b57929190616b39565b60405180910390a15050612518565b846006036121a9576000612a9661320e565b6000612b8261320e565b54600160a81b900463ffffffff16919050565b6040805180820190915260008082526020820152612bb161320e565b6001600160581b03199290921660009081526001909201602090815260409283902083518085019094525463ffffffff81168452600160201b90046001600160a01b0316908301525090565b60408051606080820183526000808352602083015291810191909152612c2161320e565b6001600160e01b03198316600090815260039190910160209081526040918290208251606081018452815460f081901b6001600160f01b03191682526201000090046001600160a01b03168184015260018201805485518186028101860187528181529295939493860193830182828015612cc957602002820191906000526020600020905b815460501b6001600160501b0319168152600190910190602001808311612ca7575b5050505050815250509050919050565b600081600881901b603082901b605083901b612cf984600160f81b613656565b8015612d0b5750612d0b846000613656565b8015612d245750612d24846001600160f81b0319613656565b8015612d395750612d3984607f60f91b613656565b15612d4a5750600095945050505050565b6001600160f81b03198316600160f81b14801590612d7157506001600160f81b0319831615155b15612d825750600095945050505050565b6001600160e01b0319821615612d9e5750600095945050505050565b6001600160501b0319811615612dba5750600095945050505050565b50600195945050505050565b60606000612dd333613232565b546001600160a01b0316905080612dfd5760405163710c949760e01b815260040160405180910390fd5b60606001600160a01b038216600114612e2057612e1d82346000366108b7565b90505b612e2b868686614248565b92506001600160a01b038216600114612e4857612e4882826109d2565b50509392505050565b6000612e5e610fd261320e565b9050336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590612e995750333014155b156130085760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015612ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f069190616a9d565b156111765760405163d68f602560e01b81526000906001600160a01b0383169063d68f602590612f4090339034908690369060040161690d565b6000604051808303816000875af1158015612f5f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612f879190810190616966565b90506000612f96888888613edb565b9050612fa3818686614590565b50604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da90612fd090849060040161663d565b600060405180830381600087803b158015612fea57600080fd5b505af1158015612ffe573d6000803e3d6000fd5b5050505050610a2c565b6000613015878787613edb565b905061116d818585614590565b600061302f610fd261320e565b9050336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480159061306a5750333014155b156131ca5760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa1580156130b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130d79190616a9d565b156111765760405163d68f602560e01b81526000906001600160a01b0383169063d68f60259061311190339034908690369060040161690d565b6000604051808303816000875af1158015613130573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131589190810190616966565b9050613165858585614248565b50604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da9061319290849060040161663d565b600060405180830381600087803b1580156131ac57600080fd5b505af11580156131c0573d6000803e3d6000fd5b50505050506131d5565b612518848484614248565b50505050565b60006131e561320e565b5460581b919050565b6000600782101561320157506001919050565b506000919050565b919050565b7f7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f90565b6001600160a01b031660009081527f1bbee3173dbdc223633258c9f337a0fff8115f206d302bea0ed3eac003b68b866020526040902090565b813536600060f883901c801561329057600181146132a557600281146132b657600080fd5b600093506001860192506001850391506132d0565b6015860192506015850391506132d0565b6001600160d81b0319841693506005860192506005850391505b509250925092565b604080517f1547321c374afde8a591d972a084b071c594c275e36724931ff96c25f2999c83602082015290810182905260009061094d906060015b60405160208183030381529060405280519060200120614659565b60008060003660006133438a8a8a8a8a614771565b93509350935093506000806133578561487d565b50915091508165ffffffffffff1642108061337957508065ffffffffffff1642115b1561339557506001600160e01b03199550610933945050505050565b6001600160a01b03861663392dffaf6001600160e01b03198e168d6133b98e6132d8565b88886040518663ffffffff1660e01b81526004016133db959493929190616b6e565b602060405180830381865afa1580156133f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061341c9190616a3a565b9c9b505050505050505050505050565b80600881901b8060ff60f084901c166001198101613452576001600160d81b0319821691505b509193909250565b60008061346561320e565b9050600061347285616bf8565b9050366000613485610100880188616a57565b909250905061349889600160f81b61093c565b156134f6576134b4886134af6101008a018a616a57565b6148b0565b604080516020601f8401819004810282018101909252828152939850919450925083908390819084018382808284376000920191909152505050506101008401525b8761350581600160f81b61093c565b156135945761358d866135188b60581c90565b6001600160a01b03166397003203878b6040518363ffffffff1660e01b8152600401613545929190616d9b565b6020604051808303816000875af1158015613564573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135889190616dbd565b6148dd565b9550613649565b60006135a08a60081b90565b6001600160e01b03198116600090815260038801602052604090205490915060f01b600160f01b16156135e6576040516314b9743f60e01b815260040160405180910390fd5b6000806135f58388888861499b565b9150915061360389836148dd565b985061364389826001600160a01b0316630ccab7a1866001600160e01b0319168b8f6040518463ffffffff1660e01b815260040161354593929190616dd6565b98505050505b5050505050949350505050565b6001600160f81b03199081169116141590565b600061367361320e565b805490915063ffffffff8084169161369591600a91600160a81b900416616dff565b63ffffffff1610156136ba5760405163e60fd64760e01b815260040160405180910390fd5b805463ffffffff600160c81b9091048116908316116136ec57604051633ab3447f60e11b815260040160405180910390fd5b805463ffffffff60c81b1916600160c81b63ffffffff8481168202929092178084559081048216600160a81b909104909116101561119857805463ffffffff60a81b198116600160c81b90910463ffffffff16600160a81b0217905550565b600061375561320e565b80546001600160a81b031916605884901c1781556040516001600160581b0319841681529091507f6789ec0c85d6458d897a36a70129b101f8b4d84c6e218046c3107373dbcbae889060200160405180910390a15050565b60006137b761320e565b80546001600160581b03198916600090815260018301602052604090205491925063ffffffff600160a81b9091048116911603613817578054600163ffffffff600160a81b808404821692909201160263ffffffff60a81b199091161781555b60208601516001600160a01b031661383157600160208701525b85518154600160a81b900463ffffffff9081169116141580613879575085516001600160581b03198816600090815260018301602052604090205463ffffffff918216911610155b1561389757604051633ab3447f60e11b815260040160405180910390fd5b6001600160581b03198716600090815260018083016020908152604090922088518154938a01516001600160a01b0316600160201b81026001600160c01b031990951663ffffffff90921691909117939093179055146139005761390086602001518484613b99565b8661390f81600160f81b61093c565b156139b15760006139208960581c90565b6040516306d61fe760e41b81529091506001600160a01b03821690636d61fe7090613951908a908a90600401616b25565b600060405180830381600087803b15801561396b57600080fd5b505af115801561397f573d6000803e3d6000fd5b50505050600080516020616f658339815191526001826040516139a3929190616b39565b60405180910390a150611d35565b6139bf81600160f91b61093c565b156139e35760006139d08960081b90565b90506139dd818888614c7b565b50611d35565b6040516361c4e91b60e11b815260040160405180910390fd5b60005b86811015611d3557613a98888883818110613a1c57613a1c616abf565b9050602002016020810190613a319190616650565b878381518110613a4357613a43616abf565b6020026020010151878785818110613a5d57613a5d616abf565b9050602002810190613a6f9190616a57565b878787818110613a8157613a81616abf565b9050602002810190613a939190616a57565b6137ad565b6001016139ff565b6000613aaa61320e565b6001600160581b03198516600081815260028301602090815260408083206001600160e01b0319891680855290835292819020805488151560ff1990911681179091558151938452918301939093528183015290519192507f9d17cd6d095ac90a655405ab29f30a7ee7e88ef3974c1bf7544bf591043bb71a919081900360600190a150505050565b613b3d84826150d4565b6040516306d61fe760e41b81526001600160a01b03851690636d61fe7090613b6b9086908690600401616b25565b600060405180830381600087803b158015613b8557600080fd5b505af1158015611d35573d6000803e3d6000fd5b6001600160a01b0383161580613bb857506001600160a01b0383166001145b15613bc257505050565b60405163d60b347f60e01b81523060048201526001600160a01b0384169063d60b347f90602401602060405180830381865afa158015613c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c2a9190616a9d565b613c9e576001600160a01b038316636d61fe70613c4a83600181876169d8565b6040518363ffffffff1660e01b8152600401613c67929190616b25565b600060405180830381600087803b158015613c8157600080fd5b505af1158015613c95573d6000803e3d6000fd5b50505050613d3d565b6001600160f81b03198282600081613cb857613cb8616abf565b9050013560f81c60f81b6001600160f81b03191603613d3d576001600160a01b038316636d61fe70613ced83600181876169d8565b6040518363ffffffff1660e01b8152600401613d0a929190616b25565b600060405180830381600087803b158015613d2457600080fd5b505af1158015613d38573d6000803e3d6000fd5b505050505b600080516020616f65833981519152600484604051613d5d929190616b39565b60405180910390a1505050565b6001600160a01b038316613d83576001600160a01b0392505b6000613d8e8661087d565b9050600083836000818110613da557613da5616abf565b9050013560f81c60f81b9050613dbf81600060f81b61093c565b15613e5c576001600160a01b038616636d61fe70613de085600181896169d8565b6040518363ffffffff1660e01b8152600401613dfd929190616b25565b600060405180830381600087803b158015613e1757600080fd5b505af1158015613e2b573d6000803e3d6000fd5b50505050600080516020616f65833981519152600387604051613e4f929190616b39565b60405180910390a1613e8c565b613e6e816001600160f81b0319613656565b15613e8c57604051632d6a6bb760e01b815260040160405180910390fd5b81546001600160a01b039586166001600160a01b03199091161782556001909101805460f89290921c600160a01b026001600160a81b0319909216959094169490941793909317909155505050565b600080613ee661320e565b805490915060581b6001600160581b031990811690861603613f1b576040516313002bdd60e31b815260040160405180910390fd5b6001600160581b03198516600090815260018201602052604090208054640100000000600160c01b03198116909155600160201b90046001600160a01b0316915084613f6b81600160f81b61093c565b15613fed576000613f7c8760581c90565b9050613fbe8187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141a192505050565b50600080516020616f85833981519152600182604051613fdf929190616b39565b60405180910390a150612e48565b613ffb81600160f91b61093c565b156139e357600061400c8760081b90565b905061401981878761512e565b50612e48565b60008061402b85613232565b80546001600160a01b031981168255604080516020601f88018190048102820181019092528681526001600160a01b03909216945091925061408a9187919087908790819084018382808284376000920191909152506141a192505050565b50600080516020616f858339815191526002866040516140ab929190616b39565b60405180910390a1509392505050565b6000806140c78561087d565b80546001600160a01b03198116825560018201546001600160a01b03909116935090915061410090600160a01b900460f81b600061093c565b15614189576001810154604080516020601f8701819004810282018101909252858152614151926001600160a01b03169187908790819084018382808284376000920191909152506141a192505050565b506001810154604051600080516020616f8583398151915291614180916003916001600160a01b031690616b39565b60405180910390a15b60010180546001600160a81b03191690559392505050565b60006141fb835a600080638a91b0e360e01b876040516024016141c4919061663d565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526152f8565b50604080516001600160a01b038616815282151560208201529192507f2b82f87bf66300af618a9621d3f221edfab735f5bacb4e004cce1b62375396c3910160405180910390a192915050565b606083600881901b61425e82600160f81b61093c565b156142e8578435850160208101903561427883600061093c565b1561428e576142878282615382565b94506142e1565b61429c83600160f81b61093c565b156142ab576142878282615452565b60405162461bcd60e51b815260206004820152600b60248201526a155b9cdd5c1c1bdc9d195960aa1b6044820152606401611410565b5050612e48565b6142f382600061093c565b1561442157600080366000614308898961557f565b6040805160018082528183019092529498509296509094509250816020015b6060815260200190600190039081614327579050509650600061434a868261093c565b1561437e5761435b858585856155d0565b8860008151811061436e5761436e616abf565b6020026020010181905250614417565b61438c86600160f81b61093c565b156142ab5761439d85858585615606565b896000815181106143b0576143b0616abf565b6020908102919091010152905080614417577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb76000896000815181106143f8576143f8616abf565b602002602001015160405161440e929190616e29565b60405180910390a15b5050505050612e48565b614433826001600160f81b031961093c565b156142ab5760408051600180825281830190925290816020015b606081526020019060019003908161444d579050509250600061447360148287896169d8565b61447c91616ae5565b60601c9050366000614491876014818b6169d8565b9150915060006144a28484846109a3565b886000815181106144b5576144b5616abf565b602090810291909101015290506144d085600160f81b61093c565b15614534578061452f577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb760008860008151811061451057614510616abf565b6020026020010151604051614526929190616e29565b60405180910390a15b614587565b61453f85600061093c565b156142ab578061452f5760405162461bcd60e51b815260206004820152601360248201527211195b1959d85d1958d85b1b0819985a5b1959606a1b6044820152606401611410565b50505050612e48565b6001600160a01b03831615806145af57506001600160a01b0383166001145b156145b957505050565b6001600160f81b031982826000816145d3576145d3616abf565b9050013560f81c60f81b6001600160f81b0319160361463957614637836145fd83600181876169d8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141a192505050565b505b600080516020616f85833981519152600484604051613d5d929190616b39565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000030147f000000000000000000000000000000000000000000000000000000000000000046141661474c5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b6000803660008061478061320e565b60408051610120810182526000808252602082018190529181018290526080810182905260a0810191909152606060c082018190526001600160e01b03198d16908201526001600160a01b038b1660e082015261010081018a90529091506147ea81838a8a615637565b878760008181106147fd576147fd616abf565b9091013560f81c60ff1490506148265760405163b32eeb6960e01b815260040160405180910390fd5b614833876001818b6169d8565b60608301516001600160e01b0319166000908152600394909401602052604093849020549390920151620100009093046001600160a01b03169c929b509950975095505050505050565b600060a082901c65ffffffffffff1682811560001981016148a25765ffffffffffff92505b508360d01c92509193909250565b60003660006148c08686866158a4565b925050506094830135830160348101906014013593509350939050565b600081830160601b8260601b81148460601b8214176001600160a01b03848618161517600181146149115760019250614993565b6001600160d01b031980851690861681811881831102188686176001600160a01b031617935065ffffffffffff60a01b861690816149565765ffffffffffff60a01b91505b5065ffffffffffff60a01b851680614974575065ffffffffffff60a01b5b80821890821102188061498d575065ffffffffffff60a01b5b92909217915b505092915050565b60008060006149a861320e565b6001600160e01b03198816600090815260038201602052604081209192506001909101905b8154811015614bbf57600080614a068484815481106149ee576149ee616abf565b60009182526020909120015460501b90605082901c90565b91509150600089896000818110614a1f57614a1f616abf565b919091013560f81c915050838103614ab2576000614a41600960018c8e6169d8565b614a4a91616e42565b60c01c9050614a5f6009808301908c8e6169d8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506101008d0152614aa88a60098301818e6169d8565b9a509a5050614aec565b838160ff161015614ad657604051630760bdcf60e11b815260040160405180910390fd5b6040805160208101909152600081526101008c01525b600160f01b8316600003614bb4576000826001600160a01b0316637129edce8e6001600160e01b0319168e6040518363ffffffff1660e01b8152600401614b34929190616e78565b6020604051808303816000875af1158015614b53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b779190616dbd565b9050806001600160a01b03811615614ba557604051631f24c1fb60e11b815260048101879052602401611410565b614baf8a836148dd565b995050505b5050506001016149cd565b5085856000818110614bd357614bd3616abf565b9091013560f81c60ff149050614bfc5760405163b32eeb6960e01b815260040160405180910390fd5b614c0985600181896169d8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101008c01949094525050506001600160e01b03198916815260039092016020525060409020546001600160a01b036201000090910416905094509492505050565b6000614c8561320e565b90508235830160208101903560fe811180614c9e575080155b15614cbc5760405163b62d956d60e01b815260040160405180910390fd5b6001600160e01b03198616600090815260038401602052604090206001015415614d0a576001600160e01b0319861660009081526003840160205260408120614d0a91600190910190615e77565b60005b6000198201811015614efe576001600160e01b0319871660009081526003850160205260409020600101838383818110614d4957614d49616abf565b9050602002810190614d5b9190616a57565b614d6a916016916000916169d8565b614d7391616e91565b81546001810183556000928352602090922090910180546001600160b01b03191660509290921c919091179055828282818110614db257614db2616abf565b9050602002810190614dc49190616a57565b614dd3916016916002916169d8565b614ddc91616ae5565b60601c636d61fe706001600160e01b03198916858585818110614e0157614e01616abf565b9050602002810190614e139190616a57565b614e219160169082906169d8565b604051602001614e3393929190616ec7565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401614e5e919061663d565b600060405180830381600087803b158015614e7857600080fd5b505af1158015614e8c573d6000803e3d6000fd5b50505050600080516020616f658339815191526005848484818110614eb357614eb3616abf565b9050602002810190614ec59190616a57565b614ed4916016916002916169d8565b614edd91616ae5565b60601c604051614eee929190616b39565b60405180910390a1600101614d0d565b50600082826000198101818110614f1757614f17616abf565b9050602002810190614f299190616a57565b614f38916016916002916169d8565b614f4191616ae5565b6001600160e01b031988166000908152600386016020526040902080546201000060609390931c92830262010000600160b01b0319909116179055905082826000198101818110614f9457614f94616abf565b9050602002810190614fa69190616a57565b614fb5916002916000916169d8565b614fbe91616ee1565b6001600160e01b0319881660008181526003870160205260409020805461ffff191660f09390931c929092179091556001600160a01b03821690636d61fe70908585600019810181811061501457615014616abf565b90506020028101906150269190616a57565b6150349160169082906169d8565b60405160200161504693929190616ec7565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401615071919061663d565b600060405180830381600087803b15801561508b57600080fd5b505af115801561509f573d6000803e3d6000fd5b50505050600080516020616f658339815191526006826040516150c3929190616b39565b60405180910390a150505050505050565b6001600160a01b0381166150e6575060015b60006150f183613232565b80546001600160a01b0319166001600160a01b038416178155604051909150600080516020616f6583398151915290613d5d906002908690616b39565b81358201602081019035600061514261320e565b6001600160e01b031987166000908152600391909101602052604090206001808201549192500182146151885760405163013dcc8d60e31b815260040160405180910390fd5b6001810160005b815481101561523d5760006151af8383815481106149ee576149ee616abf565b91505061520b818a6001600160e01b0319168888868181106151d3576151d3616abf565b90506020028101906151e59190616a57565b6040516020016151f793929190616ec7565b6040516020818303038152906040526141a1565b50600080516020616f8583398151915260058260405161522c929190616b39565b60405180910390a15060010161518f565b5061524661320e565b6001600160e01b0319881660009081526003919091016020526040812061527291600190910190615e77565b81546152a8906201000090046001600160a01b03166001600160e01b03198916868660001981018181106151d3576151d3616abf565b508154604051600080516020616f85833981519152916152da916006916201000090046001600160a01b031690616b39565b60405180910390a15080546001600160b01b03191690555050505050565b6000606060008060008661ffff166001600160401b0381111561531d5761531d616431565b6040519080825280601f01601f191660200182016040528015615347576020820181803683370190505b5090506000808751602089018b8e8ef191503d925086831115615368578692505b828152826000602083013e90999098509650505050505050565b606081806001600160401b0381111561539d5761539d616431565b6040519080825280602002602001820160405280156153d057816020015b60608152602001906001900390816153bb5790505b50915060005b8181101561499357368585838181106153f1576153f1616abf565b90506020028101906154039190616f17565b905061542c61541560208301836160c6565b60208301356154276040850185616a57565b6155d0565b84838151811061543e5761543e616abf565b6020908102919091010152506001016153d6565b606081806001600160401b0381111561546d5761546d616431565b6040519080825280602002602001820160405280156154a057816020015b606081526020019060019003908161548b5790505b50915060005b8181101561499357368585838181106154c1576154c1616abf565b90506020028101906154d39190616f17565b905060006154fe6154e760208401846160c6565b60208401356154f96040860186616a57565b615606565b86858151811061551057615510616abf565b6020908102919091010152905080615575577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb78386858151811061555657615556616abf565b602002602001015160405161556c929190616e29565b60405180910390a15b50506001016154a6565b600080368161559160148287896169d8565b61559a91616ae5565b60601c93506155ad6034601487896169d8565b6155b691616b50565b92506155c585603481896169d8565b949793965094505050565b60405181838237600038838387895af16155ed573d6000823e3d81fd5b3d8152602081013d6000823e3d01604052949350505050565b604051600090828482376000388483888a5af191503d8152602081013d6000823e3d81016040525094509492505050565b60608401516001600160e01b03191660009081526003840160205260408120600101905b8154811015610a2c576156798282815481106149ee576149ee616abf565b6001600160a01b031660a08801526001600160f01b031916608087015283836000816156a7576156a7616abf565b919091013560f81c8088528290039050615744576156c96009600185876169d8565b6156d291616e42565b60c01c602087018190526156ed9060099081019085876169d8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060c0870152602086015161573b90849060090181876169d8565b935093506157b0565b855160ff1681111561576957604051630760bdcf60e11b815260040160405180910390fd5b61577660008085876169d8565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060c08701525b6080860151600160f11b1660000361589c5760a0860151606087015160e088015161010089015160c08a015160405163184dfdbb60e11b81526000956001600160a01b03169463309bfb7694615817946001600160e01b0319909216939092600401616f37565b602060405180830381865afa158015615834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906158589190616dbd565b9050806001600160a01b0381161561588657604051631f24c1fb60e11b815260048101849052602401611410565b6158948860400151836148dd565b604089015250505b60010161565b565b600036600080366000366000366000806158bf8e8e8e61592a565b9750975097509750975097509750975060748d013560348e0101995060208a033598506158ed818b8b615adf565b9a506158fd8e89898989896137ad565b6159078383615c7f565b6159198e611f946004600086886169d8565b505050505050505050509392505050565b604080518082019091526000808252602082015236600036600036600080600061595261320e565b9050615962601460008c8e6169d8565b61596b91616ae5565b60601c89602001906001600160a01b031690816001600160a01b0316815250508060000160159054906101000a900463ffffffff16896000019063ffffffff16908163ffffffff168152505060148b013560348c010197506020880335965060348b013560348c010195506020860335945060548b013560348c0101935060208403359250615acf7fb17ab1224aca0d4255ef8161acaf2ac121b8faa32a4b2258c912cc5f8308c50560001b8d8360000160159054906101000a900463ffffffff168c602001518c8c604051615a42929190616ad5565b60405180910390208b8b604051615a5a929190616ad5565b60405180910390208a8a604051615a72929190616ad5565b6040805191829003822060208301989098526001600160581b03199096169581019590955263ffffffff90931660608501526001600160a01b03909116608084015260a083015260c082015260e081019190915261010001613313565b9150509397509397509397509397565b600080615aea61320e565b805490915060581b6000615b0282600160f81b61093c565b15615b8e578254604051637aa8f17760e11b81526001600160a81b038216916001600160a01b03169063f551e2ee90615b459030908c908c908c9060040161690d565b602060405180830381865afa158015615b62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615b869190616a3a565b915050615c44565b615b9c82600160f91b61093c565b156139e357825460601b6000615bb582308b8b8b614771565b60405163392dffaf60e01b8152919b5099509097509091506001600160a01b0382169063392dffaf90615bfe906001600160e01b031986169030908e908e908e90600401616b6e565b602060405180830381865afa158015615c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615c3f9190616a3a565b925050505b630b135d3f60e11b6001600160e01b0319821614615c75576040516362467c7760e11b815260040160405180910390fd5b5050509392505050565b6000615c8e60048284866169d8565b615c9791616a02565b905060048210615e7257602c8210615e2b57366000818180615cbd60186004898b6169d8565b615cc691616ae5565b60601c9050602c880135604c890101945060208503359350604c880135604c890101925060208303359150615d1b85856000818110615d0757615d07616abf565b9050013560f81c60f81b600060f81b61093c565b8015615d8b575060405163ecd0596160e01b8152600260048201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015615d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615d8b9190616a9d565b15615de157606c8801358801604c810190602c01356000615daf60148284866169d8565b615db891616ae5565b60601c9050615dc784826150d4565b615ddd81615dd884601481886169d8565b613b99565b5050505b615e078682615df4602c60188c8e6169d8565b615dfd91616ae5565b60601c8888613d6a565b611d35615e18602c60188a8c6169d8565b615e2191616ae5565b60601c8484613b99565b60048214615e725760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642073656c6563746f724461746160601b6044820152606401611410565b505050565b5080546000825590600052602060002090810190615e959190615e98565b50565b5b80821115615ead5760008155600101615e99565b5090565b6001600160a01b0381168114615e9557600080fd5b803561320981615eb1565b60008083601f840112615ee357600080fd5b5081356001600160401b03811115615efa57600080fd5b602083019150836020828501011115615f1257600080fd5b9250929050565b60008060008060608587031215615f2f57600080fd5b843593506020850135615f4181615eb1565b925060408501356001600160401b03811115615f5c57600080fd5b615f6887828801615ed1565b95989497509550505050565b600080600080600060808688031215615f8c57600080fd5b8535615f9781615eb1565b94506020860135615fa781615eb1565b93506040860135925060608601356001600160401b03811115615fc957600080fd5b615fd588828901615ed1565b969995985093965092949392505050565b600080600060408486031215615ffb57600080fd5b8335925060208401356001600160401b0381111561601857600080fd5b61602486828701615ed1565b9497909650939450505050565b6000610120828403121561604457600080fd5b50919050565b60008060006060848603121561605f57600080fd5b83356001600160401b0381111561607557600080fd5b61608186828701616031565b9660208601359650604090950135949350505050565b803563ffffffff8116811461320957600080fd5b6000602082840312156160bd57600080fd5b610ca382616097565b6000602082840312156160d857600080fd5b8135610ca381615eb1565b80356001600160581b03198116811461320957600080fd5b60008083601f84011261610d57600080fd5b5081356001600160401b0381111561612457600080fd5b6020830191508360208260051b8501011115615f1257600080fd5b60008060008060008060008060a0898b03121561615b57600080fd5b616164896160e3565b9750602089013561617481615eb1565b965060408901356001600160401b0381111561618f57600080fd5b61619b8b828c01615ed1565b90975095505060608901356001600160401b038111156161ba57600080fd5b6161c68b828c01615ed1565b90955093505060808901356001600160401b038111156161e557600080fd5b6161f18b828c016160fb565b999c989b5096995094979396929594505050565b6000806000806000806080878903121561621e57600080fd5b616227876160e3565b9550602087013561623781615eb1565b945060408701356001600160401b0381111561625257600080fd5b61625e89828a01615ed1565b90955093505060608701356001600160401b0381111561627d57600080fd5b61628989828a01615ed1565b979a9699509497509295939492505050565b6001600160e01b031981168114615e9557600080fd5b6000602082840312156162c357600080fd5b8135610ca38161629b565b600080604083850312156162e157600080fd5b6162ea836160e3565b915060208301356162fa8161629b565b809150509250929050565b60005b83811015616320578181015183820152602001616308565b50506000910152565b60008151808452616341816020860160208601616305565b601f01601f19169290920160200192915050565b60ff60f81b8816815260e06020820152600061637460e0830189616329565b82810360408401526163868189616329565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501528451808252602080870193509091019060005b818110156163dc5783518352602093840193909201916001016163be565b50909b9a5050505050505050505050565b6000806040838503121561640057600080fd5b82356001600160401b0381111561641657600080fd5b61642285828601616031565b95602094909401359450505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171561646957616469616431565b60405290565b60405161012081016001600160401b038111828210171561646957616469616431565b604051601f8201601f191681016001600160401b03811182821017156164ba576164ba616431565b604052919050565b60008060008060008060006080888a0312156164dd57600080fd5b87356001600160401b038111156164f357600080fd5b6164ff8a828b016160fb565b90985096505060208801356001600160401b0381111561651e57600080fd5b8801601f81018a1361652f57600080fd5b80356001600160401b0381111561654857616548616431565b61655760208260051b01616492565b8082825260208201915060208360061b85010192508c83111561657957600080fd5b6020840193505b828410156165d5576040848e03121561659857600080fd5b6165a0616447565b6165a985616097565b815260208501356165b981615eb1565b8060208301525080835250602082019150604084019350616580565b975050505060408801356001600160401b038111156165f357600080fd5b6165ff8a828b016160fb565b90955093505060608801356001600160401b0381111561661e57600080fd5b61662a8a828b016160fb565b989b979a50959850939692959293505050565b602081526000610ca36020830184616329565b60006020828403121561666257600080fd5b610ca3826160e3565b60008060008060008060008060a0898b03121561668757600080fd5b883561669281615eb1565b975060208901356166a281615eb1565b965060408901356001600160401b038111156166bd57600080fd5b6166c98b828c016160fb565b90975095505060608901356001600160401b038111156166e857600080fd5b6166f48b828c016160fb565b90955093505060808901356001600160401b0381111561671357600080fd5b6161f18b828c01615ed1565b602080825282516001600160f01b03191682820152828101516001600160a01b03166040808401919091528301516060808401528051608084018190526000929190910190829060a08501905b808310156167985783516001600160501b0319168252602093840193600193909301929091019061676c565b5095945050505050565b6000602082840312156167b457600080fd5b5035919050565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561681457603f198786030184526167ff858351616329565b945060209384019391909101906001016167e3565b50929695505050505050565b60008060008060006060868803121561683857600080fd5b616841866160e3565b945060208601356001600160401b0381111561685c57600080fd5b61686888828901615ed1565b90955093505060408601356001600160401b03811115615fc957600080fd5b60008060008060008060a087890312156168a057600080fd5b86356168ab81615eb1565b955060208701356168bb81615eb1565b9450604087013593506060870135925060808701356001600160401b0381111561627d57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b03851681528360208201526060604082015260006169356060830184866168e4565b9695505050505050565b60006001600160401b0382111561695857616958616431565b50601f01601f191660200190565b60006020828403121561697857600080fd5b81516001600160401b0381111561698e57600080fd5b8201601f8101841361699f57600080fd5b80516169b26169ad8261693f565b616492565b8181528560208385010111156169c757600080fd5b610933826020830160208601616305565b600080858511156169e857600080fd5b838611156169f557600080fd5b5050820193919092039150565b80356001600160e01b03198116906004841015616a33576001600160e01b0319600485900360031b81901b82161691505b5092915050565b600060208284031215616a4c57600080fd5b8151610ca38161629b565b6000808335601e19843603018112616a6e57600080fd5b8301803591506001600160401b03821115616a8857600080fd5b602001915036819003821315615f1257600080fd5b600060208284031215616aaf57600080fd5b81518015158114610ca357600080fd5b634e487b7160e01b600052603260045260246000fd5b8183823760009101908152919050565b80356bffffffffffffffffffffffff198116906014841015616a33576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b602081526000610b016020830184866168e4565b9182526001600160a01b0316602082015260400190565b8035602083101561094d57600019602084900360031b1b1692915050565b85815260018060a01b0385166020820152836040820152608060608201526000616b9c6080830184866168e4565b979650505050505050565b600082601f830112616bb857600080fd5b8135616bc66169ad8261693f565b818152846020838601011115616bdb57600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215616c0b57600080fd5b616c1361646f565b616c1c83615ec6565b81526020838101359082015260408301356001600160401b03811115616c4157600080fd5b616c4d36828601616ba7565b60408301525060608301356001600160401b03811115616c6c57600080fd5b616c7836828601616ba7565b6060830152506080838101359082015260a0808401359082015260c0808401359082015260e08301356001600160401b03811115616cb557600080fd5b616cc136828601616ba7565b60e0830152506101008301356001600160401b03811115616ce157600080fd5b616ced36828601616ba7565b6101008301525092915050565b80516001600160a01b0316825260208101516020830152600060408201516101206040850152616d2e610120850182616329565b905060608301518482036060860152616d478282616329565b9150506080830151608085015260a083015160a085015260c083015160c085015260e083015184820360e0860152616d7f8282616329565b9150506101008301518482036101008601526109338282616329565b604081526000616dae6040830185616cfa565b90508260208301529392505050565b600060208284031215616dcf57600080fd5b5051919050565b838152606060208201526000616def6060830185616cfa565b9050826040830152949350505050565b63ffffffff818116838216019081111561094d57634e487b7160e01b600052601160045260246000fd5b828152604060208201526000610b016040830184616329565b80356001600160c01b03198116906008841015616a33576001600160c01b031960089490940360031b84901b1690921692915050565b828152604060208201526000610b016040830184616cfa565b80356001600160501b03198116906016841015616a33576001600160501b031960169490940360031b84901b1690921692915050565b838152818360208301376000910160200190815292915050565b80356001600160f01b03198116906002841015616a33576001600160f01b031960029490940360031b84901b1690921692915050565b60008235605e19833603018112616f2d57600080fd5b9190910192915050565b84815260018060a01b0384166020820152826040820152608060608201526000616935608083018461632956fed21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e"; + bytes constant KERNEL_WITH_SETSELECTOR_BYTECODE = + hex"61014060405234801561001157600080fd5b506040516172913803806172918339810160408190526100309161015a565b306080524660a05260608061007a604080518082018252600681526512d95c9b995b60d21b60208083019190915282518084019093526005835264302e332e3160d81b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152808501939093528281019190915246606083015230608083015260a0909120610100526001600160a01b03851661012052805163deadbeef60e01b92810192909252805160048184030181526024909201905261011b9250905061018a565b7f7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f80546001600160a81b03191660589290921c919091179055506101c8565b60006020828403121561016c57600080fd5b81516001600160a01b038116811461018357600080fd5b9392505050565b805160208201516001600160581b03198116919060158210156101c1576001600160581b0319601583900360031b81901b82161692505b5050919050565b60805160a05160c05160e051610100516101205161702d610264600039600081816102fa015281816106bf01528181610ce201528181611017015281816111e1015281816115de01528181611aac01528181611bd001528181611d940152818161257401528181612ea6015261307701526000614696015260006147500152600061472a015260006146da015260006146b7015261702d6000f3fe6080604052600436106101dc5760003560e01c80639198bdf511610102578063c3e5897811610095578063e9ae5c5311610064578063e9ae5c531461081a578063f1f7f0f91461082d578063f23a6e611461085b578063f2dc691d146108885761021b565b8063c3e589781461079a578063d03c7914146107c7578063d691c964146107e7578063e6f3d50a146108075761021b565b8063a71763a8116100d1578063a71763a8146106f9578063adb610a31461070c578063b8afe17d14610721578063bc197c811461076b5761021b565b80639198bdf5146106425780639517e29f146106555780639cfd7cff14610668578063a65d69d4146106ad5761021b565b80633c3b752b1161017a578063721e67f411610149578063721e67f4146105a557806384b0196e146105dd5780638dd7712f1461060557806390ef8862146106185761021b565b80633c3b752b146104f857806352141cd91461051857806357b3a5f41461052b5780636e6fa0c6146105855761021b565b806319822f7c116101b657806319822f7c1461048f5780631f1b92e3146104b05780633659cfe6146104c557806337bb6ef2146104d85761021b565b8063112d3a7d146103f5578063150b7a021461042a5780631626ba7e1461046f5761021b565b3661021b57604080513381523460208201527f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f88525874910160405180910390a1005b60006102326000356001600160e01b0319166108a8565b604080516060808201835283546001600160a01b039081168084526001909501549081166020840152600160a01b900460f81b6001600160f81b03191692820192909252925060009161029857604051631cd4b64760e21b815260040160405180910390fd5b82516060906001600160a01b03166001148015906102c1575083516001600160a01b0390811614155b156102dc5783516102d590346000366108e2565b9050610338565b83516001600160a01b03908116900361033857336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610338576040516348f5c3ed60e01b815260040160405180910390fd5b6040840151610348906000610967565b156103645761035a846020015161097e565b90935091506103a9565b604084015161037b906001600160f81b0319610967565b156103905761035a84602001516000366109ce565b604051632d6a6bb760e01b815260040160405180910390fd5b826103b657815160208301fd5b83516001600160a01b03166001148015906103dc575083516001600160a01b0390811614155b156103ed5783516103ed90826109fd565b815160208301f35b34801561040157600080fd5b50610415610410366004615f4f565b610a5f565b60405190151581526020015b60405180910390f35b34801561043657600080fd5b50610456610445366004615faa565b630a85bd0160e11b95945050505050565b6040516001600160e01b03199091168152602001610421565b34801561047b57600080fd5b5061045661048a36600461601c565b610b34565b6104a261049d366004616080565b610cd5565b604051908152602001610421565b6104c36104be3660046160e1565b610ff0565b005b6104c36104d33660046160fc565b6111c7565b3480156104e457600080fd5b506104c36104f3366004616155565b6113e0565b34801561050457600080fd5b506104c36105133660046161e2565b6113f0565b6104c36105263660046162a8565b6115c4565b34801561053757600080fd5b5061054b61054636600461633e565b611959565b6040805182516001600160a01b03908116825260208085015190911690820152918101516001600160f81b03191690820152606001610421565b34801561059157600080fd5b506104156105a036600461635b565b6119c5565b3480156105b157600080fd5b506105c56105c03660046160fc565b611a0d565b60405190516001600160a01b03168152602001610421565b3480156105e957600080fd5b506105f2611a43565b60405161042197969594939291906163e2565b6104c361061336600461647a565b611aa1565b34801561062457600080fd5b5061062d611b99565b60405163ffffffff9091168152602001610421565b6104c361065036600461654f565b611bb6565b6104c3610663366004615f4f565b611d7a565b34801561067457600080fd5b5060408051808201825260168152756b65726e656c2e616476616e6365642e76302e332e3160501b6020820152905161042191906166ca565b3480156106b957600080fd5b506106e17f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610421565b6104c3610707366004615f4f565b61255a565b34801561071857600080fd5b5061062d612bb3565b34801561072d57600080fd5b5061074161073c3660046166dd565b612bd0565b60408051825163ffffffff1681526020928301516001600160a01b03169281019290925201610421565b34801561077757600080fd5b506104566107863660046166f8565b63bc197c8160e01b98975050505050505050565b3480156107a657600080fd5b506107ba6107b536600461633e565b612c38565b60405161042191906167ac565b3480156107d357600080fd5b506104156107e236600461682f565b612d14565b6107fa6107f536600461601c565b612e01565b6040516104219190616848565b6104c36108153660046168ad565b612e8c565b6104c361082836600461601c565b61305d565b34801561083957600080fd5b50610842613216565b6040516001600160581b03199091168152602001610421565b34801561086757600080fd5b50610456610876366004616914565b63f23a6e6160e01b9695505050505050565b34801561089457600080fd5b506104156108a336600461682f565b613229565b6001600160e01b03191660009081527f7c341349a4360fdd5d5bc07e69f325dc6aaea3eb018b3e0ea7e53cc0bb0d6f3b6020526040902090565b60405163d68f602560e01b81526060906001600160a01b0386169063d68f60259061091790339088908890889060040161699a565b6000604051808303816000875af1158015610936573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261095e91908101906169f3565b95945050505050565b6001600160f81b0319828116908216145b92915050565b6000606060408051368101909152366000823760408051601481019091523360601b9052600080366014018382885af192505060405190503d8152602081013d6000823e3d810160405250915091565b604051600090828482376000388483885af491503d8152602081013d6000823e3d810160405250935093915050565b604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da90610a299084906004016166ca565b600060405180830381600087803b158015610a4357600080fd5b505af1158015610a57573d6000803e3d6000fd5b505050505050565b600060018503610abc576000610a73613249565b6001016000610a888760581b600160f81b1790565b6001600160581b0319168152602081019190915260400160002054600160201b90046001600160a01b031614159050610b2c565b60028503610ae2576000610acf8561326d565b546001600160a01b031614159050610b2c565b60038503610b28576001600160a01b038416610b13610b05600460008688616a65565b610b0e91616a8f565b6108a8565b600101546001600160a01b0316149050610b2c565b5060005b949350505050565b600080610b3f613249565b90506000366000610b5087876132a6565b925092509250610b67610b608490565b6000610967565b15610b7457835460581b92505b6001600160581b031983166000908152600185016020526040902054600160201b90046001600160a01b0316610bbd57604051631a0a9b9f60e21b815260040160405180910390fd5b610bcb83600160f81b610967565b15610c65576000610bdc8460581c90565b9050806001600160a01b031663f551e2ee33610bf78c613313565b86866040518563ffffffff1660e01b8152600401610c18949392919061699a565b602060405180830381865afa158015610c35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c599190616ac7565b95505050505050610cce565b6000610c718460081b90565b6001600160e01b03198116600090815260038701602052604090205490915060f01b600160f11b811615610cb857604051635b71057960e01b815260040160405180910390fd5b610cc582338c8787613369565b96505050505050505b9392505050565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d20576040516348f5c3ed60e01b815260040160405180910390fd5b6000610d2a613249565b90506000806000610d3e8860200135613467565b91945092509050610d50826000610967565b15610d5c5750825460581b5b610d6883828a8a613495565b6001600160581b031982166000908152600186016020908152604080832081518083019092525463ffffffff81168252600160201b90046001600160a01b031691810191909152919650610dbd908490613691565b8015610ddb57508454815163ffffffff600160c81b90920482169116105b15610df957604051633ab3447f60e11b815260040160405180910390fd5b60208101516001600160a01b038116610e2557604051631a0a9b9f60e21b815260040160405180910390fd5b600089815260208190526040902080546001600160a01b0319166001600160a01b03831690811790915560001901610eed57610e62846000613691565b8015610eca57506001600160581b031983166000908152600287016020526040812090610e9260608d018d616ae4565b610ea191600491600091616a65565b610eaa91616a8f565b6001600160e01b031916815260208101919091526040016000205460ff16155b15610ee857604051631a0a9b9f60e21b815260040160405180910390fd5b610fd3565b610ef8846000613691565b8015610f6057506001600160581b031983166000908152600287016020526040812090610f2860608d018d616ae4565b610f3791600891600491616a65565b610f4091616a8f565b6001600160e01b031916815260208101919091526040016000205460ff16155b15610f7e57604051631a0a9b9f60e21b815260040160405180910390fd5b638dd7712f60e01b610f9360608c018c616ae4565b610fa291600491600091616a65565b610fab91616a8f565b6001600160e01b03191614610fd35760405163dbbb044b60e01b815260040160405180910390fd5b8715610fe357343434348b335af1505b5050505050509392505050565b600061100a610ffd613249565b546001600160a81b031690565b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906110455750333014155b156111ba5760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa15801561108e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b29190616b2a565b156111a15760405163d68f602560e01b81526000906001600160a01b0383169063d68f6025906110ec90339034908690369060040161699a565b6000604051808303816000875af115801561110b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261113391908101906169f3565b905061113e836136a4565b604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da9061116a9084906004016166ca565b600060405180830381600087803b15801561118457600080fd5b505af1158015611198573d6000803e3d6000fd5b50505050505050565b6040516348f5c3ed60e01b815260040160405180910390fd5b6111c3826136a4565b5050565b60006111d4610ffd613249565b9050336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480159061120f5750333014155b156113845760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015611258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127c9190616b2a565b156111a15760405163d68f602560e01b81526000906001600160a01b0383169063d68f6025906112b690339034908690369060040161699a565b6000604051808303816000875af11580156112d5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112fd91908101906169f3565b9050827f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55826001600160a01b03167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a2604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da9061116a9084906004016166ca565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8290556040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b6113eb838383613786565b505050565b60006113fa613249565b805490915060581b6001600160581b031916156114545760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b60448201526064015b60405180910390fd5b6001600160581b0319891661147c57604051631a0a9b9f60e21b815260040160405180910390fd5b8861148b81600160f81b613691565b80156114a057506114a081600160f91b613691565b156114be576040516361c4e91b60e11b815260040160405180910390fd5b6114c78a613819565b60408051808201909152600181526001600160a01b038a166020820152825463ffffffff60a81b1916600160a81b1783556115068b828b8b8b8b61387b565b60005b848110156115b65760003087878481811061152657611526616b47565b90506020028101906115389190616ae4565b604051611546929190616b5d565b6000604051808303816000865af19150503d8060008114611583576040519150601f19603f3d011682016040523d82523d6000602084013e611588565b606091505b50509050806115ad57604051636534eae560e11b81526004810183905260240161144b565b50600101611509565b505050505050505050505050565b60006115d1610ffd613249565b9050336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480159061160c5750333014155b156118585760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015611655573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116799190616b2a565b156111a15760405163d68f602560e01b81526000906001600160a01b0383169063d68f6025906116b390339034908690369060040161699a565b6000604051808303816000875af11580156116d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116fa91908101906169f3565b90506000611706613249565b90506001600160581b0319891661173057604051631a0a9b9f60e21b815260040160405180910390fd5b8861173f81600160f81b613691565b8015611754575061175481600160f91b613691565b15611772576040516361c4e91b60e11b815260040160405180910390fd5b61177b8a613819565b6000611785613249565b6001600160581b03198c1660009081526001919091016020526040902054600160201b90046001600160a01b0316036117f257604080518082019091528254600160a81b900463ffffffff1681526001600160a01b038a1660208201526117f08b828b8b8b8b61387b565b505b5050604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da906118209084906004016166ca565b600060405180830381600087803b15801561183a57600080fd5b505af115801561184e573d6000803e3d6000fd5b5050505050611198565b6000611862613249565b90506001600160581b0319881661188c57604051631a0a9b9f60e21b815260040160405180910390fd5b8761189b81600160f81b613691565b80156118b057506118b081600160f91b613691565b156118ce576040516361c4e91b60e11b815260040160405180910390fd5b6118d789613819565b60006118e1613249565b6001600160581b03198b1660009081526001919091016020526040902054600160201b90046001600160a01b03160361194e57604080518082019091528254600160a81b900463ffffffff1681526001600160a01b038916602082015261194c8a828a8a8a8a61387b565b505b505050505050505050565b604080516060810182526000808252602082018190529181019190915261197f826108a8565b6040805160608101825282546001600160a01b0390811682526001909301549283166020820152600160a01b90920460f81b6001600160f81b0319169082015292915050565b60006119cf613249565b6001600160581b031984166000908152600291909101602090815260408083206001600160e01b03198616845290915290205460ff16905092915050565b604080516020810190915260008152611a258261326d565b604080516020810190915290546001600160a01b0316815292915050565b600f60f81b6060806000808083611a8f604080518082018252600681526512d95c9b995b60d21b60208083019190915282518084019093526005835264302e332e3160d81b9083015291565b97989097965046955030945091925090565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611aea576040516348f5c3ed60e01b815260040160405180910390fd5b6000818152602081905260409020546060906001600160a01b031660018114611b3557611b328134611b1f6060880188616ae4565b611b2d916004908290616a65565b6108e2565b91505b600080611b5c30611b496060890189616ae4565b611b57916004908290616a65565b6109ce565b9150915081611b7e5760405163f21e646b60e01b815260040160405180910390fd5b6001600160a01b038316600114610a5757610a5783856109fd565b6000611ba3613249565b54600160c81b900463ffffffff16919050565b6000611bc3610ffd613249565b9050336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590611bfe5750333014155b15611d615760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015611c47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6b9190616b2a565b156111a15760405163d68f602560e01b81526000906001600160a01b0383169063d68f602590611ca590339034908690369060040161699a565b6000604051808303816000875af1158015611cc4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cec91908101906169f3565b9050611cfd89898989898989613aca565b604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da90611d299084906004016166ca565b600060405180830381600087803b158015611d4357600080fd5b505af1158015611d57573d6000803e3d6000fd5b5050505050611d70565b611d7088888888888888613aca565b5050505050505050565b6000611d87610ffd613249565b9050336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590611dc25750333014155b156122615760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015611e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2f9190616b2a565b156111a15760405163d68f602560e01b81526000906001600160a01b0383169063d68f602590611e6990339034908690369060040161699a565b6000604051808303816000875af1158015611e88573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611eb091908101906169f3565b905060018603611fed576000611ec4613249565b90506000611ed88760581b600160f81b1790565b82546001600160581b03198216600090815260018501602052604090205491925063ffffffff600160a81b9091048116911603611f38578154600163ffffffff600160a81b808404821692909201160263ffffffff60a81b199091161782555b604080518082019091528254600160a81b900463ffffffff16815260009060208101611f676014848a8c616a65565b611f7091616b6d565b60601c9052905060148781013588016034818101929182013591818b01358b0180830192908201359160548d01358d01918201910135611fb488888888888861387b565b6004819003611fdf57611fdf88611fcf600460008587616a65565b611fd891616a8f565b6001613786565b5050505050505050506121fd565b600286036120545760148481013585016034818101929182013591818801358801918201918101359060009061202590828a8c616a65565b61202e91616b6d565b60601c905061203f8a868684613b6e565b61204a818484613bd4565b50505050506121fd565b600386036120e457601884810135850160388181019291820135918188013588019182019101356120b761208c600460008a8c616a65565b61209591616a8f565b8a6120a4601860048c8e616a65565b6120ad91616b6d565b60601c8787613da5565b6120db6120c8601860048a8c616a65565b6120d191616b6d565b60601c8383613bd4565b505050506121fd565b60048603612178576040516306d61fe760e41b81526001600160a01b03861690636d61fe709061211a9087908790600401616bad565b600060405180830381600087803b15801561213457600080fd5b505af1158015612148573d6000803e3d6000fd5b50505050600080516020616fed833981519152868660405161216b929190616bc1565b60405180910390a16121fd565b600586036121ae576040516306d61fe760e41b81526001600160a01b03861690636d61fe709061211a9087908790600401616bad565b600686036121e4576040516306d61fe760e41b81526001600160a01b03861690636d61fe709061211a9087908790600401616bad565b604051631092ef5760e11b815260040160405180910390fd5b604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da906122299084906004016166ca565b600060405180830381600087803b15801561224357600080fd5b505af1158015612257573d6000803e3d6000fd5b5050505050612553565b6001850361238c576000612273613249565b905060006122878660581b600160f81b1790565b82546001600160581b03198216600090815260018501602052604090205491925063ffffffff600160a81b90910481169116036122e7578154600163ffffffff600160a81b808404821692909201160263ffffffff60a81b199091161782555b604080518082019091528254600160a81b900463ffffffff16815260009060208101612316601484898b616a65565b61231f91616b6d565b60601c9052905060148681013587016034818101929182013591818a01358a0180830192908201359160548c01358c0191820191013561236388888888888861387b565b600481900361237e5761237e88611fcf600460008587616a65565b505050505050505050612553565b600285036123e9576014838101358401603481810192918201359181870135870191820191810135906000906123c49082898b616a65565b6123cd91616b6d565b60601c90506123de89868684613b6e565b612257818484613bd4565b60038503612453576018838101358401603881810192918201359181870135870191820191013561243961242160046000898b616a65565b61242a91616a8f565b896120a4601860048b8d616a65565b61244a6120c860186004898b616a65565b50505050612553565b600485036124e7576040516306d61fe760e41b81526001600160a01b03851690636d61fe70906124899086908690600401616bad565b600060405180830381600087803b1580156124a357600080fd5b505af11580156124b7573d6000803e3d6000fd5b50505050600080516020616fed83398151915285856040516124da929190616bc1565b60405180910390a1612553565b6005850361251d576040516306d61fe760e41b81526001600160a01b03851690636d61fe70906124899086908690600401616bad565b600685036121e4576040516306d61fe760e41b81526001600160a01b03851690636d61fe70906124899086908690600401616bad565b5050505050565b6000612567610ffd613249565b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906125a25750333014155b156129285760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa1580156125eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260f9190616b2a565b156111a15760405163d68f602560e01b81526000906001600160a01b0383169063d68f60259061264990339034908690369060040161699a565b6000604051808303816000875af1158015612668573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261269091908101906169f3565b9050856001036126c05760006126ac8660581b600160f81b1790565b90506126b9818686613f16565b50506121fd565b856002036126d9576126d385858561405a565b506121fd565b856003036127115760006126f06004828688616a65565b6126f991616a8f565b90506126b98161270c866004818a616a65565b6140f6565b8560040361282e576000612723613249565b5460581b90506001600160a01b03861661273b613249565b6001600160581b0319831660009081526001919091016020526040902054600160201b90046001600160a01b0316036127c0576001612778613249565b6001600160581b0319831660009081526001919091016020526040902080546001600160a01b0392909216600160201b02640100000000600160c01b03199092169190911790555b6128008686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141dc92505050565b5060008051602061700d8339815191528787604051612820929190616bc1565b60405180910390a1506121fd565b85600503612916576000612840613249565b5460581b905060006128556020828789616a65565b61285e91616bd8565b905061286f825b600160f91b610967565b156128a75761287e8260081b90565b6001600160e01b03191681036128a7576040516313002bdd60e31b815260040160405180910390fd5b6128e78787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141dc92505050565b5060008051602061700d8339815191528888604051612907929190616bc1565b60405180910390a150506121fd565b856006036121e4576000612840613249565b846001036129565760006129428560581b600160f81b1790565b905061294f818585613f16565b5050612553565b8460020361296f5761296984848461405a565b50612553565b846003036129a25760006129866004828587616a65565b61298f91616a8f565b905061294f8161270c8560048189616a65565b84600403612abf5760006129b4613249565b5460581b90506001600160a01b0385166129cc613249565b6001600160581b0319831660009081526001919091016020526040902054600160201b90046001600160a01b031603612a51576001612a09613249565b6001600160581b0319831660009081526001919091016020526040902080546001600160a01b0392909216600160201b02640100000000600160c01b03199092169190911790555b612a918585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141dc92505050565b5060008051602061700d8339815191528686604051612ab1929190616bc1565b60405180910390a150612553565b84600503612ba1576000612ad1613249565b5460581b90506000612ae66020828688616a65565b612aef91616bd8565b9050612afa82612865565b15612b3257612b098260081b90565b6001600160e01b0319168103612b32576040516313002bdd60e31b815260040160405180910390fd5b612b728686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141dc92505050565b5060008051602061700d8339815191528787604051612b92929190616bc1565b60405180910390a15050612553565b846006036121e4576000612ad1613249565b6000612bbd613249565b54600160a81b900463ffffffff16919050565b6040805180820190915260008082526020820152612bec613249565b6001600160581b03199290921660009081526001909201602090815260409283902083518085019094525463ffffffff81168452600160201b90046001600160a01b0316908301525090565b60408051606080820183526000808352602083015291810191909152612c5c613249565b6001600160e01b03198316600090815260039190910160209081526040918290208251606081018452815460f081901b6001600160f01b03191682526201000090046001600160a01b03168184015260018201805485518186028101860187528181529295939493860193830182828015612d0457602002820191906000526020600020905b815460501b6001600160501b0319168152600190910190602001808311612ce2575b5050505050815250509050919050565b600081600881901b603082901b605083901b612d3484600160f81b613691565b8015612d465750612d46846000613691565b8015612d5f5750612d5f846001600160f81b0319613691565b8015612d745750612d7484607f60f91b613691565b15612d855750600095945050505050565b6001600160f81b03198316600160f81b14801590612dac57506001600160f81b0319831615155b15612dbd5750600095945050505050565b6001600160e01b0319821615612dd95750600095945050505050565b6001600160501b0319811615612df55750600095945050505050565b50600195945050505050565b60606000612e0e3361326d565b546001600160a01b0316905080612e385760405163710c949760e01b815260040160405180910390fd5b60606001600160a01b038216600114612e5b57612e5882346000366108e2565b90505b612e66868686614283565b92506001600160a01b038216600114612e8357612e8382826109fd565b50509392505050565b6000612e99610ffd613249565b9050336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590612ed45750333014155b156130435760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015612f1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f419190616b2a565b156111a15760405163d68f602560e01b81526000906001600160a01b0383169063d68f602590612f7b90339034908690369060040161699a565b6000604051808303816000875af1158015612f9a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fc291908101906169f3565b90506000612fd1888888613f16565b9050612fde8186866145cb565b50604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da9061300b9084906004016166ca565b600060405180830381600087803b15801561302557600080fd5b505af1158015613039573d6000803e3d6000fd5b5050505050610a57565b6000613050878787613f16565b90506111988185856145cb565b600061306a610ffd613249565b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906130a55750333014155b156132055760405163ecd0596160e01b81526004808201526001600160a01b0382169063ecd0596190602401602060405180830381865afa1580156130ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131129190616b2a565b156111a15760405163d68f602560e01b81526000906001600160a01b0383169063d68f60259061314c90339034908690369060040161699a565b6000604051808303816000875af115801561316b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261319391908101906169f3565b90506131a0858585614283565b50604051630b9dfbed60e11b81526001600160a01b0383169063173bf7da906131cd9084906004016166ca565b600060405180830381600087803b1580156131e757600080fd5b505af11580156131fb573d6000803e3d6000fd5b5050505050613210565b612553848484614283565b50505050565b6000613220613249565b5460581b919050565b6000600782101561323c57506001919050565b506000919050565b919050565b7f7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f90565b6001600160a01b031660009081527f1bbee3173dbdc223633258c9f337a0fff8115f206d302bea0ed3eac003b68b866020526040902090565b813536600060f883901c80156132cb57600181146132e057600281146132f157600080fd5b6000935060018601925060018503915061330b565b60158601925060158503915061330b565b6001600160d81b0319841693506005860192506005850391505b509250925092565b604080517f1547321c374afde8a591d972a084b071c594c275e36724931ff96c25f2999c836020820152908101829052600090610978906060015b60405160208183030381529060405280519060200120614694565b600080600036600061337e8a8a8a8a8a6147ac565b9350935093509350600080613392856148b8565b50915091508165ffffffffffff164210806133b457508065ffffffffffff1642115b156133d057506001600160e01b0319955061095e945050505050565b6001600160a01b03861663392dffaf6001600160e01b03198e168d6133f48e613313565b88886040518663ffffffff1660e01b8152600401613416959493929190616bf6565b602060405180830381865afa158015613433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134579190616ac7565b9c9b505050505050505050505050565b80600881901b8060ff60f084901c16600119810161348d576001600160d81b0319821691505b509193909250565b6000806134a0613249565b905060006134ad85616c80565b90503660006134c0610100880188616ae4565b90925090506134d389600160f81b610967565b15613531576134ef886134ea6101008a018a616ae4565b6148eb565b604080516020601f8401819004810282018101909252828152939850919450925083908390819084018382808284376000920191909152505050506101008401525b8761354081600160f81b610967565b156135cf576135c8866135538b60581c90565b6001600160a01b03166397003203878b6040518363ffffffff1660e01b8152600401613580929190616e23565b6020604051808303816000875af115801561359f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c39190616e45565b614918565b9550613684565b60006135db8a60081b90565b6001600160e01b03198116600090815260038801602052604090205490915060f01b600160f01b1615613621576040516314b9743f60e01b815260040160405180910390fd5b600080613630838888886149d6565b9150915061363e8983614918565b985061367e89826001600160a01b0316630ccab7a1866001600160e01b0319168b8f6040518463ffffffff1660e01b815260040161358093929190616e5e565b98505050505b5050505050949350505050565b6001600160f81b03199081169116141590565b60006136ae613249565b805490915063ffffffff808416916136d091600a91600160a81b900416616e87565b63ffffffff1610156136f55760405163e60fd64760e01b815260040160405180910390fd5b805463ffffffff600160c81b90910481169083161161372757604051633ab3447f60e11b815260040160405180910390fd5b805463ffffffff60c81b1916600160c81b63ffffffff8481168202929092178084559081048216600160a81b90910490911610156111c357805463ffffffff60a81b198116600160c81b90910463ffffffff16600160a81b0217905550565b6000613790613249565b6001600160581b03198516600081815260028301602090815260408083206001600160e01b0319891680855290835292819020805488151560ff1990911681179091558151938452918301939093528183015290519192507f9d17cd6d095ac90a655405ab29f30a7ee7e88ef3974c1bf7544bf591043bb71a919081900360600190a150505050565b6000613823613249565b80546001600160a81b031916605884901c1781556040516001600160581b0319841681529091507f6789ec0c85d6458d897a36a70129b101f8b4d84c6e218046c3107373dbcbae889060200160405180910390a15050565b6000613885613249565b80546001600160581b03198916600090815260018301602052604090205491925063ffffffff600160a81b90910481169116036138e5578054600163ffffffff600160a81b808404821692909201160263ffffffff60a81b199091161781555b60208601516001600160a01b03166138ff57600160208701525b85518154600160a81b900463ffffffff9081169116141580613947575085516001600160581b03198816600090815260018301602052604090205463ffffffff918216911610155b1561396557604051633ab3447f60e11b815260040160405180910390fd5b6001600160581b03198716600090815260018083016020908152604090922088518154938a01516001600160a01b0316600160201b81026001600160c01b031990951663ffffffff90921691909117939093179055146139ce576139ce86602001518484613bd4565b866139dd81600160f81b610967565b15613a7f5760006139ee8960581c90565b6040516306d61fe760e41b81529091506001600160a01b03821690636d61fe7090613a1f908a908a90600401616bad565b600060405180830381600087803b158015613a3957600080fd5b505af1158015613a4d573d6000803e3d6000fd5b50505050600080516020616fed833981519152600182604051613a71929190616bc1565b60405180910390a150611d70565b613a8d81600160f91b610967565b15613ab1576000613a9e8960081b90565b9050613aab818888614cb6565b50611d70565b6040516361c4e91b60e11b815260040160405180910390fd5b60005b86811015611d7057613b66888883818110613aea57613aea616b47565b9050602002016020810190613aff91906166dd565b878381518110613b1157613b11616b47565b6020026020010151878785818110613b2b57613b2b616b47565b9050602002810190613b3d9190616ae4565b878787818110613b4f57613b4f616b47565b9050602002810190613b619190616ae4565b61387b565b600101613acd565b613b78848261510f565b6040516306d61fe760e41b81526001600160a01b03851690636d61fe7090613ba69086908690600401616bad565b600060405180830381600087803b158015613bc057600080fd5b505af1158015611d70573d6000803e3d6000fd5b6001600160a01b0383161580613bf357506001600160a01b0383166001145b15613bfd57505050565b60405163d60b347f60e01b81523060048201526001600160a01b0384169063d60b347f90602401602060405180830381865afa158015613c41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c659190616b2a565b613cd9576001600160a01b038316636d61fe70613c858360018187616a65565b6040518363ffffffff1660e01b8152600401613ca2929190616bad565b600060405180830381600087803b158015613cbc57600080fd5b505af1158015613cd0573d6000803e3d6000fd5b50505050613d78565b6001600160f81b03198282600081613cf357613cf3616b47565b9050013560f81c60f81b6001600160f81b03191603613d78576001600160a01b038316636d61fe70613d288360018187616a65565b6040518363ffffffff1660e01b8152600401613d45929190616bad565b600060405180830381600087803b158015613d5f57600080fd5b505af1158015613d73573d6000803e3d6000fd5b505050505b600080516020616fed833981519152600484604051613d98929190616bc1565b60405180910390a1505050565b6001600160a01b038316613dbe576001600160a01b0392505b6000613dc9866108a8565b9050600083836000818110613de057613de0616b47565b9050013560f81c60f81b9050613dfa81600060f81b610967565b15613e97576001600160a01b038616636d61fe70613e1b8560018189616a65565b6040518363ffffffff1660e01b8152600401613e38929190616bad565b600060405180830381600087803b158015613e5257600080fd5b505af1158015613e66573d6000803e3d6000fd5b50505050600080516020616fed833981519152600387604051613e8a929190616bc1565b60405180910390a1613ec7565b613ea9816001600160f81b0319613691565b15613ec757604051632d6a6bb760e01b815260040160405180910390fd5b81546001600160a01b039586166001600160a01b03199091161782556001909101805460f89290921c600160a01b026001600160a81b0319909216959094169490941793909317909155505050565b600080613f21613249565b805490915060581b6001600160581b031990811690861603613f56576040516313002bdd60e31b815260040160405180910390fd5b6001600160581b03198516600090815260018201602052604090208054640100000000600160c01b03198116909155600160201b90046001600160a01b0316915084613fa681600160f81b610967565b15614028576000613fb78760581c90565b9050613ff98187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141dc92505050565b5060008051602061700d83398151915260018260405161401a929190616bc1565b60405180910390a150612e83565b61403681600160f91b610967565b15613ab15760006140478760081b90565b9050614054818787615169565b50612e83565b6000806140668561326d565b80546001600160a01b031981168255604080516020601f88018190048102820181019092528681526001600160a01b0390921694509192506140c59187919087908790819084018382808284376000920191909152506141dc92505050565b5060008051602061700d8339815191526002866040516140e6929190616bc1565b60405180910390a1509392505050565b600080614102856108a8565b80546001600160a01b03198116825560018201546001600160a01b03909116935090915061413b90600160a01b900460f81b6000610967565b156141c4576001810154604080516020601f870181900481028201810190925285815261418c926001600160a01b03169187908790819084018382808284376000920191909152506141dc92505050565b50600181015460405160008051602061700d833981519152916141bb916003916001600160a01b031690616bc1565b60405180910390a15b60010180546001600160a81b03191690559392505050565b6000614236835a600080638a91b0e360e01b876040516024016141ff91906166ca565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152615333565b50604080516001600160a01b038616815282151560208201529192507f2b82f87bf66300af618a9621d3f221edfab735f5bacb4e004cce1b62375396c3910160405180910390a192915050565b606083600881901b61429982600160f81b610967565b1561432357843585016020810190356142b3836000610967565b156142c9576142c282826153bd565b945061431c565b6142d783600160f81b610967565b156142e6576142c2828261548d565b60405162461bcd60e51b815260206004820152600b60248201526a155b9cdd5c1c1bdc9d195960aa1b604482015260640161144b565b5050612e83565b61432e826000610967565b1561445c5760008036600061434389896155ba565b6040805160018082528183019092529498509296509094509250816020015b606081526020019060019003908161436257905050965060006143858682610967565b156143b9576143968585858561560b565b886000815181106143a9576143a9616b47565b6020026020010181905250614452565b6143c786600160f81b610967565b156142e6576143d885858585615641565b896000815181106143eb576143eb616b47565b6020908102919091010152905080614452577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb760008960008151811061443357614433616b47565b6020026020010151604051614449929190616eb1565b60405180910390a15b5050505050612e83565b61446e826001600160f81b0319610967565b156142e65760408051600180825281830190925290816020015b606081526020019060019003908161448857905050925060006144ae6014828789616a65565b6144b791616b6d565b60601c90503660006144cc876014818b616a65565b9150915060006144dd8484846109ce565b886000815181106144f0576144f0616b47565b6020908102919091010152905061450b85600160f81b610967565b1561456f578061456a577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb760008860008151811061454b5761454b616b47565b6020026020010151604051614561929190616eb1565b60405180910390a15b6145c2565b61457a856000610967565b156142e6578061456a5760405162461bcd60e51b815260206004820152601360248201527211195b1959d85d1958d85b1b0819985a5b1959606a1b604482015260640161144b565b50505050612e83565b6001600160a01b03831615806145ea57506001600160a01b0383166001145b156145f457505050565b6001600160f81b0319828260008161460e5761460e616b47565b9050013560f81c60f81b6001600160f81b0319160361467457614672836146388360018187616a65565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506141dc92505050565b505b60008051602061700d833981519152600484604051613d98929190616bc1565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000030147f00000000000000000000000000000000000000000000000000000000000000004614166147875750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b600080366000806147bb613249565b60408051610120810182526000808252602082018190529181018290526080810182905260a0810191909152606060c082018190526001600160e01b03198d16908201526001600160a01b038b1660e082015261010081018a905290915061482581838a8a615672565b8787600081811061483857614838616b47565b9091013560f81c60ff1490506148615760405163b32eeb6960e01b815260040160405180910390fd5b61486e876001818b616a65565b60608301516001600160e01b0319166000908152600394909401602052604093849020549390920151620100009093046001600160a01b03169c929b509950975095505050505050565b600060a082901c65ffffffffffff1682811560001981016148dd5765ffffffffffff92505b508360d01c92509193909250565b60003660006148fb8686866158df565b925050506094830135830160348101906014013593509350939050565b600081830160601b8260601b81148460601b8214176001600160a01b038486181615176001811461494c57600192506149ce565b6001600160d01b031980851690861681811881831102188686176001600160a01b031617935065ffffffffffff60a01b861690816149915765ffffffffffff60a01b91505b5065ffffffffffff60a01b8516806149af575065ffffffffffff60a01b5b8082189082110218806149c8575065ffffffffffff60a01b5b92909217915b505092915050565b60008060006149e3613249565b6001600160e01b03198816600090815260038201602052604081209192506001909101905b8154811015614bfa57600080614a41848481548110614a2957614a29616b47565b60009182526020909120015460501b90605082901c90565b91509150600089896000818110614a5a57614a5a616b47565b919091013560f81c915050838103614aed576000614a7c600960018c8e616a65565b614a8591616eca565b60c01c9050614a9a6009808301908c8e616a65565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506101008d0152614ae38a60098301818e616a65565b9a509a5050614b27565b838160ff161015614b1157604051630760bdcf60e11b815260040160405180910390fd5b6040805160208101909152600081526101008c01525b600160f01b8316600003614bef576000826001600160a01b0316637129edce8e6001600160e01b0319168e6040518363ffffffff1660e01b8152600401614b6f929190616f00565b6020604051808303816000875af1158015614b8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bb29190616e45565b9050806001600160a01b03811615614be057604051631f24c1fb60e11b81526004810187905260240161144b565b614bea8a83614918565b995050505b505050600101614a08565b5085856000818110614c0e57614c0e616b47565b9091013560f81c60ff149050614c375760405163b32eeb6960e01b815260040160405180910390fd5b614c448560018189616a65565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506101008c01949094525050506001600160e01b03198916815260039092016020525060409020546001600160a01b036201000090910416905094509492505050565b6000614cc0613249565b90508235830160208101903560fe811180614cd9575080155b15614cf75760405163b62d956d60e01b815260040160405180910390fd5b6001600160e01b03198616600090815260038401602052604090206001015415614d45576001600160e01b0319861660009081526003840160205260408120614d4591600190910190615ead565b60005b6000198201811015614f39576001600160e01b0319871660009081526003850160205260409020600101838383818110614d8457614d84616b47565b9050602002810190614d969190616ae4565b614da591601691600091616a65565b614dae91616f19565b81546001810183556000928352602090922090910180546001600160b01b03191660509290921c919091179055828282818110614ded57614ded616b47565b9050602002810190614dff9190616ae4565b614e0e91601691600291616a65565b614e1791616b6d565b60601c636d61fe706001600160e01b03198916858585818110614e3c57614e3c616b47565b9050602002810190614e4e9190616ae4565b614e5c916016908290616a65565b604051602001614e6e93929190616f4f565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401614e9991906166ca565b600060405180830381600087803b158015614eb357600080fd5b505af1158015614ec7573d6000803e3d6000fd5b50505050600080516020616fed8339815191526005848484818110614eee57614eee616b47565b9050602002810190614f009190616ae4565b614f0f91601691600291616a65565b614f1891616b6d565b60601c604051614f29929190616bc1565b60405180910390a1600101614d48565b50600082826000198101818110614f5257614f52616b47565b9050602002810190614f649190616ae4565b614f7391601691600291616a65565b614f7c91616b6d565b6001600160e01b031988166000908152600386016020526040902080546201000060609390931c92830262010000600160b01b0319909116179055905082826000198101818110614fcf57614fcf616b47565b9050602002810190614fe19190616ae4565b614ff091600291600091616a65565b614ff991616f69565b6001600160e01b0319881660008181526003870160205260409020805461ffff191660f09390931c929092179091556001600160a01b03821690636d61fe70908585600019810181811061504f5761504f616b47565b90506020028101906150619190616ae4565b61506f916016908290616a65565b60405160200161508193929190616f4f565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016150ac91906166ca565b600060405180830381600087803b1580156150c657600080fd5b505af11580156150da573d6000803e3d6000fd5b50505050600080516020616fed8339815191526006826040516150fe929190616bc1565b60405180910390a150505050505050565b6001600160a01b038116615121575060015b600061512c8361326d565b80546001600160a01b0319166001600160a01b038416178155604051909150600080516020616fed83398151915290613d98906002908690616bc1565b81358201602081019035600061517d613249565b6001600160e01b031987166000908152600391909101602052604090206001808201549192500182146151c35760405163013dcc8d60e31b815260040160405180910390fd5b6001810160005b81548110156152785760006151ea838381548110614a2957614a29616b47565b915050615246818a6001600160e01b03191688888681811061520e5761520e616b47565b90506020028101906152209190616ae4565b60405160200161523293929190616f4f565b6040516020818303038152906040526141dc565b5060008051602061700d833981519152600582604051615267929190616bc1565b60405180910390a1506001016151ca565b50615281613249565b6001600160e01b031988166000908152600391909101602052604081206152ad91600190910190615ead565b81546152e3906201000090046001600160a01b03166001600160e01b031989168686600019810181811061520e5761520e616b47565b50815460405160008051602061700d83398151915291615315916006916201000090046001600160a01b031690616bc1565b60405180910390a15080546001600160b01b03191690555050505050565b6000606060008060008661ffff166001600160401b03811115615358576153586164be565b6040519080825280601f01601f191660200182016040528015615382576020820181803683370190505b5090506000808751602089018b8e8ef191503d9250868311156153a3578692505b828152826000602083013e90999098509650505050505050565b606081806001600160401b038111156153d8576153d86164be565b60405190808252806020026020018201604052801561540b57816020015b60608152602001906001900390816153f65790505b50915060005b818110156149ce573685858381811061542c5761542c616b47565b905060200281019061543e9190616f9f565b905061546761545060208301836160fc565b60208301356154626040850185616ae4565b61560b565b84838151811061547957615479616b47565b602090810291909101015250600101615411565b606081806001600160401b038111156154a8576154a86164be565b6040519080825280602002602001820160405280156154db57816020015b60608152602001906001900390816154c65790505b50915060005b818110156149ce57368585838181106154fc576154fc616b47565b905060200281019061550e9190616f9f565b9050600061553961552260208401846160fc565b60208401356155346040860186616ae4565b615641565b86858151811061554b5761554b616b47565b60209081029190910101529050806155b0577fe723f28f104e46b47fd3531f3608374ac226bcf3ddda334a23a266453e0efdb78386858151811061559157615591616b47565b60200260200101516040516155a7929190616eb1565b60405180910390a15b50506001016154e1565b60008036816155cc6014828789616a65565b6155d591616b6d565b60601c93506155e8603460148789616a65565b6155f191616bd8565b92506156008560348189616a65565b949793965094505050565b60405181838237600038838387895af1615628573d6000823e3d81fd5b3d8152602081013d6000823e3d01604052949350505050565b604051600090828482376000388483888a5af191503d8152602081013d6000823e3d81016040525094509492505050565b60608401516001600160e01b03191660009081526003840160205260408120600101905b8154811015610a57576156b4828281548110614a2957614a29616b47565b6001600160a01b031660a08801526001600160f01b031916608087015283836000816156e2576156e2616b47565b919091013560f81c808852829003905061577f57615704600960018587616a65565b61570d91616eca565b60c01c60208701819052615728906009908101908587616a65565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060c087015260208601516157769084906009018187616a65565b935093506157eb565b855160ff168111156157a457604051630760bdcf60e11b815260040160405180910390fd5b6157b16000808587616a65565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050505060c08701525b6080860151600160f11b166000036158d75760a0860151606087015160e088015161010089015160c08a015160405163184dfdbb60e11b81526000956001600160a01b03169463309bfb7694615852946001600160e01b0319909216939092600401616fbf565b602060405180830381865afa15801561586f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906158939190616e45565b9050806001600160a01b038116156158c157604051631f24c1fb60e11b81526004810184905260240161144b565b6158cf886040015183614918565b604089015250505b600101615696565b600036600080366000366000366000806158fa8e8e8e615965565b9750975097509750975097509750975060748d013560348e0101995060208a03359850615928818b8b615b1a565b9a506159388e898989898961387b565b6159428383615cba565b6159548e611fcf600460008688616a65565b505050505050505050509392505050565b604080518082019091526000808252602082015236600036600036600080600061598d613249565b905061599d601460008c8e616a65565b6159a691616b6d565b60601c89602001906001600160a01b031690816001600160a01b0316815250508060000160159054906101000a900463ffffffff16896000019063ffffffff16908163ffffffff168152505060148b013560348c010197506020880335965060348b013560348c010195506020860335945060548b013560348c0101935060208403359250615b0a7fb17ab1224aca0d4255ef8161acaf2ac121b8faa32a4b2258c912cc5f8308c50560001b8d8360000160159054906101000a900463ffffffff168c602001518c8c604051615a7d929190616b5d565b60405180910390208b8b604051615a95929190616b5d565b60405180910390208a8a604051615aad929190616b5d565b6040805191829003822060208301989098526001600160581b03199096169581019590955263ffffffff90931660608501526001600160a01b03909116608084015260a083015260c082015260e08101919091526101000161334e565b9150509397509397509397509397565b600080615b25613249565b805490915060581b6000615b3d82600160f81b610967565b15615bc9578254604051637aa8f17760e11b81526001600160a81b038216916001600160a01b03169063f551e2ee90615b809030908c908c908c9060040161699a565b602060405180830381865afa158015615b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615bc19190616ac7565b915050615c7f565b615bd782600160f91b610967565b15613ab157825460601b6000615bf082308b8b8b6147ac565b60405163392dffaf60e01b8152919b5099509097509091506001600160a01b0382169063392dffaf90615c39906001600160e01b031986169030908e908e908e90600401616bf6565b602060405180830381865afa158015615c56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615c7a9190616ac7565b925050505b630b135d3f60e11b6001600160e01b0319821614615cb0576040516362467c7760e11b815260040160405180910390fd5b5050509392505050565b6000615cc96004828486616a65565b615cd291616a8f565b9050600482106113eb57602c8210615e6657366000818180615cf860186004898b616a65565b615d0191616b6d565b60601c9050602c880135604c890101945060208503359350604c880135604c890101925060208303359150615d5685856000818110615d4257615d42616b47565b9050013560f81c60f81b600060f81b610967565b8015615dc6575060405163ecd0596160e01b8152600260048201526001600160a01b0382169063ecd0596190602401602060405180830381865afa158015615da2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615dc69190616b2a565b15615e1c57606c8801358801604c810190602c01356000615dea6014828486616a65565b615df391616b6d565b60601c9050615e02848261510f565b615e1881615e138460148188616a65565b613bd4565b5050505b615e428682615e2f602c60188c8e616a65565b615e3891616b6d565b60601c8888613da5565b611d70615e53602c60188a8c616a65565b615e5c91616b6d565b60601c8484613bd4565b600482146113eb5760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642073656c6563746f724461746160601b604482015260640161144b565b5080546000825590600052602060002090810190615ecb9190615ece565b50565b5b80821115615ee35760008155600101615ecf565b5090565b6001600160a01b0381168114615ecb57600080fd5b803561324481615ee7565b60008083601f840112615f1957600080fd5b5081356001600160401b03811115615f3057600080fd5b602083019150836020828501011115615f4857600080fd5b9250929050565b60008060008060608587031215615f6557600080fd5b843593506020850135615f7781615ee7565b925060408501356001600160401b03811115615f9257600080fd5b615f9e87828801615f07565b95989497509550505050565b600080600080600060808688031215615fc257600080fd5b8535615fcd81615ee7565b94506020860135615fdd81615ee7565b93506040860135925060608601356001600160401b03811115615fff57600080fd5b61600b88828901615f07565b969995985093965092949392505050565b60008060006040848603121561603157600080fd5b8335925060208401356001600160401b0381111561604e57600080fd5b61605a86828701615f07565b9497909650939450505050565b6000610120828403121561607a57600080fd5b50919050565b60008060006060848603121561609557600080fd5b83356001600160401b038111156160ab57600080fd5b6160b786828701616067565b9660208601359650604090950135949350505050565b803563ffffffff8116811461324457600080fd5b6000602082840312156160f357600080fd5b610cce826160cd565b60006020828403121561610e57600080fd5b8135610cce81615ee7565b80356001600160581b03198116811461324457600080fd5b6001600160e01b031981168114615ecb57600080fd5b8015158114615ecb57600080fd5b60008060006060848603121561616a57600080fd5b61617384616119565b9250602084013561618381616131565b9150604084013561619381616147565b809150509250925092565b60008083601f8401126161b057600080fd5b5081356001600160401b038111156161c757600080fd5b6020830191508360208260051b8501011115615f4857600080fd5b60008060008060008060008060a0898b0312156161fe57600080fd5b61620789616119565b9750602089013561621781615ee7565b965060408901356001600160401b0381111561623257600080fd5b61623e8b828c01615f07565b90975095505060608901356001600160401b0381111561625d57600080fd5b6162698b828c01615f07565b90955093505060808901356001600160401b0381111561628857600080fd5b6162948b828c0161619e565b999c989b5096995094979396929594505050565b600080600080600080608087890312156162c157600080fd5b6162ca87616119565b955060208701356162da81615ee7565b945060408701356001600160401b038111156162f557600080fd5b61630189828a01615f07565b90955093505060608701356001600160401b0381111561632057600080fd5b61632c89828a01615f07565b979a9699509497509295939492505050565b60006020828403121561635057600080fd5b8135610cce81616131565b6000806040838503121561636e57600080fd5b61637783616119565b9150602083013561638781616131565b809150509250929050565b60005b838110156163ad578181015183820152602001616395565b50506000910152565b600081518084526163ce816020860160208601616392565b601f01601f19169290920160200192915050565b60ff60f81b8816815260e06020820152600061640160e08301896163b6565b828103604084015261641381896163b6565b606084018890526001600160a01b038716608085015260a0840186905283810360c08501528451808252602080870193509091019060005b8181101561646957835183526020938401939092019160010161644b565b50909b9a5050505050505050505050565b6000806040838503121561648d57600080fd5b82356001600160401b038111156164a357600080fd5b6164af85828601616067565b95602094909401359450505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156164f6576164f66164be565b60405290565b60405161012081016001600160401b03811182821017156164f6576164f66164be565b604051601f8201601f191681016001600160401b0381118282101715616547576165476164be565b604052919050565b60008060008060008060006080888a03121561656a57600080fd5b87356001600160401b0381111561658057600080fd5b61658c8a828b0161619e565b90985096505060208801356001600160401b038111156165ab57600080fd5b8801601f81018a136165bc57600080fd5b80356001600160401b038111156165d5576165d56164be565b6165e460208260051b0161651f565b8082825260208201915060208360061b85010192508c83111561660657600080fd5b6020840193505b82841015616662576040848e03121561662557600080fd5b61662d6164d4565b616636856160cd565b8152602085013561664681615ee7565b806020830152508083525060208201915060408401935061660d565b975050505060408801356001600160401b0381111561668057600080fd5b61668c8a828b0161619e565b90955093505060608801356001600160401b038111156166ab57600080fd5b6166b78a828b0161619e565b989b979a50959850939692959293505050565b602081526000610cce60208301846163b6565b6000602082840312156166ef57600080fd5b610cce82616119565b60008060008060008060008060a0898b03121561671457600080fd5b883561671f81615ee7565b9750602089013561672f81615ee7565b965060408901356001600160401b0381111561674a57600080fd5b6167568b828c0161619e565b90975095505060608901356001600160401b0381111561677557600080fd5b6167818b828c0161619e565b90955093505060808901356001600160401b038111156167a057600080fd5b6162948b828c01615f07565b602080825282516001600160f01b03191682820152828101516001600160a01b03166040808401919091528301516060808401528051608084018190526000929190910190829060a08501905b808310156168255783516001600160501b031916825260209384019360019390930192909101906167f9565b5095945050505050565b60006020828403121561684157600080fd5b5035919050565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b828110156168a157603f1987860301845261688c8583516163b6565b94506020938401939190910190600101616870565b50929695505050505050565b6000806000806000606086880312156168c557600080fd5b6168ce86616119565b945060208601356001600160401b038111156168e957600080fd5b6168f588828901615f07565b90955093505060408601356001600160401b03811115615fff57600080fd5b60008060008060008060a0878903121561692d57600080fd5b863561693881615ee7565b9550602087013561694881615ee7565b9450604087013593506060870135925060808701356001600160401b0381111561632057600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b03851681528360208201526060604082015260006169c2606083018486616971565b9695505050505050565b60006001600160401b038211156169e5576169e56164be565b50601f01601f191660200190565b600060208284031215616a0557600080fd5b81516001600160401b03811115616a1b57600080fd5b8201601f81018413616a2c57600080fd5b8051616a3f616a3a826169cc565b61651f565b818152856020838501011115616a5457600080fd5b61095e826020830160208601616392565b60008085851115616a7557600080fd5b83861115616a8257600080fd5b5050820193919092039150565b80356001600160e01b03198116906004841015616ac0576001600160e01b0319600485900360031b81901b82161691505b5092915050565b600060208284031215616ad957600080fd5b8151610cce81616131565b6000808335601e19843603018112616afb57600080fd5b8301803591506001600160401b03821115616b1557600080fd5b602001915036819003821315615f4857600080fd5b600060208284031215616b3c57600080fd5b8151610cce81616147565b634e487b7160e01b600052603260045260246000fd5b8183823760009101908152919050565b80356bffffffffffffffffffffffff198116906014841015616ac0576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b602081526000610b2c602083018486616971565b9182526001600160a01b0316602082015260400190565b8035602083101561097857600019602084900360031b1b1692915050565b85815260018060a01b0385166020820152836040820152608060608201526000616c24608083018486616971565b979650505050505050565b600082601f830112616c4057600080fd5b8135616c4e616a3a826169cc565b818152846020838601011115616c6357600080fd5b816020850160208301376000918101602001919091529392505050565b60006101208236031215616c9357600080fd5b616c9b6164fc565b616ca483615efc565b81526020838101359082015260408301356001600160401b03811115616cc957600080fd5b616cd536828601616c2f565b60408301525060608301356001600160401b03811115616cf457600080fd5b616d0036828601616c2f565b6060830152506080838101359082015260a0808401359082015260c0808401359082015260e08301356001600160401b03811115616d3d57600080fd5b616d4936828601616c2f565b60e0830152506101008301356001600160401b03811115616d6957600080fd5b616d7536828601616c2f565b6101008301525092915050565b80516001600160a01b0316825260208101516020830152600060408201516101206040850152616db66101208501826163b6565b905060608301518482036060860152616dcf82826163b6565b9150506080830151608085015260a083015160a085015260c083015160c085015260e083015184820360e0860152616e0782826163b6565b91505061010083015184820361010086015261095e82826163b6565b604081526000616e366040830185616d82565b90508260208301529392505050565b600060208284031215616e5757600080fd5b5051919050565b838152606060208201526000616e776060830185616d82565b9050826040830152949350505050565b63ffffffff818116838216019081111561097857634e487b7160e01b600052601160045260246000fd5b828152604060208201526000610b2c60408301846163b6565b80356001600160c01b03198116906008841015616ac0576001600160c01b031960089490940360031b84901b1690921692915050565b828152604060208201526000610b2c6040830184616d82565b80356001600160501b03198116906016841015616ac0576001600160501b031960169490940360031b84901b1690921692915050565b838152818360208301376000910160200190815292915050565b80356001600160f01b03198116906002841015616ac0576001600160f01b031960029490940360031b84901b1690921692915050565b60008235605e19833603018112616fb557600080fd5b9190910192915050565b84815260018060a01b03841660208201528260408201526080606082015260006169c260808301846163b656fed21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e"; + bytes constant KERNEL_FACTORY_BYTECODE = + hex"60a0604052348015600f57600080fd5b506040516104ce3803806104ce833981016040819052602c91603c565b6001600160a01b0316608052606a565b600060208284031215604d57600080fd5b81516001600160a01b0381168114606357600080fd5b9392505050565b60805161043d6100916000396000818160870152818160f10152610159015261043d6000f3fe6080604052600436106100345760003560e01c806348aac392146100395780635c60da1b14610075578063ea6d13ac146100a9575b600080fd5b34801561004557600080fd5b506100596100543660046103a2565b6100bc565b6040516001600160a01b03909116815260200160405180910390f35b34801561008157600080fd5b506100597f000000000000000000000000000000000000000000000000000000000000000081565b6100596100b73660046103a2565b610120565b6000808484846040516020016100d49392919061041b565b6040516020818303038152906040528051906020012090506101177f00000000000000000000000000000000000000000000000000000000000000008230610213565b95945050505050565b6000808484846040516020016101389392919061041b565b60405160208183030381529060405280519060200120905060008061017e347f00000000000000000000000000000000000000000000000000000000000000008561029c565b9150915081610209576000816001600160a01b031688886040516101a392919061042d565b6000604051808303816000865af19150503d80600081146101e0576040519150601f19603f3d011682016040523d82523d6000602084013e6101e5565b606091505b50509050806102075760405163487e630960e11b815260040160405180910390fd5b505b9695505050505050565b60008061028f85604080517fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f360609081527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e20768352616009602052601e9390935268603d3d8160223d3973600a52605f6021209152600090915290565b9050610117818585610380565b6000806040517fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f36060527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e207660405261600960205284601e5268603d3d8160223d3973600a52605f60212060358201523060581b815260ff8153836015820152605581209150813b6103485783605f602188f59150816103435763301164256000526004601cfd5b61036e565b60019250851561036e5760003860003889865af161036e5763b12d13eb6000526004601cfd5b80604052506000606052935093915050565b600060ff60005350603592835260601b60015260155260556000908120915290565b6000806000604084860312156103b757600080fd5b833567ffffffffffffffff8111156103ce57600080fd5b8401601f810186136103df57600080fd5b803567ffffffffffffffff8111156103f657600080fd5b86602082840101111561040857600080fd5b6020918201979096509401359392505050565b82848237909101908152602001919050565b818382376000910190815291905056"; +} diff --git a/src/test/precompiles/NexusPrecompiles.sol b/src/test/precompiles/NexusPrecompiles.sol index e46fa723..ca5b0526 100644 --- a/src/test/precompiles/NexusPrecompiles.sol +++ b/src/test/precompiles/NexusPrecompiles.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; // Interfaces import { INexusAccountFactory } from "src/accounts/nexus/interfaces/INexusAccountFactory.sol"; @@ -7,9 +7,10 @@ import { INexusBootstrap } from "src/accounts/nexus/interfaces/INexusBootstrap.s // Utils import { label } from "src/test/utils/Vm.sol"; +import { BytecodeDeployer } from "./BytecodeDeployer.sol"; /// @notice Nexus contracts precompiled using --via-ir -contract NexusPrecompiles { +contract NexusPrecompiles is BytecodeDeployer { /*////////////////////////////////////////////////////////////// DEPLOY //////////////////////////////////////////////////////////////*/ @@ -49,18 +50,6 @@ contract NexusPrecompiles { label(address(bootstrap), "NexusBootstrap"); } - /*////////////////////////////////////////////////////////////// - PRIVATE - //////////////////////////////////////////////////////////////*/ - - /// @notice Deploys a contract using CREATE, reverts on failure - function _deploy(bytes memory creationBytecode) private returns (address contractAddress) { - assembly { - contractAddress := create(0, add(creationBytecode, 0x20), mload(creationBytecode)) - } - require(contractAddress != address(0), "NexusPrecompiles: deployment failed"); - } - /*////////////////////////////////////////////////////////////// BYTECODES //////////////////////////////////////////////////////////////*/ diff --git a/src/test/precompiles/Safe7579Precompiles.sol b/src/test/precompiles/Safe7579Precompiles.sol new file mode 100644 index 00000000..b0e1138d --- /dev/null +++ b/src/test/precompiles/Safe7579Precompiles.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.23 <0.9.0; + +// Interfaces +import { ISafe7579 } from "src/accounts/safe/interfaces/ISafe7579.sol"; +import { ISafe7579Launchpad } from "src/accounts/safe/interfaces/ISafe7579Launchpad.sol"; + +// Utils +import { label } from "src/test/utils/Vm.sol"; +import { BytecodeDeployer } from "./BytecodeDeployer.sol"; + +contract Safe7579Precompiles is BytecodeDeployer { + /*////////////////////////////////////////////////////////////// + DEPLOY + //////////////////////////////////////////////////////////////*/ + + function deploySafe7579() internal returns (ISafe7579 safe) { + safe = ISafe7579(_deploy(SAFE7579_BYTECODE)); + label(address(safe), "Safe7579"); + } + + function deploySafe7579Launchpad( + address entrypoint, + address registry + ) + internal + returns (ISafe7579Launchpad safeLaunchpad) + { + // Concat constructor params to bytecode + bytes memory creationBytecode = + bytes.concat(SAFE7579_LAUNCHPAD_BYTECODE, abi.encode(entrypoint, registry)); + safeLaunchpad = ISafe7579Launchpad(_deploy(creationBytecode)); + label(address(safeLaunchpad), "Safe7579Launchpad"); + } + + /*////////////////////////////////////////////////////////////// + BYTECODES + //////////////////////////////////////////////////////////////*/ + + bytes constant SAFE7579_BYTECODE = + hex"60a0604052348015600f57600080fd5b50604051601a906046565b604051809103906000f0801580156035573d6000803e3d6000fd5b506001600160a01b03166080526053565b6109e180614ee983390190565b608051614e2e6100bb600039600081816112230152818161141b0152818161157c01528181611dc501528181612216015281816122f0015281816123870152818161241e0152818161357a015281816136320152818161395a0152613a7a0152614e2e6000f3fe60806040526004361061012e5760003560e01c8063a71763a8116100ab578063d828435d1161006f578063d828435d146104a2578063e9ae5c53146104c2578063ea5f61d0146104e2578063eab77e1714610502578063f2dc691d14610522578063f698da251461054257610135565b8063a71763a8146103c7578063b0d691fe146103e7578063b875d5d81461040a578063d03c791414610455578063d691c9641461047557610135565b806355d559f4116100f257806355d559f4146102dd5780635faac46b1461030d57806379aad60e1461033b5780639517e29f1461035b5780639cfd7cff1461037b57610135565b80630a664dba146101e0578063112d3a7d146102245780631626ba7e1461025457806319822f7c1461028d578063540fb4f9146102bb57610135565b3661013557005b600036606060003560e01c63bc197c81811463f23a6e6182141763150b7a028214171561016657806020526020603cf35b50336000818152600460209081526040808320546001600160e01b031984351680855260058452828520958552949092528220546001600160a01b0391821692911690806101b48484610557565b915091506101c28888610615565b95506101d084848484610728565b5050505050915050805190602001f35b3480156101ec57600080fd5b50336000908152600460205260409020546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561023057600080fd5b5061024461023f366004613d49565b6107ab565b604051901515815260200161021b565b34801561026057600080fd5b5061027461026f366004613da4565b610820565b6040516001600160e01b0319909116815260200161021b565b34801561029957600080fd5b506102ad6102a8366004613e08565b610b96565b60405190815260200161021b565b3480156102c757600080fd5b506102db6102d6366004613eab565b610caa565b005b3480156102e957600080fd5b506102fd6102f8366004613fa7565b610d5a565b60405161021b9493929190614048565b34801561031957600080fd5b5061032d610328366004614094565b610fb7565b60405161021b9291906140c0565b34801561034757600080fd5b506102db610356366004614123565b610fd3565b34801561036757600080fd5b506102db610376366004613d49565b6110c8565b34801561038757600080fd5b50604080518082018252601a81527f7268696e6573746f6e652e73616665373537392e76312e302e300000000000006020820152905161021b9190614164565b3480156103d357600080fd5b506102db6103e2366004613d49565b611293565b3480156103f357600080fd5b506f71727de22e5e9d8baf0edac6f37da032610207565b34801561041657600080fd5b5061020761042536600461418d565b6001600160e01b03191660009081526005602090815260408083203384529091529020546001600160a01b031690565b34801561046157600080fd5b506102446104703660046141aa565b6115ba565b34801561048157600080fd5b50610495610490366004613da4565b611662565b60405161021b91906141c3565b3480156104ae57600080fd5b506102ad6104bd366004614228565b61174b565b3480156104ce57600080fd5b506102db6104dd366004613da4565b6117eb565b3480156104ee57600080fd5b5061032d6104fd366004614094565b611b88565b34801561050e57600080fd5b506102db61051d366004614267565b611b99565b34801561052e57600080fd5b5061024461053d3660046141aa565b611c08565b34801561054e57600080fd5b506102ad611c57565b6060806001600160a01b038416156105d7576105be33856000610578611cb0565b3460003660405160240161058f94939291906142f6565b60408051601f198184030181529190526020810180516001600160e01b031663d68f602560e01b179052611cbc565b9150818060200190518101906105d491906143df565b91505b6001600160a01b0383161561060e576105f533846000610578611cb0565b90508080602001905181019061060b91906143df565b90505b9250929050565b600080356001600160e01b031916815260036020908152604080832033845290915290208054606091906001600160a01b03811690600160a01b900460f81b8161068557604051632464e76d60e11b81526001600160e01b03196000351660048201526024015b60405180910390fd5b61069381607f60f91b611d65565b156106d7576106cd338388886106a7611cb0565b6040516020016106b993929190614413565b604051602081830303815290604052611d77565b9350505050610722565b6106e2816000611d65565b1561071e576106cd3383600089896106f8611cb0565b60405160200161070a93929190614413565b604051602081830303815290604052611cbc565b5050505b92915050565b6001600160a01b0384161561077e5761077e338560008560405160240161074f9190614164565b60408051601f198184030181529190526020810180516001600160e01b0316630b9dfbed60e11b179052611e4c565b6001600160a01b038316156107a5576107a5338460008460405160240161074f9190614164565b50505050565b6000600185036107dd57336001600160a01b038516036107cd57506001610818565b6107d684611eeb565b9050610818565b600285036107ee576107d684611ef9565b60038503610801576107d6848484611f07565b60048503610814576107d6848484611f53565b5060005b949350505050565b6000338282036109ba5760006108f1826001600160a01b031663f698da256040518163ffffffff1660e01b8152600401602060405180830381865afa15801561086d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108919190614439565b60408051602081018a90527f60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca91015b60408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052611f8e565b8051602090910120604051635ae6bd3760e01b8152600481018290529091506001600160a01b03831690635ae6bd3790602401602060405180830381865afa158015610941573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109659190614439565b6000036109a85760405162461bcd60e51b815260206004820152601160248201527012185cda081b9bdd08185c1c1c9bdd9959607a1b604482015260640161067c565b50630b135d3f60e11b9150610b8f9050565b60006109c96014828688614452565b6109d29161447c565b60601c90508015806109ea57506109e881611eeb565b155b15610b14576000610a89836001600160a01b031663f698da256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a569190614439565b60408051602081018b90527f60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca91016108c0565b805160208201209091506001600160a01b03841663934f3a118284610ab18a6014818e614452565b6040518563ffffffff1660e01b8152600401610ad094939291906144c9565b60006040518083038186803b158015610ae857600080fd5b505afa158015610afc573d6000803e3d6000fd5b50630b135d3f60e11b9750610b8f9650505050505050565b6000610b733383610b23611cb0565b8a610b318a6014818e614452565b604051602401610b4494939291906142f6565b60408051601f198184030181529190526020810180516001600160e01b0316637aa8f17760e11b179052611d77565b905080806020019051810190610b8991906144f5565b93505050505b9392505050565b60006f71727de22e5e9d8baf0edac6f37da032610bb1611cb0565b6001600160a01b031614610bd857604051635629665f60e11b815260040160405180910390fd5b6020840135606081901c90811580610bf65750610bf482611eeb565b155b15610c0b57610c0486612008565b9250610c70565b6000610c56338460008a8a604051602401610c27929190614557565b60408051601f198184030181529190526020810180516001600160e01b0316639700320360e01b179052611cbc565b905080806020019051810190610c6c9190614439565b9350505b8315610ca157610ca1336f71727de22e5e9d8baf0edac6f37da0328660405180602001604052806000815250611e4c565b50509392505050565b6f71727de22e5e9d8baf0edac6f37da032610cc3611cb0565b6001600160a01b03161480610cf05750610cdb611cb0565b6001600160a01b0316336001600160a01b0316145b610d0d57604051635629665f60e11b815260040160405180910390fd5b610d3f610d1d602083018361465b565b610d2a6020840184614678565b610d3a60608601604087016146c1565b6120b7565b610d4f898989898989898961216e565b505050505050505050565b6060600080823682610d706101008901896146dc565b9092509050610d83600660008385614452565b610d8c91614722565b60d01c9450610d9f600c60068385614452565b610da891614722565b60d01c9350610dba81600c8185614452565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516101c081019091527fc03dfc11d8b10bf9cf703d558958c8c42777f785d998c62060d85a4f0ef6ea7f815294975095509293505060208084019250610e3691508a018a61465b565b6001600160a01b0316815260200188602001358152602001888060400190610e5e91906146dc565b604051610e6c929190614758565b6040519081900390208152602001610e8760608a018a6146dc565b604051610e95929190614758565b60405180910390208152602001610eab8961248d565b6001600160801b03168152602001610ec28961249d565b6001600160801b031681526020018860a001358152602001610ee3896124b2565b6001600160801b03168152602001610efa896124c1565b6001600160801b03168152602001610f1560e08a018a6146dc565b604051610f23929190614758565b6040805191829003909120825265ffffffffffff80881660208401528616908201526001600160a01b0388166060909101526101c08120909150601960f81b600160f81b610f6f611c57565b6040516001600160f81b031993841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529550505092959194509250565b60606000610fc860013386866124d6565b915091509250929050565b6f71727de22e5e9d8baf0edac6f37da032610fec611cb0565b6001600160a01b031614806110195750611004611cb0565b6001600160a01b0316336001600160a01b0316145b61103657604051635629665f60e11b815260040160405180910390fd5b61104160013361269a565b8060005b81811015611097573684848381811061106057611060614768565b9050602002810190611072919061477e565b905061108e33611085602084018461465b565b60019190612715565b50600101611045565b5060405133907ff48581d8a62b775b74f2fb67f1d5806a9a356fbcc598040ab3071d3e37af40c290600090a2505050565b336000908152600460209081526040808320547fd00bcad91b775f25eb0aee15808d12dfdaa6dc5a7d6b754e26f9c205d2a3b8df909252822054639517e29f60e01b926001600160a01b039283169290911690806111268484610557565b915091506111416f71727de22e5e9d8baf0edac6f37da03290565b6001600160a01b0316611152611cb0565b6001600160a01b0316148061117f575061116a611cb0565b6001600160a01b0316336001600160a01b0316145b61119c57604051635629665f60e11b815260040160405180910390fd5b606060018a036111b8576111b189898961280a565b905061121d565b60028a036111cb576111b1898989612866565b60038a036111de576111b1898989612881565b60048a036111f1576111b1898989612a00565b89611201576111b1898989612ba0565b60405163041c38b360e41b8152600481018b905260240161067c565b611286337f00000000000000000000000000000000000000000000000000000000000000008c8c856040516024016112579392919061479e565b60408051601f198184030181529190526020810180516001600160e01b0316639517e29f60e01b179052612d51565b50610d4f84848484610728565b336000908152600460209081526040808320547fc45a7acaba78a7b4c4432b604d301355b314c0a7811768a1ee2563c9d34ca4e09092529091205484916314e2ec7560e31b916001600160a01b0391821691908116908416821480159061130c5750806001600160a01b0316846001600160a01b031614155b156114925760008061131e8484610557565b915091506113396f71727de22e5e9d8baf0edac6f37da03290565b6001600160a01b031661134a611cb0565b6001600160a01b031614806113775750611362611cb0565b6001600160a01b0316336001600160a01b0316145b61139457604051635629665f60e11b815260040160405180910390fd5b606060018b036113b0576113a98a8a8a612dea565b9050611415565b60028b036113c3576113a98a8a8a612e13565b60038b036113d6576113a98a8a8a612e34565b60048b036113e9576113a98a8a8a612e80565b8a6113f9576113a98a8a8a612f38565b60405163041c38b360e41b8152600481018c905260240161067c565b61147e337f00000000000000000000000000000000000000000000000000000000000000008d8d8560405160240161144f9392919061479e565b60408051601f198184030181529190526020810180516001600160e01b0316637827252560e01b17905261308b565b5061148b84848484610728565b50506115b0565b6f71727de22e5e9d8baf0edac6f37da0326114ab611cb0565b6001600160a01b031614806114d857506114c3611cb0565b6001600160a01b0316336001600160a01b0316145b6114f557604051635629665f60e11b815260040160405180910390fd5b6060600189036115115761150a888888612dea565b9050611576565b600289036115245761150a888888612e13565b600389036115375761150a888888612e34565b6004890361154a5761150a888888612e80565b8861155a5761150a888888612f38565b60405163041c38b360e41b8152600481018a905260240161067c565b610d4f337f00000000000000000000000000000000000000000000000000000000000000008b8b8560405160240161144f9392919061479e565b5050505050505050565b600081600881901b6115d082600160f81b611d65565b156115de5760019250611621565b6115e9826000611d65565b156115f75760019250611621565b611609826001600160f81b0319611d65565b156116175760019250611621565b5060009392505050565b8280156116345750611634816000611d65565b15611640575050919050565b828015611656575061165681600160f81b611d65565b15611617575050919050565b606061167461166f611cb0565b611ef9565b6116a557611680611cb0565b604051635c93ff2f60e11b81526001600160a01b03909116600482015260240161067c565b336000908152600460209081526040808320547f4162c930ade27880570b0eb31efbc8a626b97e81a40ced27163509dfe16398829092528220546335a4725960e21b926001600160a01b039283169290911690806117038484610557565b9150915061170f611cb0565b600261171b8282613141565b8a600881901b61172d81838e8e6131cc565b99505050505061173f84848484610728565b50505050509392505050565b6000602082901b640100000000600160c01b03166f71727de22e5e9d8baf0edac6f37da032604051631aab3f0d60e11b81526001600160a01b0386811660048301526001600160c01b038416602483015291909116906335567e1a90604401602060405180830381865afa1580156117c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108189190614439565b336000908152600460209081526040808320547fccfe1b2bef70acd8e661aeb5430e147f4c75cb320972acba718a28da428e1a3090925282205463e9ae5c5360e01b926001600160a01b039283169290911690806118498484610557565b915091506118646f71727de22e5e9d8baf0edac6f37da03290565b6001600160a01b0316611875611cb0565b6001600160a01b031614806118a2575061188d611cb0565b6001600160a01b0316336001600160a01b0316145b6118bf57604051635629665f60e11b815260040160405180910390fd5b87600881901b336118d1826000611d65565b15611a2a576118e483600160f81b611d65565b156119055789358a016020810190356118fe838383613574565b5050611b79565b611910836000611d65565b15611978576000803660006119258e8e6135db565b935093509350935061196f85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e4c92505050565b50505050611b79565b61198a836001600160f81b0319611d65565b15611a0f57600061199e6014828c8e614452565b6119a79161447c565b60601c90503660008c8c60149080926119c293929190614452565b91509150611a07848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d5192505050565b505050611b79565b82604051632e5bf3f960e21b815260040161067c91906147d1565b611a3882600160f81b611d65565b15611b5e57611a4b83600160f81b611d65565b15611a655789358a016020810190356118fe83838361362c565b611a70836000611d65565b15611acf57600080366000611a858e8e6135db565b935093509350935061196f85858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061369392505050565b611ae1836001600160f81b0319611d65565b15611a0f576000611af56014828c8e614452565b611afe9161447c565b60601c90503660008c8c6014908092611b1993929190614452565b91509150611a07848484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061308b92505050565b816040516308c3ee0360e11b815260040161067c91906147d1565b5050506115b084848484610728565b60606000610fc860023386866124d6565b6f71727de22e5e9d8baf0edac6f37da032611bb2611cb0565b6001600160a01b03161480611bdf5750611bca611cb0565b6001600160a01b0316336001600160a01b0316145b611bfc57604051635629665f60e11b815260040160405180910390fd5b6107a5848484846120b7565b600060018203611c1a57506001919050565b60028203611c2a57506001919050565b60038203611c3a57506001919050565b60048203611c4a57506001919050565b506000919050565b919050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b60131936013560601c90565b60606000856001600160a01b0316635229073f86868660006040518563ffffffff1660e01b8152600401611cf3949392919061481e565b6000604051808303816000875af1158015611d12573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d3a9190810190614864565b9250905080611d5c57604051632b3f6d1160e21b815260040160405180910390fd5b50949350505050565b6001600160f81b031990811691161490565b606060008383604051602401611d8e9291906148b1565b60408051601f198184030181529181526020820180516001600160e01b0316636a22165760e01b17905251909150600090611def907f00000000000000000000000000000000000000000000000000000000000000009084906024016148b1565b60408051601f19818403018152919052602080820180516001600160e01b031663b4faba0960e01b17815282519293509091600091895afa5060203d036040519350808401604052806020853e50600051610ca157825160208401fd5b60405163468721a760e01b81526000906001600160a01b0386169063468721a790611e8190879087908790879060040161481e565b6020604051808303816000875af1158015611ea0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec491906148d5565b905080611ee457604051632b3f6d1160e21b815260040160405180910390fd5b5050505050565b600061072260013384613749565b600061072260023384613749565b600080611f168385018561418d565b6001600160e01b03191660009081526003602090815260408083203384529091529020546001600160a01b03908116908616149150509392505050565b60008080611f63848601866148ff565b915091506000611f73838361378d565b6001600160a01b039081169088161493505050509392505050565b6060601960f81b600160f81b858585604051602001611fae92919061492b565b60408051808303601f190181529082905280516020918201206001600160f81b0319958616918301919091529290931660218401526022830152604282015260620160405160208183030381529060405290509392505050565b600080808080612028866f71727de22e5e9d8baf0edac6f37da032610d5a565b8351602085012060405163934f3a1160e01b81529498509296509094509250339163934f3a119161205f9188908690600401614951565b60006040518083038186803b15801561207757600080fd5b505afa925050508015612088575060015b61209f5761209860018385613823565b94506120ae565b6120ab60008385613823565b94505b50505050919050565b33600090815260208190526040902080546001600160a01b0319166001600160a01b0386169081179091551561213257612132338560008487876040516024016121039392919061497c565b60408051601f198184030181529190526020810180516001600160e01b031663f05c04e160e01b179052611e4c565b6040516001600160a01b0385169033907f9452c8fb077c3ea8f28a77c87488af657b1e44d010ad9a5992d73870da040e9490600090a350505050565b3360009081527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f602052604090205460609088906001600160a01b0316612266576121ba60013361269a565b60005b8181101561226057368b8b838181106121d8576121d8614768565b90506020028101906121ea919061477e565b905061220e6121fc602083018361465b565b61220960208401846146dc565b61280a565b9350612257337f00000000000000000000000000000000000000000000000000000000000000006001612244602086018661465b565b886040516024016112579392919061479e565b506001016121bd565b50612287565b80156122875760405163d8e3ed1b60e01b815233600482015260240161067c565b61229260023361269a565b508560005b8181101561232757368989838181106122b2576122b2614768565b90506020028101906122c4919061477e565b90506122e86122d6602083018361465b565b6122e360208401846146dc565b612866565b935061231e337f00000000000000000000000000000000000000000000000000000000000000006002612244602086018661465b565b50600101612297565b5084905060005b818110156123be573687878381811061234957612349614768565b905060200281019061235b919061477e565b905061237f61236d602083018361465b565b61237a60208401846146dc565b612881565b93506123b5337f00000000000000000000000000000000000000000000000000000000000000006003612244602086018661465b565b5060010161232e565b5082905060005b8181101561245557368585838181106123e0576123e0614768565b90506020028101906123f2919061477e565b9050612416612404602083018361465b565b61241160208401846146dc565b612a00565b935061244c337f00000000000000000000000000000000000000000000000000000000000000006004612244602086018661465b565b506001016123c5565b5060405133907ff48581d8a62b775b74f2fb67f1d5806a9a356fbcc598040ab3071d3e37af40c290600090a250505050505050505050565b6000610722826080013560801c90565b60006001600160801b03608083013516610722565b600060c082013560801c610722565b60006001600160801b0360c083013516610722565b606060006001600160a01b0384166001148015906124fc57506124fa868686613749565b155b1561252557604051637c84ecfb60e01b81526001600160a01b038516600482015260240161067c565b826000036125465760405163f725081760e01b815260040160405180910390fd5b826001600160401b0381111561255e5761255e614328565b604051908082528060200260200182016040528015612587578160200160208202803683370190505b506001600160a01b038086166000908152602089815260408083208a85168452909152812054929450911691505b6001600160a01b038216158015906125d757506001600160a01b038216600114155b80156125e257508381105b1561264757818382815181106125fa576125fa614768565b6001600160a01b039283166020918202929092018101919091529281166000908152888452604080822089841683529094529290922054909116908061263f816149ea565b9150506125b5565b6001600160a01b0382166001148015906126615750600081115b1561268d5782612672600183614a03565b8151811061268257612682614768565b602002602001015191505b8083525094509492505050565b60016000908152602083815260408083206001600160a01b03808616855292529091205416156126dd576040516329e42f3360e11b815260040160405180910390fd5b60016000818152602093845260408082206001600160a01b0394909416825292909352912080546001600160a01b0319169091179055565b6001600160a01b038116158061273457506001600160a01b0381166001145b1561275d57604051637c84ecfb60e01b81526001600160a01b038216600482015260240161067c565b6001600160a01b03818116600090815260208581526040808320868516845290915290205416156127ac57604051631034f46960e21b81526001600160a01b038216600482015260240161067c565b60016000908152602084815260408083206001600160a01b039586168085528184528285208054968816808752988552838620918652908452919093208054949095166001600160a01b031994851617909455528154169091179055565b60608360016128198282613141565b61282560013388612715565b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929998505050505050505050565b60608360026128758282613141565b61282560023388612715565b60608360036128908282613141565b600080806128a087890189614a67565b919450925090506001600160e01b031983166306d61fe760e41b14806128d657506001600160e01b03198316638a91b0e360e01b145b15612900576040516379bd117b60e01b81526001600160e01b03198416600482015260240161067c565b61290b826000611d65565b8015612920575061292082607f60f91b611d65565b1561294057816040516376087dc160e01b815260040161067c91906147d1565b6001600160e01b0319831660009081526003602090815260408083203384529091529020546001600160a01b031615612998576040516374420d1560e01b81526001600160e01b03198416600482015260240161067c565b6001600160e01b03199092166000908152600360209081526040808320338452909152902080546001600160a01b038a166001600160a01b031960f89490941c600160a01b02939093166001600160a81b031990911617919091179055925050509392505050565b6060836004612a0f8282613141565b60008080612a1f87890189614ad5565b91945092509050600080846001811115612a3b57612a3b6147e6565b148015612a5057506001600160e01b03198316155b15612ac65750336000908152600460205260409020546001600160a01b03168015612a995760405163741cbe0360e01b81526001600160a01b038216600482015260240161067c565b33600090815260046020526040902080546001600160a01b0319166001600160a01b038c16179055612b93565b6001846001811115612ada57612ada6147e6565b03612b7a57506001600160e01b0319821660009081526005602090815260408083203384529091529020546001600160a01b03168015612b385760405163741cbe0360e01b81526001600160a01b038216600482015260240161067c565b6001600160e01b031983166000908152600560209081526040808320338452909152902080546001600160a01b0319166001600160a01b038c16179055612b93565b604051635691922f60e01b815260040160405180910390fd5b5098975050505050505050565b60608235830160208181019135908581013586018082019190359060408801358801908101903584838114612be85760405163b4fa3fb360e01b815260040160405180910390fd5b60005b81811015612d0a576000888883818110612c0757612c07614768565b90506020020135905060018103612c4657612c408d888885818110612c2e57612c2e614768565b905060200281019061220991906146dc565b50612d01565b60028103612c7657612c408d888885818110612c6457612c64614768565b90506020028101906122e391906146dc565b60038103612ca657612c408d888885818110612c9457612c94614768565b905060200281019061237a91906146dc565b60048103612cd657612c408d888885818110612cc457612cc4614768565b905060200281019061241191906146dc565b60405163484d218160e01b81526001600160a01b038e1660048201526024810182905260440161067c565b50600101612beb565b5082828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929e9d5050505050505050505050505050565b60405163468721a760e01b81526000906001600160a01b0385169063468721a790612d879086908590879060019060040161481e565b6020604051808303816000875af1158015612da6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dca91906148d5565b9050806107a557604051632b3f6d1160e21b815260040160405180910390fd5b60606000612dfa83850185614b03565b92509050612e0b600133838861385b565b509392505050565b60606000612e2383850185614b03565b92509050612e0b600233838861385b565b60606000612e4483850185614b48565b6001600160e01b03199091166000908152600360209081526040808320338452909152902080546001600160a01b031916905595945050505050565b6060600080612e9184860186614ad5565b945090925090506000826001811115612eac57612eac6147e6565b148015612ec157506001600160e01b03198116155b15612ee85733600090815260046020526040902080546001600160a01b0319169055610ca1565b6001826001811115612efc57612efc6147e6565b03612b7a576001600160e01b031981166000908152600560209081526040808320338452909152902080546001600160a01b0319169055610ca1565b60608235830160208181019135908581013586018082019190359060408801358801908101903584838114612f805760405163b4fa3fb360e01b815260040160405180910390fd5b60005b81811015612d0a576000888883818110612f9f57612f9f614768565b90506020020135905060018103612fe357612fdd8d888885818110612fc657612fc6614768565b9050602002810190612fd891906146dc565b612dea565b50613082565b6002810361301857612fdd8d88888581811061300157613001614768565b905060200281019061301391906146dc565b612e13565b6003810361304d57612fdd8d88888581811061303657613036614768565b905060200281019061304891906146dc565b612e34565b60048103612cd657612fdd8d88888581811061306b5761306b614768565b905060200281019061307d91906146dc565b612e80565b50600101612f83565b60405163468721a760e01b81526000906001600160a01b0385169063468721a7906130c19086908590879060019060040161481e565b6020604051808303816000875af11580156130e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061310491906148d5565b9050806107a557604080516001600160a01b038616815260006020820152600080516020614dd9833981519152910160405180910390a150505050565b336000908152602081905260409020546001600160a01b031680156131c75760405163529562a160e01b81523360048201526001600160a01b0384811660248301526044820184905282169063529562a19060640160006040518083038186803b1580156131ae57600080fd5b505afa1580156131c2573d6000803e3d6000fd5b505050505b505050565b60606131d9856000611d65565b156133c5576131ec84600160f81b611d65565b1561320f5782358301602081019035613206338383613952565b92505050610818565b61321a846000611d65565b156132ce5760008036600061322f87876135db565b6040805160018082528183019092529498509296509094509250816020015b606081526020019060019003908161324e5790505094506132a733858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611cbc92505050565b856000815181106132ba576132ba614768565b602002602001018190525050505050610818565b6132e0846001600160f81b0319611d65565b156133aa5760006132f46014828587614452565b6132fd9161447c565b60601c90503660006133128560148189614452565b604080516001808252818301909252929450909250816020015b606081526020019060019003908161332c579050509350613384338484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506139ce92505050565b8460008151811061339757613397614768565b6020026020010181905250505050610818565b83604051632e5bf3f960e21b815260040161067c91906147d1565b6133d385600160f81b611d65565b15613559576133e684600160f81b611d65565b1561340b5782358301602081019035613400338383613a6f565b935061081892505050565b613416846000611d65565b156134a35760008036600061342b87876135db565b6040805160018082528183019092529498509296509094509250816020015b606081526020019060019003908161344a5790505094506132a733858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613b6592505050565b6134b5846001600160f81b0319611d65565b156133aa5760006134c96014828587614452565b6134d29161447c565b60601c90503660006134e78560148189614452565b604080516001808252818301909252929450909250816020015b6060815260200190600190039081613501579050509350613384338484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613c2592505050565b846040516308c3ee0360e11b815260040161067c91906147d1565b6131c7837f000000000000000000000000000000000000000000000000000000000000000084846040516024016135ac929190614b66565b60408051601f198184030181529190526020810180516001600160e01b0316633f707e6b60e01b179052612d51565b60008036816135ed6014828789614452565b6135f69161447c565b60601c9350613609603460148789614452565b61361291614c18565b92506136218560348189614452565b949793965094505050565b6131c7837f00000000000000000000000000000000000000000000000000000000000000008484604051602401613664929190614b66565b60408051601f198184030181529190526020810180516001600160e01b0316632864481160e11b17905261308b565b60405163468721a760e01b81526000906001600160a01b0386169063468721a7906136c890879087908790879060040161481e565b6020604051808303816000875af11580156136e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061370b91906148d5565b905080611ee457604080516001600160a01b038716815260006020820152600080516020614dd9833981519152910160405180910390a15050505050565b600060016001600160a01b038316148015906108185750506001600160a01b0390811660009081526020938452604080822093831682529290935291205416151590565b6000808360018111156137a2576137a26147e6565b1480156137b757506001600160e01b03198216155b156137d75750336000908152600460205260409020546001600160a01b03165b60018360018111156137eb576137eb6147e6565b0361072257506001600160e01b03191660009081526005602090815260408083203384529091529020546001600160a01b0316919050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b8561384b57600061384e565b60015b60ff161717949350505050565b6001600160a01b038116158061387a57506001600160a01b0381166001145b156138a357604051637c84ecfb60e01b81526001600160a01b038316600482015260240161067c565b6001600160a01b0382811660009081526020868152604080832087851684529091529020548116908216146138f657604051637c84ecfb60e01b81526001600160a01b038216600482015260240161067c565b6001600160a01b039081166000908152602085815260408083209584168084528683528184208054968616855297835281842090845282529091208054939092166001600160a01b031993841617909155919091528154169055565b60606139bb847f0000000000000000000000000000000000000000000000000000000000000000858560405160240161398c929190614b66565b60408051601f198184030181529190526020810180516001600160e01b0316636108557360e01b1790526139ce565b8060200190518101906108189190614ce5565b60606000846001600160a01b0316635229073f8560008660016040518563ffffffff1660e01b8152600401613a06949392919061481e565b6000604051808303816000875af1158015613a25573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a4d9190810190614864565b9250905080612e0b57604051632b3f6d1160e21b815260040160405180910390fd5b6060806000613adb867f00000000000000000000000000000000000000000000000000000000000000008787604051602401613aac929190614b66565b60408051601f198184030181529190526020810180516001600160e01b0316639abb6e1760e01b179052613c25565b905080806020019051810190613af19190614d19565b8151919450925060005b81811015613b5a57848181518110613b1557613b15614768565b6020026020010151613b5257604080516001600160a01b038a16815260208101839052600080516020614dd9833981519152910160405180910390a15b600101613afb565b505050935093915050565b60606000856001600160a01b0316635229073f86868660006040518563ffffffff1660e01b8152600401613b9c949392919061481e565b6000604051808303816000875af1158015613bbb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613be39190810190614864565b9250905080611d5c57604080516001600160a01b038816815260006020820152600080516020614dd9833981519152910160405180910390a150949350505050565b60606000846001600160a01b0316635229073f8560008660016040518563ffffffff1660e01b8152600401613c5d949392919061481e565b6000604051808303816000875af1158015613c7c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613ca49190810190614864565b9250905080612e0b57604080516001600160a01b038716815260006020820152600080516020614dd9833981519152910160405180910390a1509392505050565b6001600160a01b0381168114613cfa57600080fd5b50565b8035611c5281613ce5565b60008083601f840112613d1a57600080fd5b5081356001600160401b03811115613d3157600080fd5b60208301915083602082850101111561060e57600080fd5b60008060008060608587031215613d5f57600080fd5b843593506020850135613d7181613ce5565b925060408501356001600160401b03811115613d8c57600080fd5b613d9887828801613d08565b95989497509550505050565b600080600060408486031215613db957600080fd5b8335925060208401356001600160401b03811115613dd657600080fd5b613de286828701613d08565b9497909650939450505050565b60006101208284031215613e0257600080fd5b50919050565b600080600060608486031215613e1d57600080fd5b83356001600160401b03811115613e3357600080fd5b613e3f86828701613def565b9660208601359650604090950135949350505050565b60008083601f840112613e6757600080fd5b5081356001600160401b03811115613e7e57600080fd5b6020830191508360208260051b850101111561060e57600080fd5b600060608284031215613e0257600080fd5b600080600080600080600080600060a08a8c031215613ec957600080fd5b89356001600160401b03811115613edf57600080fd5b613eeb8c828d01613e55565b909a5098505060208a01356001600160401b03811115613f0a57600080fd5b613f168c828d01613e55565b90985096505060408a01356001600160401b03811115613f3557600080fd5b613f418c828d01613e55565b90965094505060608a01356001600160401b03811115613f6057600080fd5b613f6c8c828d01613e55565b90945092505060808a01356001600160401b03811115613f8b57600080fd5b613f978c828d01613e99565b9150509295985092959850929598565b60008060408385031215613fba57600080fd5b82356001600160401b03811115613fd057600080fd5b613fdc85828601613def565b9250506020830135613fed81613ce5565b809150509250929050565b60005b83811015614013578181015183820152602001613ffb565b50506000910152565b60008151808452614034816020860160208601613ff8565b601f01601f19169290920160200192915050565b60808152600061405b608083018761401c565b65ffffffffffff8616602084015265ffffffffffff851660408401528281036060840152614089818561401c565b979650505050505050565b600080604083850312156140a757600080fd5b82356140b281613ce5565b946020939093013593505050565b6040808252835190820181905260009060208501906060840190835b818110156141035783516001600160a01b03168352602093840193909201916001016140dc565b50506001600160a01b039490941660209390930192909252509092915050565b6000806020838503121561413657600080fd5b82356001600160401b0381111561414c57600080fd5b61415885828601613e55565b90969095509350505050565b602081526000610b8f602083018461401c565b6001600160e01b031981168114613cfa57600080fd5b60006020828403121561419f57600080fd5b8135610b8f81614177565b6000602082840312156141bc57600080fd5b5035919050565b6000602082016020835280845180835260408501915060408160051b86010192506020860160005b8281101561421c57603f1987860301845261420785835161401c565b945060209384019391909101906001016141eb565b50929695505050505050565b6000806040838503121561423b57600080fd5b823561424681613ce5565b91506020830135613fed81613ce5565b803560ff81168114611c5257600080fd5b6000806000806060858703121561427d57600080fd5b843561428881613ce5565b935060208501356001600160401b038111156142a357600080fd5b6142af87828801613e55565b90945092506142c2905060408601614256565b905092959194509250565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b038516815283602082015260606040820152600061431e6060830184866142cd565b9695505050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561436657614366614328565b604052919050565b60006001600160401b0382111561438757614387614328565b50601f01601f191660200190565b600082601f8301126143a657600080fd5b81516143b96143b48261436e565b61433e565b8181528460208386010111156143ce57600080fd5b610818826020830160208701613ff8565b6000602082840312156143f157600080fd5b81516001600160401b0381111561440757600080fd5b61081884828501614395565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60006020828403121561444b57600080fd5b5051919050565b6000808585111561446257600080fd5b8386111561446f57600080fd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156144c2576bffffffffffffffffffffffff196bffffffffffffffffffffffff198560140360031b1b82161691505b5092915050565b8481526060602082015260006144e2606083018661401c565b82810360408401526140898185876142cd565b60006020828403121561450757600080fd5b8151610b8f81614177565b6000808335601e1984360301811261452957600080fd5b83016020810192503590506001600160401b0381111561454857600080fd5b80360382131561060e57600080fd5b604081526145786040820161456b85613cfd565b6001600160a01b03169052565b6020830135606082015260006145916040850185614512565b61012060808501526145a8610160850182846142cd565b9150506145b86060860186614512565b848303603f190160a08601526145cf8382846142cd565b608088013560c08781019190915260a089013560e0808901919091529089013561010088015290935061460792508701905086614512565b848303603f190161012086015261461f8382846142cd565b92505050614631610100860186614512565b848303603f19016101408601526146498382846142cd565b93505050508260208301529392505050565b60006020828403121561466d57600080fd5b8135610b8f81613ce5565b6000808335601e1984360301811261468f57600080fd5b8301803591506001600160401b038211156146a957600080fd5b6020019150600581901b360382131561060e57600080fd5b6000602082840312156146d357600080fd5b610b8f82614256565b6000808335601e198436030181126146f357600080fd5b8301803591506001600160401b0382111561470d57600080fd5b60200191503681900382131561060e57600080fd5b80356001600160d01b031981169060068410156144c2576001600160d01b031960069490940360031b84901b1690921692915050565b8183823760009101908152919050565b634e487b7160e01b600052603260045260246000fd5b60008235603e1983360301811261479457600080fd5b9190910192915050565b8381526001600160a01b03831660208201526060604082018190526000906147c89083018461401c565b95945050505050565b6001600160f81b031991909116815260200190565b634e487b7160e01b600052602160045260246000fd5b6002811061481a57634e487b7160e01b600052602160045260246000fd5b9052565b60018060a01b0385168152836020820152608060408201526000614845608083018561401c565b90506147c860608301846147fc565b80518015158114611c5257600080fd5b6000806040838503121561487757600080fd5b61488083614854565b915060208301516001600160401b0381111561489b57600080fd5b6148a785828601614395565b9150509250929050565b6001600160a01b03831681526040602082018190526000906108189083018461401c565b6000602082840312156148e757600080fd5b610b8f82614854565b803560028110611c5257600080fd5b6000806040838503121561491257600080fd5b61491b836148f0565b91506020830135613fed81614177565b82815260008251614943816020850160208701613ff8565b919091016020019392505050565b83815260606020820152600061496a606083018561401c565b828103604084015261431e818561401c565b60ff84168152604060208201819052810182905260008360608301825b858110156149c95782356149ac81613ce5565b6001600160a01b0316825260209283019290910190600101614999565b509695505050505050565b634e487b7160e01b600052601160045260246000fd5b6000600182016149fc576149fc6149d4565b5060010190565b81810381811115610722576107226149d4565b600082601f830112614a2757600080fd5b8135614a356143b48261436e565b818152846020838601011115614a4a57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215614a7c57600080fd5b8335614a8781614177565b925060208401356001600160f81b031981168114614aa457600080fd5b915060408401356001600160401b03811115614abf57600080fd5b614acb86828701614a16565b9150509250925092565b600080600060608486031215614aea57600080fd5b614af3846148f0565b92506020840135614aa481614177565b60008060408385031215614b1657600080fd5b8235614b2181613ce5565b915060208301356001600160401b03811115614b3c57600080fd5b6148a785828601614a16565b60008060408385031215614b5b57600080fd5b8235614b2181614177565b6020808252810182905260006040600584901b830181019083018583605e1936839003015b87821015614c0b57868503603f190184528235818112614baa57600080fd5b89018035614bb781613ce5565b6001600160a01b0316865260208181013590870152614bd96040820182614512565b915060606040880152614bf06060880183836142cd565b96505050602083019250602084019350600182019150614b8b565b5092979650505050505050565b8035602083101561072257600019602084900360031b1b1692915050565b60006001600160401b03821115614c4f57614c4f614328565b5060051b60200190565b600082601f830112614c6a57600080fd5b8151614c786143b482614c36565b8082825260208201915060208360051b860101925085831115614c9a57600080fd5b602085015b83811015614cdb5780516001600160401b03811115614cbd57600080fd5b614ccc886020838a0101614395565b84525060209283019201614c9f565b5095945050505050565b600060208284031215614cf757600080fd5b81516001600160401b03811115614d0d57600080fd5b61081884828501614c59565b60008060408385031215614d2c57600080fd5b82516001600160401b03811115614d4257600080fd5b8301601f81018513614d5357600080fd5b8051614d616143b482614c36565b8082825260208201915060208360051b850101925087831115614d8357600080fd5b6020840193505b82841015614dac57614d9b84614854565b825260209384019390910190614d8a565b8095505050505060208301516001600160401b03811115614dcc57600080fd5b6148a785828601614c5956feb8bc84bd77f5eb08210b8eb20fd63b3ec6a7992d277ab94663bae0e066f792aca2646970667358221220ea7603497be0a0e1ddc106666c75af038c8db18b0f9143f6418b0e8b232c109164736f6c634300081a00336080604052348015600f57600080fd5b506109c28061001f6000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80636a2216571161005b5780636a221657146100d357806378272525146100e65780639517e29f146100f95780639abb6e171461010c57600080fd5b80633f707e6b1461008257806350c890221461009757806361085573146100aa575b600080fd5b6100956100903660046105ba565b61012d565b005b6100956100a53660046105ba565b610197565b6100bd6100b83660046105ba565b6101fc565b6040516100ca91906106c4565b60405180910390f35b6100956100e1366004610710565b6102be565b6100956100f43660046107da565b6102e1565b6100956101073660046107da565b61038a565b61011f61011a3660046105ba565b610429565b6040516100ca929190610864565b8060005b81811015610191573684848381811061014c5761014c6108be565b905060200281019061015e91906108d4565b905061018761017060208301836108f4565b6020830135610182604085018561090f565b610553565b5050600101610131565b50505050565b8060005b8181101561019157368484838181106101b6576101b66108be565b90506020028101906101c891906108d4565b90506101f16101da60208301836108f4565b60208301356101ec604085018561090f565b610589565b50505060010161019b565b6060818067ffffffffffffffff811115610218576102186106fa565b60405190808252806020026020018201604052801561024b57816020015b60608152602001906001900390816102365790505b50915060005b818110156102b6573685858381811061026c5761026c6108be565b905060200281019061027e91906108d4565b905061029061017060208301836108f4565b8483815181106102a2576102a26108be565b602090810291909101015250600101610251565b505092915050565b604051600080835160208501865afa3d6000833e80156102dc573d82f35b503d81fd5b604051638a91b0e360e01b81526001600160a01b03841690638a91b0e39061030f908590859060040161095d565b600060405180830381600087803b15801561032957600080fd5b505af115801561033d573d6000803e3d6000fd5b5050604080518781526001600160a01b03871660208201527f341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e93500190505b60405180910390a150505050565b6040516306d61fe760e41b81526001600160a01b03841690636d61fe70906103b8908590859060040161095d565b600060405180830381600087803b1580156103d257600080fd5b505af11580156103e6573d6000803e3d6000fd5b5050604080518781526001600160a01b03871660208201527fd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123935001905061037c565b606080828067ffffffffffffffff811115610446576104466106fa565b60405190808252806020026020018201604052801561047957816020015b60608152602001906001900390816104645790505b5091508067ffffffffffffffff811115610495576104956106fa565b6040519080825280602002602001820160405280156104be578160200160208202803683370190505b50925060005b8181101561054a57368686838181106104df576104df6108be565b90506020028101906104f191906108d4565b90506105036101da60208301836108f4565b868481518110610515576105156108be565b6020026020010186858151811061052e5761052e6108be565b60209081029190910101919091529015159052506001016104c4565b50509250929050565b60405181838237600038838387895af1610570573d6000823e3d81fd5b3d8152602081013d6000823e3d01604052949350505050565b604051600090828482376000388483888a5af191503d8152602081013d6000823e3d81016040525094509492505050565b600080602083850312156105cd57600080fd5b823567ffffffffffffffff8111156105e457600080fd5b8301601f810185136105f557600080fd5b803567ffffffffffffffff81111561060c57600080fd5b8560208260051b840101111561062157600080fd5b6020919091019590945092505050565b600082825180855260208501945060208160051b8301016020850160005b838110156106b857848303601f190188528151805180855260005b818110156106865760208184018101518783018201520161066a565b506000602082870101526020601f19601f8301168601019450505060208201915060208801975060018101905061064f565b50909695505050505050565b6020815260006106d76020830184610631565b9392505050565b80356001600160a01b03811681146106f557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072357600080fd5b61072c836106de565b9150602083013567ffffffffffffffff81111561074857600080fd5b8301601f8101851361075957600080fd5b803567ffffffffffffffff811115610773576107736106fa565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156107a2576107a26106fa565b6040528181528282016020018710156107ba57600080fd5b816020840160208301376000602083830101528093505050509250929050565b600080600080606085870312156107f057600080fd5b84359350610800602086016106de565b9250604085013567ffffffffffffffff81111561081c57600080fd5b8501601f8101871361082d57600080fd5b803567ffffffffffffffff81111561084457600080fd5b87602082840101111561085657600080fd5b949793965060200194505050565b6040808252835190820181905260009060208501906060840190835b818110156108a05783511515835260209384019390920191600101610880565b505083810360208501526108b48186610631565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b60008235605e198336030181126108ea57600080fd5b9190910192915050565b60006020828403121561090657600080fd5b6106d7826106de565b6000808335601e1984360301811261092657600080fd5b83018035915067ffffffffffffffff82111561094157600080fd5b60200191503681900382131561095657600080fd5b9250929050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea26469706673582212205c0679bac7989901111b6824de732603e322da5b9b75ee077344853294d8b7b664736f6c634300081a0033"; + bytes constant SAFE7579_LAUNCHPAD_BYTECODE = + hex"60e060405234801561001057600080fd5b50604051612dea380380612dea83398101604081905261002f91610089565b6001600160a01b03821661005657604051632039d3c960e01b815260040160405180910390fd5b306080526001600160a01b0391821660a0521660c0526100c3565b6001600160a01b038116811461008657600080fd5b50565b6000806040838503121561009c57600080fd5b82516100a781610071565b60208401519092506100b881610071565b809150509250929050565b60805160a05160c051612cc161012960003960008181610159015281816104900152610fc60152600081816101aa015281816105be015281816110a701526113ea01526000818160f6015281816105690152818161099301526111100152612cc16000f3fe6080604052600436106100ec5760003560e01c8063663c87d81161008a578063d78343d911610059578063d78343d914610348578063d9ed0e8f14610368578063f2dc691d14610388578063f698da25146103a857600080fd5b8063663c87d81461028c578063928107f9146102ac5780639cfd7cff146102cc578063d03c79141461031857600080fd5b806319822f7c116100c657806319822f7c146101ec5780633c9de1b81461021a5780634fff40e11461023c57806355d559f41461025c57600080fd5b806306433b1b14610147578063137e051e1461019857806315cca638146101cc57600080fd5b36610142576000547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03908116911614610140576040516308e3edd160e41b815260040160405180910390fd5b005b600080fd5b34801561015357600080fd5b5061017b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101a457600080fd5b5061017b7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101d857600080fd5b506101406101e7366004611ab5565b6103bd565b3480156101f857600080fd5b5061020c610207366004611bc2565b610563565b60405190815260200161018f565b34801561022657600080fd5b50600080516020612c6c8339815191525461020c565b34801561024857600080fd5b50610140610257366004611c0f565b61098e565b34801561026857600080fd5b5061027c610277366004611c99565b610abe565b60405161018f9493929190611d3a565b34801561029857600080fd5b5061017b6102a7366004611e94565b610d1b565b3480156102b857600080fd5b5061020c6102c7366004612094565b610df5565b3480156102d857600080fd5b50604080518082018252601a81527f7268696e6573746f6e652e73616665373537392e76312e302e300000000000006020820152905161018f91906121c2565b34801561032457600080fd5b506103386103333660046121dc565b610e47565b604051901515815260200161018f565b34801561035457600080fd5b506101406103633660046121f5565b610ef0565b34801561037457600080fd5b50610140610383366004612321565b61109c565b34801561039457600080fd5b506103386103a33660046121dc565b611324565b3480156103b457600080fd5b5061020c611373565b3330146103dd57604051630a57d61d60e01b815260040160405180910390fd5b60405163610b592560e01b81526001600160a01b038b166004820152309063610b592590602401600060405180830381600087803b15801561041e57600080fd5b505af1158015610432573d6000803e3d6000fd5b50506040805160008082526020820190925230935063540fb4f992509061047c565b6040805180820190915260008152606060208201528152602001906001900390816104545790505b508b8b8b8b8b8b60405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018d8d8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060ff8c166020909101526040516001600160e01b031960e08b901b16815261052598979695949392919060040161255c565b600060405180830381600087803b15801561053f57600080fd5b505af1158015610553573d6000803e3d6000fd5b5050505050505050505050505050565b600080547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169116146105b3576040516308e3edd160e41b815260040160405180910390fd5b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105fc57604051632039d3c960e01b815260040160405180910390fd5b61060960608501856125cf565b61061891600491600091612615565b6106219161263f565b6001600160e01b03191663d9ed0e8f60e01b146106515760405163c3d40f7760e01b815260040160405180910390fd5b600061066060608601866125cf565b61066e916004908290612615565b81019061067b9190612094565b9050610693600080516020612c6c8339815191525490565b61069c82610df5565b146106ba5760405163278328b160e21b815260040160405180910390fd5b600080866020013590508060601c915060008360a001516001600160a01b03168460c001516040516024016106ef9190612677565b60408051601f19818403018152918152602080830180516001600160e01b0316633cd56b0760e11b1790529051610729929133910161268a565b60408051601f1981840301815290829052610743916126bc565b6000604051808303816000865af19150503d8060008114610780576040519150601f19603f3d011682016040523d82523d6000602084013e610785565b606091505b50509050806107a75760405163c3d40f7760e01b815260040160405180910390fd5b60c084015151600090815b818110156108c95760008760c0015182815181106107d2576107d26126d8565b6020026020010151600001519050806001600160a01b0316636d61fe708960c001518481518110610805576108056126d8565b6020026020010151602001516040518263ffffffff1660e01b815260040161082d91906121c2565b600060405180830381600087803b15801561084757600080fd5b505af115801561085b573d6000803e3d6000fd5b505060408051600181526001600160a01b03851660208201527fd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123935001905060405180910390a1866001600160a01b0316816001600160a01b0316036108c057600193505b506001016107b2565b50811561094857604051639700320360e01b81526001600160a01b038616906397003203906108fe908d908d906004016127ce565b6020604051808303816000875af115801561091d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094191906127f0565b965061096f565b6000806000610957898e6113cc565b92509250925061096983158383611542565b99505050505b8715610981576000806000808b335af1505b5050505050509392505050565b6000547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169116146109dd576040516308e3edd160e41b815260040160405180910390fd5b60006109f5600080516020612c6c8339815191525490565b14610a135760405163d4d496e560e01b815260040160405180910390fd5b610a2984600080516020612c6c83398151915255565b6001600160a01b03831615610ab8576000836001600160a01b03168383604051610a54929190612809565b600060405180830381855af49150503d8060008114610a8f576040519150601f19603f3d011682016040523d82523d6000602084013e610a94565b606091505b5050905080610ab657604051631f57fed560e31b815260040160405180910390fd5b505b50505050565b6060600080823682610ad46101008901896125cf565b9092509050610ae7600660008385612615565b610af091612819565b60d01c9450610b03600c60068385612615565b610b0c91612819565b60d01c9350610b1e81600c8185612615565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516101c081019091527fc03dfc11d8b10bf9cf703d558958c8c42777f785d998c62060d85a4f0ef6ea7f815294975095509293505060208084019250610b9a91508a018a61284f565b6001600160a01b0316815260200188602001358152602001888060400190610bc291906125cf565b604051610bd0929190612809565b6040519081900390208152602001610beb60608a018a6125cf565b604051610bf9929190612809565b60405180910390208152602001610c0f8961157a565b6001600160801b03168152602001610c2689611590565b6001600160801b031681526020018860a001358152602001610c47896115a5565b6001600160801b03168152602001610c5e896115b4565b6001600160801b03168152602001610c7960e08a018a6125cf565b604051610c87929190612809565b6040805191829003909120825265ffffffffffff80881660208401528616908201526001600160a01b0388166060909101526101c08120909150601960f81b600160f81b610cd3611373565b6040516001600160f81b031993841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529550505092959194509250565b6000818051906020012083604051602001610d40929190918252602082015260400190565b60405160208183030381529060405280519060200120925060ff60f81b858486896001600160a01b0316604051602001610d7b92919061286c565b60405160208183030381529060405280519060200120604051602001610dd394939291906001600160f81b031994909416845260609290921b6001600160601b03191660018401526015830152603582015260550190565b60408051601f1981840301815291905280516020909101209695505050505050565b80516020808301516040808501516060860151608087015160a088015160c08901519451600098610e2a98909796910161288e565b604051602081830303815290604052805190602001209050919050565b600081600881901b6001600160f81b03198216600160f81b03610e6d5760019250610ea9565b6001600160f81b03198216610e855760019250610ea9565b6001600160f81b031980831603610e9f5760019250610ea9565b5060009392505050565b828015610ebe57506001600160f81b03198116155b15610eca575050919050565b828015610ee457506001600160f81b03198116600160f81b145b15610e9f575050919050565b60405163610b592560e01b81526001600160a01b038d166004820152309063610b592590602401600060405180830381600087803b158015610f3157600080fd5b505af1158015610f45573d6000803e3d6000fd5b505060405163f08a032360e01b81526001600160a01b038f16600482015230925063f08a03239150602401600060405180830381600087803b158015610f8a57600080fd5b505af1158015610f9e573d6000803e3d6000fd5b50505050306001600160a01b031663540fb4f98c8c8c8c8c8c8c8c60405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e8e8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050509082525060ff8d166020909101526040516001600160e01b031960e08c901b16815261105c9998979695949392919060040161290b565b600060405180830381600087803b15801561107657600080fd5b505af115801561108a573d6000803e3d6000fd5b50505050505050505050505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110e557604051632039d3c960e01b815260040160405180910390fd5b6110f2602082018261284f565b600080546001600160a01b0319166001600160a01b039283161790557f000000000000000000000000000000000000000000000000000000000000000016611140608083016060840161284f565b6001600160a01b03161461116757604051633007073760e01b815260040160405180910390fd5b6302b994c760e31b61117c60808301836125cf565b61118b91600491600091612615565b6111949161263f565b6001600160e01b031916146111bc57604051633007073760e01b815260040160405180910390fd5b3063b63e800d6111cf6020840184612980565b60408501356111e4608087016060880161284f565b6111f160808801886125cf565b61120160c08a0160a08b0161284f565b60008060006040518b63ffffffff1660e01b815260040161122b9a999897969594939291906129c9565b600060405180830381600087803b15801561124557600080fd5b505af1158015611259573d6000803e3d6000fd5b50506000600080516020612c6c83398151915255506112759050565b60008061128860c0840160a0850161284f565b6001600160a01b031661129e60e08501856125cf565b306040516020016112b193929190612a80565b60408051601f19818403018152908290526112cb916126bc565b6000604051808303816000865af19150503d8060008114611308576040519150601f19603f3d011682016040523d82523d6000602084013e61130d565b606091505b50915091508161131f57805160208201fd5b505050565b60006001820361133657506001919050565b6002820361134657506001919050565b6003820361135657506001919050565b6004820361136657506001919050565b506000919050565b919050565b604080517f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692186020820152469181019190915230606082015260009060800160405160208183030381529060405280519060200120905090565b60008060006060808660a001516001600160a01b03166355d559f4877f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401611426929190612aa1565b600060405180830381865afa158015611443573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261146b9190810190612b2e565b8351602085012060408c01519298509296509294509192509060009061149490839085906115c9565b905061149f816118c1565b60208901516114ad816118c1565b6114b6816118cd565b80516000805b8281101561152e5760006114f28583815181106114db576114db6126d8565b6020026020010151876118d690919063ffffffff16565b5090508015611525578261150581612bcc565b9350508d6040015183106115255760019b5050505050505050505061153b565b506001016114bc565b5060009950505050505050505b9250925092565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b8561156a57600061156d565b60015b60ff161717949350505050565b600061158a826080013560801c90565b92915050565b60006001600160801b0360808301351661158a565b600060c082013560801c61158a565b60006001600160801b0360c08301351661158a565b606060006115d8836041612be5565b8451909150836001600160401b038111156115f5576115f5611d86565b60405190808252806020026020018201604052801561161e578160200160208202803683370190505b5092508181101561164257604051638baa579f60e01b815260040160405180910390fd5b60005b848110156118b7576000806000806116758a86604102016020810151604082015160609092015160001a92909190565b9250925092508260ff16600003611816579092508290611696896041612be5565b8110156116cc576040516338a245ff60e11b81526004810182905260006024820181905260448201526064015b60405180910390fd5b856116d8826020612bfc565b1115611708576040516338a245ff60e11b81526004810182905260006024820152604481018790526064016116c3565b6020818b018101519087908290611720908590612bfc565b61172a9190612bfc565b111561175a576040516338a245ff60e11b81526004810183905260248101829052604481018890526064016116c3565b60606020838d01019050631626ba7e60e01b6001600160e01b031916866001600160a01b0316631626ba7e8f846040518363ffffffff1660e01b81526004016117a4929190612c0f565b602060405180830381865afa1580156117c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e59190612c28565b6001600160e01b0319161461180f578060405163605d348960e01b81526004016116c391906121c2565b505061187c565b601e8360ff16111561186d576118666118548c6020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c60042090565b61185f600486612c52565b84846118f9565b935061187c565b6118798b8484846118f9565b93505b8388868151811061188f5761188f6126d8565b6001600160a01b03909216602092830291909101909101525050600190920191506116459050565b5050509392505050565b6118ca81611937565b50565b6118ca8161198c565b6000806118ee84846001600160a01b031660006119d5565b909590945092505050565b60006040518560005260ff85166020528360405282606052602060406080600060015afa5060006060523d6060185191508060405250949350505050565b8051600082528060051b82016020601f198185015b8201838111611984578051828201805182811161196b5750505061194c565b5b818601528301805182811161196c575084015261194c565b505050915250565b60028151106118ca576020810160408201600183510160051b83015b81518351146119bc57602083019250815183525b6020820191508082036119a857505081900360051c9052565b60008060001960018651600087870197505b81830160011c94508460051b8901518701905087811482841117611a2157808811611a165783850191506119e7565b6001850192506119e7565b84151597148716989290930190950295509350505050565b6001600160a01b03811681146118ca57600080fd5b803561136e81611a39565b60008083601f840112611a6b57600080fd5b5081356001600160401b03811115611a8257600080fd5b6020830191508360208260051b8501011115611a9d57600080fd5b9250929050565b803560ff8116811461136e57600080fd5b60008060008060008060008060008060c08b8d031215611ad457600080fd5b611add8b611a4e565b995060208b01356001600160401b03811115611af857600080fd5b611b048d828e01611a59565b909a5098505060408b01356001600160401b03811115611b2357600080fd5b611b2f8d828e01611a59565b90985096505060608b01356001600160401b03811115611b4e57600080fd5b611b5a8d828e01611a59565b90965094505060808b01356001600160401b03811115611b7957600080fd5b611b858d828e01611a59565b9094509250611b98905060a08c01611aa4565b90509295989b9194979a5092959850565b60006101208284031215611bbc57600080fd5b50919050565b600080600060608486031215611bd757600080fd5b83356001600160401b03811115611bed57600080fd5b611bf986828701611ba9565b9660208601359650604090950135949350505050565b60008060008060608587031215611c2557600080fd5b843593506020850135611c3781611a39565b925060408501356001600160401b03811115611c5257600080fd5b8501601f81018713611c6357600080fd5b80356001600160401b03811115611c7957600080fd5b876020828401011115611c8b57600080fd5b949793965060200194505050565b60008060408385031215611cac57600080fd5b82356001600160401b03811115611cc257600080fd5b611cce85828601611ba9565b9250506020830135611cdf81611a39565b809150509250929050565b60005b83811015611d05578181015183820152602001611ced565b50506000910152565b60008151808452611d26816020860160208601611cea565b601f01601f19169290920160200192915050565b608081526000611d4d6080830187611d0e565b65ffffffffffff8616602084015265ffffffffffff851660408401528281036060840152611d7b8185611d0e565b979650505050505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611dbe57611dbe611d86565b60405290565b60405161010081016001600160401b0381118282101715611dbe57611dbe611d86565b604051601f8201601f191681016001600160401b0381118282101715611e0f57611e0f611d86565b604052919050565b60006001600160401b03821115611e3057611e30611d86565b50601f01601f191660200190565b600082601f830112611e4f57600080fd5b8135611e62611e5d82611e17565b611de7565b818152846020838601011115611e7757600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215611eac57600080fd5b8535611eb781611a39565b94506020860135611ec781611a39565b935060408601356001600160401b03811115611ee257600080fd5b611eee88828901611e3e565b9350506060860135915060808601356001600160401b03811115611f1157600080fd5b611f1d88828901611e3e565b9150509295509295909350565b60006001600160401b03821115611f4357611f43611d86565b5060051b60200190565b600082601f830112611f5e57600080fd5b8135611f6c611e5d82611f2a565b8082825260208201915060208360051b860101925085831115611f8e57600080fd5b602085015b83811015611fb4578035611fa681611a39565b835260209283019201611f93565b5095945050505050565b600082601f830112611fcf57600080fd5b8135611fdd611e5d82611f2a565b8082825260208201915060208360051b860101925085831115611fff57600080fd5b602085015b83811015611fb45780356001600160401b0381111561202257600080fd5b86016040818903601f1901121561203857600080fd5b612040611d9c565b602082013561204e81611a39565b815260408201356001600160401b0381111561206957600080fd5b6120788a602083860101611e3e565b6020830152508085525050602083019250602081019050612004565b6000602082840312156120a657600080fd5b81356001600160401b038111156120bc57600080fd5b820161010081850312156120cf57600080fd5b6120d7611dc4565b6120e082611a4e565b815260208201356001600160401b038111156120fb57600080fd5b61210786828501611f4d565b6020830152506040828101359082015261212360608301611a4e565b606082015260808201356001600160401b0381111561214157600080fd5b61214d86828501611e3e565b60808301525061215f60a08301611a4e565b60a082015260c08201356001600160401b0381111561217d57600080fd5b61218986828501611fbe565b60c08301525060e08201356001600160401b038111156121a857600080fd5b6121b486828501611e3e565b60e083015250949350505050565b6020815260006121d56020830184611d0e565b9392505050565b6000602082840312156121ee57600080fd5b5035919050565b60008060008060008060008060008060008060e08d8f03121561221757600080fd5b6122208d611a4e565b9b506001600160401b0360208e0135111561223a57600080fd5b61224a8e60208f01358f01611a59565b909b5099506001600160401b0360408e0135111561226757600080fd5b6122778e60408f01358f01611a59565b90995097506001600160401b0360608e0135111561229457600080fd5b6122a48e60608f01358f01611a59565b90975095506001600160401b0360808e013511156122c157600080fd5b6122d18e60808f01358f01611a59565b90955093506001600160401b0360a08e013511156122ee57600080fd5b6122fe8e60a08f01358f01611a59565b909350915061230f60c08e01611aa4565b90509295989b509295989b509295989b565b60006020828403121561233357600080fd5b81356001600160401b0381111561234957600080fd5b820161010081850312156121d557600080fd5b600082825180855260208501945060208160051b8301016020850160005b838110156123cc57848303601f19018852815180516001600160a01b031684526020908101516040918501829052906123b590850182611d0e565b6020998a019990945092909201915060010161237a565b50909695505050505050565b6000808335601e198436030181126123ef57600080fd5b83016020810192503590506001600160401b0381111561240e57600080fd5b803603821315611a9d57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008383855260208501945060208460051b8201018360005b868110156123cc57838303601f19018852813536879003603e1901811261248557600080fd5b8601803561249281611a39565b6001600160a01b031684526124aa60208201826123d8565b9150604060208601526124c160408601838361241d565b60209a8b019a9095509390930192505060010161245f565b600081518084526020840193506020830160005b828110156125145781516001600160a01b03168652602095860195909101906001016124ed565b5093949350505050565b60018060a01b038151168252600060208201516060602085015261254560608501826124d9565b60409384015160ff16949093019390935250919050565b60a08152600061256f60a083018b61235c565b8281036020840152612582818a8c612446565b9050828103604084015261259781888a612446565b905082810360608401526125ac818688612446565b905082810360808401526125c0818561251e565b9b9a5050505050505050505050565b6000808335601e198436030181126125e657600080fd5b8301803591506001600160401b0382111561260057600080fd5b602001915036819003821315611a9d57600080fd5b6000808585111561262557600080fd5b8386111561263257600080fd5b5050820193919092039150565b80356001600160e01b03198116906004841015612670576001600160e01b0319600485900360031b81901b82161691505b5092915050565b6020815260006121d5602083018461235c565b6000835161269c818460208801611cea565b60609390931b6001600160601b0319169190920190815260140192915050565b600082516126ce818460208701611cea565b9190910192915050565b634e487b7160e01b600052603260045260246000fd5b612708826126fb83611a4e565b6001600160a01b03169052565b60208181013590830152600061272160408301836123d8565b61012060408601526127386101208601828461241d565b91505061274860608401846123d8565b858303606087015261275b83828461241d565b6080868101359088015260a0808701359088015260c08087013590880152925061278b91505060e08401846123d8565b85830360e087015261279e83828461241d565b925050506127b06101008401846123d8565b8583036101008701526127c483828461241d565b9695505050505050565b6040815260006127e160408301856126ee565b90508260208301529392505050565b60006020828403121561280257600080fd5b5051919050565b8183823760009101908152919050565b80356001600160d01b03198116906006841015612670576001600160d01b031960069490940360031b84901b1690921692915050565b60006020828403121561286157600080fd5b81356121d581611a39565b6000835161287e818460208801611cea565b9190910191825250602001919050565b6001600160a01b038816815260e0602082018190526000906128b2908301896124d9565b604083018890526001600160a01b038716606084015282810360808401526128da8187611d0e565b6001600160a01b03861660a085015283810360c085015290506128fd818561235c565b9a9950505050505050505050565b60a08152600061291f60a083018b8d612446565b8281036020840152612932818a8c612446565b9050828103604084015261294781888a612446565b9050828103606084015261295c818688612446565b90508281036080840152612970818561251e565b9c9b505050505050505050505050565b6000808335601e1984360301811261299757600080fd5b8301803591506001600160401b038211156129b157600080fd5b6020019150600581901b3603821315611a9d57600080fd5b61010080825281018a905260008b6101208301825b8d811015612a0e5782356129f181611a39565b6001600160a01b03168252602092830192909101906001016129de565b508b6020850152612a2a604085018c6001600160a01b03169052565b8381036060850152612a3d818a8c61241d565b92505050612a5660808301876001600160a01b03169052565b6001600160a01b03851660a08301528360c08301526125c060e08301846001600160a01b03169052565b8284823760609190911b6001600160601b0319169101908152601401919050565b604081526000612ab460408301856126ee565b905060018060a01b03831660208301529392505050565b600082601f830112612adc57600080fd5b8151612aea611e5d82611e17565b818152846020838601011115612aff57600080fd5b612b10826020830160208701611cea565b949350505050565b805165ffffffffffff8116811461136e57600080fd5b60008060008060808587031215612b4457600080fd5b84516001600160401b03811115612b5a57600080fd5b612b6687828801612acb565b945050612b7560208601612b18565b9250612b8360408601612b18565b915060608501516001600160401b03811115612b9e57600080fd5b612baa87828801612acb565b91505092959194509250565b634e487b7160e01b600052601160045260246000fd5b600060018201612bde57612bde612bb6565b5060010190565b808202811582820484141761158a5761158a612bb6565b8082018082111561158a5761158a612bb6565b828152604060208201526000612b106040830184611d0e565b600060208284031215612c3a57600080fd5b81516001600160e01b0319811681146121d557600080fd5b60ff828116828216039081111561158a5761158a612bb656fe982e06ee6a56dfc0f1ac189a5d23506361ca0a3ce45a9c7b8d33d65d43746a24a2646970667358221220b8570cdd622e1fbbf9414238ac24ec7629c0bf87595f396efe2bec7415eff9ce64736f6c634300081a0033"; +} diff --git a/src/test/precompiles/SmartSessions.sol b/src/test/precompiles/SmartSessions.sol index 4b612eaf..4ced16a7 100644 --- a/src/test/precompiles/SmartSessions.sol +++ b/src/test/precompiles/SmartSessions.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable max-line-length */ import "../utils/Vm.sol"; diff --git a/src/test/predeploy/EntryPoint.sol b/src/test/predeploy/EntryPoint.sol index e3fc9541..719a10db 100644 --- a/src/test/predeploy/EntryPoint.sol +++ b/src/test/predeploy/EntryPoint.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable max-line-length */ import "../utils/Vm.sol"; diff --git a/src/test/predeploy/MockFactory.sol b/src/test/predeploy/MockFactory.sol index b6f227b0..27416d51 100644 --- a/src/test/predeploy/MockFactory.sol +++ b/src/test/predeploy/MockFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-enable no-unused-import */ import { MockUniswap, ISwapRouter } from "../../integrations/uniswap/MockUniswap.sol"; diff --git a/src/test/predeploy/Registry.sol b/src/test/predeploy/Registry.sol index 35688aa9..970485a3 100644 --- a/src/test/predeploy/Registry.sol +++ b/src/test/predeploy/Registry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { IERC7484 } from "src/Interfaces.sol"; import { MockRegistry } from "src/Mocks.sol"; diff --git a/src/test/utils/ERC4337Helpers.sol b/src/test/utils/ERC4337Helpers.sol index 4545336d..216d3372 100644 --- a/src/test/utils/ERC4337Helpers.sol +++ b/src/test/utils/ERC4337Helpers.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { PackedUserOperation, diff --git a/src/test/utils/Log.sol b/src/test/utils/Log.sol index 172607fb..080e7691 100644 --- a/src/test/utils/Log.sol +++ b/src/test/utils/Log.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; library ModuleKitLogs { /* solhint-disable event-name-camelcase */ diff --git a/src/test/utils/Storage.sol b/src/test/utils/Storage.sol index 6a171b75..945caaa7 100644 --- a/src/test/utils/Storage.sol +++ b/src/test/utils/Storage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /*////////////////////////////////////////////////////////////// EXPECT REVERT diff --git a/src/test/utils/Vm.sol b/src/test/utils/Vm.sol index a9bb5775..8478a585 100644 --- a/src/test/utils/Vm.sol +++ b/src/test/utils/Vm.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { Vm, VmSafe } from "forge-std/Vm.sol"; diff --git a/src/test/utils/gas/GasCalculations.sol b/src/test/utils/gas/GasCalculations.sol index 5f7301d3..0c11e107 100644 --- a/src/test/utils/gas/GasCalculations.sol +++ b/src/test/utils/gas/GasCalculations.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { UD60x18, ud, intoUint256 } from "@prb/math/UD60x18.sol"; import { PRBMathCastingUint256 } from "@prb/math/casting/Uint256.sol"; diff --git a/src/test/utils/gas/GasParser.sol b/src/test/utils/gas/GasParser.sol index a1600f3f..9a552548 100644 --- a/src/test/utils/gas/GasParser.sol +++ b/src/test/utils/gas/GasParser.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import "../Vm.sol"; import "./GasCalculations.sol"; diff --git a/src/test/utils/gas/UserOpGasLog.sol b/src/test/utils/gas/UserOpGasLog.sol index 49f0a0d8..98eeeae8 100644 --- a/src/test/utils/gas/UserOpGasLog.sol +++ b/src/test/utils/gas/UserOpGasLog.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { PackedUserOperation, diff --git a/src/trampolines/ERC7579.sol b/src/trampolines/ERC7579.sol deleted file mode 100644 index d1c1b002..00000000 --- a/src/trampolines/ERC7579.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; - -import { ModuleManager } from "erc7579/core/ModuleManager.sol"; -import { HookManager, IHook } from "erc7579/core/HookManager.sol"; - -contract RhinestoneBootstrap is ModuleManager, HookManager { - address internal constant REGISTRY = 0xe0cde9239d16bEf05e62Bbf7aA93e420f464c826; - address internal constant REGISTRY_HOOK = 0x34dEDac925C00d63bD91800Ff821e535fE59d6F5; - - function init() external { - // add Registry Hook - _setHook(REGISTRY_HOOK); - IHook(REGISTRY_HOOK).onInstall(abi.encodePacked(REGISTRY)); - } -} diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index a639d2e8..4bd78193 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import "forge-std/Test.sol"; import "src/ModuleKit.sol"; diff --git a/test/Diff.t.sol b/test/Diff.t.sol index e89d005a..5f2f187c 100644 --- a/test/Diff.t.sol +++ b/test/Diff.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import "src/ModuleKit.sol"; import "./BaseTest.t.sol"; @@ -9,15 +9,16 @@ import { MODULE_TYPE_EXECUTOR, MODULE_TYPE_HOOK, MODULE_TYPE_FALLBACK, - CALLTYPE_SINGLE -} from "src/external/ERC7579.sol"; + VALIDATION_SUCCESS, + VALIDATION_FAILED +} from "src/accounts/common/interfaces/IERC7579Modules.sol"; +import { CALLTYPE_SINGLE } from "src/accounts/common/lib/ModeLib.sol"; import { getAccountType, InstalledModule } from "src/test/utils/Storage.sol"; import { toString } from "src/test/utils/Vm.sol"; import { MockValidatorFalse } from "test/mocks/MockValidatorFalse.sol"; import { MockK1Validator, VALIDATION_SUCCESS } from "test/mocks/MockK1Validator.sol"; import { MockK1ValidatorUncompliantUninstall } from "test/mocks/MockK1ValidatorUncompliantUninstall.sol"; -import { VALIDATION_SUCCESS, VALIDATION_FAILED } from "erc7579/interfaces/IERC7579Module.sol"; import { VmSafe } from "src/test/utils/Vm.sol"; contract ERC7579DifferentialModuleKitLibTest is BaseTest { @@ -169,8 +170,8 @@ contract ERC7579DifferentialModuleKitLibTest is BaseTest { revertSelector = abi.encodePacked(bytes4(0xf21e646b)); revertMessage = abi.encodePacked(bytes4(0xf21e646b)); } else { - revertSelector = abi.encodePacked(bytes4(0x08c379a0)); - revertMessage = abi.encodeWithSignature("Error(string)", "MockTarget: not authorized"); + revertSelector = abi.encodePacked(bytes4(0x82b42900)); + revertMessage = abi.encodePacked(bytes4(0x82b42900)); } // Revert selector diff --git a/test/RegistryDeployer.t.sol b/test/RegistryDeployer.t.sol index ade2f773..02a90e4e 100644 --- a/test/RegistryDeployer.t.sol +++ b/test/RegistryDeployer.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import "./BaseTest.t.sol"; import { diff --git a/test/integrations/ExampleFactory.t.sol b/test/integrations/ExampleFactory.t.sol index eb8ce3fb..6d24fa8a 100644 --- a/test/integrations/ExampleFactory.t.sol +++ b/test/integrations/ExampleFactory.t.sol @@ -1,29 +1,31 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { BaseTest } from "test/BaseTest.t.sol"; -import { ERC7579Account, ERC7579Bootstrap } from "src/external/ERC7579.sol"; +import { IERC7579Account } from "src/accounts/common/interfaces/IERC7579Account.sol"; +import { IERC7579Bootstrap } from "src/accounts/erc7579/interfaces/IERC7579Bootstrap.sol"; import { ExampleFactory } from "src/integrations/registry/ExampleFactory.sol"; import { ModuleKitHelpers, ModuleKitUserOp } from "src/ModuleKit.sol"; import { IStakeManager } from "src/external/ERC4337.sol"; import { ENTRYPOINT_ADDR } from "src/test/predeploy/EntryPoint.sol"; import { getHelper } from "src/test/utils/Storage.sol"; import { AccountType } from "src/test/RhinestoneModuleKit.sol"; +import { ERC7579Precompiles } from "src/test/precompiles/ERC7579Precompiles.sol"; -contract ExampleFactoryTest is BaseTest { +contract ExampleFactoryTest is BaseTest, ERC7579Precompiles { using ModuleKitHelpers for *; using ModuleKitUserOp for *; - ERC7579Account implementation; - ERC7579Bootstrap bootstrap; + IERC7579Account implementation; + IERC7579Bootstrap bootstrap; ExampleFactory factory; function setUp() public override { super.setUp(); - implementation = new ERC7579Account(); + implementation = deployERC7579Account(); vm.label(address(implementation), "AccountSingleton"); - bootstrap = new ERC7579Bootstrap(); + bootstrap = deployERC7579Bootstrap(); vm.label(address(bootstrap), "Bootstrap"); address[] memory trustedAttesters = new address[](2); trustedAttesters[0] = makeAddr("attester1"); @@ -48,7 +50,7 @@ contract ExampleFactoryTest is BaseTest { address account = factory.createAccount(keccak256("1"), address(instance.defaultValidator), ""); assertTrue(account != address(0)); - assertEq(ERC7579Account(payable(account)).accountId(), "uMSA.advanced/withHook.v0.1"); + assertEq(IERC7579Account(payable(account)).accountId(), "uMSA.advanced/withHook.v0.1"); } function test_userOpFlow() public { diff --git a/test/integrations/SmartSession.t.sol b/test/integrations/SmartSession.t.sol index 63185741..8e04af4a 100644 --- a/test/integrations/SmartSession.t.sol +++ b/test/integrations/SmartSession.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; // Constants -import { MODULE_TYPE_VALIDATOR } from "src/external/ERC7579.sol"; +import { MODULE_TYPE_VALIDATOR } from "src/accounts/common/interfaces/IERC7579Modules.sol"; // Libraries import { ModuleKitHelpers, AccountInstance } from "src/ModuleKit.sol"; @@ -24,7 +24,7 @@ import { Session, ISessionValidator } from "src/test/helpers/interfaces/ISmartSession.sol"; -import { Execution } from "src/external/ERC7579.sol"; +import { Execution } from "src/accounts/erc7579/lib/ExecutionLib.sol"; import { UserOpData, PackedUserOperation } from "src/test/RhinestoneModuleKit.sol"; /// @dev Tests for smart session integration within the RhinestoneModuleKit diff --git a/test/integrations/SwapTest.t.sol b/test/integrations/SwapTest.t.sol index fb014aa2..1c3527e6 100644 --- a/test/integrations/SwapTest.t.sol +++ b/test/integrations/SwapTest.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import "test/BaseTest.t.sol"; import "src/ModuleKit.sol"; diff --git a/test/mocks/MockK1Validator.sol b/test/mocks/MockK1Validator.sol index 0f663c04..6cbdc237 100644 --- a/test/mocks/MockK1Validator.sol +++ b/test/mocks/MockK1Validator.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { IValidator, VALIDATION_SUCCESS, VALIDATION_FAILED, MODULE_TYPE_VALIDATOR -} from "erc7579/interfaces/IERC7579Module.sol"; +} from "src/accounts/common/interfaces/IERC7579Modules.sol"; import { PackedUserOperation } from "src/external/ERC4337.sol"; import { ECDSA } from "solady/utils/ECDSA.sol"; import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol"; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; -import { EIP1271_MAGIC_VALUE, IERC1271 } from "module-bases/interfaces/IERC1271.sol"; +import { EIP1271_MAGIC_VALUE, IERC1271 } from "src/module-bases/interfaces/IERC1271.sol"; contract MockK1Validator is IValidator { bytes4 constant ERC1271_INVALID = 0xffffffff; @@ -22,7 +22,7 @@ contract MockK1Validator is IValidator { bytes32 userOpHash ) external - view + payable returns (uint256 validation) { return ECDSA.recover(MessageHashUtils.toEthSignedMessageHash(userOpHash), userOp.signature) diff --git a/test/mocks/MockK1ValidatorUncompliantUninstall.sol b/test/mocks/MockK1ValidatorUncompliantUninstall.sol index 79c79c08..1d643c39 100644 --- a/test/mocks/MockK1ValidatorUncompliantUninstall.sol +++ b/test/mocks/MockK1ValidatorUncompliantUninstall.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; import { IValidator, VALIDATION_SUCCESS, VALIDATION_FAILED, MODULE_TYPE_VALIDATOR -} from "erc7579/interfaces/IERC7579Module.sol"; +} from "src/accounts/common/interfaces/IERC7579Modules.sol"; import { PackedUserOperation } from "src/external/ERC4337.sol"; import { ECDSA } from "solady/utils/ECDSA.sol"; import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol"; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; -import { EIP1271_MAGIC_VALUE, IERC1271 } from "module-bases/interfaces/IERC1271.sol"; +import { EIP1271_MAGIC_VALUE, IERC1271 } from "src/module-bases/interfaces/IERC1271.sol"; contract MockK1ValidatorUncompliantUninstall is IValidator { bytes4 constant ERC1271_INVALID = 0xffffffff; @@ -22,7 +22,7 @@ contract MockK1ValidatorUncompliantUninstall is IValidator { bytes32 userOpHash ) external - view + payable returns (uint256 validation) { return ECDSA.recover(MessageHashUtils.toEthSignedMessageHash(userOpHash), userOp.signature) @@ -47,7 +47,7 @@ contract MockK1ValidatorUncompliantUninstall is IValidator { smartAccountOwners[msg.sender] = owner; } - function onUninstall(bytes calldata data) external pure { + function onUninstall(bytes calldata data) external { data; } diff --git a/test/mocks/MockValidatorFalse.sol b/test/mocks/MockValidatorFalse.sol index ce1c0106..ca67a2fc 100644 --- a/test/mocks/MockValidatorFalse.sol +++ b/test/mocks/MockValidatorFalse.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; +pragma solidity >=0.8.23 <0.9.0; /* solhint-disable no-unused-vars */ import { ERC7579ValidatorBase } from "src/Modules.sol"; @@ -57,7 +57,6 @@ contract MockValidatorFalse is ERC7579ValidatorBase { ) external pure - override returns (bool validSig) { return false;