diff --git a/.github/workflows/forge.yml b/.github/workflows/forge.yml
new file mode 100644
index 0000000..344fd22
--- /dev/null
+++ b/.github/workflows/forge.yml
@@ -0,0 +1,28 @@
+on: [push]
+
+name: Forge Tests
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: Install submodules
+ run: |
+ git config --global url."https://github.com/".insteadOf "git@github.com:"
+ git submodule update --init --recursive
+
+ - name: Install dependencies
+ run: forge install
+
+ - name: Compile
+ run: forge build
+
+ - name: Run Forge tests
+ run: forge test -vvv
diff --git a/.gitmodules b/.gitmodules
index 888d42d..30eccb2 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,9 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
+[submodule "lib/hydra-s3-zkps"]
+ path = lib/hydra-s3-zkps
+ url = https://github.com/sismo-core/hydra-s3-zkps
+[submodule "lib/openzeppelin-contracts"]
+ path = lib/openzeppelin-contracts
+ url = https://github.com/OpenZeppelin/openzeppelin-contracts
diff --git a/.hardhat/README.md b/.hardhat/README.md
new file mode 100644
index 0000000..125f958
--- /dev/null
+++ b/.hardhat/README.md
@@ -0,0 +1,69 @@
+
+
+
+
+
+ Sismo Connect Solidity
+
+
+
+ Made by Sismo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sismo Connect Solidity is a Solidity library that allows you to verify the zk-proofs of your Sismo Connect Application onchain and simplify the use of the [sismo-connect-onchain-verifier](https://github.com/sismo-core/sismo-connect-onchain-verifier).
+
+Here is the link to the full documentation of the library: [Sismo Connect Solidity Library](https://docs.sismo.io/build-with-sismo-connect/technical-documentation/solidity)
+
+You can learn more on Sismo Connect [here](https://docs.sismo.io/discover-sismo-connect/empower-your-app).
+
+### Prerequisites
+
+- [Node.js](https://nodejs.org/en/download/) >= 18.15.0 (Latest LTS version)
+- [Yarn](https://classic.yarnpkg.com/en/docs/install)
+
+## Usage
+
+### Installation
+
+```bash
+# install the package
+yarn add @sismo-core/sismo-connect-solidity
+```
+
+### Import the library
+In your solidity file:
+
+```solidity
+import {SismoConnect} from "@sismo-core/sismo-connect-solidity/contracts/libs/SismoLib.sol";
+```
+
+You will find here how to use the library: [Sismo Connect Solidity Library](https://docs.sismo.io/build-with-sismo-connect/technical-documentation/solidity)
+
+## License
+
+Distributed under the MIT License.
+
+## Contribute
+
+Please, feel free to open issues, PRs or simply provide feedback!
+
+## Contact
+
+Send us a message in [Telegram](https://builders.sismo.io/) or [Discord](https://discord.gg/sismo)
+
+
+
diff --git a/.hardhat/package.json b/.hardhat/package.json
new file mode 100644
index 0000000..360b5e4
--- /dev/null
+++ b/.hardhat/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "@sismo-core/sismo-connect-solidity",
+ "description": "Sismo Connect Library",
+ "version": "0.0.19",
+ "scripts": {
+ "prepare": "mkdir -p contracts; cp -r ../src/* contracts"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/sismo-core/sismo-connect-onchain-verifier.git"
+ },
+ "keywords": [
+ "solidity",
+ "ethereum",
+ "smart",
+ "contracts"
+ ],
+ "author": "Sismo ",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/sismo-core/sismo-connect-onchain-verifier/issues"
+ },
+ "homepage": "https://github.com/sismo-core/sismo-connect-onchain-verifier#readme",
+ "main": "index.js"
+}
diff --git a/README.md b/README.md
index ef50180..cd1cfaa 100644
--- a/README.md
+++ b/README.md
@@ -24,11 +24,11 @@
-Sismo Connect Solidity is a Solidity library that allows you to verify the zk-proofs of your Sismo Connect Application onchain and simplify the use of the [sismo-connect-onchain-verifier](https://github.com/sismo-core/sismo-connect-onchain-verifier).
+Sismo Connect Solidity is a Solidity library that allows you to verify the zk-proofs of your Sismo Connect Application onchain.
Here is the link to the full documentation of the library: [Sismo Connect Solidity Library](https://docs.sismo.io/build-with-sismo-connect/technical-documentation/solidity)
-You can learn more on Sismo Connect [here](https://docs.sismo.io/discover-sismo-connect/empower-your-app).
+You can learn more on Sismo Connect [here](https://docs.sismo.io/sismo-docs/build-with-sismo-connect/getting-started).
### Prerequisites
@@ -48,7 +48,7 @@ foundryup
forge install sismo-core/sismo-connect-solidity --no-commit
# add the remapping in remappings.txt
-echo $'sismo-connect-solidity/=lib/sismo-connect-packages/src/' >> remappings.txt
+echo $'sismo-connect-solidity/=lib/sismo-connect-solidity/src/' >> remappings.txt
```
### Import the library
@@ -58,7 +58,7 @@ In your solidity file:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
-import "sismo-connect-solidity/SismoLib.sol"; // import the library
+import "sismo-connect-solidity/SismoConnectLib.sol"; // import the library
```
## License
diff --git a/deployments/arbitrum-goerli.json b/deployments/arbitrum-goerli.json
new file mode 100644
index 0000000..3aa216d
--- /dev/null
+++ b/deployments/arbitrum-goerli.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0xD4339e6d873b584FFfeACceE4CcB8Bf31Cd96ebb",
+ "availableRootsRegistry": "0x32725B00400b799D41c852b6Fd94604e10cb487F",
+ "claimRequestBuilder": "0xF03dA119efEc165DbDc15D593aB455810C7fEd74",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0x497f369f94F207663A348b0ac085397C71279bf5",
+ "hydraS3Verifier": "0x9854860CBEa52E19Ca252D1948F04070eBC46b2C",
+ "owner": "0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B",
+ "proxyAdmin": "0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc",
+ "requestBuilder": "0x0bB5c193aa815F7815aB8e854A87E041519CD2ad",
+ "rootsOwner": "0x8eAb4616d47F82C890fdb6eE311A4C0aE34ba7fb",
+ "signatureBuilder": "0xc8F165a3B4CfB7CD2Ae92A582F17b0d7EB3BcE11",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0xb1327210BAF0E8793f3f4D671573ac1A45619edf"
+}
\ No newline at end of file
diff --git a/deployments/arbitrum-one.json b/deployments/arbitrum-one.json
new file mode 100644
index 0000000..41e1819
--- /dev/null
+++ b/deployments/arbitrum-one.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0x8D090172DA53A21D27E7B651ab6E7D9334Ea0783",
+ "availableRootsRegistry": "0xEB2952A4098e15C97E1Ce126FE479f27E2FFB40c",
+ "claimRequestBuilder": "0x1B05f16686396398F16f8916A032D738005126b7",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0x43A6b844f52CB2CC3c9dBcAE9D853B21fF05c4bD",
+ "hydraS3Verifier": "0xAa745f3833faCE895E0e7f99eD0A4989a470E150",
+ "owner": "0x00c92065F759c3d1c94d08C27a2Ab97a1c874Cbc",
+ "proxyAdmin": "0x2110475dfbB8d331b300178A867372991ff35fA3",
+ "requestBuilder": "0x40e208f4815Ce25b32BeEEC7415C6CA9424a898F",
+ "rootsOwner": "0x1BB9AD70F529e36B7Ffed0cfA44fA4cf0213Fa09",
+ "signatureBuilder": "0x1e7a99e06Ca2C1A63330eC2df8D4fC15EfDa4C55",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0x80a914AaFB60519a58f531D80fd402ae88047896"
+}
\ No newline at end of file
diff --git a/deployments/gnosis.json b/deployments/gnosis.json
new file mode 100644
index 0000000..eb8621d
--- /dev/null
+++ b/deployments/gnosis.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0x900F4aD11Ec071e7f93Bf4e0c8976aE2Af5D28E5",
+ "availableRootsRegistry": "0x9B0C9EF48DEc082904054cf9183878E1f4e04D79",
+ "claimRequestBuilder": "0x0c5a188E778a9A0736fCBf25aF6298E92182D676",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0xEB2952A4098e15C97E1Ce126FE479f27E2FFB40c",
+ "hydraS3Verifier": "0x0F85c4Fe7644E85579e27A027D94d1Fb3A388710",
+ "owner": "0x00c92065F759c3d1c94d08C27a2Ab97a1c874Cbc",
+ "proxyAdmin": "0x2110475dfbB8d331b300178A867372991ff35fA3",
+ "requestBuilder": "0x1B05f16686396398F16f8916A032D738005126b7",
+ "rootsOwner": "0xEf809a50de35c762FBaCf1ae1F6B861CE42911D1",
+ "signatureBuilder": "0x8D090172DA53A21D27E7B651ab6E7D9334Ea0783",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0xd1fbf35B45748B2F6998fb7B86eb6A3d73fe91ED"
+}
\ No newline at end of file
diff --git a/deployments/mainnet.json b/deployments/mainnet.json
new file mode 100644
index 0000000..f49d27e
--- /dev/null
+++ b/deployments/mainnet.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0x94E772DBe3ce4BD32274a2053C444C802Bb836A5",
+ "availableRootsRegistry": "0x2E7f4aC6AC90faeC2D870D012A3BCDBcF792B25C",
+ "claimRequestBuilder": "0x900F4aD11Ec071e7f93Bf4e0c8976aE2Af5D28E5",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0xb4463Dbcd773F7Ca37E63f12dce9852e59dC86C9",
+ "hydraS3Verifier": "0x89f40fd037e62eAec7511b0711f781AA57A3e96f",
+ "owner": "0x00c92065F759c3d1c94d08C27a2Ab97a1c874Cbc",
+ "proxyAdmin": "0x2110475dfbB8d331b300178A867372991ff35fA3",
+ "requestBuilder": "0x8D090172DA53A21D27E7B651ab6E7D9334Ea0783",
+ "rootsOwner": "0x2a265b954B96d4940B94eb69E8Fc8E7346369D05",
+ "signatureBuilder": "0x0c5a188E778a9A0736fCBf25aF6298E92182D676",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0x0568ecE836a0881cd305ad53046AB51467B0886a"
+}
diff --git a/deployments/optimism-goerli.json b/deployments/optimism-goerli.json
new file mode 100644
index 0000000..7a483e0
--- /dev/null
+++ b/deployments/optimism-goerli.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0xD4339e6d873b584FFfeACceE4CcB8Bf31Cd96ebb",
+ "availableRootsRegistry": "0x32725B00400b799D41c852b6Fd94604e10cb487F",
+ "claimRequestBuilder": "0xF03dA119efEc165DbDc15D593aB455810C7fEd74",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0x497f369f94F207663A348b0ac085397C71279bf5",
+ "hydraS3Verifier": "0x51B3ec080D1459232dbea86B751F75b5204a4abC",
+ "owner": "0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B",
+ "proxyAdmin": "0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc",
+ "requestBuilder": "0x0bB5c193aa815F7815aB8e854A87E041519CD2ad",
+ "rootsOwner": "0xe807B5153e3eD4767C3F4EB50b65Fab90c57596B",
+ "signatureBuilder": "0xc8F165a3B4CfB7CD2Ae92A582F17b0d7EB3BcE11",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0xAe5f6F591d9F8a5eEB3E6853888B0E80eC9B25E4"
+}
\ No newline at end of file
diff --git a/deployments/optimism.json b/deployments/optimism.json
new file mode 100644
index 0000000..90d54f7
--- /dev/null
+++ b/deployments/optimism.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0x8D090172DA53A21D27E7B651ab6E7D9334Ea0783",
+ "availableRootsRegistry": "0xEB2952A4098e15C97E1Ce126FE479f27E2FFB40c",
+ "claimRequestBuilder": "0x1B05f16686396398F16f8916A032D738005126b7",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0x43A6b844f52CB2CC3c9dBcAE9D853B21fF05c4bD",
+ "hydraS3Verifier": "0x1C4Bd61F5b19750ffb7b0b2D97c77dcf68F49152",
+ "owner": "0x00c92065F759c3d1c94d08C27a2Ab97a1c874Cbc",
+ "proxyAdmin": "0x2110475dfbB8d331b300178A867372991ff35fA3",
+ "requestBuilder": "0x40e208f4815Ce25b32BeEEC7415C6CA9424a898F",
+ "rootsOwner": "0xf8640cE5532BCbc788489Bf5A786635ae585258B",
+ "signatureBuilder": "0x1e7a99e06Ca2C1A63330eC2df8D4fC15EfDa4C55",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0xAE116c797ae424BF232DfFcdF8a3b741D9e6460c"
+}
\ No newline at end of file
diff --git a/deployments/polygon.json b/deployments/polygon.json
new file mode 100644
index 0000000..063795f
--- /dev/null
+++ b/deployments/polygon.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0x900F4aD11Ec071e7f93Bf4e0c8976aE2Af5D28E5",
+ "availableRootsRegistry": "0x818c0f863C6B8E92c316924711bfEb2D903B4A77",
+ "claimRequestBuilder": "0x0c5a188E778a9A0736fCBf25aF6298E92182D676",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0xEB2952A4098e15C97E1Ce126FE479f27E2FFB40c",
+ "hydraS3Verifier": "0x027AcA627F7D13572A54ac2d027A770ca3eF22c8",
+ "owner": "0x00c92065F759c3d1c94d08C27a2Ab97a1c874Cbc",
+ "proxyAdmin": "0x2110475dfbB8d331b300178A867372991ff35fA3",
+ "requestBuilder": "0x1B05f16686396398F16f8916A032D738005126b7",
+ "rootsOwner": "0xF0a0B692e1c764281c211948D03edEeF5Fb57111",
+ "signatureBuilder": "0x8D090172DA53A21D27E7B651ab6E7D9334Ea0783",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0x1C4Bd61F5b19750ffb7b0b2D97c77dcf68F49152"
+}
\ No newline at end of file
diff --git a/deployments/scroll-testnet-goerli.json b/deployments/scroll-testnet-goerli.json
new file mode 100644
index 0000000..29045a6
--- /dev/null
+++ b/deployments/scroll-testnet-goerli.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0xD4339e6d873b584FFfeACceE4CcB8Bf31Cd96ebb",
+ "availableRootsRegistry": "0x32725B00400b799D41c852b6Fd94604e10cb487F",
+ "claimRequestBuilder": "0xF03dA119efEc165DbDc15D593aB455810C7fEd74",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0x497f369f94F207663A348b0ac085397C71279bf5",
+ "hydraS3Verifier": "0x51B3ec080D1459232dbea86B751F75b5204a4abC",
+ "owner": "0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B",
+ "proxyAdmin": "0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc",
+ "requestBuilder": "0x0bB5c193aa815F7815aB8e854A87E041519CD2ad",
+ "rootsOwner": "0x8f9c04d7bA132Fd0CbA124eFCE3936328d217458",
+ "signatureBuilder": "0xc8F165a3B4CfB7CD2Ae92A582F17b0d7EB3BcE11",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0xAe5f6F591d9F8a5eEB3E6853888B0E80eC9B25E4"
+}
\ No newline at end of file
diff --git a/deployments/testnet-goerli.json b/deployments/testnet-goerli.json
new file mode 100644
index 0000000..628d5f1
--- /dev/null
+++ b/deployments/testnet-goerli.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0xD4339e6d873b584FFfeACceE4CcB8Bf31Cd96ebb",
+ "availableRootsRegistry": "0x32725B00400b799D41c852b6Fd94604e10cb487F",
+ "claimRequestBuilder": "0xF03dA119efEc165DbDc15D593aB455810C7fEd74",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0x497f369f94F207663A348b0ac085397C71279bf5",
+ "hydraS3Verifier": "0x1F60E4023C84e7e5897722b04BEc3De7eEa78DEF",
+ "owner": "0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B",
+ "proxyAdmin": "0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc",
+ "requestBuilder": "0x0bB5c193aa815F7815aB8e854A87E041519CD2ad",
+ "rootsOwner": "0xa687922C4bf2eB22297FdF89156B49eD3727618b",
+ "signatureBuilder": "0xc8F165a3B4CfB7CD2Ae92A582F17b0d7EB3BcE11",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0x2bF68E251A94c83dB3da30a5A997c73705DF1B8b"
+}
\ No newline at end of file
diff --git a/deployments/testnet-mumbai.json b/deployments/testnet-mumbai.json
new file mode 100644
index 0000000..5f85447
--- /dev/null
+++ b/deployments/testnet-mumbai.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0xF392c4EAB659Ba22cF40F201996178929f3C9d65",
+ "availableRootsRegistry": "0x51B3ec080D1459232dbea86B751F75b5204a4abC",
+ "claimRequestBuilder": "0xb1327210BAF0E8793f3f4D671573ac1A45619edf",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0xAe5f6F591d9F8a5eEB3E6853888B0E80eC9B25E4",
+ "hydraS3Verifier": "0xBA63Ad5f5570B7Adc82319529eB0694B31f2422E",
+ "owner": "0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B",
+ "proxyAdmin": "0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc",
+ "requestBuilder": "0xc33d0496571513c676de73b13c7166e245CD4d5E",
+ "rootsOwner": "0xCA0583A6682607282963d3E2545Cd2e75697C2bb",
+ "signatureBuilder": "0x16Cb98567cE6f177C1855906230874AE8c5a8B7f",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0xf219113C648dA1D9F0f12EB1898A6a22fEe86dF8"
+}
\ No newline at end of file
diff --git a/deployments/testnet-sepolia.json b/deployments/testnet-sepolia.json
new file mode 100644
index 0000000..d23fe51
--- /dev/null
+++ b/deployments/testnet-sepolia.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0xD4339e6d873b584FFfeACceE4CcB8Bf31Cd96ebb",
+ "availableRootsRegistry": "0x32725B00400b799D41c852b6Fd94604e10cb487F",
+ "claimRequestBuilder": "0xF03dA119efEc165DbDc15D593aB455810C7fEd74",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0x497f369f94F207663A348b0ac085397C71279bf5",
+ "hydraS3Verifier": "0x51B3ec080D1459232dbea86B751F75b5204a4abC",
+ "owner": "0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B",
+ "proxyAdmin": "0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc",
+ "requestBuilder": "0x0bB5c193aa815F7815aB8e854A87E041519CD2ad",
+ "rootsOwner": "0x1C0c54EA7Bb55f655fb8Ff6D51557368bA8624E6",
+ "signatureBuilder": "0xc8F165a3B4CfB7CD2Ae92A582F17b0d7EB3BcE11",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0xAe5f6F591d9F8a5eEB3E6853888B0E80eC9B25E4"
+}
\ No newline at end of file
diff --git a/deployments/tmp/example.json b/deployments/tmp/example.json
new file mode 100644
index 0000000..159f9e9
--- /dev/null
+++ b/deployments/tmp/example.json
@@ -0,0 +1,18 @@
+{
+ "authRequestBuilder": "0x99BDC397D261C8B2D15967dd4605d9785e2E7761",
+ "availableRootsRegistry": "0xfB548eC30347c220E4e7733248ff25e3699A4648",
+ "claimRequestBuilder": "0x32D604958f5b2206a426E85cc8d965E5148dA1F9",
+ "commitmentMapperEdDSAPubKey": {
+ "pubKeyX": 3602196582082511412345093208859330584743530098298494929484637038525722574265,
+ "pubKeyY": 14672613011011178056703002414016466661118036128791343632962870104486584019450
+ },
+ "commitmentMapperRegistry": "0x2ff87b43dbE95d94F56F059cA3506d5d4E8F0470",
+ "hydraS3Verifier": "0x6DfBF9f1610CB69d5722ED4b8366eB7Ed3c2C77a",
+ "owner": "0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B",
+ "proxyAdmin": "0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc",
+ "requestBuilder": "0xDb7Ec66521700F00ccaf7F7B8aA1853b9541484B",
+ "rootsOwner": "0xa687922C4bf2eB22297FdF89156B49eD3727618b",
+ "signatureBuilder": "0xD6710F81Be249EA575Fe9A39Ff6D28da6601f37c",
+ "sismoAddressesProviderV2": "0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6",
+ "sismoConnectVerifier": "0x9dbC9d0ce3CC784BB5fD42a6f7686670a7e0b4eE"
+}
diff --git a/foundry.toml b/foundry.toml
index 4d9fd31..08e868a 100644
--- a/foundry.toml
+++ b/foundry.toml
@@ -6,9 +6,6 @@ fs_permissions = [{ access = "read-write", path = "./"}]
bytecode_hash="none"
-[fmt]
-ignore = ["test/libs/SimoConnectLib.t.sol"]
-
[rpc_endpoints]
polygon = "${RPC_URL}"
gnosis = "${RPC_URL}"
diff --git a/lib/hydra-s3-zkps b/lib/hydra-s3-zkps
new file mode 160000
index 0000000..33ac760
--- /dev/null
+++ b/lib/hydra-s3-zkps
@@ -0,0 +1 @@
+Subproject commit 33ac7603405dfa5d1806da4c150dab160e763e18
diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts
new file mode 160000
index 0000000..d00acef
--- /dev/null
+++ b/lib/openzeppelin-contracts
@@ -0,0 +1 @@
+Subproject commit d00acef4059807535af0bd0dd0ddf619747a044b
diff --git a/remappings.txt b/remappings.txt
index 83fbb69..3a33c7a 100644
--- a/remappings.txt
+++ b/remappings.txt
@@ -1 +1,3 @@
-forge-std/=lib/forge-std/src/
\ No newline at end of file
+forge-std/=lib/forge-std/src/
+@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
+@sismo-core/hydra-s3/=lib/hydra-s3-zkps/package/contracts/
\ No newline at end of file
diff --git a/script/01_DeployAll.s.sol b/script/01_DeployAll.s.sol
new file mode 100644
index 0000000..01f232d
--- /dev/null
+++ b/script/01_DeployAll.s.sol
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/Script.sol";
+import "forge-std/console.sol";
+import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
+import "@openzeppelin/contracts/utils/Address.sol";
+
+import "src/periphery/AvailableRootsRegistry.sol";
+import "src/periphery/CommitmentMapperRegistry.sol";
+import {HydraS3Verifier} from "src/verifiers/HydraS3Verifier.sol";
+
+import {SismoConnectVerifier} from "src/SismoConnectVerifier.sol";
+import {AuthRequestBuilder} from "src/utils/AuthRequestBuilder.sol";
+import {ClaimRequestBuilder} from "src/utils/ClaimRequestBuilder.sol";
+import {SignatureBuilder} from "src/utils/SignatureBuilder.sol";
+import {RequestBuilder} from "src/utils/RequestBuilder.sol";
+import {DeploymentConfig, BaseDeploymentConfig} from "script/BaseConfig.sol";
+import {IAddressesProvider} from "src/periphery/interfaces/IAddressesProvider.sol";
+
+contract DeployAll is Script, BaseDeploymentConfig {
+ AvailableRootsRegistry availableRootsRegistry;
+ CommitmentMapperRegistry commitmentMapperRegistry;
+ HydraS3Verifier hydraS3Verifier;
+ SismoConnectVerifier sismoConnectVerifier;
+
+ // external libraries
+ AuthRequestBuilder authRequestBuilder;
+ ClaimRequestBuilder claimRequestBuilder;
+ SignatureBuilder signatureBuilder;
+ RequestBuilder requestBuilder;
+
+ function runFor(
+ string memory chainName
+ ) public returns (ScriptTypes.DeployAllContracts memory contracts) {
+ console.log("Run for CHAIN_NAME:", chainName);
+ console.log("Deployer:", msg.sender);
+
+ vm.startBroadcast();
+
+ _setDeploymentConfig({chainName: chainName, checkIfEmpty: true});
+
+ availableRootsRegistry = _deployAvailableRootsRegistry(config.rootsOwner);
+ commitmentMapperRegistry = _deployCommitmentMapperRegistry(
+ config.owner,
+ config.commitmentMapperEdDSAPubKey
+ );
+
+ hydraS3Verifier = _deployHydraS3Verifier(
+ address(commitmentMapperRegistry),
+ address(availableRootsRegistry)
+ );
+ sismoConnectVerifier = _deploySismoConnectVerifier(msg.sender);
+
+ sismoConnectVerifier.registerVerifier(
+ hydraS3Verifier.HYDRA_S3_VERSION(),
+ address(hydraS3Verifier)
+ );
+
+ sismoConnectVerifier.transferOwnership(config.owner);
+
+ contracts.availableRootsRegistry = availableRootsRegistry;
+ contracts.commitmentMapperRegistry = commitmentMapperRegistry;
+ contracts.hydraS3Verifier = hydraS3Verifier;
+ contracts.sismoConnectVerifier = sismoConnectVerifier;
+
+ // external libraries
+
+ authRequestBuilder = _deployAuthRequestBuilder();
+ claimRequestBuilder = _deployClaimRequestBuilder();
+ signatureBuilder = _deploySignatureBuilder();
+ requestBuilder = _deployRequestBuilder();
+
+ contracts.authRequestBuilder = authRequestBuilder;
+ contracts.claimRequestBuilder = claimRequestBuilder;
+ contracts.signatureBuilder = signatureBuilder;
+ contracts.requestBuilder = requestBuilder;
+
+ DeploymentConfig memory newDeploymentConfig = DeploymentConfig({
+ proxyAdmin: config.proxyAdmin,
+ owner: config.owner,
+ rootsOwner: config.rootsOwner,
+ commitmentMapperEdDSAPubKey: config.commitmentMapperEdDSAPubKey,
+ sismoAddressesProviderV2: config.sismoAddressesProviderV2,
+ availableRootsRegistry: address(availableRootsRegistry),
+ commitmentMapperRegistry: address(commitmentMapperRegistry),
+ hydraS3Verifier: address(hydraS3Verifier),
+ sismoConnectVerifier: address(sismoConnectVerifier),
+ authRequestBuilder: address(authRequestBuilder),
+ claimRequestBuilder: address(claimRequestBuilder),
+ signatureBuilder: address(signatureBuilder),
+ requestBuilder: address(requestBuilder)
+ });
+
+ _saveDeploymentConfig(chainName, newDeploymentConfig);
+
+ vm.stopBroadcast();
+ }
+
+ function _deployAvailableRootsRegistry(address owner) private returns (AvailableRootsRegistry) {
+ address availableRootsRegistryAddress = config.availableRootsRegistry;
+ if (availableRootsRegistryAddress != address(0)) {
+ console.log("Using existing availableRootsRegistry:", availableRootsRegistryAddress);
+ return AvailableRootsRegistry(availableRootsRegistryAddress);
+ }
+ AvailableRootsRegistry rootsRegistryImplem = new AvailableRootsRegistry(owner);
+ console.log("rootsRegistry Implem Deployed:", address(rootsRegistryImplem));
+
+ TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
+ address(rootsRegistryImplem),
+ config.proxyAdmin,
+ abi.encodeWithSelector(rootsRegistryImplem.initialize.selector, owner)
+ );
+ console.log("rootsRegistry Proxy Deployed:", address(proxy));
+ return AvailableRootsRegistry(address(proxy));
+ }
+
+ function _deployCommitmentMapperRegistry(
+ address owner,
+ uint256[2] memory commitmentMapperEdDSAPubKey
+ ) private returns (CommitmentMapperRegistry) {
+ address commitmentMapperRegistryAddress = config.commitmentMapperRegistry;
+ if (commitmentMapperRegistryAddress != address(0)) {
+ console.log("Using existing commitmentMapperRegistry:", commitmentMapperRegistryAddress);
+ return CommitmentMapperRegistry(commitmentMapperRegistryAddress);
+ }
+ CommitmentMapperRegistry commitmentMapperImplem = new CommitmentMapperRegistry(
+ owner,
+ commitmentMapperEdDSAPubKey
+ );
+ console.log("commitmentMapper Implem Deployed:", address(commitmentMapperImplem));
+ console.log("owner:", owner);
+
+ TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
+ address(commitmentMapperImplem),
+ config.proxyAdmin,
+ abi.encodeWithSelector(
+ commitmentMapperImplem.initialize.selector,
+ owner,
+ commitmentMapperEdDSAPubKey
+ )
+ );
+ console.log("commitmentMapper Proxy Deployed:", address(proxy));
+ return CommitmentMapperRegistry(address(proxy));
+ }
+
+ function _deployHydraS3Verifier(
+ address commitmentMapperRegistryAddr,
+ address availableRootsRegistryAddr
+ ) private returns (HydraS3Verifier) {
+ address hydraS3VerifierAddress = config.hydraS3Verifier;
+ if (hydraS3VerifierAddress != address(0)) {
+ console.log("Using existing hydraS3Verifier:", hydraS3VerifierAddress);
+ return HydraS3Verifier(hydraS3VerifierAddress);
+ }
+ HydraS3Verifier hydraS3VerifierImplem = new HydraS3Verifier(
+ commitmentMapperRegistryAddr,
+ availableRootsRegistryAddr
+ );
+ console.log("hydraS3Verifier Implem Deployed:", address(hydraS3VerifierImplem));
+
+ TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
+ address(hydraS3VerifierImplem),
+ config.proxyAdmin,
+ abi.encodeWithSelector(hydraS3VerifierImplem.initialize.selector)
+ );
+ console.log("hydraS3Verifier Proxy Deployed:", address(proxy));
+ return HydraS3Verifier(address(proxy));
+ }
+
+ function _deploySismoConnectVerifier(address owner) private returns (SismoConnectVerifier) {
+ address sismoConnectVerifierAddress = config.sismoConnectVerifier;
+ if (sismoConnectVerifierAddress != address(0)) {
+ console.log("Using existing sismoConnectVerifier:", sismoConnectVerifierAddress);
+ return SismoConnectVerifier(sismoConnectVerifierAddress);
+ }
+ SismoConnectVerifier sismoConnectVerifierImplem = new SismoConnectVerifier(owner);
+ console.log("sismoConnectVerifier Implem Deployed:", address(sismoConnectVerifierImplem));
+
+ TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
+ address(sismoConnectVerifierImplem),
+ config.proxyAdmin,
+ abi.encodeWithSelector(sismoConnectVerifierImplem.initialize.selector, owner)
+ );
+ console.log("sismoConnectVerifier Proxy Deployed:", address(proxy));
+ return SismoConnectVerifier(address(proxy));
+ }
+
+ // External libraries
+
+ function _deployAuthRequestBuilder() private returns (AuthRequestBuilder) {
+ address authRequestBuilderAddress = config.authRequestBuilder;
+ if (authRequestBuilderAddress != address(0)) {
+ console.log("Using existing authrequestBuilder:", authRequestBuilderAddress);
+ return AuthRequestBuilder(authRequestBuilderAddress);
+ }
+ authRequestBuilder = new AuthRequestBuilder();
+ console.log("authRequestBuilder Deployed:", address(authRequestBuilder));
+ return authRequestBuilder;
+ }
+
+ function _deployClaimRequestBuilder() private returns (ClaimRequestBuilder) {
+ address claimRequestBuilderAddress = config.claimRequestBuilder;
+ if (claimRequestBuilderAddress != address(0)) {
+ console.log("Using existing claimRequestBuilder:", claimRequestBuilderAddress);
+ return ClaimRequestBuilder(claimRequestBuilderAddress);
+ }
+ claimRequestBuilder = new ClaimRequestBuilder();
+ console.log("claimRequestBuilder Deployed:", address(claimRequestBuilder));
+ return claimRequestBuilder;
+ }
+
+ function _deploySignatureBuilder() private returns (SignatureBuilder) {
+ address signatureBuilderAddress = config.signatureBuilder;
+ if (signatureBuilderAddress != address(0)) {
+ console.log("Using existing signatureBuilder:", signatureBuilderAddress);
+ return SignatureBuilder(signatureBuilderAddress);
+ }
+ signatureBuilder = new SignatureBuilder();
+ console.log("signatureBuilder Deployed:", address(signatureBuilder));
+ return signatureBuilder;
+ }
+
+ function _deployRequestBuilder() private returns (RequestBuilder) {
+ address requestBuilderAddress = config.requestBuilder;
+ if (requestBuilderAddress != address(0)) {
+ console.log("Using existing requestBuilder:", requestBuilderAddress);
+ return RequestBuilder(requestBuilderAddress);
+ }
+ requestBuilder = new RequestBuilder();
+ console.log("requestBuilder Deployed:", address(requestBuilder));
+ return requestBuilder;
+ }
+
+ function run() public returns (ScriptTypes.DeployAllContracts memory contracts) {
+ string memory chainName = vm.envString("CHAIN_NAME");
+ return runFor(chainName);
+ }
+
+ function deploymentConfigFilePath() external view returns (string memory) {
+ return _deploymentConfigFilePath();
+ }
+}
+
+library ScriptTypes {
+ struct DeployAllContracts {
+ AvailableRootsRegistry availableRootsRegistry;
+ CommitmentMapperRegistry commitmentMapperRegistry;
+ HydraS3Verifier hydraS3Verifier;
+ SismoConnectVerifier sismoConnectVerifier;
+ // external libraries
+ AuthRequestBuilder authRequestBuilder;
+ ClaimRequestBuilder claimRequestBuilder;
+ SignatureBuilder signatureBuilder;
+ RequestBuilder requestBuilder;
+ }
+}
diff --git a/script/BaseConfig.sol b/script/BaseConfig.sol
new file mode 100644
index 0000000..8206353
--- /dev/null
+++ b/script/BaseConfig.sol
@@ -0,0 +1,560 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {Script} from "forge-std/Script.sol";
+import "forge-std/console.sol";
+
+// struct fields are sorted by alphabetical order to be able to parse the config from the deployment files
+struct DeploymentConfig {
+ address authRequestBuilder;
+ address availableRootsRegistry;
+ address claimRequestBuilder;
+ uint256[2] commitmentMapperEdDSAPubKey;
+ address commitmentMapperRegistry;
+ address hydraS3Verifier;
+ address owner;
+ address proxyAdmin;
+ address requestBuilder;
+ address rootsOwner;
+ address signatureBuilder;
+ address sismoAddressesProviderV2;
+ address sismoConnectVerifier;
+}
+
+// Minimal config is used to create empty config files
+struct MinimalConfig {
+ address owner;
+ address proxyAdmin;
+ address rootsOwner;
+ uint256[2] commitmentMapperEdDSAPubKey;
+}
+
+contract BaseDeploymentConfig is Script {
+ MinimalConfig minimalConfig;
+ DeploymentConfig config;
+
+ string public _chainName;
+ bool public _checkIfEmpty;
+
+ address immutable SISMO_ADDRESSES_PROVIDER_V2 = 0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6;
+ address immutable ZERO_ADDRESS = 0x0000000000000000000000000000000000000000;
+
+ // Main Env
+ address immutable MAIN_PROXY_ADMIN = 0x2110475dfbB8d331b300178A867372991ff35fA3;
+ address immutable MAIN_OWNER = 0x00c92065F759c3d1c94d08C27a2Ab97a1c874Cbc;
+ address immutable MAIN_GNOSIS_ROOTS_OWNER = 0xEf809a50de35c762FBaCf1ae1F6B861CE42911D1;
+ address immutable MAIN_POLYGON_ROOTS_OWNER = 0xF0a0B692e1c764281c211948D03edEeF5Fb57111;
+ address immutable MAIN_OPTIMISM_ROOTS_OWNER = 0xf8640cE5532BCbc788489Bf5A786635ae585258B;
+ address immutable MAIN_ARBITRUM_ONE_ROOTS_OWNER = 0x1BB9AD70F529e36B7Ffed0cfA44fA4cf0213Fa09;
+ address immutable MAIN_MAINNET_ROOTS_OWNER = 0x2a265b954B96d4940B94eb69E8Fc8E7346369D05;
+
+ // Testnet Env
+ address immutable TESTNET_PROXY_ADMIN = 0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc;
+ address immutable TESTNET_OWNER = 0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B;
+ address immutable TESTNET_GOERLI_ROOTS_OWNER = 0xa687922C4bf2eB22297FdF89156B49eD3727618b;
+ address immutable TESTNET_SEPOLIA_ROOTS_OWNER = 0x1C0c54EA7Bb55f655fb8Ff6D51557368bA8624E6;
+ address immutable TESTNET_MUMBAI_ROOTS_OWNER = 0xCA0583A6682607282963d3E2545Cd2e75697C2bb;
+ address immutable TESTNET_OPTIMISM_GOERLI_ROOTS_OWNER =
+ 0xe807B5153e3eD4767C3F4EB50b65Fab90c57596B;
+ address immutable TESTNET_ARBITRUM_GOERLI_ROOTS_OWNER =
+ 0x8eAb4616d47F82C890fdb6eE311A4C0aE34ba7fb;
+ address immutable TESTNET_SCROLL_GOERLI_ROOTS_OWNER = 0x8f9c04d7bA132Fd0CbA124eFCE3936328d217458;
+
+ // Sismo Staging env (Sismo internal use only)
+ address immutable STAGING_PROXY_ADMIN = 0x246E71bC2a257f4BE9C7fAD4664E6D7444844Adc;
+ address immutable STAGING_OWNER = 0xBB8FcA8f2381CFeEDe5D7541d7bF76343EF6c67B;
+ address immutable STAGING_GOERLI_ROOTS_OWNER = 0x7f2e6E158643BCaF85f30c57Ae8625f623D82659;
+ address immutable STAGING_MUMBAI_ROOTS_OWNER = 0x63F08f8F13126B9eADC76dd683902C61c5115138;
+
+ // commitment mapper pubkeys
+ uint256 immutable PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X =
+ 0x07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb9;
+ uint256 immutable PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y =
+ 0x20706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa;
+
+ error ChainNotConfigured(DeployChain chain);
+ error ChainNameNotFound(string chainName);
+
+ enum DeployChain {
+ Mainnet,
+ Gnosis,
+ Polygon,
+ Optimism,
+ ArbitrumOne,
+ TestnetGoerli,
+ TestnetSepolia,
+ TestnetMumbai,
+ OptimismGoerli,
+ ArbitrumGoerli,
+ ScrollTestnetGoerli,
+ StagingGoerli,
+ StagingMumbai,
+ Test
+ }
+
+ function getChainName(string memory chainName) internal pure returns (DeployChain) {
+ if (_compareStrings(chainName, "mainnet")) {
+ return DeployChain.Mainnet;
+ } else if (_compareStrings(chainName, "gnosis")) {
+ return DeployChain.Gnosis;
+ } else if (_compareStrings(chainName, "polygon")) {
+ return DeployChain.Polygon;
+ } else if (_compareStrings(chainName, "optimism")) {
+ return DeployChain.Optimism;
+ } else if (_compareStrings(chainName, "arbitrum-one")) {
+ return DeployChain.ArbitrumOne;
+ } else if (_compareStrings(chainName, "testnet-goerli")) {
+ return DeployChain.TestnetGoerli;
+ } else if (_compareStrings(chainName, "testnet-sepolia")) {
+ return DeployChain.TestnetSepolia;
+ } else if (_compareStrings(chainName, "testnet-mumbai")) {
+ return DeployChain.TestnetMumbai;
+ } else if (_compareStrings(chainName, "optimism-goerli")) {
+ return DeployChain.OptimismGoerli;
+ } else if (_compareStrings(chainName, "arbitrum-goerli")) {
+ return DeployChain.ArbitrumGoerli;
+ } else if (_compareStrings(chainName, "scroll-testnet-goerli")) {
+ return DeployChain.ScrollTestnetGoerli;
+ } else if (_compareStrings(chainName, "staging-goerli")) {
+ return DeployChain.StagingGoerli;
+ } else if (_compareStrings(chainName, "staging-mumbai")) {
+ return DeployChain.StagingMumbai;
+ } else if (_compareStrings(chainName, "test")) {
+ return DeployChain.Test;
+ }
+ revert ChainNameNotFound(chainName);
+ }
+
+ function _getEmptyDeploymentConfig(DeployChain chain) internal returns (DeploymentConfig memory) {
+ minimalConfig = _getMinimalConfig(chain);
+
+ config = DeploymentConfig({
+ proxyAdmin: minimalConfig.proxyAdmin,
+ owner: minimalConfig.owner,
+ rootsOwner: minimalConfig.rootsOwner,
+ commitmentMapperEdDSAPubKey: minimalConfig.commitmentMapperEdDSAPubKey,
+ availableRootsRegistry: ZERO_ADDRESS,
+ commitmentMapperRegistry: ZERO_ADDRESS,
+ sismoAddressesProviderV2: _tryReadingAddressFromDeploymentConfigAtKey(
+ ".sismoAddressesProviderV2"
+ ),
+ sismoConnectVerifier: ZERO_ADDRESS,
+ hydraS3Verifier: ZERO_ADDRESS,
+ // external libraries
+ authRequestBuilder: ZERO_ADDRESS,
+ claimRequestBuilder: ZERO_ADDRESS,
+ signatureBuilder: ZERO_ADDRESS,
+ requestBuilder: ZERO_ADDRESS
+ });
+
+ return config;
+ }
+
+ function _getMinimalConfig(DeployChain chain) internal returns (MinimalConfig memory) {
+ if (chain == DeployChain.Mainnet) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: MAIN_PROXY_ADMIN,
+ owner: MAIN_OWNER,
+ rootsOwner: MAIN_MAINNET_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.Gnosis) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: MAIN_PROXY_ADMIN,
+ owner: MAIN_OWNER,
+ rootsOwner: MAIN_GNOSIS_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.Polygon) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: MAIN_PROXY_ADMIN,
+ owner: MAIN_OWNER,
+ rootsOwner: MAIN_POLYGON_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.Optimism) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: MAIN_PROXY_ADMIN,
+ owner: MAIN_OWNER,
+ rootsOwner: MAIN_OPTIMISM_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.ArbitrumOne) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: MAIN_PROXY_ADMIN,
+ owner: MAIN_OWNER,
+ rootsOwner: MAIN_ARBITRUM_ONE_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.TestnetGoerli) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: TESTNET_PROXY_ADMIN,
+ owner: TESTNET_OWNER,
+ rootsOwner: TESTNET_GOERLI_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.TestnetSepolia) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: TESTNET_PROXY_ADMIN,
+ owner: TESTNET_OWNER,
+ rootsOwner: TESTNET_SEPOLIA_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.TestnetMumbai) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: TESTNET_PROXY_ADMIN,
+ owner: TESTNET_OWNER,
+ rootsOwner: TESTNET_MUMBAI_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.OptimismGoerli) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: TESTNET_PROXY_ADMIN,
+ owner: TESTNET_OWNER,
+ rootsOwner: TESTNET_OPTIMISM_GOERLI_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.ArbitrumGoerli) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: TESTNET_PROXY_ADMIN,
+ owner: TESTNET_OWNER,
+ rootsOwner: TESTNET_ARBITRUM_GOERLI_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.ScrollTestnetGoerli) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: TESTNET_PROXY_ADMIN,
+ owner: TESTNET_OWNER,
+ rootsOwner: TESTNET_SCROLL_GOERLI_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.StagingGoerli) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: STAGING_PROXY_ADMIN,
+ owner: STAGING_OWNER,
+ rootsOwner: STAGING_GOERLI_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.StagingMumbai) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: STAGING_PROXY_ADMIN,
+ owner: STAGING_OWNER,
+ rootsOwner: STAGING_MUMBAI_ROOTS_OWNER,
+ commitmentMapperEdDSAPubKey: [
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_X,
+ PROD_BETA_COMMITMENT_MAPPER_PUB_KEY_Y
+ ]
+ });
+ } else if (chain == DeployChain.Test) {
+ minimalConfig = MinimalConfig({
+ proxyAdmin: address(1),
+ owner: address(2),
+ rootsOwner: address(3),
+ commitmentMapperEdDSAPubKey: [uint256(10), uint256(11)]
+ });
+ } else {
+ revert ChainNotConfigured(chain);
+ }
+
+ return minimalConfig;
+ }
+
+ function _setDeploymentConfig(string memory chainName, bool checkIfEmpty) internal {
+ _chainName = chainName;
+ _checkIfEmpty = checkIfEmpty;
+ // read deployment config from file if the chain is different from `test`
+ string memory filePath = string.concat(_deploymentConfigFilePath());
+
+ string memory json;
+ try vm.readFile(filePath) returns (string memory _json) {
+ json = _json;
+ } catch {
+ console.log(
+ string.concat("Deployment config file not found, creating a new one at ", filePath, ".")
+ );
+ // create a new empty file
+ vm.writeFile(filePath, "");
+ json = "";
+ }
+
+ // if the config is not created, create a new empty one
+ if (checkIfEmpty) {
+ if (_compareStrings(json, "") || _compareStrings(chainName, "test") || _isLocalFork()) {
+ _saveDeploymentConfig(chainName, _getEmptyDeploymentConfig(getChainName(_chainName)));
+ } else {
+ _readDeploymentConfig(_chainName);
+ }
+ } else {
+ _readDeploymentConfig(_chainName);
+ }
+ }
+
+ function _readDeploymentConfig(string memory chainName) internal {
+ _chainName = chainName;
+ minimalConfig = _getMinimalConfig(getChainName(chainName));
+ address owner = minimalConfig.owner;
+ address proxyAdmin = minimalConfig.proxyAdmin;
+ address rootsOwner = minimalConfig.rootsOwner;
+ uint256[2] memory commitmentMapperEdDSAPubKey = minimalConfig.commitmentMapperEdDSAPubKey;
+ address availableRootsRegistry = _tryReadingAddressFromDeploymentConfigAtKey(
+ ".availableRootsRegistry"
+ );
+ address commitmentMapperRegistry = _tryReadingAddressFromDeploymentConfigAtKey(
+ ".commitmentMapperRegistry"
+ );
+ address sismoAddressesProviderV2 = _tryReadingAddressFromDeploymentConfigAtKey(
+ ".sismoAddressesProviderV2"
+ );
+ address sismoConnectVerifier = _tryReadingAddressFromDeploymentConfigAtKey(
+ ".sismoConnectVerifier"
+ );
+ address hydraS3Verifier = _tryReadingAddressFromDeploymentConfigAtKey(".hydraS3Verifier");
+ address authRequestBuilder = _tryReadingAddressFromDeploymentConfigAtKey(".authRequestBuilder");
+ address claimRequestBuilder = _tryReadingAddressFromDeploymentConfigAtKey(
+ ".claimRequestBuilder"
+ );
+ address signatureBuilder = _tryReadingAddressFromDeploymentConfigAtKey(".signatureBuilder");
+ address requestBuilder = _tryReadingAddressFromDeploymentConfigAtKey(".requestBuilder");
+
+ config = DeploymentConfig({
+ proxyAdmin: proxyAdmin,
+ owner: owner,
+ rootsOwner: rootsOwner,
+ commitmentMapperEdDSAPubKey: commitmentMapperEdDSAPubKey,
+ availableRootsRegistry: availableRootsRegistry,
+ commitmentMapperRegistry: commitmentMapperRegistry,
+ sismoAddressesProviderV2: sismoAddressesProviderV2,
+ sismoConnectVerifier: sismoConnectVerifier,
+ hydraS3Verifier: hydraS3Verifier,
+ // external libraries
+ authRequestBuilder: authRequestBuilder,
+ claimRequestBuilder: claimRequestBuilder,
+ signatureBuilder: signatureBuilder,
+ requestBuilder: requestBuilder
+ });
+ }
+
+ function _readAddressFromDeploymentConfigAtKey(
+ string memory key
+ ) internal view returns (address) {
+ bytes memory encodedAddress = vm.parseJson(vm.readFile(_deploymentConfigFilePath()), key);
+ return
+ abi.decode(encodedAddress, (address)) == address(0x20)
+ ? address(0)
+ : abi.decode(encodedAddress, (address));
+ }
+
+ function _tryReadingAddressFromDeploymentConfigAtKey(
+ string memory key
+ ) internal view returns (address) {
+ try vm.parseJson(vm.readFile(_deploymentConfigFilePath()), key) returns (
+ bytes memory encodedAddress
+ ) {
+ return
+ abi.decode(encodedAddress, (address)) == address(0x20)
+ ? address(0)
+ : abi.decode(encodedAddress, (address));
+ } catch {
+ return ZERO_ADDRESS;
+ }
+ }
+
+ function _readCommitmentMapperEdDSAPubKeyFromDeploymentConfig()
+ internal
+ view
+ returns (uint256[2] memory pubKey)
+ {
+ try
+ vm.parseJson(vm.readFile(_deploymentConfigFilePath()), ".commitmentMapperEdDSAPubKey")
+ returns (bytes memory value) {
+ return abi.decode(value, (uint256[2]));
+ } catch {
+ require(
+ false,
+ string.concat(
+ "Error reading commitmentMapperEdDSAPubKey from deployment config, you need to specify a public key."
+ )
+ );
+ }
+ }
+
+ function _tryReadingCommitmentMapperEdDSAPubKeyFromDeploymentConfig()
+ internal
+ view
+ returns (uint256[2] memory pubKey)
+ {
+ try
+ vm.parseJson(vm.readFile(_deploymentConfigFilePath()), ".commitmentMapperEdDSAPubKey")
+ returns (bytes memory value) {
+ return abi.decode(value, (uint256[2]));
+ } catch {
+ return [uint256(0), uint256(0)];
+ }
+ }
+
+ function _saveDeploymentConfig(
+ string memory chainName,
+ DeploymentConfig memory deploymentConfig
+ ) internal {
+ // serialize deployment config by creating an object with key `chainName`
+ vm.serializeAddress(
+ chainName,
+ "availableRootsRegistry",
+ address(deploymentConfig.availableRootsRegistry)
+ );
+ vm.serializeAddress(
+ chainName,
+ "commitmentMapperRegistry",
+ address(deploymentConfig.commitmentMapperRegistry)
+ );
+ vm.serializeAddress(chainName, "hydraS3Verifier", address(deploymentConfig.hydraS3Verifier));
+ vm.serializeAddress(
+ chainName,
+ "sismoConnectVerifier",
+ address(deploymentConfig.sismoConnectVerifier)
+ );
+ vm.serializeAddress(
+ chainName,
+ "authRequestBuilder",
+ address(deploymentConfig.authRequestBuilder)
+ );
+ vm.serializeAddress(
+ chainName,
+ "claimRequestBuilder",
+ address(deploymentConfig.claimRequestBuilder)
+ );
+ vm.serializeAddress(chainName, "signatureBuilder", address(deploymentConfig.signatureBuilder));
+ vm.serializeAddress(chainName, "requestBuilder", address(deploymentConfig.requestBuilder));
+ vm.serializeAddress(chainName, "proxyAdmin", address(deploymentConfig.proxyAdmin));
+ vm.serializeAddress(chainName, "owner", address(deploymentConfig.owner));
+ vm.serializeAddress(chainName, "rootsOwner", address(deploymentConfig.rootsOwner));
+
+ // serialize commitment mapper pub key by creating a new json object with key "commitmentMapperEdDSAPubKey
+ vm.serializeUint(
+ "commitmentMapperEdDSAPubKey",
+ "pubKeyX",
+ deploymentConfig.commitmentMapperEdDSAPubKey[0]
+ );
+ string memory commitmentMapperPubKeyConfig = vm.serializeUint(
+ "commitmentMapperEdDSAPubKey",
+ "pubKeyY",
+ deploymentConfig.commitmentMapperEdDSAPubKey[1]
+ );
+
+ // serialize this json object as a string to be able to save it in the main json object with key `chainName`
+ vm.serializeString(chainName, "commitmentMapperEdDSAPubKey", commitmentMapperPubKeyConfig);
+ string memory finalJson = vm.serializeAddress(
+ chainName,
+ "sismoAddressesProviderV2",
+ address(deploymentConfig.sismoAddressesProviderV2)
+ );
+
+ if (_compareStrings(chainName, "test") || _isLocalFork()) {
+ vm.writeJson(finalJson, _deploymentConfigFilePath());
+ } else {
+ try vm.envBool("OVERRIDE_DEPLOYMENT_CONFIG") returns (bool overrideDeploymentConfig) {
+ if (overrideDeploymentConfig == true) {
+ vm.writeJson(finalJson, _deploymentConfigFilePath());
+ }
+ } catch {
+ console.log("OVERRIDE_DEPLOYMENT_CONFIG not set, skipping deployment config override.");
+ }
+ }
+ }
+
+ function _deploymentConfigFilePath() internal view returns (string memory) {
+ // we return the real config if USE_DEPLOYMENT_CONFIG is true
+ // and the RPC_URL is different from localhost
+ // otherwise we return the temporary config
+ try vm.envBool("USE_DEPLOYMENT_CONFIG") returns (bool useDeploymentConfig) {
+ return _checkLocalhostFork(useDeploymentConfig == true);
+ } catch {
+ return _checkLocalhostFork(false);
+ }
+ }
+
+ function _checkLocalhostFork(bool useDeploymentConfig) internal view returns (string memory) {
+ // check if we are using a fork
+ bool isLocalFork = _isLocalFork();
+
+ // if the chainId is different from 31337 (localhost) we need to check if the user wants to use the real development config
+ // otherwise it can be dangerous to deploy to a real chain with a config that is temporary
+ if (!_compareStrings(vm.toString(block.chainid), "31337")) {
+ require(
+ useDeploymentConfig == true || isLocalFork == true,
+ "If you want to deploy to a chain different from localhost, you either need to use the deployment config by specifying `USE_DEPLOYMENT_CONFIG=true` in your command. Or set `FORK=true` and `--rpc-url http://localhost:8545` in your command to deploy to a fork."
+ );
+ require(
+ !_compareStrings(_chainName, "test"),
+ "If you want to deploy to a chain different from localhost, you need to specify a chain name different from `test`."
+ );
+ // return the real config if we are NOT using a fork
+ return
+ isLocalFork == true
+ ? string.concat(vm.projectRoot(), "/deployments/tmp/", _chainName, ".json")
+ : string.concat(vm.projectRoot(), "/deployments/", _chainName, ".json");
+ }
+ // return the temporary config
+ return string.concat(vm.projectRoot(), "/deployments/tmp/", _chainName, ".json");
+ }
+
+ function _isLocalFork() internal view returns (bool) {
+ bool isLocalFork;
+ try vm.envBool("FORK") returns (bool fork) {
+ isLocalFork = fork;
+ } catch {
+ isLocalFork = false;
+ }
+ return isLocalFork;
+ }
+
+ function _compareStrings(string memory a, string memory b) internal pure returns (bool) {
+ return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));
+ }
+
+ /// @dev broadcast transaction modifier
+ /// @param pk private key to broadcast transaction
+ modifier broadcast(uint256 pk) {
+ vm.startBroadcast(pk);
+
+ _;
+
+ vm.stopBroadcast();
+ }
+}
diff --git a/script/DeployAddressesProviderV2.s.sol b/script/DeployAddressesProviderV2.s.sol
new file mode 100644
index 0000000..be3db99
--- /dev/null
+++ b/script/DeployAddressesProviderV2.s.sol
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/Script.sol";
+import {DeploymentConfig, BaseDeploymentConfig} from "script/BaseConfig.sol";
+import {AddressesProviderV2} from "../src/periphery/AddressesProviderV2.sol";
+import {TransparentUpgradeableProxy} from "./utils/deterministic-deployments/TransparentUpgradeableProxy.sol";
+import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
+
+contract DeployAddressesProviderV2 is Script, BaseDeploymentConfig {
+ bytes32 internal constant SALT = keccak256("sismo-addresses-provider-V2");
+ // create2Factory address from https://github.com/Arachnid/deterministic-deployment-proxy
+ address internal constant CREATE2_FACTORY_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+ address internal constant DETERMINISTIC_DEPLOYMENT_ADDRESS =
+ 0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6;
+
+ function run() public returns (AddressesProviderV2) {
+ string memory chainName = vm.envString("CHAIN_NAME");
+ return runFor(chainName);
+ }
+
+ function runFor(string memory chainName) public returns (AddressesProviderV2) {
+ console.log("Run for CHAIN_NAME:", chainName);
+ console.log("Deployer:", msg.sender);
+
+ _setDeploymentConfig({chainName: chainName, checkIfEmpty: true});
+
+ address addressesProviderV2Address = config.sismoAddressesProviderV2;
+ address owner = config.owner;
+ address proxyAdmin = config.proxyAdmin;
+ address deployer = msg.sender;
+
+ bytes32 TRANSPARENT_UPGRADEABLE_PROXY_INIT_CODE_HASH = keccak256(
+ abi.encodePacked(
+ type(TransparentUpgradeableProxy).creationCode,
+ abi.encode(CREATE2_FACTORY_ADDRESS, deployer, bytes(""))
+ )
+ );
+
+ vm.startBroadcast(deployer);
+
+ if (addressesProviderV2Address != address(0)) {
+ require(false, "AddressesPoviderV2 contract is already deployed!");
+ }
+
+ if (deployer != 0x36D79cf2448b6063DdA4338352da4AFD4C16bf24) {
+ require(
+ false,
+ "Only 0x36D79cf2448b6063DdA4338352da4AFD4C16bf24 can deploy AddressesPoviderV2 contract!"
+ );
+ }
+ if (
+ _getAddress(SALT, TRANSPARENT_UPGRADEABLE_PROXY_INIT_CODE_HASH, CREATE2_FACTORY_ADDRESS) !=
+ DETERMINISTIC_DEPLOYMENT_ADDRESS
+ ) {
+ require(
+ false,
+ "AddressesPoviderV2 contract address should be 0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6!"
+ );
+ }
+
+ console.log("Deploying AddressesPoviderV2 Proxy...");
+
+ // deterministicly deploy the proxy by porviding the create2Factory address as implementation address
+ TransparentUpgradeableProxy addressesProviderV2Proxy = new TransparentUpgradeableProxy{
+ salt: SALT
+ }(CREATE2_FACTORY_ADDRESS, deployer, bytes(""));
+ console.log("AddressesPoviderV2 Proxy Deployed:", address(addressesProviderV2Proxy));
+
+ AddressesProviderV2 addressesProviderV2Implem = new AddressesProviderV2(deployer);
+ console.log("AddressesPoviderV2 Implem Deployed:", address(addressesProviderV2Implem));
+
+ // Upgrade the proxy to use the correct deployed implementation
+ addressesProviderV2Proxy.upgradeToAndCall(
+ address(addressesProviderV2Implem),
+ abi.encodeWithSelector(addressesProviderV2Implem.initialize.selector, deployer)
+ );
+
+ // change proxy admin to proxyAdmin
+ if (addressesProviderV2Proxy.admin() != proxyAdmin) {
+ addressesProviderV2Proxy.changeAdmin(proxyAdmin);
+ console.log("AddressesPoviderV2 proxy admin changed from", deployer, "to", proxyAdmin);
+ }
+
+ AddressesProviderV2 addressesProviderV2 = AddressesProviderV2(
+ address(addressesProviderV2Proxy)
+ );
+
+ // transfer ownership to owner
+ if (addressesProviderV2.owner() != owner) {
+ addressesProviderV2.transferOwnership(owner);
+ console.log("AddressesPoviderV2 ownership transferred from", deployer, "to", owner);
+ }
+
+ DeploymentConfig memory newDeploymentConfig = DeploymentConfig({
+ proxyAdmin: config.proxyAdmin,
+ owner: config.owner,
+ rootsOwner: config.rootsOwner,
+ commitmentMapperEdDSAPubKey: config.commitmentMapperEdDSAPubKey,
+ sismoAddressesProviderV2: address(addressesProviderV2),
+ availableRootsRegistry: config.availableRootsRegistry,
+ commitmentMapperRegistry: config.commitmentMapperRegistry,
+ hydraS3Verifier: config.hydraS3Verifier,
+ sismoConnectVerifier: config.sismoConnectVerifier,
+ authRequestBuilder: config.authRequestBuilder,
+ claimRequestBuilder: config.claimRequestBuilder,
+ signatureBuilder: config.signatureBuilder,
+ requestBuilder: config.requestBuilder
+ });
+
+ _saveDeploymentConfig(chainName, newDeploymentConfig);
+
+ vm.stopBroadcast();
+
+ return addressesProviderV2;
+ }
+
+ function _getAddress(
+ bytes32 _salt,
+ bytes32 _initCodeHash,
+ address create2FactoryAddress
+ ) private pure returns (address) {
+ address deterministicAddress = Create2.computeAddress(
+ _salt,
+ _initCodeHash,
+ create2FactoryAddress
+ );
+ return deterministicAddress;
+ }
+}
diff --git a/script/DeployAvailableRootsRegistry.s.sol b/script/DeployAvailableRootsRegistry.s.sol
new file mode 100644
index 0000000..8f2c16d
--- /dev/null
+++ b/script/DeployAvailableRootsRegistry.s.sol
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/Script.sol";
+import {DeploymentConfig, BaseDeploymentConfig} from "script/BaseConfig.sol";
+import {AvailableRootsRegistry} from "../src/periphery/AvailableRootsRegistry.sol";
+import {TransparentUpgradeableProxy} from "./utils/deterministic-deployments/TransparentUpgradeableProxy.sol";
+import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
+
+contract DeployAvailableRootsRegistry is Script, BaseDeploymentConfig {
+ bytes32 internal constant SALT = keccak256("sismo-available-roots-registry");
+ // create2Factory address from https://github.com/Arachnid/deterministic-deployment-proxy
+ address internal constant CREATE2_FACTORY_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+ address internal constant DETERMINISTIC_DEPLOYMENT_ADDRESS =
+ 0xfB548eC30347c220E4e7733248ff25e3699A4648;
+
+ function run() public returns (AvailableRootsRegistry) {
+ string memory chainName = vm.envString("CHAIN_NAME");
+ return runFor(chainName);
+ }
+
+ function runFor(string memory chainName) public returns (AvailableRootsRegistry) {
+ console.log("Run for CHAIN_NAME:", chainName);
+ console.log("Deployer:", msg.sender);
+
+ _setDeploymentConfig({chainName: chainName, checkIfEmpty: true});
+
+ address availableRootsRegistryAddress = config.availableRootsRegistry;
+ address owner = config.owner;
+ address proxyAdmin = config.proxyAdmin;
+ address deployer = msg.sender;
+
+ bytes32 TRANSPARENT_UPGRADEABLE_PROXY_INIT_CODE_HASH = keccak256(
+ abi.encodePacked(
+ type(TransparentUpgradeableProxy).creationCode,
+ abi.encode(CREATE2_FACTORY_ADDRESS, deployer, bytes(""))
+ )
+ );
+
+ vm.startBroadcast(deployer);
+
+ if ((availableRootsRegistryAddress != address(0)) && (!_compareStrings(chainName, "test"))) {
+ require(false, "AvailableRootsRegistry contract is already deployed!");
+ }
+
+ if (
+ (deployer != 0x36D79cf2448b6063DdA4338352da4AFD4C16bf24) &&
+ (!_compareStrings(chainName, "test"))
+ ) {
+ require(
+ false,
+ "Only 0x36D79cf2448b6063DdA4338352da4AFD4C16bf24 can deploy AvailableRootsRegistry contract!"
+ );
+ }
+ if (
+ (_getAddress(SALT, TRANSPARENT_UPGRADEABLE_PROXY_INIT_CODE_HASH, CREATE2_FACTORY_ADDRESS) !=
+ DETERMINISTIC_DEPLOYMENT_ADDRESS) && (!_compareStrings(chainName, "test"))
+ ) {
+ require(
+ false,
+ "AvailableRootsRegistry contract address should be 0xfB548eC30347c220E4e7733248ff25e3699A4648!"
+ );
+ }
+
+ console.log("Deploying AvailableRootsRegistry Proxy...");
+
+ // deterministicly deploy the proxy by porviding the create2Factory address as implementation address
+ TransparentUpgradeableProxy availableRootsRegistryProxy = new TransparentUpgradeableProxy{
+ salt: SALT
+ }(CREATE2_FACTORY_ADDRESS, deployer, bytes(""));
+ console.log("AvailableRootsRegistry Proxy Deployed:", address(availableRootsRegistryProxy));
+
+ AvailableRootsRegistry availableRootsRegistryImplem = new AvailableRootsRegistry(deployer);
+ console.log("AvailableRootsRegistry Implem Deployed:", address(availableRootsRegistryImplem));
+
+ // Upgrade the proxy to use the correct deployed implementation
+ availableRootsRegistryProxy.upgradeToAndCall(
+ address(availableRootsRegistryImplem),
+ abi.encodeWithSelector(availableRootsRegistryImplem.initialize.selector, deployer)
+ );
+
+ if (availableRootsRegistryProxy.admin() != proxyAdmin) {
+ // change proxy admin to proxyAdmin
+ availableRootsRegistryProxy.changeAdmin(proxyAdmin);
+ console.log("AvailableRootsRegistry proxy admin changed from", deployer, "to", proxyAdmin);
+ }
+
+ AvailableRootsRegistry availableRootsRegistry = AvailableRootsRegistry(
+ address(availableRootsRegistryProxy)
+ );
+
+ if (availableRootsRegistry.owner() != owner) {
+ // transfer ownership to owner
+ availableRootsRegistry.transferOwnership(owner);
+ console.log("AvailableRootsRegistry ownership transferred from", deployer, "to", owner);
+ }
+
+ DeploymentConfig memory newDeploymentConfig = DeploymentConfig({
+ proxyAdmin: proxyAdmin,
+ owner: owner,
+ rootsOwner: config.rootsOwner,
+ commitmentMapperEdDSAPubKey: config.commitmentMapperEdDSAPubKey,
+ sismoAddressesProviderV2: config.sismoAddressesProviderV2,
+ availableRootsRegistry: address(availableRootsRegistry),
+ commitmentMapperRegistry: config.commitmentMapperRegistry,
+ hydraS3Verifier: config.hydraS3Verifier,
+ sismoConnectVerifier: config.sismoConnectVerifier,
+ authRequestBuilder: config.authRequestBuilder,
+ claimRequestBuilder: config.claimRequestBuilder,
+ signatureBuilder: config.signatureBuilder,
+ requestBuilder: config.requestBuilder
+ });
+
+ _saveDeploymentConfig(chainName, newDeploymentConfig);
+
+ vm.stopBroadcast();
+
+ return availableRootsRegistry;
+ }
+
+ function _getAddress(
+ bytes32 _salt,
+ bytes32 _initCodeHash,
+ address create2FactoryAddress
+ ) private pure returns (address) {
+ address deterministicAddress = Create2.computeAddress(
+ _salt,
+ _initCodeHash,
+ create2FactoryAddress
+ );
+ return deterministicAddress;
+ }
+}
diff --git a/script/DeployCommitmentMapperRegistry.s.sol b/script/DeployCommitmentMapperRegistry.s.sol
new file mode 100644
index 0000000..5ef954d
--- /dev/null
+++ b/script/DeployCommitmentMapperRegistry.s.sol
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/Script.sol";
+import {DeploymentConfig, BaseDeploymentConfig} from "script/BaseConfig.sol";
+import {CommitmentMapperRegistry} from "../src/periphery/CommitmentMapperRegistry.sol";
+import {TransparentUpgradeableProxy} from "./utils/deterministic-deployments/TransparentUpgradeableProxy.sol";
+import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
+
+contract DeployCommitmentMapperRegistry is Script, BaseDeploymentConfig {
+ bytes32 internal constant SALT = keccak256("sismo-commitment-mapper-registry");
+ // create2Factory address from https://github.com/Arachnid/deterministic-deployment-proxy
+ address internal constant CREATE2_FACTORY_ADDRESS = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+ address internal constant DETERMINISTIC_DEPLOYMENT_ADDRESS =
+ 0x2ff87b43dbE95d94F56F059cA3506d5d4E8F0470;
+
+ function run() public returns (CommitmentMapperRegistry) {
+ string memory chainName = vm.envString("CHAIN_NAME");
+ return runFor(chainName);
+ }
+
+ function runFor(string memory chainName) public returns (CommitmentMapperRegistry) {
+ console.log("Run for CHAIN_NAME:", chainName);
+ console.log("Deployer:", msg.sender);
+
+ _setDeploymentConfig({chainName: chainName, checkIfEmpty: true});
+
+ address commitmentMapperRegistryAddress = config.commitmentMapperRegistry;
+ address owner = config.owner;
+ uint256[2] memory commitmentMapperPubKeys = config.commitmentMapperEdDSAPubKey;
+ address proxyAdmin = config.proxyAdmin;
+ address deployer = msg.sender;
+
+ bytes32 TRANSPARENT_UPGRADEABLE_PROXY_INIT_CODE_HASH = keccak256(
+ abi.encodePacked(
+ type(TransparentUpgradeableProxy).creationCode,
+ abi.encode(CREATE2_FACTORY_ADDRESS, deployer, bytes(""))
+ )
+ );
+
+ vm.startBroadcast(deployer);
+
+ if ((commitmentMapperRegistryAddress != address(0)) && (!_compareStrings(chainName, "test"))) {
+ require(false, "CommitmentMapperRegistry contract is already deployed!");
+ }
+
+ if (
+ (deployer != 0x36D79cf2448b6063DdA4338352da4AFD4C16bf24) &&
+ (!_compareStrings(chainName, "test"))
+ ) {
+ require(
+ false,
+ "Only 0x36D79cf2448b6063DdA4338352da4AFD4C16bf24 can deploy CommitmentMapperRegistry contract!"
+ );
+ }
+ if (
+ (_getAddress(SALT, TRANSPARENT_UPGRADEABLE_PROXY_INIT_CODE_HASH, CREATE2_FACTORY_ADDRESS) !=
+ DETERMINISTIC_DEPLOYMENT_ADDRESS) && (!_compareStrings(chainName, "test"))
+ ) {
+ require(
+ false,
+ "CommitmentMapperRegistry contract address should be 0x2ff87b43dbE95d94F56F059cA3506d5d4E8F0470!"
+ );
+ }
+
+ console.log("Deploying CommitmentMapperRegistry Proxy...");
+
+ // deterministicly deploy the proxy by porviding the create2Factory address as implementation address
+ TransparentUpgradeableProxy commitmentMapperRegistryProxy = new TransparentUpgradeableProxy{
+ salt: SALT
+ }(CREATE2_FACTORY_ADDRESS, deployer, bytes(""));
+ console.log("CommitmentMapperRegistry Proxy Deployed:", address(commitmentMapperRegistryProxy));
+
+ CommitmentMapperRegistry commitmentMapperRegistryImplem = new CommitmentMapperRegistry(
+ deployer,
+ commitmentMapperPubKeys
+ );
+ console.log(
+ "CommitmentMapperRegistry Implem Deployed:",
+ address(commitmentMapperRegistryImplem)
+ );
+
+ // Upgrade the proxy to use the correct deployed implementation
+ commitmentMapperRegistryProxy.upgradeToAndCall(
+ address(commitmentMapperRegistryImplem),
+ abi.encodeWithSelector(
+ commitmentMapperRegistryImplem.initialize.selector,
+ deployer,
+ commitmentMapperPubKeys
+ )
+ );
+
+ if (commitmentMapperRegistryProxy.admin() != proxyAdmin) {
+ // change proxy admin to proxyAdmin
+ commitmentMapperRegistryProxy.changeAdmin(proxyAdmin);
+ console.log("CommitmentMapperRegistry proxy admin changed from", deployer, "to", proxyAdmin);
+ }
+
+ CommitmentMapperRegistry commitmentMapperRegistry = CommitmentMapperRegistry(
+ address(commitmentMapperRegistryProxy)
+ );
+
+ if (commitmentMapperRegistry.owner() != owner) {
+ // change owner to owner
+ commitmentMapperRegistry.transferOwnership(owner);
+ console.log("CommitmentMapperRegistry ownership transferred from", deployer, "to", owner);
+ }
+
+ DeploymentConfig memory newDeploymentConfig = DeploymentConfig({
+ proxyAdmin: proxyAdmin,
+ owner: owner,
+ rootsOwner: config.rootsOwner,
+ commitmentMapperEdDSAPubKey: commitmentMapperPubKeys,
+ sismoAddressesProviderV2: config.sismoAddressesProviderV2,
+ availableRootsRegistry: config.availableRootsRegistry,
+ commitmentMapperRegistry: address(commitmentMapperRegistry),
+ hydraS3Verifier: config.hydraS3Verifier,
+ sismoConnectVerifier: config.sismoConnectVerifier,
+ authRequestBuilder: config.authRequestBuilder,
+ claimRequestBuilder: config.claimRequestBuilder,
+ signatureBuilder: config.signatureBuilder,
+ requestBuilder: config.requestBuilder
+ });
+
+ _saveDeploymentConfig(chainName, newDeploymentConfig);
+
+ vm.stopBroadcast();
+
+ return commitmentMapperRegistry;
+ }
+
+ function _getAddress(
+ bytes32 _salt,
+ bytes32 _initCodeHash,
+ address create2FactoryAddress
+ ) private pure returns (address) {
+ address deterministicAddress = Create2.computeAddress(
+ _salt,
+ _initCodeHash,
+ create2FactoryAddress
+ );
+ return deterministicAddress;
+ }
+}
diff --git a/script/bash/setup-fork.sh b/script/bash/setup-fork.sh
new file mode 100755
index 0000000..54e00e8
--- /dev/null
+++ b/script/bash/setup-fork.sh
@@ -0,0 +1,60 @@
+#! /bin/bash
+
+# Usage
+# in a first terminal, launch a fork with anvil: `anvil --fork-url https://rpc.ankr.com/polygon_mumbai`
+# in a second terminal, setup the fork to your needs: `yarn setup-fork testnet-mumbai`
+
+# Get chain name from command line arguments to get the config file
+chain_name=$1
+config_file="./deployments/tmp/${chain_name}.json"
+ADDRESSES_PROVIDER_V2_ADDRESS=0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6
+
+# Deploy Sismo Connect protocol contracts on a local fork
+# Deployment is made from the first account of anvil
+FORK=true CHAIN_NAME=$chain_name forge script DeployAll --rpc-url http://127.0.0.1:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --broadcast
+
+# Get AddressesProvider owner
+ADDRESSES_PROVIDER_OWNER=$(cast call $ADDRESSES_PROVIDER_V2_ADDRESS 'owner()' --rpc-url http://localhost:8545 | sed 's/000000000000000000000000//')
+# Impersonate AddressesProvider owner
+cast rpc anvil_impersonateAccount "$ADDRESSES_PROVIDER_OWNER"
+
+# Check if config file is provided and exists
+if [[ -z "$config_file" ]]; then
+ echo "Usage: $0 "
+ exit 1
+elif [[ ! -f "$config_file" ]]; then
+ echo "Error: Config file $config_file does not exist."
+ exit 1
+fi
+
+# Define the contract names
+declare -a contract_keys=("authRequestBuilder"
+ "availableRootsRegistry"
+ "claimRequestBuilder"
+ "commitmentMapperRegistry"
+ "hydraS3Verifier"
+ "requestBuilder"
+ "signatureBuilder"
+ "sismoConnectVerifier")
+
+declare -a contract_values=("authRequestBuilder-v1.1"
+ "sismoConnectAvailableRootsRegistry"
+ "claimRequestBuilder-v1.1"
+ "sismoConnectCommitmentMapperRegistry"
+ "hydraS3Verifier"
+ "requestBuilder-v1.1"
+ "signatureBuilder-v1.1"
+ "sismoConnectVerifier-v1.2")
+
+# Loop over contract names
+for index in "${!contract_keys[@]}"
+do
+ name=${contract_keys[$index]}
+ value=${contract_values[$index]}
+ echo "Set address of contract ${name} to ${value} in the AddressesProvider"
+ # Use jq to parse the JSON file and get the contract address
+ contract_address=$(jq -r .${name} ${config_file})
+
+ # Set the contract address in the AddressesProvider by impersonating the owner thanks to --unlocked
+ cast send $ADDRESSES_PROVIDER_V2_ADDRESS "set(address,string)" ${contract_address} ${value} --unlocked --from $ADDRESSES_PROVIDER_OWNER
+done
\ No newline at end of file
diff --git a/script/utils/PrankAddressesProvider.sol b/script/utils/PrankAddressesProvider.sol
new file mode 100644
index 0000000..d2dc174
--- /dev/null
+++ b/script/utils/PrankAddressesProvider.sol
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/Script.sol";
+import "forge-std/console.sol";
+
+import {IAddressesProvider} from "src/periphery/interfaces/IAddressesProvider.sol";
+
+contract PrankAddressesProvider is Script {
+ function run() external {
+ IAddressesProvider sismoAddressProvider = IAddressesProvider(
+ 0x3340Ac0CaFB3ae34dDD53dba0d7344C1Cf3EFE05
+ );
+ // Addressess Provider owner
+ vm.prank(0xaee4acd5c4Bf516330ca8fe11B07206fC6709294);
+ sismoAddressProvider.set(
+ 0xB8159fe3E3a41213d8AeCE447cfE41037F714cA4,
+ string("sismoConnectVerifier")
+ );
+ }
+}
diff --git a/script/utils/SetAddressesProvider.s.sol b/script/utils/SetAddressesProvider.s.sol
new file mode 100644
index 0000000..b2eed77
--- /dev/null
+++ b/script/utils/SetAddressesProvider.s.sol
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/Script.sol";
+import "forge-std/console.sol";
+
+import {IAddressesProvider} from "src/periphery/interfaces/IAddressesProvider.sol";
+import {BaseDeploymentConfig, DeploymentConfig} from "script/BaseConfig.sol";
+
+contract SetAddressesProvider is Script, BaseDeploymentConfig {
+ function run() external {
+ string memory chainName = vm.envString("CHAIN_NAME");
+ _setDeploymentConfig({chainName: chainName, checkIfEmpty: false});
+
+ console.log("Run for CHAIN_NAME:", chainName);
+ console.log("Sender:", msg.sender);
+
+ vm.startBroadcast();
+
+ _setAddress(config.sismoConnectVerifier, string("sismoConnectVerifier-v1.2"));
+ _setAddress(config.hydraS3Verifier, string("hydraS3Verifier"));
+ _setAddress(config.availableRootsRegistry, string("sismoConnectAvailableRootsRegistry"));
+ _setAddress(config.commitmentMapperRegistry, string("sismoConnectCommitmentMapperRegistry"));
+
+ // external libraries
+
+ _setAddress(config.authRequestBuilder, string("authRequestBuilder-v1.1"));
+ _setAddress(config.claimRequestBuilder, string("claimRequestBuilder-v1.1"));
+ _setAddress(config.signatureBuilder, string("signatureBuilder-v1.1"));
+ _setAddress(config.requestBuilder, string("requestBuilder-v1.1"));
+
+ vm.stopBroadcast();
+ }
+
+ function _setAddress(address contractAddress, string memory contractName) internal {
+ IAddressesProvider sismoAddressProvider = IAddressesProvider(SISMO_ADDRESSES_PROVIDER_V2);
+ address currentContractAddress = sismoAddressProvider.get(contractName);
+
+ if (currentContractAddress != contractAddress) {
+ console.log(
+ "current contract address for ",
+ contractName,
+ " is different. Updating address to ",
+ contractAddress
+ );
+ sismoAddressProvider.set(contractAddress, contractName);
+ } else {
+ console.log(
+ "current contract address for ",
+ contractName,
+ " is already the expected one. skipping update"
+ );
+ }
+ }
+}
diff --git a/script/utils/deterministic-deployments/TransparentUpgradeableProxy.sol b/script/utils/deterministic-deployments/TransparentUpgradeableProxy.sol
new file mode 100644
index 0000000..fe45503
--- /dev/null
+++ b/script/utils/deterministic-deployments/TransparentUpgradeableProxy.sol
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol)
+
+/////////////////////////////////////////////////////////////////////////////////////
+// This contract should be used for Sismo's deterministic deployments of proxies. //
+// It is a copy of the OpenZeppelin's TransparentUpgradeableProxy.sol contract. //
+// The tag of the OpenZeppelin library used along this contract should be v4.8.2. //
+// The commit hash should be d00acef4059807535af0bd0dd0ddf619747a044b. //
+/////////////////////////////////////////////////////////////////////////////////////
+
+pragma solidity ^0.8.0;
+
+import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
+
+/**
+ * @dev This contract implements a proxy that is upgradeable by an admin.
+ *
+ * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
+ * clashing], which can potentially be used in an attack, this contract uses the
+ * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
+ * things that go hand in hand:
+ *
+ * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
+ * that call matches one of the admin functions exposed by the proxy itself.
+ * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
+ * implementation. If the admin tries to call a function on the implementation it will fail with an error that says
+ * "admin cannot fallback to proxy target".
+ *
+ * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
+ * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
+ * to sudden errors when trying to call a function from the proxy implementation.
+ *
+ * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
+ * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
+ */
+contract TransparentUpgradeableProxy is ERC1967Proxy {
+ /**
+ * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
+ * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
+ */
+ constructor(
+ address _logic,
+ address admin_,
+ bytes memory _data
+ ) payable ERC1967Proxy(_logic, _data) {
+ _changeAdmin(admin_);
+ }
+
+ /**
+ * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
+ */
+ modifier ifAdmin() {
+ if (msg.sender == _getAdmin()) {
+ _;
+ } else {
+ _fallback();
+ }
+ }
+
+ /**
+ * @dev Returns the current admin.
+ *
+ * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
+ *
+ * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
+ * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
+ * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
+ */
+ function admin() external ifAdmin returns (address admin_) {
+ admin_ = _getAdmin();
+ }
+
+ /**
+ * @dev Returns the current implementation.
+ *
+ * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
+ *
+ * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
+ * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
+ * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
+ */
+ function implementation() external ifAdmin returns (address implementation_) {
+ implementation_ = _implementation();
+ }
+
+ /**
+ * @dev Changes the admin of the proxy.
+ *
+ * Emits an {AdminChanged} event.
+ *
+ * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
+ */
+ function changeAdmin(address newAdmin) external virtual ifAdmin {
+ _changeAdmin(newAdmin);
+ }
+
+ /**
+ * @dev Upgrade the implementation of the proxy.
+ *
+ * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
+ */
+ function upgradeTo(address newImplementation) external ifAdmin {
+ _upgradeToAndCall(newImplementation, bytes(""), false);
+ }
+
+ /**
+ * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
+ * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
+ * proxied contract.
+ *
+ * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
+ */
+ function upgradeToAndCall(
+ address newImplementation,
+ bytes calldata data
+ ) external payable ifAdmin {
+ _upgradeToAndCall(newImplementation, data, true);
+ }
+
+ /**
+ * @dev Returns the current admin.
+ */
+ function _admin() internal view virtual returns (address) {
+ return _getAdmin();
+ }
+
+ /**
+ * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
+ */
+ function _beforeFallback() internal virtual override {
+ require(
+ msg.sender != _getAdmin(),
+ "TransparentUpgradeableProxy: admin cannot fallback to proxy target"
+ );
+ super._beforeFallback();
+ }
+}
diff --git a/src/SismoConnectVerifier.sol b/src/SismoConnectVerifier.sol
new file mode 100644
index 0000000..c306fe6
--- /dev/null
+++ b/src/SismoConnectVerifier.sol
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.17;
+
+import "./interfaces/ISismoConnectVerifier.sol";
+import {AuthMatchingLib} from "./utils/AuthMatchingLib.sol";
+import {ClaimMatchingLib} from "./utils/ClaimMatchingLib.sol";
+import {IBaseVerifier} from "./interfaces/IBaseVerifier.sol";
+import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
+import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
+
+contract SismoConnectVerifier is ISismoConnectVerifier, Initializable, Ownable {
+ using AuthMatchingLib for Auth;
+ using ClaimMatchingLib for Claim;
+
+ uint8 public constant IMPLEMENTATION_VERSION = 1;
+ bytes32 public immutable SISMO_CONNECT_VERSION = "sismo-connect-v1.1";
+
+ mapping(bytes32 => IBaseVerifier) public _verifiers;
+
+ // struct to store informations about the number of verified auths and claims returned
+ // indexes of the first available slot in the arrays of auths and claims are also stored
+ // this struct is used to avoid stack to deep errors without using via_ir in foundry
+ struct VerifiedArraysInfos {
+ uint256 nbOfAuths; // number of verified auths
+ uint256 nbOfClaims; // number of verified claims
+ uint256 authsIndex; // index of the first available slot in the array of verified auths
+ uint256 claimsIndex; // index of the first available slot in the array of verified claims
+ }
+
+ // Struct holding the verified Auths and Claims from the snark proofs
+ // This struct is used to avoid stack too deep error
+ struct VerifiedProofs {
+ VerifiedAuth[] auths;
+ VerifiedClaim[] claims;
+ }
+
+ constructor(address owner) {
+ initialize(owner);
+ }
+
+ function initialize(address ownerAddress) public reinitializer(IMPLEMENTATION_VERSION) {
+ // if proxy did not setup owner yet or if called by constructor (for implem setup)
+ if (owner() == address(0) || address(this).code.length == 0) {
+ _transferOwnership(ownerAddress);
+ }
+ }
+
+ function verify(
+ SismoConnectResponse memory response,
+ SismoConnectRequest memory request,
+ SismoConnectConfig memory config
+ ) external override returns (SismoConnectVerifiedResult memory) {
+ if (response.appId != config.appId) {
+ revert AppIdMismatch(response.appId, config.appId);
+ }
+
+ _checkResponseMatchesWithRequest(response, request);
+
+ uint256 responseProofsArrayLength = response.proofs.length;
+ VerifiedArraysInfos memory infos = VerifiedArraysInfos({
+ nbOfAuths: 0,
+ nbOfClaims: 0,
+ authsIndex: 0,
+ claimsIndex: 0
+ });
+
+ // Count the number of auths and claims in the response
+ for (uint256 i = 0; i < responseProofsArrayLength; i++) {
+ infos.nbOfAuths += response.proofs[i].auths.length;
+ infos.nbOfClaims += response.proofs[i].claims.length;
+ }
+
+ VerifiedProofs memory verifiedProofs = VerifiedProofs({
+ auths: new VerifiedAuth[](infos.nbOfAuths),
+ claims: new VerifiedClaim[](infos.nbOfClaims)
+ });
+
+ for (uint256 i = 0; i < responseProofsArrayLength; i++) {
+ (VerifiedAuth memory verifiedAuth, VerifiedClaim memory verifiedClaim) = _verifiers[
+ response.proofs[i].provingScheme
+ ].verify({
+ appId: response.appId,
+ namespace: response.namespace,
+ isImpersonationMode: config.vault.isImpersonationMode,
+ signedMessage: response.signedMessage,
+ sismoConnectProof: response.proofs[i]
+ });
+
+ // we only want to add the verified auths and claims to the result
+ // if they are not empty, for that we check the length of the proofData that should always be different from 0
+ if (verifiedAuth.proofData.length != 0) {
+ verifiedProofs.auths[infos.authsIndex] = verifiedAuth;
+ infos.authsIndex++;
+ }
+ if (verifiedClaim.proofData.length != 0) {
+ verifiedProofs.claims[infos.claimsIndex] = verifiedClaim;
+ infos.claimsIndex++;
+ }
+ }
+
+ return
+ SismoConnectVerifiedResult({
+ appId: response.appId,
+ namespace: response.namespace,
+ version: response.version,
+ auths: verifiedProofs.auths,
+ claims: verifiedProofs.claims,
+ signedMessage: response.signedMessage
+ });
+ }
+
+ function _checkResponseMatchesWithRequest(
+ SismoConnectResponse memory response,
+ SismoConnectRequest memory request
+ ) internal view {
+ if (response.version != SISMO_CONNECT_VERSION) {
+ revert VersionMismatch(response.version, SISMO_CONNECT_VERSION);
+ }
+
+ if (response.namespace != request.namespace) {
+ revert NamespaceMismatch(response.namespace, request.namespace);
+ }
+
+ // Check if the message of the signature matches between the request and the response
+ // if the signature request is NOT selectable by the user
+ if (request.signature.isSelectableByUser == false) {
+ // Check if the message signature matches between the request and the response
+ // only if the content of the signature is different from the hash of "MESSAGE_SELECTED_BY_USER"
+ if (
+ keccak256(request.signature.message) != keccak256("MESSAGE_SELECTED_BY_USER") &&
+ // we hash the messages to be able to compare them (as they are of type bytes)
+ keccak256(request.signature.message) != keccak256(response.signedMessage)
+ ) {
+ revert SignatureMessageMismatch(request.signature.message, response.signedMessage);
+ }
+ }
+
+ // we store the auths and claims in the response
+ uint256 nbOfAuths = 0;
+ uint256 nbOfClaims = 0;
+ for (uint256 i = 0; i < response.proofs.length; i++) {
+ nbOfAuths += response.proofs[i].auths.length;
+ nbOfClaims += response.proofs[i].claims.length;
+ }
+
+ Auth[] memory authsInResponse = new Auth[](nbOfAuths);
+ uint256 authsIndex = 0;
+ Claim[] memory claimsInResponse = new Claim[](nbOfClaims);
+ uint256 claimsIndex = 0;
+ // we store the auths and claims in the response in a single respective array
+ for (uint256 i = 0; i < response.proofs.length; i++) {
+ // we do a loop on the proofs array and on the auths array of each proof
+ for (uint256 j = 0; j < response.proofs[i].auths.length; j++) {
+ authsInResponse[authsIndex] = response.proofs[i].auths[j];
+ authsIndex++;
+ }
+ // we do a loop on the proofs array and on the claims array of each proof
+ for (uint256 j = 0; j < response.proofs[i].claims.length; j++) {
+ claimsInResponse[claimsIndex] = response.proofs[i].claims[j];
+ claimsIndex++;
+ }
+ }
+
+ // Check if the auths and claims in the request match the auths and claims int the response
+ _checkAuthsInRequestMatchWithAuthsInResponse({
+ authsInRequest: request.auths,
+ authsInResponse: authsInResponse
+ });
+ _checkClaimsInRequestMatchWithClaimsInResponse({
+ claimsInRequest: request.claims,
+ claimsInResponse: claimsInResponse
+ });
+ }
+
+ function _checkAuthsInRequestMatchWithAuthsInResponse(
+ AuthRequest[] memory authsInRequest,
+ Auth[] memory authsInResponse
+ ) internal pure {
+ // for each auth in the request, we check if it matches with one of the auths in the response
+ for (uint256 i = 0; i < authsInRequest.length; i++) {
+ AuthRequest memory authRequest = authsInRequest[i];
+ if (authRequest.isOptional) {
+ // if the auth in the request is optional, we consider that its properties are all matching
+ // and we don't need to check for errors
+ continue;
+ }
+ // we store the information about the maximum matching properties in a uint8
+ // if the auth in the request matches with an auth in the response, the matchingProperties will be equal to 7 (111)
+ // otherwise, we can look at the binary representation of the matchingProperties to know which properties are not matching and throw an error
+ uint8 maxMatchingPropertiesLevel = 0;
+
+ for (uint256 j = 0; j < authsInResponse.length; j++) {
+ // we store the matching properties for the current auth in the response in a uint8
+ // we will store it in the maxMatchingPropertiesLevel variable if it is greater than the current value of maxMatchingPropertiesLevel
+ Auth memory auth = authsInResponse[j];
+ uint8 matchingPropertiesLevel = auth._matchLevel(authRequest);
+
+ // if the matchingPropertiesLevel are greater than the current value of maxMatchingPropertiesLevel, we update the value of maxMatchingPropertiesLevel
+ // by doing so we will be able to know how close the auth in the request is to the auth in the response
+ if (matchingPropertiesLevel > maxMatchingPropertiesLevel) {
+ maxMatchingPropertiesLevel = matchingPropertiesLevel;
+ }
+ }
+ AuthMatchingLib.handleAuthErrors(maxMatchingPropertiesLevel, authRequest);
+ }
+ }
+
+ function _checkClaimsInRequestMatchWithClaimsInResponse(
+ ClaimRequest[] memory claimsInRequest,
+ Claim[] memory claimsInResponse
+ ) internal pure {
+ // for each claim in the request, we check if it matches with one of the claims in the response
+ for (uint256 i = 0; i < claimsInRequest.length; i++) {
+ ClaimRequest memory claimRequest = claimsInRequest[i];
+ if (claimRequest.isOptional) {
+ // if the claim in the request is optional, we consider that its properties are all matching
+ continue;
+ }
+ // we store the information about the maximum matching properties in a uint8
+ // if the claim in the request matches with a claim in the response, the matchingProperties will be equal to 7 (111)
+ // otherwise, we can look at the binary representation of the matchingProperties to know which properties are not matching and throw an error
+ uint8 maxMatchingProperties = 0;
+
+ for (uint256 j = 0; j < claimsInResponse.length; j++) {
+ Claim memory claim = claimsInResponse[j];
+ uint8 matchingProperties = claim._matchLevel(claimRequest);
+
+ // if the matchingProperties are greater than the current value of maxMatchingProperties, we update the value of maxMatchingProperties
+ // by doing so we will be able to know how close the claim in the request is to the claim in the response
+ if (matchingProperties > maxMatchingProperties) {
+ maxMatchingProperties = matchingProperties;
+ }
+ }
+ ClaimMatchingLib.handleClaimErrors(maxMatchingProperties, claimRequest);
+ }
+ }
+
+ function registerVerifier(bytes32 provingScheme, address verifierAddress) public onlyOwner {
+ _setVerifier(provingScheme, verifierAddress);
+ }
+
+ function getVerifier(bytes32 provingScheme) public view returns (address) {
+ return address(_verifiers[provingScheme]);
+ }
+
+ function _setVerifier(bytes32 provingScheme, address verifierAddress) internal {
+ _verifiers[provingScheme] = IBaseVerifier(verifierAddress);
+ emit VerifierSet(provingScheme, verifierAddress);
+ }
+}
diff --git a/src/misc/CheatSheet.sol b/src/misc/CheatSheet.sol
new file mode 100644
index 0000000..cbe7fae
--- /dev/null
+++ b/src/misc/CheatSheet.sol
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "src/SismoConnectLib.sol";
+import "forge-std/console.sol";
+
+contract CheatSheet is SismoConnect {
+ // reference your appId
+ bytes16 private _appId = 0x32403ced4b65f2079eda77c84e7d2be6;
+ // allow impersonation
+ bool private _isImpersonationMode = true;
+
+ constructor()
+ // use buildConfig helper to easily build a Sismo Connect config in Solidity
+ SismoConnect(buildConfig({appId: _appId, isImpersonationMode: _isImpersonationMode}))
+ {}
+
+ function verifySismoConnectResponse(bytes memory response) public {
+ // Recreate the request made in the fontend to verify the proof
+ AuthRequest[] memory auths = new AuthRequest[](6);
+ auths[0] = _authRequestBuilder.build({authType: AuthType.VAULT});
+ auths[1] = _authRequestBuilder.build({authType: AuthType.EVM_ACCOUNT});
+ auths[2] = _authRequestBuilder.build({
+ authType: AuthType.EVM_ACCOUNT,
+ userId: uint160(0xA4C94A6091545e40fc9c3E0982AEc8942E282F38)
+ });
+ auths[3] = _authRequestBuilder.build({authType: AuthType.GITHUB});
+ auths[4] = _authRequestBuilder.build({
+ authType: AuthType.TWITTER,
+ userId: 295218901,
+ isOptional: true,
+ isSelectableByUser: false
+ });
+ auths[5] = _authRequestBuilder.build({
+ authType: AuthType.TELEGRAM,
+ userId: 875608110,
+ isOptional: true,
+ isSelectableByUser: false
+ });
+
+ ClaimRequest[] memory claims = new ClaimRequest[](6);
+ claims[0] = _claimRequestBuilder.build({groupId: 0xfae674b6cba3ff2f8ce2114defb200b1});
+ claims[1] = _claimRequestBuilder.build({
+ groupId: 0x1cde61966decb8600dfd0749bd371f12,
+ claimType: ClaimType.GTE,
+ value: 15
+ });
+ claims[2] = _claimRequestBuilder.build({
+ groupId: 0xfae674b6cba3ff2f8ce2114defb200b1,
+ claimType: ClaimType.EQ,
+ value: 10
+ });
+ claims[3] = _claimRequestBuilder.build({
+ groupId: 0x1cde61966decb8600dfd0749bd371f12,
+ claimType: ClaimType.EQ,
+ value: 15,
+ isSelectableByUser: true,
+ isOptional: true
+ });
+ claims[4] = _claimRequestBuilder.build({
+ groupId: 0xfae674b6cba3ff2f8ce2114defb200b1,
+ claimType: ClaimType.GTE,
+ isSelectableByUser: true,
+ isOptional: true
+ });
+ claims[5] = _claimRequestBuilder.build({
+ groupId: 0x1cde61966decb8600dfd0749bd371f12,
+ claimType: ClaimType.GTE,
+ value: 25,
+ isSelectableByUser: true,
+ isOptional: false
+ });
+
+ SismoConnectVerifiedResult memory result = verify({
+ responseBytes: response,
+ auths: auths,
+ claims: claims,
+ signature: _signatureBuilder.build({message: abi.encode("I love Sismo!")})
+ });
+
+ uint256 vaultId = SismoConnectHelper.getUserId(result, AuthType.VAULT);
+ uint256 githubId = SismoConnectHelper.getUserId(result, AuthType.GITHUB);
+ uint256 telegramId = SismoConnectHelper.getUserId(result, AuthType.TELEGRAM);
+ uint256[] memory evmAccountIds = SismoConnectHelper.getUserIds(result, AuthType.EVM_ACCOUNT);
+
+ console.log("Vault ID: %s", vaultId);
+ console.log("Github ID: %s", githubId);
+ console.log("Telegram ID: %s", telegramId);
+ console.log("First EVM Account ID: %s", evmAccountIds[0]);
+ console.log("Second EVM Account ID: %s", evmAccountIds[1]);
+ }
+}
diff --git a/src/misc/ZKDropERC721.sol b/src/misc/ZKDropERC721.sol
new file mode 100644
index 0000000..87281a3
--- /dev/null
+++ b/src/misc/ZKDropERC721.sol
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "src/SismoConnectLib.sol";
+import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
+
+contract ZKDropERC721 is ERC721, SismoConnect {
+ using SismoConnectHelper for SismoConnectVerifiedResult;
+
+ bytes16 public immutable GROUP_ID;
+
+ string private _baseTokenURI;
+
+ event BaseTokenURIChanged(string baseTokenURI);
+
+ constructor(
+ string memory name,
+ string memory symbol,
+ string memory baseTokenURI,
+ bytes16 appId,
+ bytes16 groupId
+ ) ERC721(name, symbol) SismoConnect(buildConfig(appId)) {
+ GROUP_ID = groupId;
+ _setBaseTokenURI(baseTokenURI);
+ }
+
+ function claimWithSismoConnect(bytes memory response, address to) public {
+ SismoConnectVerifiedResult memory result = verify({
+ responseBytes: response,
+ auth: buildAuth({authType: AuthType.VAULT}),
+ claim: buildClaim({groupId: GROUP_ID}),
+ signature: buildSignature({message: abi.encode(to)})
+ });
+
+ uint256 tokenId = result.getUserId(AuthType.VAULT);
+ _mint(to, tokenId);
+ }
+
+ function transferWithSismoConnect(bytes memory response, address to) public {
+ SismoConnectVerifiedResult memory result = verify({
+ responseBytes: response,
+ auth: buildAuth({authType: AuthType.VAULT}),
+ claim: buildClaim({groupId: GROUP_ID}),
+ signature: buildSignature({message: abi.encode(to)})
+ });
+
+ uint256 tokenId = result.getUserId(AuthType.VAULT);
+ address from = ownerOf(tokenId);
+ _transfer(from, to, tokenId);
+ }
+
+ function tokenURI(uint256) public view virtual override returns (string memory) {
+ return _baseTokenURI;
+ }
+
+ function _setBaseTokenURI(string memory baseURI) private {
+ _baseTokenURI = baseURI;
+ emit BaseTokenURIChanged(baseURI);
+ }
+}
diff --git a/src/periphery/AddressesProviderV2.sol b/src/periphery/AddressesProviderV2.sol
new file mode 100644
index 0000000..3acecd7
--- /dev/null
+++ b/src/periphery/AddressesProviderV2.sol
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.14;
+
+import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
+import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
+
+import {IAddressesProvider} from "./interfaces/IAddressesProvider.sol";
+
+contract AddressesProviderV2 is IAddressesProvider, Initializable, Ownable {
+ uint8 public constant IMPLEMENTATION_VERSION = 1;
+
+ mapping(bytes32 => address) private _contractAddresses;
+ string[] private _contractNames;
+
+ event ContractAddressSet(address contractAddress, string contractName);
+
+ constructor(address ownerAddress) {
+ initialize(ownerAddress);
+ }
+
+ function initialize(address ownerAddress) public reinitializer(IMPLEMENTATION_VERSION) {
+ // if proxy did not setup owner yet or if called by constructor (for implem setup)
+ if (owner() == address(0) || address(this).code.length == 0) {
+ _transferOwnership(ownerAddress);
+ }
+ }
+
+ /**
+ * @dev Sets the address of a contract.
+ * @param contractAddress Address of the contract.
+ * @param contractName Name of the contract.
+ */
+ function set(address contractAddress, string memory contractName) public onlyOwner {
+ _set(contractAddress, contractName);
+ }
+
+ /**
+ * @dev Sets the address of multiple contracts.
+ * @param contractAddresses Addresses of the contracts.
+ * @param contractNames Names of the contracts.
+ */
+ function setBatch(
+ address[] calldata contractAddresses,
+ string[] calldata contractNames
+ ) external onlyOwner {
+ for (uint256 i = 0; i < contractAddresses.length; i++) {
+ _set(contractAddresses[i], contractNames[i]);
+ }
+ }
+
+ /**
+ * @dev Returns the address of a contract.
+ * @param contractName Name of the contract (string).
+ * @return Address of the contract.
+ */
+ function get(string memory contractName) public view returns (address) {
+ bytes32 contractNameHash = keccak256(abi.encodePacked(contractName));
+
+ return _contractAddresses[contractNameHash];
+ }
+
+ /**
+ * @dev Returns the address of a contract.
+ * @param contractNameHash Hash of the name of the contract (bytes32).
+ * @return Address of the contract.
+ */
+ function get(bytes32 contractNameHash) public view returns (address) {
+ return _contractAddresses[contractNameHash];
+ }
+
+ /**
+ * @dev Returns the addresses of all contracts inputed.
+ * @param contractNames Names of the contracts as strings.
+ */
+ function getBatch(string[] calldata contractNames) external view returns (address[] memory) {
+ address[] memory contractAddresses = new address[](contractNames.length);
+
+ for (uint256 i = 0; i < contractNames.length; i++) {
+ contractAddresses[i] = get(contractNames[i]);
+ }
+
+ return contractAddresses;
+ }
+
+ /**
+ * @dev Returns the addresses of all contracts inputed.
+ * @param contractNamesHash Names of the contracts as bytes32.
+ */
+ function getBatch(bytes32[] calldata contractNamesHash) external view returns (address[] memory) {
+ address[] memory contractAddresses = new address[](contractNamesHash.length);
+
+ for (uint256 i = 0; i < contractNamesHash.length; i++) {
+ contractAddresses[i] = get(contractNamesHash[i]);
+ }
+
+ return contractAddresses;
+ }
+
+ /**
+ * @dev Returns the addresses of all contracts in `_contractNames`
+ * @return Names, Hashed Names and Addresses of all contracts.
+ */
+ function getAll() external view returns (string[] memory, bytes32[] memory, address[] memory) {
+ string[] memory contractNames = _contractNames;
+ bytes32[] memory contractNamesHash = new bytes32[](contractNames.length);
+ address[] memory contractAddresses = new address[](contractNames.length);
+
+ for (uint256 i = 0; i < contractNames.length; i++) {
+ contractAddresses[i] = get(contractNames[i]);
+ contractNamesHash[i] = keccak256(abi.encodePacked(contractNames[i]));
+ }
+
+ return (contractNames, contractNamesHash, contractAddresses);
+ }
+
+ /**
+ * @dev Sets the address of a contract.
+ * @param contractAddress Address of the contract.
+ * @param contractName Name of the contract.
+ */
+ function _set(address contractAddress, string memory contractName) internal {
+ bytes32 contractNameHash = keccak256(abi.encodePacked(contractName));
+
+ if (_contractAddresses[contractNameHash] == address(0)) {
+ _contractNames.push(contractName);
+ }
+
+ _contractAddresses[contractNameHash] = contractAddress;
+
+ emit ContractAddressSet(contractAddress, contractName);
+ }
+}
diff --git a/src/periphery/AvailableRootsRegistry.sol b/src/periphery/AvailableRootsRegistry.sol
new file mode 100644
index 0000000..3265927
--- /dev/null
+++ b/src/periphery/AvailableRootsRegistry.sol
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
+import {IAvailableRootsRegistry} from "./interfaces/IAvailableRootsRegistry.sol";
+import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
+
+/**
+ * @title Attesters Groups Registry
+ * @author Sismo
+ * @notice This contract stores that data required by attesters to be available so they can verify user claims
+ * This contract is deployed behind a proxy and this implementation is focused on storing merkle roots
+ * For more information: https://available-roots-registry.docs.sismo.io
+ *
+ *
+ */
+contract AvailableRootsRegistry is IAvailableRootsRegistry, Initializable, Ownable {
+ uint8 public constant IMPLEMENTATION_VERSION = 1;
+
+ mapping(uint256 => bool) public _roots;
+
+ /**
+ * @dev Constructor
+ * @param owner Owner of the contract, can register/ unregister roots
+ */
+ constructor(address owner) {
+ initialize(owner);
+ }
+
+ /**
+ * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
+ * @param ownerAddress Owner of the contract, can update public key and address
+ * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
+ */
+ function initialize(address ownerAddress) public reinitializer(IMPLEMENTATION_VERSION) {
+ // if proxy did not setup owner yet or if called by constructor (for implem setup)
+ if (owner() == address(0) || address(this).code.length == 0) {
+ _transferOwnership(ownerAddress);
+ }
+ }
+
+ /**
+ * @dev Registers a root
+ * @param root Root to register
+ */
+ function registerRoot(uint256 root) external onlyOwner {
+ _registerRoot(root);
+ }
+
+ /**
+ * @dev Unregister a root
+ * @param root Root to unregister
+ */
+ function unregisterRoot(uint256 root) external onlyOwner {
+ _unregisterRoot(root);
+ }
+
+ /**
+ * @dev returns whether a root is available
+ * @param root root to check whether it is registered
+ */
+ function isRootAvailable(uint256 root) external view returns (bool) {
+ return _roots[root];
+ }
+
+ function _registerRoot(uint256 root) internal {
+ _roots[root] = true;
+ emit RegisteredRoot(root);
+ }
+
+ function _unregisterRoot(uint256 root) internal {
+ _roots[root] = false;
+ emit UnregisteredRoot(root);
+ }
+}
diff --git a/src/periphery/CommitmentMapperRegistry.sol b/src/periphery/CommitmentMapperRegistry.sol
new file mode 100644
index 0000000..f2cbe88
--- /dev/null
+++ b/src/periphery/CommitmentMapperRegistry.sol
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
+import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
+import {ICommitmentMapperRegistry} from "./interfaces/ICommitmentMapperRegistry.sol";
+
+/**
+ * @title Commitment Mapper Registry Contract
+ * @author Sismo
+ * @notice This contract stores information about the commitment mapper.
+ * Its ethereum address and its EdDSA public key
+ * For more information: https://commitment-mapper.docs.sismo.io
+ *
+ *
+ */
+contract CommitmentMapperRegistry is ICommitmentMapperRegistry, Initializable, Ownable {
+ uint8 public constant IMPLEMENTATION_VERSION = 1;
+
+ uint256[2] internal _commitmentMapperPubKey;
+
+ /**
+ * @dev Constructor
+ * @param owner Owner of the contract, can update public key and address
+ * @param commitmentMapperEdDSAPubKey EdDSA public key of the commitment mapper
+ */
+ constructor(address owner, uint256[2] memory commitmentMapperEdDSAPubKey) {
+ initialize(owner, commitmentMapperEdDSAPubKey);
+ }
+
+ /**
+ * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
+ * @param ownerAddress Owner of the contract, can update public key and address
+ * @param commitmentMapperEdDSAPubKey EdDSA public key of the commitment mapper
+ * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
+ */
+ function initialize(
+ address ownerAddress,
+ uint256[2] memory commitmentMapperEdDSAPubKey
+ ) public reinitializer(IMPLEMENTATION_VERSION) {
+ // if proxy did not setup owner yet or if called by constructor (for implem setup)
+ if (owner() == address(0) || address(this).code.length == 0) {
+ _transferOwnership(ownerAddress);
+ _updateCommitmentMapperEdDSAPubKey(commitmentMapperEdDSAPubKey);
+ }
+ }
+
+ /**
+ * @dev Updates the EdDSA public key
+ * @param newEdDSAPubKey new EdDSA pubic key
+ */
+ function updateCommitmentMapperEdDSAPubKey(uint256[2] memory newEdDSAPubKey) external onlyOwner {
+ _updateCommitmentMapperEdDSAPubKey(newEdDSAPubKey);
+ }
+
+ /**
+ * @dev Getter of the EdDSA public key of the commitment mapper
+ */
+ function getEdDSAPubKey() external view override returns (uint256[2] memory) {
+ return _commitmentMapperPubKey;
+ }
+
+ function _updateCommitmentMapperEdDSAPubKey(uint256[2] memory pubKey) internal {
+ _commitmentMapperPubKey = pubKey;
+ emit UpdatedCommitmentMapperEdDSAPubKey(pubKey);
+ }
+}
diff --git a/src/periphery/interfaces/IAddressesProvider.sol b/src/periphery/interfaces/IAddressesProvider.sol
new file mode 100644
index 0000000..54b42e6
--- /dev/null
+++ b/src/periphery/interfaces/IAddressesProvider.sol
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+interface IAddressesProvider {
+ /**
+ * @dev Sets the address of a contract.
+ * @param contractAddress Address of the contract.
+ * @param contractName Name of the contract.
+ */
+ function set(address contractAddress, string memory contractName) external;
+
+ /**
+ * @dev Sets the address of multiple contracts.
+ * @param contractAddresses Addresses of the contracts.
+ * @param contractNames Names of the contracts.
+ */
+ function setBatch(address[] calldata contractAddresses, string[] calldata contractNames) external;
+
+ /**
+ * @dev Returns the address of a contract.
+ * @param contractName Name of the contract (string).
+ * @return Address of the contract.
+ */
+ function get(string memory contractName) external view returns (address);
+
+ /**
+ * @dev Returns the address of a contract.
+ * @param contractNameHash Hash of the name of the contract (bytes32).
+ * @return Address of the contract.
+ */
+ function get(bytes32 contractNameHash) external view returns (address);
+
+ /**
+ * @dev Returns the addresses of all contracts inputed.
+ * @param contractNames Names of the contracts as strings.
+ */
+ function getBatch(string[] calldata contractNames) external view returns (address[] memory);
+
+ /**
+ * @dev Returns the addresses of all contracts inputed.
+ * @param contractNamesHash Names of the contracts as strings.
+ */
+ function getBatch(bytes32[] calldata contractNamesHash) external view returns (address[] memory);
+
+ /**
+ * @dev Returns the addresses of all contracts in `_contractNames`
+ * @return Names, Hashed Names and Addresses of all contracts.
+ */
+ function getAll() external view returns (string[] memory, bytes32[] memory, address[] memory);
+}
diff --git a/src/periphery/interfaces/IAvailableRootsRegistry.sol b/src/periphery/interfaces/IAvailableRootsRegistry.sol
new file mode 100644
index 0000000..338218b
--- /dev/null
+++ b/src/periphery/interfaces/IAvailableRootsRegistry.sol
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.17;
+
+/**
+ * @title IAvailableRootsRegistry
+ * @author Sismo
+ * @notice Interface for (Merkle) Roots Registry
+ */
+interface IAvailableRootsRegistry {
+ event RegisteredRoot(uint256 root);
+ event UnregisteredRoot(uint256 root);
+
+ /**
+ * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
+ * @param owner Owner of the contract, can update public key and address
+ * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
+ */
+ function initialize(address owner) external;
+
+ /**
+ * @dev Register a root
+ * @param root Root to register
+ */
+ function registerRoot(uint256 root) external;
+
+ /**
+ * @dev Unregister a root
+ * @param root Root to unregister
+ */
+ function unregisterRoot(uint256 root) external;
+
+ /**
+ * @dev returns whether a root is available
+ * @param root root to check whether it is registered
+ */
+ function isRootAvailable(uint256 root) external view returns (bool);
+}
diff --git a/src/periphery/interfaces/ICommitmentMapperRegistry.sol b/src/periphery/interfaces/ICommitmentMapperRegistry.sol
new file mode 100644
index 0000000..9b4df2d
--- /dev/null
+++ b/src/periphery/interfaces/ICommitmentMapperRegistry.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+interface ICommitmentMapperRegistry {
+ event UpdatedCommitmentMapperEdDSAPubKey(uint256[2] newEdDSAPubKey);
+
+ error PubKeyNotValid(uint256[2] pubKey);
+
+ /**
+ * @dev Initializes the contract, to be called by the proxy delegating calls to this implementation
+ * @param owner Owner of the contract, can update public key and address
+ * @param commitmentMapperEdDSAPubKey EdDSA public key of the commitment mapper
+ * @notice The reinitializer modifier is needed to configure modules that are added through upgrades and that require initialization.
+ */
+ function initialize(address owner, uint256[2] memory commitmentMapperEdDSAPubKey) external;
+
+ /**
+ * @dev Updates the EdDSA public key
+ * @param newEdDSAPubKey new EdDSA pubic key
+ */
+ function updateCommitmentMapperEdDSAPubKey(uint256[2] memory newEdDSAPubKey) external;
+
+ /**
+ * @dev Getter of the address of the commitment mapper
+ */
+ function getEdDSAPubKey() external view returns (uint256[2] memory);
+}
diff --git a/src/verifiers/HydraS3Lib.sol b/src/verifiers/HydraS3Lib.sol
new file mode 100644
index 0000000..7ba5307
--- /dev/null
+++ b/src/verifiers/HydraS3Lib.sol
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+struct HydraS3CircomSnarkProof {
+ uint256[2] a;
+ uint256[2][2] b;
+ uint256[2] c;
+}
+
+struct HydraS3ProofData {
+ HydraS3CircomSnarkProof proof;
+ uint256[14] input;
+ // destinationIdentifier;
+ // extraData;
+ // commitmentMapperPubKey.X;
+ // commitmentMapperPubKey.Y;
+ // registryTreeRoot;
+ // requestIdentifier;
+ // proofIdentifier;
+ // claimValue;
+ // accountsTreeValue;
+ // claimComparator;
+ // vaultIdentifier;
+ // vaultNamespace;
+ // sourceVerificationEnabled;
+ // destinationVerificationEnabled;
+}
+
+struct HydraS3ProofInput {
+ address destinationIdentifier;
+ uint256 extraData;
+ uint256[2] commitmentMapperPubKey;
+ uint256 registryTreeRoot;
+ uint256 requestIdentifier;
+ uint256 proofIdentifier;
+ uint256 claimValue;
+ uint256 accountsTreeValue;
+ uint256 claimComparator;
+ uint256 vaultIdentifier;
+ uint256 vaultNamespace;
+ bool sourceVerificationEnabled;
+ bool destinationVerificationEnabled;
+}
+
+library HydraS3Lib {
+ uint256 public constant SNARK_FIELD =
+ 21888242871839275222246405745257275088548364400416034343698204186575808495617;
+
+ function _input(HydraS3ProofData memory self) internal pure returns (HydraS3ProofInput memory) {
+ return
+ HydraS3ProofInput(
+ _getDestinationIdentifier(self),
+ _getExtraData(self),
+ _getCommitmentMapperPubKey(self),
+ _getRegistryRoot(self),
+ _getRequestIdentifier(self),
+ _getProofIdentifier(self),
+ _getClaimValue(self),
+ _getAccountsTreeValue(self),
+ _getClaimComparator(self),
+ _getVaultIdentifier(self),
+ _getVaultNamespace(self),
+ _getSourceVerificationEnabled(self),
+ _getDestinationVerificationEnabled(self)
+ );
+ }
+
+ function _toCircomFormat(
+ HydraS3ProofData memory self
+ )
+ internal
+ pure
+ returns (uint256[2] memory, uint256[2][2] memory, uint256[2] memory, uint256[14] memory)
+ {
+ return (self.proof.a, self.proof.b, self.proof.c, self.input);
+ }
+
+ function _getDestinationIdentifier(HydraS3ProofData memory self) internal pure returns (address) {
+ return address(uint160(self.input[0]));
+ }
+
+ function _getExtraData(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[1];
+ }
+
+ function _getCommitmentMapperPubKey(
+ HydraS3ProofData memory self
+ ) internal pure returns (uint256[2] memory) {
+ return [self.input[2], self.input[3]];
+ }
+
+ function _getRegistryRoot(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[4];
+ }
+
+ function _getRequestIdentifier(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[5];
+ }
+
+ function _getProofIdentifier(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[6];
+ }
+
+ function _getClaimValue(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[7];
+ }
+
+ function _getAccountsTreeValue(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[8];
+ }
+
+ function _getClaimComparator(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[9];
+ }
+
+ function _getVaultIdentifier(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[10];
+ }
+
+ function _getVaultNamespace(HydraS3ProofData memory self) internal pure returns (uint256) {
+ return self.input[11];
+ }
+
+ function _getSourceVerificationEnabled(
+ HydraS3ProofData memory self
+ ) internal pure returns (bool) {
+ return self.input[12] == 1;
+ }
+
+ function _getDestinationVerificationEnabled(
+ HydraS3ProofData memory self
+ ) internal pure returns (bool) {
+ return self.input[13] == 1;
+ }
+}
diff --git a/src/verifiers/HydraS3Verifier.sol b/src/verifiers/HydraS3Verifier.sol
new file mode 100644
index 0000000..959632b
--- /dev/null
+++ b/src/verifiers/HydraS3Verifier.sol
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/console.sol";
+import {IBaseVerifier} from "../interfaces/IBaseVerifier.sol";
+import {IHydraS3Verifier} from "./IHydraS3Verifier.sol";
+import {HydraS3Verifier as HydraS3SnarkVerifier} from "@sismo-core/hydra-s3/HydraS3Verifier.sol";
+import {ICommitmentMapperRegistry} from "../periphery/interfaces/ICommitmentMapperRegistry.sol";
+import {IAvailableRootsRegistry} from "../periphery/interfaces/IAvailableRootsRegistry.sol";
+import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
+import {HydraS3ProofData, HydraS3Lib, HydraS3ProofInput} from "./HydraS3Lib.sol";
+import {Auth, ClaimType, AuthType, Claim, SismoConnectProof, VerifiedAuth, VerifiedClaim} from "src/utils/Structs.sol";
+
+contract HydraS3Verifier is IHydraS3Verifier, IBaseVerifier, HydraS3SnarkVerifier, Initializable {
+ using HydraS3Lib for HydraS3ProofData;
+ using HydraS3Lib for Auth;
+ using HydraS3Lib for Claim;
+
+ // Struct holding the decoded Hydra-S3 snark proof and decoded public inputs
+ // This struct is used to avoid stack too deep error
+ struct HydraS3Proof {
+ HydraS3ProofData data;
+ HydraS3ProofInput input;
+ }
+
+ // Struct holding the verified Auth and Claim from the Hydra-S3 snark proof
+ // This struct is used to avoid stack too deep error
+ struct VerifiedProof {
+ VerifiedAuth auth;
+ VerifiedClaim claim;
+ }
+
+ uint8 public constant IMPLEMENTATION_VERSION = 1;
+ bytes32 public immutable HYDRA_S3_VERSION = "hydra-s3.1";
+ // Registry storing the Commitment Mapper EdDSA Public key
+ ICommitmentMapperRegistry public immutable COMMITMENT_MAPPER_REGISTRY;
+ // Registry storing the Registry Tree Roots of the Attester's available ClaimData
+ IAvailableRootsRegistry public immutable AVAILABLE_ROOTS_REGISTRY;
+
+ // Impersonation Commitment Mapper EdDSA Public key
+ uint256 public constant impersonationCommitmentMapperPubKeyX =
+ 0x1801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b;
+ uint256 public constant impersonationCommitmentMapperPubKeyY =
+ 0x057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b;
+
+ constructor(address commitmentMapperRegistry, address availableRootsRegistry) {
+ COMMITMENT_MAPPER_REGISTRY = ICommitmentMapperRegistry(commitmentMapperRegistry);
+ AVAILABLE_ROOTS_REGISTRY = IAvailableRootsRegistry(availableRootsRegistry);
+ initialize();
+ }
+
+ function initialize() public reinitializer(IMPLEMENTATION_VERSION) {}
+
+ function verify(
+ bytes16 appId,
+ bytes16 namespace,
+ bool isImpersonationMode,
+ bytes memory signedMessage,
+ SismoConnectProof memory sismoConnectProof
+ ) external returns (VerifiedAuth memory, VerifiedClaim memory) {
+ // Verify the sismoConnectProof version corresponds to the current verifier.
+ if (sismoConnectProof.provingScheme != HYDRA_S3_VERSION) {
+ revert InvalidVersion(sismoConnectProof.provingScheme);
+ }
+
+ HydraS3Proof memory hydraS3Proof = HydraS3Proof({
+ // Decode the snark proof data from the sismoConnectProof
+ data: abi.decode(sismoConnectProof.proofData, (HydraS3ProofData)),
+ // Get the public inputs from the snark proof data
+ input: abi.decode(sismoConnectProof.proofData, (HydraS3ProofData))._input()
+ });
+
+ // We only support one Auth and one Claim in the hydra-s3 proving scheme
+ // We revert if there is more than one Auth or Claim in the sismoConnectProof
+ if (sismoConnectProof.auths.length > 1 || sismoConnectProof.claims.length > 1) {
+ revert OnlyOneAuthAndOneClaimIsSupported();
+ }
+
+ // Verify Claim, Auth and SignedMessage validity by checking corresponding
+ // snarkProof public input
+ VerifiedProof memory verifiedProof;
+ if (sismoConnectProof.auths.length == 1) {
+ // Get the Auth from the sismoConnectProof
+ // We only support one Auth in the hydra-s3 proving scheme
+ Auth memory auth = sismoConnectProof.auths[0];
+ verifiedProof.auth = _verifyAuthValidity(
+ hydraS3Proof.input,
+ sismoConnectProof.proofData,
+ auth,
+ appId,
+ isImpersonationMode
+ );
+ }
+ if (sismoConnectProof.claims.length == 1) {
+ // Get the Claim from the sismoConnectProof
+ // We only support one Claim in the hydra-s3 proving scheme
+ Claim memory claim = sismoConnectProof.claims[0];
+ verifiedProof.claim = _verifyClaimValidity(
+ hydraS3Proof.input,
+ sismoConnectProof.proofData,
+ claim,
+ appId,
+ namespace,
+ isImpersonationMode
+ );
+ }
+
+ _validateSignedMessageInput(hydraS3Proof.input, signedMessage);
+
+ // Check the snarkProof is valid
+ _checkSnarkProof(hydraS3Proof.data);
+ return (verifiedProof.auth, verifiedProof.claim);
+ }
+
+ function _verifyClaimValidity(
+ HydraS3ProofInput memory input,
+ bytes memory proofData,
+ Claim memory claim,
+ bytes16 appId,
+ bytes16 namespace,
+ bool isImpersonationMode
+ ) private view returns (VerifiedClaim memory) {
+ // Check claim value validity
+ if (input.claimValue != claim.value) {
+ revert ClaimValueMismatch();
+ }
+
+ // Check requestIdentifier validity
+ uint256 expectedRequestIdentifier = _encodeRequestIdentifier(
+ claim.groupId,
+ claim.groupTimestamp,
+ appId,
+ namespace
+ );
+ if (input.requestIdentifier != expectedRequestIdentifier) {
+ revert RequestIdentifierMismatch(input.requestIdentifier, expectedRequestIdentifier);
+ }
+
+ // commitmentMapperPubKey
+ // In impersonation mode, we use the EdDSA public key of the Impersonation Commitment Mapper
+ // otherwise we use the EdDSA public key of the Commitment Mapper Registry
+ uint256[2] memory commitmentMapperPubKey = isImpersonationMode
+ ? [impersonationCommitmentMapperPubKeyX, impersonationCommitmentMapperPubKeyY]
+ : COMMITMENT_MAPPER_REGISTRY.getEdDSAPubKey();
+
+ if (
+ input.commitmentMapperPubKey[0] != commitmentMapperPubKey[0] ||
+ input.commitmentMapperPubKey[1] != commitmentMapperPubKey[1]
+ ) {
+ revert CommitmentMapperPubKeyMismatch(
+ bytes32(commitmentMapperPubKey[0]),
+ bytes32(commitmentMapperPubKey[1]),
+ bytes32(input.commitmentMapperPubKey[0]),
+ bytes32(input.commitmentMapperPubKey[1])
+ );
+ }
+
+ // sourceVerificationEnabled
+ if (input.sourceVerificationEnabled == false) {
+ revert SourceVerificationNotEnabled();
+ }
+ // isRootAvailable
+ if (!AVAILABLE_ROOTS_REGISTRY.isRootAvailable(input.registryTreeRoot)) {
+ revert RegistryRootNotAvailable(input.registryTreeRoot);
+ }
+ // accountsTreeValue
+ uint256 groupSnapshotId = _encodeAccountsTreeValue(claim.groupId, claim.groupTimestamp);
+ if (input.accountsTreeValue != groupSnapshotId) {
+ revert AccountsTreeValueMismatch(input.accountsTreeValue, groupSnapshotId);
+ }
+
+ bool claimComparatorEQ = input.claimComparator == 1;
+ bool isClaimTypeFromClaimEqualToEQ = claim.claimType == ClaimType.EQ;
+ if (claimComparatorEQ != isClaimTypeFromClaimEqualToEQ) {
+ revert ClaimTypeMismatch(input.claimComparator, uint256(claim.claimType));
+ }
+
+ return
+ VerifiedClaim({
+ groupId: claim.groupId,
+ groupTimestamp: claim.groupTimestamp,
+ value: claim.value,
+ claimType: claim.claimType,
+ proofId: input.proofIdentifier,
+ proofData: proofData,
+ extraData: claim.extraData
+ });
+ }
+
+ function _verifyAuthValidity(
+ HydraS3ProofInput memory input,
+ bytes memory proofData,
+ Auth memory auth,
+ bytes16 appId,
+ bool isImpersonationMode
+ ) private view returns (VerifiedAuth memory) {
+ uint256 userIdFromProof;
+ if (auth.authType == AuthType.VAULT) {
+ // vaultNamespace validity
+ uint256 vaultNamespaceFromProof = input.vaultNamespace;
+ uint256 expectedVaultNamespace = _encodeVaultNamespace(appId);
+ if (vaultNamespaceFromProof != expectedVaultNamespace) {
+ revert VaultNamespaceMismatch(vaultNamespaceFromProof, expectedVaultNamespace);
+ }
+ userIdFromProof = input.vaultIdentifier;
+ } else {
+ if (input.destinationVerificationEnabled == false) {
+ revert DestinationVerificationNotEnabled();
+ }
+ // commitmentMapperPubKey
+ uint256[2] memory commitmentMapperPubKey = isImpersonationMode
+ ? [impersonationCommitmentMapperPubKeyX, impersonationCommitmentMapperPubKeyY]
+ : COMMITMENT_MAPPER_REGISTRY.getEdDSAPubKey();
+ if (
+ input.commitmentMapperPubKey[0] != commitmentMapperPubKey[0] ||
+ input.commitmentMapperPubKey[1] != commitmentMapperPubKey[1]
+ ) {
+ revert CommitmentMapperPubKeyMismatch(
+ bytes32(commitmentMapperPubKey[0]),
+ bytes32(commitmentMapperPubKey[1]),
+ bytes32(input.commitmentMapperPubKey[0]),
+ bytes32(input.commitmentMapperPubKey[1])
+ );
+ }
+ userIdFromProof = uint256(uint160(input.destinationIdentifier));
+ _checkSismoIdentifierValidity(userIdFromProof, auth.authType);
+ }
+
+ // check that the userId from the proof is the same as the userId in the auth
+ // the userId in the proof is the vaultIdentifier for AuthType.VAULT and the destinationIdentifier for other Auth types
+ if (
+ auth.userId != userIdFromProof && !auth.isSelectableByUser // we do NOT check the userId if it has been made selectable by user in the vault app
+ ) {
+ revert UserIdMismatch(userIdFromProof, auth.userId);
+ }
+
+ return
+ VerifiedAuth({
+ authType: auth.authType,
+ isAnon: auth.isAnon,
+ userId: userIdFromProof,
+ extraData: auth.extraData,
+ proofData: proofData
+ });
+ }
+
+ function _validateSignedMessageInput(
+ HydraS3ProofInput memory input,
+ bytes memory signedMessage
+ ) private pure {
+ // don't check extraData if signedMessage from response is empty
+ if (keccak256(signedMessage) == keccak256(abi.encode(0x00))) {
+ return;
+ }
+ if (input.extraData != uint256(keccak256(signedMessage)) % HydraS3Lib.SNARK_FIELD) {
+ revert InvalidExtraData(
+ input.extraData,
+ uint256(keccak256(signedMessage)) % HydraS3Lib.SNARK_FIELD
+ );
+ }
+ }
+
+ function _checkSismoIdentifierValidity(uint256 userId, AuthType authType) private pure {
+ // the userId is 160 bits long (20 bytes), since it has the format of an evm address
+ if (authType == AuthType.GITHUB) {
+ // check that the userId starts with 0x1001 -> sismoIdentifier for dataSource GITHUB
+ // 160 bits - 16 bits = 144 bits
+ // we check that the first 16 bits are equal to 0x1001
+ if ((userId) >> 144 != 0x1001) {
+ revert InvalidSismoIdentifier(bytes32(userId), uint8(authType));
+ }
+ }
+ if (authType == AuthType.TWITTER) {
+ // check that the userId starts with 0x1002 -> sismoIdentifier for dataSource Twitter
+ // 160 bits - 16 bits = 144 bits
+ // we check that the first 16 bits are equal to 0x1002
+ if ((userId) >> 144 != 0x1002) {
+ revert InvalidSismoIdentifier(bytes32(userId), uint8(authType));
+ }
+ }
+ if (authType == AuthType.TELEGRAM) {
+ // check that the userId starts with 0x1003 -> sismoIdentifier for dataSource Telegram
+ // 160 bits - 16 bits = 144 bits
+ // we check that the first 16 bits are equal to 0x1003
+ if ((userId) >> 144 != 0x1003) {
+ revert InvalidSismoIdentifier(bytes32(userId), uint8(authType));
+ }
+ }
+ }
+
+ function _checkSnarkProof(HydraS3ProofData memory snarkProofData) internal {
+ // low-level call to the `verifyProof` function
+ // since the function only accepts arguments located in calldata
+ (bool success, bytes memory result) = address(this).call(
+ abi.encodeWithSelector(
+ this.verifyProof.selector,
+ snarkProofData.proof.a,
+ snarkProofData.proof.b,
+ snarkProofData.proof.c,
+ snarkProofData.input
+ )
+ );
+
+ if (!success) {
+ revert CallToVerifyProofFailed();
+ }
+ bool isVerified = abi.decode(result, (bool));
+
+ if (!isVerified) {
+ revert InvalidProof();
+ }
+ }
+
+ function _encodeRequestIdentifier(
+ bytes16 groupId,
+ bytes16 groupTimestamp,
+ bytes16 appId,
+ bytes16 namespace
+ ) internal pure returns (uint256) {
+ bytes32 groupSnapshotId = _encodeGroupSnapshotId(groupId, groupTimestamp);
+ bytes32 serviceId = _encodeServiceId(appId, namespace);
+ return
+ uint256(keccak256(abi.encodePacked(serviceId, groupSnapshotId))) % HydraS3Lib.SNARK_FIELD;
+ }
+
+ function _encodeAccountsTreeValue(
+ bytes16 groupId,
+ bytes16 groupTimestamp
+ ) internal pure returns (uint256) {
+ return uint256(_encodeGroupSnapshotId(groupId, groupTimestamp)) % HydraS3Lib.SNARK_FIELD;
+ }
+
+ function _encodeGroupSnapshotId(
+ bytes16 groupId,
+ bytes16 groupTimestamp
+ ) internal pure returns (bytes32) {
+ return bytes32(abi.encodePacked(groupId, groupTimestamp));
+ }
+
+ function _encodeServiceId(bytes16 appId, bytes16 namespace) internal pure returns (bytes32) {
+ return bytes32(abi.encodePacked(appId, namespace));
+ }
+
+ function _encodeVaultNamespace(bytes16 appId) internal pure returns (uint256) {
+ return uint256(keccak256(abi.encodePacked(appId, bytes16(0)))) % HydraS3Lib.SNARK_FIELD;
+ }
+}
diff --git a/src/verifiers/IHydraS3Verifier.sol b/src/verifiers/IHydraS3Verifier.sol
new file mode 100644
index 0000000..a73c766
--- /dev/null
+++ b/src/verifiers/IHydraS3Verifier.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+contract IHydraS3Verifier {
+ error InvalidProof();
+ error CallToVerifyProofFailed();
+ error InvalidSismoIdentifier(bytes32 userId, uint8 authType);
+ error OnlyOneAuthAndOneClaimIsSupported();
+
+ error InvalidVersion(bytes32 version);
+ error RegistryRootNotAvailable(uint256 inputRoot);
+ error DestinationMismatch(address destinationFromProof, address expectedDestination);
+ error CommitmentMapperPubKeyMismatch(
+ bytes32 expectedX,
+ bytes32 expectedY,
+ bytes32 inputX,
+ bytes32 inputY
+ );
+
+ error ClaimTypeMismatch(uint256 claimTypeFromProof, uint256 expectedClaimType);
+ error RequestIdentifierMismatch(
+ uint256 requestIdentifierFromProof,
+ uint256 expectedRequestIdentifier
+ );
+ error InvalidExtraData(uint256 extraDataFromProof, uint256 expectedExtraData);
+ error ClaimValueMismatch();
+ error DestinationVerificationNotEnabled();
+ error SourceVerificationNotEnabled();
+ error AccountsTreeValueMismatch(
+ uint256 accountsTreeValueFromProof,
+ uint256 expectedAccountsTreeValue
+ );
+ error VaultNamespaceMismatch(uint256 vaultNamespaceFromProof, uint256 expectedVaultNamespace);
+ error UserIdMismatch(uint256 userIdFromProof, uint256 expectedUserId);
+}
diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol
new file mode 100644
index 0000000..dd68314
--- /dev/null
+++ b/test/BaseTest.t.sol
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/Test.sol";
+import "forge-std/console.sol";
+import {AddressesProviderMock} from "./mocks/AddressesProviderMock.sol";
+import {IAddressesProvider} from "src/periphery/interfaces/IAddressesProvider.sol";
+import {SismoConnectVerifier} from "src/SismoConnectVerifier.sol";
+import {RequestBuilder, AuthRequestBuilder, ClaimRequestBuilder, SignatureBuilder} from "src/SismoConnectLib.sol";
+
+contract BaseTest is Test {
+ address immutable user1 = vm.addr(1);
+ address immutable user2 = vm.addr(2);
+ address immutable owner = vm.addr(3);
+ address immutable sismoAddressProviderV2 = 0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6;
+
+ AddressesProviderMock addressesProvider;
+ SismoConnectVerifier sismoConnectVerifier;
+
+ // external libraries
+ AuthRequestBuilder authRequestBuilder;
+ ClaimRequestBuilder claimRequestBuilder;
+ SignatureBuilder signatureBuilder;
+ RequestBuilder requestBuilder;
+
+ function setUp() public virtual {
+ addressesProvider = new AddressesProviderMock();
+ sismoConnectVerifier = new SismoConnectVerifier(owner);
+
+ // external libraries
+ authRequestBuilder = new AuthRequestBuilder();
+ claimRequestBuilder = new ClaimRequestBuilder();
+ signatureBuilder = new SignatureBuilder();
+ requestBuilder = new RequestBuilder();
+
+ vm.etch(sismoAddressProviderV2, address(addressesProvider).code);
+
+ IAddressesProvider(sismoAddressProviderV2).set(
+ address(sismoConnectVerifier),
+ string("sismoConnectVerifier-v1.2")
+ );
+ IAddressesProvider(sismoAddressProviderV2).set(
+ address(authRequestBuilder),
+ string("authRequestBuilder-v1.1")
+ );
+ IAddressesProvider(sismoAddressProviderV2).set(
+ address(claimRequestBuilder),
+ string("claimRequestBuilder-v1.1")
+ );
+ IAddressesProvider(sismoAddressProviderV2).set(
+ address(signatureBuilder),
+ string("signatureBuilder-v1.1")
+ );
+ IAddressesProvider(sismoAddressProviderV2).set(
+ address(requestBuilder),
+ string("requestBuilder-v1.1")
+ );
+ }
+}
diff --git a/test/e2e/SismoConnectE2E.t.sol b/test/e2e/SismoConnectE2E.t.sol
new file mode 100644
index 0000000..3aef7b0
--- /dev/null
+++ b/test/e2e/SismoConnectE2E.t.sol
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.17;
+
+import "forge-std/console.sol";
+import "src/utils/Fmt.sol";
+import {HydraS3BaseTest} from "../verifiers/hydra-s3/HydraS3BaseTest.t.sol";
+import {SismoConnect, RequestBuilder, ClaimRequestBuilder} from "src/SismoConnectLib.sol";
+import {ZKDropERC721} from "src/misc/ZKDropERC721.sol";
+import {CheatSheet} from "src/misc/CheatSheet.sol";
+import "src/utils/Structs.sol";
+import {SismoConnectHarness} from "../harness/SismoConnectHarness.sol";
+
+import {AuthBuilder} from "src/utils/AuthBuilder.sol";
+import {ClaimBuilder} from "src/utils/ClaimBuilder.sol";
+import {ResponseBuilder, ResponseWithoutProofs} from "../utils/ResponseBuilderLib.sol";
+import {BaseDeploymentConfig} from "script/BaseConfig.sol";
+import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
+import {UpgradeableExample} from "../misc/UpgradeableExample.sol";
+
+// E2E tests for SismoConnect Solidity Library
+// These tests are made with proofs generated from the Vault App
+// These tests should not use any Verifier mocks
+
+contract SismoConnectE2E is HydraS3BaseTest {
+ using ResponseBuilder for SismoConnectResponse;
+ using ResponseBuilder for ResponseWithoutProofs;
+
+ SismoConnectHarness sismoConnect;
+ address user = 0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE;
+
+ // default values for tests
+ bytes16 public DEFAULT_APP_ID = 0x11b1de449c6c4adb0b5775b3868b28b3;
+ bytes16 public DEFAULT_NAMESPACE = bytes16(keccak256("main"));
+ bytes32 public DEFAULT_VERSION = bytes32("sismo-connect-v1.1");
+ bytes public DEFAULT_SIGNED_MESSAGE = abi.encode(user);
+
+ bool public DEFAULT_IS_IMPERSONATION_MODE = false;
+
+ ResponseWithoutProofs public DEFAULT_RESPONSE =
+ ResponseBuilder
+ .emptyResponseWithoutProofs()
+ .withAppId(DEFAULT_APP_ID)
+ .withVersion(DEFAULT_VERSION)
+ .withNamespace(DEFAULT_NAMESPACE)
+ .withSignedMessage(DEFAULT_SIGNED_MESSAGE);
+
+ ClaimRequest claimRequest;
+ AuthRequest authRequest;
+ SignatureRequest signature;
+
+ bytes16 immutable APP_ID_ZK_DROP = 0x11b1de449c6c4adb0b5775b3868b28b3;
+ bytes16 immutable ZK = 0xe9ed316946d3d98dfcd829a53ec9822e;
+ ZKDropERC721 zkdrop;
+
+ CheatSheet cheatsheet;
+
+ function setUp() public virtual override {
+ super.setUp();
+ sismoConnect = new SismoConnectHarness(DEFAULT_APP_ID, DEFAULT_IS_IMPERSONATION_MODE);
+ claimRequest = sismoConnect.exposed_buildClaim({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+ authRequest = sismoConnect.exposed_buildAuth({authType: AuthType.VAULT});
+ signature = sismoConnect.exposed_buildSignature({message: abi.encode(user)});
+
+ zkdrop = new ZKDropERC721({
+ appId: APP_ID_ZK_DROP,
+ groupId: ZK,
+ name: "ZKDrop test",
+ symbol: "test",
+ baseTokenURI: "https://test.com"
+ });
+ console.log("ZkDrop contract deployed at", address(zkdrop));
+
+ cheatsheet = new CheatSheet();
+ }
+
+ function test_SismoConnectLibWithOnlyClaimAndMessage() public {
+ (, bytes memory responseEncoded) = hydraS3Proofs.getResponseWithOneClaimAndSignature();
+
+ sismoConnect.exposed_verify({
+ responseBytes: responseEncoded,
+ request: requestBuilder.build({
+ claim: sismoConnect.exposed_buildClaim({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e}),
+ signature: sismoConnect.exposed_buildSignature({message: abi.encode(user)})
+ })
+ });
+ }
+
+ function test_SismoConnectLibWithTwoClaimsAndMessage() public {
+ (, bytes memory responseEncoded) = hydraS3Proofs.getResponseWithTwoClaimsAndSignature();
+
+ ClaimRequest[] memory claims = new ClaimRequest[](2);
+ claims[0] = sismoConnect.exposed_buildClaim({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+ claims[1] = sismoConnect.exposed_buildClaim({groupId: 0x02d241fdb9d4330c564ffc0a36af05f6});
+
+ sismoConnect.exposed_verify({
+ responseBytes: responseEncoded,
+ request: requestBuilder.build({
+ claims: claims,
+ signature: sismoConnect.exposed_buildSignature({message: abi.encode(user)})
+ })
+ });
+ }
+
+ function test_SismoConnectLibWithOnlyOneAuth() public {
+ (, bytes memory responseEncoded) = hydraS3Proofs.getResponseWithOnlyOneAuthAndMessage();
+
+ SismoConnectRequest memory request = requestBuilder.build({
+ auth: sismoConnect.exposed_buildAuth({authType: AuthType.VAULT}),
+ signature: signature
+ });
+
+ SismoConnectVerifiedResult memory verifiedResult = sismoConnect.exposed_verify(
+ responseEncoded,
+ request
+ );
+ assertTrue(verifiedResult.auths[0].userId != 0);
+ }
+
+ function test_SismoConnectLibWithClaimAndAuth() public {
+ (, bytes memory responseEncoded) = hydraS3Proofs.getResponseWithOneClaimOneAuthAndOneMessage();
+ SismoConnectRequest memory request = requestBuilder.build({
+ auth: sismoConnect.exposed_buildAuth({authType: AuthType.VAULT}),
+ claim: sismoConnect.exposed_buildClaim({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e}),
+ signature: signature
+ });
+
+ SismoConnectVerifiedResult memory verifiedResult = sismoConnect.exposed_verify(
+ responseEncoded,
+ request
+ );
+ assertTrue(verifiedResult.auths[0].userId != 0);
+ }
+
+ function test_ClaimAndAuthWithSignedMessageZKDROP() public {
+ // address that reverts if not modulo SNARK_FIELD after hashing the signedMessage for the circuit
+ // should keep this address for testing purposes
+ user = 0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE;
+
+ // proof of membership for user in group 0xe9ed316946d3d98dfcd829a53ec9822e
+ // vault ownership
+ // signedMessage: 0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE
+ bytes
+ memory responseEncoded = hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007def1d6d28d6bda49e69fa89ad75d160becba3ae00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c00e13d5898f45a0578526ca3d9048c9a0ed6a6dc6af46118f330a10c2bd905a180a5606df9b8c074aa82aa92fba759f79bfe2ea93b120f88477fc2506071e07932953767a6bba7cde1264cd886e85f97233cf12dec2cdf5ee8f3d295a1c603ee200a14357ed867808c4c9cfdd3eadbaaccab985c3c98563eb9bd97f0ae4a86dfb1854e21c9405301c914a1bcd93e827f34bcedb21419c5edcf2c022a719da63262a905da8df1c751d7aa8761ca691f950011a9016f152e06d67a076f72547002b1af4e79cb9e150f94bfb43b295ee3eba90f4f21c096cbda50215e37d86b095920d953743b8c045b0d4342370648b1f9444ce5c706602f20d2df4a2139997ee4b000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000e9ed316946d3d98dfcd829a53ec9822e000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c02f1f6f738b95cb3ad82c8d6f9d3f76542a489959b5c54da7d9d7b48413136b580dcd5851ffe286e00cbcdb644972e2f98b96772258f243160c501fa350a98282301793ae676f391ef110b70c0fd3286c5f2679582cbb3371792174af6f1c78490851df3f5b6054ab215fd07ad52bcaac91e7a342611126ec56ceed3ce47a756e066fea74f29aba48ed861174b8adb71406661e423e19a9c49df73c8b2b868d3d2c9fe708d9654b09e0ae44948b81d3970118e6bc771ca258f79a5047bfac8e8c2bd36792147ed1c1e4d5bea0ccc70abc636b98e49aa89f3b857673b3cac2cad809c1face7ad71275738dd61ca3683d1edb5d6acea0b177ddcf7771ff8758f057000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ zkdrop.claimWithSismoConnect(responseEncoded, user);
+ }
+
+ function test_TwoClaimsOneVaultAuthWithSignature() public {
+ ClaimRequest[] memory claims = new ClaimRequest[](2);
+ claims[0] = claimRequestBuilder.build({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+ claims[1] = claimRequestBuilder.build({groupId: 0x02d241fdb9d4330c564ffc0a36af05f6});
+
+ AuthRequest[] memory auths = new AuthRequest[](1);
+ auths[0] = authRequestBuilder.build({authType: AuthType.VAULT});
+
+ SismoConnectRequest memory request = requestBuilder.build({
+ claims: claims,
+ auths: auths,
+ signature: signature
+ });
+
+ (, bytes memory responseEncoded) = hydraS3Proofs
+ .getResponseWithTwoClaimsOneAuthAndOneSignature();
+
+ SismoConnectVerifiedResult memory verifiedResult = sismoConnect.exposed_verify({
+ responseBytes: responseEncoded,
+ request: request
+ });
+ console.log("Claims in Verified result: %s", verifiedResult.claims.length);
+ }
+
+ function test_ThreeClaimsOneVaultAuthWithSignatureOneClaimOptional() public {
+ ClaimRequest[] memory claims = new ClaimRequest[](3);
+ claims[0] = claimRequestBuilder.build({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+ claims[1] = claimRequestBuilder.build({groupId: 0x02d241fdb9d4330c564ffc0a36af05f6});
+ claims[2] = claimRequestBuilder.build({
+ groupId: 0x42c768bb8ae79e4c5c05d3b51a4ec74a,
+ isOptional: true,
+ isSelectableByUser: false
+ });
+
+ AuthRequest[] memory auths = new AuthRequest[](1);
+ auths[0] = authRequestBuilder.build({authType: AuthType.VAULT});
+
+ SismoConnectRequest memory request = requestBuilder.build({
+ claims: claims,
+ auths: auths,
+ signature: signature
+ });
+
+ (, bytes memory responseEncoded) = hydraS3Proofs
+ .getResponseWithTwoClaimsOneAuthAndOneSignature();
+
+ SismoConnectVerifiedResult memory verifiedResult = sismoConnect.exposed_verify({
+ responseBytes: responseEncoded,
+ request: request
+ });
+ console.log("Claims in Verified result: %s", verifiedResult.claims.length);
+ }
+
+ function test_ThreeClaimsOneVaultAuthOneTwitterAuthWithSignatureOneClaimOptional() public {
+ ClaimRequest[] memory claims = new ClaimRequest[](3);
+ claims[0] = claimRequestBuilder.build({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+ claims[1] = claimRequestBuilder.build({groupId: 0x02d241fdb9d4330c564ffc0a36af05f6});
+ claims[2] = claimRequestBuilder.build({
+ groupId: 0x42c768bb8ae79e4c5c05d3b51a4ec74a,
+ isOptional: true,
+ isSelectableByUser: false
+ });
+
+ AuthRequest[] memory auths = new AuthRequest[](2);
+ auths[0] = authRequestBuilder.build({authType: AuthType.VAULT});
+ auths[1] = authRequestBuilder.build({
+ authType: AuthType.TWITTER,
+ isOptional: true,
+ isSelectableByUser: true
+ });
+
+ SismoConnectRequest memory request = requestBuilder.build({
+ claims: claims,
+ auths: auths,
+ signature: signature
+ });
+
+ (, bytes memory responseEncoded) = hydraS3Proofs
+ .getResponseWithTwoClaimsOneAuthAndOneSignature();
+
+ SismoConnectVerifiedResult memory verifiedResult = sismoConnect.exposed_verify({
+ responseBytes: responseEncoded,
+ request: request
+ });
+ console.log("Claims in Verified result: %s", verifiedResult.claims.length);
+ }
+
+ function test_OneClaimOneOptionalTwitterAuthOneGithubAuthWithSignature() public {
+ ClaimRequest[] memory claims = new ClaimRequest[](1);
+ claims[0] = claimRequestBuilder.build({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+
+ AuthRequest[] memory auths = new AuthRequest[](2);
+ auths[0] = authRequestBuilder.build({authType: AuthType.GITHUB});
+ auths[1] = authRequestBuilder.build({
+ authType: AuthType.TWITTER,
+ isOptional: true,
+ isSelectableByUser: true
+ });
+
+ SismoConnectRequest memory request = requestBuilder.build({
+ claims: claims,
+ auths: auths,
+ signature: signature
+ });
+
+ bytes
+ memory responseEncoded = hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007def1d6d28d6bda49e69fa89ad75d160becba3ae00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000009e000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000100100000000000000000000000000009999037000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c01f5237cda37ca2237bfa10de427ae030eeec24a6ce9d8d1131b15f7fcb5f168f2cd27a37a8cecf4a922e209910d04ab67165610d401aeb8d3f9c8b4a6f81239425860952ce7cdf52b06c6f7861e10ab049b8df45c18b1fec6230c1bb9d5744fe1cc5acd00634a05a6dbf82f95b338f2d71fb3c88ec5219b2b8c98bea55a4dd3014d0a71a383a1e1d31902460cf0fa23c528be517436887dd4b82af41d6ab09c2062c4454dca040336cda21c314f5bc213f0b917908a89c5b0c1b2db31b8953ba1e1b07dbd0f19bec715b1aa331f632c258d9e084e309972550004c05f6340d732ca967c1ff768dd26409f9f987b9522fad5c4112f203a9b93119fadc85e30c9a000000000000000000000000100100000000000000000000000000009999037009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000100200000000000000000000000000288480976500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0254797b44b8f3a253c02e3b84c8694458a8d498c2592e7b36c965519fc92503400c58413e606342362077d258766e55fc09135bdcb933e11db23bdcdce4ad23c2828525ef73b62575d2f2e6a471349e28e3ca63bc6b542bd6a0c8a3995750deb2da5fc828781d6aa5c5993bc43cb1e58cf6ddb8353503efc0d8f927956c9ec871dc864a6441d35fd9b774ac4a5380933666f6ad7c9e1ef1f1b24b87037fa2f5513ac71eaa4f51ddcf248dafff8e6c8205cabafcfacab21b7adb98167e9c5bb5f2aea54095c0246922547be93dce8b8e3fd87d4c5399d67377e63d9b90a30195025918b506c8d12293e48f224acddf120e8f890fe851bb9ba178b642beb4ded23000000000000000000000000100200000000000000000000000000288480976509f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000e9ed316946d3d98dfcd829a53ec9822e000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c025f517407b6ea0ed90092fefb10a570a25e5c769acb42b98671e5ecc381a01bc26f2a04c85eec86c263e919be89ed6bae72fff9267e25674b0b1242f68c9722601dc85685a7d3423f9b1a3b63ef08a76379118fb1eb29821acd8165ae8e1d12f0528e916f26707be18a37f1c8f0a2792a5891d340438d6221cb137614c8b5b7520c0d1e29393509cbd8822cd8f5278e8a4203ca6baf007f5328b5abe9e175d802d3ecc77bb73e2f85b32033405a3dbe0920ac3a318bd329fc1b410e22f98f518269b9554c33dbc905c5f210d9555ca2b166733c814e904bd21ea298e2894ae6b0251474f760ccc6c335321cc4fb58f6d858ac6d6de7c2670a93148f9d3a1b060000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+
+ SismoConnectVerifiedResult memory verifiedResult = sismoConnect.exposed_verify({
+ responseBytes: responseEncoded,
+ request: request
+ });
+ console.log("Claims in Verified result: %s", verifiedResult.claims.length);
+ }
+
+ function test_GitHubAuth() public {
+ (, bytes memory encodedResponse) = hydraS3Proofs.getResponseWithGitHubAuth();
+
+ SismoConnectRequest memory request = requestBuilder.build({
+ auth: sismoConnect.exposed_buildAuth({authType: AuthType.GITHUB}),
+ signature: signature
+ });
+
+ sismoConnect.exposed_verify({responseBytes: encodedResponse, request: request});
+ }
+
+ function test_GitHubAuthWithoutSignature() public {
+ (, bytes memory encodedResponse) = hydraS3Proofs.getResponseWithGitHubAuthWithoutSignature();
+
+ SismoConnectRequest memory request = requestBuilder.build({
+ auth: sismoConnect.exposed_buildAuth({authType: AuthType.GITHUB})
+ });
+
+ sismoConnect.exposed_verify({responseBytes: encodedResponse, request: request});
+ }
+
+ function test_withProxy() public {
+ SignatureRequest memory signatureRequest = sismoConnect.exposed_buildSignature({
+ message: abi.encode(user)
+ });
+
+ UpgradeableExample sismoConnectImplem = new UpgradeableExample(
+ DEFAULT_APP_ID,
+ DEFAULT_IS_IMPERSONATION_MODE,
+ 0xe9ed316946d3d98dfcd829a53ec9822e
+ );
+
+ TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
+ address(sismoConnectImplem),
+ address(1),
+ abi.encodeWithSelector(
+ sismoConnectImplem.initialize.selector,
+ bytes16(0xe9ed316946d3d98dfcd829a53ec9822e)
+ )
+ );
+
+ UpgradeableExample upgradeable = UpgradeableExample(address(proxy));
+
+ (, bytes memory responseEncoded) = hydraS3Proofs.getResponseWithOneClaimAndSignature();
+
+ upgradeable.exposed_verify({responseBytes: responseEncoded, signature: signatureRequest});
+
+ // add an additional groupId in the contract
+ upgradeable.addGroupId({groupId: 0xff7653240feecd7448150005a95ac86b});
+
+ // verify again
+ // it should throw since the response is the same but another claim request is required
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "ClaimGroupIdNotFound(bytes16)",
+ bytes16(0xff7653240feecd7448150005a95ac86b)
+ )
+ );
+ upgradeable.exposed_verify({responseBytes: responseEncoded, signature: signatureRequest});
+ }
+
+ function test_RevertWithInvalidSismoIdentifier() public {
+ (SismoConnectResponse memory response, ) = hydraS3Proofs
+ .getResponseWithGitHubAuthWithoutSignature();
+
+ // specify in the response that the proof comes from a telegram ownership
+ // but the proof is actually a github ownership
+ response.proofs[0].auths[0].authType = AuthType.TELEGRAM;
+
+ // request a telegram proof of ownership
+ SismoConnectRequest memory request = requestBuilder.build({
+ auth: sismoConnect.exposed_buildAuth({authType: AuthType.TELEGRAM})
+ });
+
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "InvalidSismoIdentifier(bytes32,uint8)",
+ 0x0000000000000000000000001001000000000000000000000000000099990370,
+ 4
+ )
+ );
+ sismoConnect.exposed_verify({responseBytes: abi.encode(response), request: request});
+ }
+
+ function test_CheatSheet() public {
+ bytes memory responseBytes = hydraS3Proofs.getCheatSheetResponse();
+ cheatsheet.verifySismoConnectResponse(responseBytes);
+ }
+
+ // helpers
+
+ function emptyResponse() private pure returns (SismoConnectResponse memory) {
+ return ResponseBuilder.empty();
+ }
+}
diff --git a/test/harness/SismoConnectHarness.sol b/test/harness/SismoConnectHarness.sol
new file mode 100644
index 0000000..ac6f133
--- /dev/null
+++ b/test/harness/SismoConnectHarness.sol
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.17;
+
+import "src/SismoConnectLib.sol";
+
+// This contract is used to expose internal functions of SismoConnect for testing purposes
+// It is NOT deployed in production
+// see: https://book.getfoundry.sh/tutorials/best-practices?highlight=coverage#test-harnesses
+contract SismoConnectHarness is SismoConnect {
+ constructor(
+ bytes16 appId,
+ bool isImpersonationMode
+ ) SismoConnect(buildConfig(appId, isImpersonationMode)) {}
+
+ function exposed_buildClaim(bytes16 groupId) external view returns (ClaimRequest memory) {
+ return buildClaim(groupId);
+ }
+
+ function exposed_buildAuth(AuthType authType) external view returns (AuthRequest memory) {
+ return buildAuth(authType);
+ }
+
+ function exposed_buildAuth(
+ AuthType authType,
+ bool isAnon
+ ) external view returns (AuthRequest memory) {
+ return buildAuth({authType: authType, isAnon: isAnon});
+ }
+
+ function exposed_buildAuth(
+ AuthType authType,
+ bool isOptional,
+ bool isSelectableByUser
+ ) external view returns (AuthRequest memory) {
+ return
+ buildAuth({
+ authType: authType,
+ isOptional: isOptional,
+ isSelectableByUser: isSelectableByUser
+ });
+ }
+
+ function exposed_buildAuth(
+ AuthType authType,
+ uint256 userId
+ ) external view returns (AuthRequest memory) {
+ return buildAuth({authType: authType, userId: userId});
+ }
+
+ function exposed_buildAuth(
+ AuthType authType,
+ bool isSelectableByUser,
+ bool isOptional,
+ uint256 userId
+ ) external view returns (AuthRequest memory) {
+ return
+ buildAuth({
+ authType: authType,
+ isSelectableByUser: isSelectableByUser,
+ isOptional: isOptional,
+ userId: userId
+ });
+ }
+
+ function exposed_buildSignature(
+ bytes memory message
+ ) external view returns (SignatureRequest memory) {
+ return buildSignature(message);
+ }
+
+ function exposed_verify(
+ bytes memory responseBytes,
+ ClaimRequest memory claim
+ ) external returns (SismoConnectVerifiedResult memory) {
+ return verify({responseBytes: responseBytes, claim: claim});
+ }
+
+ function exposed_verify(
+ bytes memory responseBytes,
+ ClaimRequest memory claim,
+ bytes16 namespace
+ ) external returns (SismoConnectVerifiedResult memory) {
+ return verify({responseBytes: responseBytes, claim: claim, namespace: namespace});
+ }
+
+ function exposed_verify(
+ bytes memory responseBytes,
+ ClaimRequest memory claim,
+ SignatureRequest memory signature
+ ) external returns (SismoConnectVerifiedResult memory) {
+ return verify({responseBytes: responseBytes, claim: claim, signature: signature});
+ }
+
+ function exposed_verify(
+ bytes memory responseBytes,
+ AuthRequest memory auth,
+ SignatureRequest memory signature
+ ) external returns (SismoConnectVerifiedResult memory) {
+ return verify({responseBytes: responseBytes, auth: auth, signature: signature});
+ }
+
+ function exposed_verify(
+ bytes memory responseBytes,
+ SismoConnectRequest memory request
+ ) external returns (SismoConnectVerifiedResult memory) {
+ return verify({responseBytes: responseBytes, request: request});
+ }
+}
diff --git a/test/libs/SismoConnectLib.t.sol b/test/libs/SismoConnectLib.t.sol
new file mode 100644
index 0000000..a11e797
--- /dev/null
+++ b/test/libs/SismoConnectLib.t.sol
@@ -0,0 +1,449 @@
+// SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.17;
+
+import "forge-std/console.sol";
+import "src/utils/Fmt.sol";
+import {VerifierMockBaseTest} from "../verifiers/mocks/VerifierMockBaseTest.t.sol";
+import {SismoConnect, RequestBuilder, ClaimRequestBuilder} from "src/SismoConnectLib.sol";
+import {ZKDropERC721} from "src/misc/ZKDropERC721.sol";
+import "src/utils/Structs.sol";
+import {SismoConnectHarness} from "../harness/SismoConnectHarness.sol";
+
+import {AuthBuilder} from "src/utils/AuthBuilder.sol";
+import {ClaimBuilder} from "src/utils/ClaimBuilder.sol";
+import {ResponseBuilder, ResponseWithoutProofs} from "../utils/ResponseBuilderLib.sol";
+import {BaseDeploymentConfig} from "script/BaseConfig.sol";
+
+contract SismoConnectLibTest is VerifierMockBaseTest {
+ using ResponseBuilder for SismoConnectResponse;
+ using ResponseBuilder for ResponseWithoutProofs;
+
+ SismoConnectHarness sismoConnect;
+ address user = 0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE;
+
+ // default values for tests
+ bytes16 public DEFAULT_APP_ID = 0x11b1de449c6c4adb0b5775b3868b28b3;
+ bytes16 public DEFAULT_NAMESPACE = bytes16(keccak256("main"));
+ bytes32 public DEFAULT_VERSION = bytes32("sismo-connect-v1.1");
+ bytes public DEFAULT_SIGNED_MESSAGE = abi.encode(user);
+
+ bool public DEFAULT_IS_IMPERSONATION_MODE = false;
+
+ bytes32 public DEFAULT_PROVING_SCHEME = bytes32("mock-scheme");
+
+ ResponseWithoutProofs public DEFAULT_RESPONSE =
+ ResponseBuilder
+ .emptyResponseWithoutProofs()
+ .withAppId(DEFAULT_APP_ID)
+ .withVersion(DEFAULT_VERSION)
+ .withNamespace(DEFAULT_NAMESPACE)
+ .withSignedMessage(DEFAULT_SIGNED_MESSAGE);
+
+ ClaimRequest claimRequest;
+ AuthRequest authRequest;
+ SignatureRequest signature;
+
+ bytes16 immutable APP_ID_ZK_DROP = 0x11b1de449c6c4adb0b5775b3868b28b3;
+ bytes16 immutable ZK = 0xe9ed316946d3d98dfcd829a53ec9822e;
+ ZKDropERC721 zkdrop;
+
+ function setUp() public virtual override {
+ super.setUp();
+ sismoConnect = new SismoConnectHarness(DEFAULT_APP_ID, DEFAULT_IS_IMPERSONATION_MODE);
+ claimRequest = sismoConnect.exposed_buildClaim({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+ authRequest = sismoConnect.exposed_buildAuth({authType: AuthType.VAULT});
+ signature = sismoConnect.exposed_buildSignature({message: abi.encode(user)});
+
+ zkdrop = new ZKDropERC721({
+ appId: APP_ID_ZK_DROP,
+ groupId: ZK,
+ name: "ZKDrop test",
+ symbol: "test",
+ baseTokenURI: "https://test.com"
+ });
+ console.log("ZkDrop contract deployed at", address(zkdrop));
+ }
+
+ // Tests that should revert
+
+ function test_RevertWith_EmptyMessageIfSismoConnectResponseIsEmpty() public {
+ bytes memory responseBytes = hex"";
+ // we just expect a revert with an empty responseBytes as far as the decoding will not be successful
+ vm.expectRevert();
+ sismoConnect.exposed_verify({responseBytes: responseBytes, claim: claimRequest});
+ }
+
+ function test_RevertWith_InvalidUserIdAndIsSelectableByUserAuthType() public {
+ // When `userId` is 0, it means the app does not require a specific auth account and the user needs
+ // to choose the account they want to use for the app.
+ // When `isSelectableByUser` is true, the user can select the account they want to use.
+ // The combination of `userId = 0` and `isSelectableByUser = false` does not make sense and should not be used.
+
+ // Here we do expect the revert since we set isSelectableByUser to false
+ // and we keep the default value for userId which is 0
+ // effectivelly triggering the revert
+ // Note: we use an AuthType different from VAULT to not trigger another revert
+ vm.expectRevert(abi.encodeWithSignature("InvalidUserIdAndIsSelectableByUserAuthType()"));
+ sismoConnect.exposed_buildAuth({
+ authType: AuthType.GITHUB,
+ isOptional: false,
+ isSelectableByUser: false
+ });
+ }
+
+ function test_RevertWith_InvalidUserIdAndAuthType() public {
+ // When `userId` is 0, it means the app does not require a specific auth account and the user needs
+ // to choose the account they want to use for the app.
+ // When `isSelectableByUser` is true, the user can select the account they want to use.
+ // The combination of `userId = 0` and `isSelectableByUser = false` does not make sense and should not be used.
+
+ // Here we set isSelectableByUser to false but we add a userId different from zero
+ // while choosing The AuthType VAULT, which does NOT make sense since it states that we allow the user to choose a vault account in his vault
+ // but in the case of the AuthType VAULT, the account is the vault itself and therefore there is no choice to make
+ // we should definitely revert based on this reasoning
+ vm.expectRevert(abi.encodeWithSignature("InvalidUserIdAndAuthType()"));
+ sismoConnect.exposed_buildAuth({
+ authType: AuthType.VAULT,
+ isOptional: false,
+ isSelectableByUser: false,
+ userId: uint256(bytes32("wrong-id"))
+ });
+ }
+
+ function test_RevertWith_VersionMismatch() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE
+ .withVersion(bytes32("wrong-version"))
+ .build();
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "VersionMismatch(bytes32,bytes32)",
+ invalidResponse.version,
+ DEFAULT_VERSION
+ )
+ );
+ sismoConnect.exposed_verify({responseBytes: abi.encode(invalidResponse), claim: claimRequest});
+ }
+
+ function test_RevertWith_NamespaceMismatch() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE
+ .withNamespace(bytes16(keccak256("wrong-namespace")))
+ .build();
+
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "NamespaceMismatch(bytes16,bytes16)",
+ invalidResponse.namespace,
+ DEFAULT_NAMESPACE
+ )
+ );
+ sismoConnect.exposed_verify({responseBytes: abi.encode(invalidResponse), claim: claimRequest});
+ }
+
+ function test_RevertWith_AppIdMismatch() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withAppId("wrong-id").build();
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "AppIdMismatch(bytes16,bytes16)",
+ invalidResponse.appId,
+ DEFAULT_APP_ID
+ )
+ );
+ sismoConnect.exposed_verify({responseBytes: abi.encode(invalidResponse), claim: claimRequest});
+ }
+
+ function test_RevertWith_SignatureMessageMismatch() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE
+ .withSignedMessage("wrong-signed-message")
+ .build();
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "SignatureMessageMismatch(bytes,bytes)",
+ signature.message,
+ invalidResponse.signedMessage
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_AuthInRequestNotFoundInResponse() public {
+ // we expect a revert since no proofs are provided in the response
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.build();
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "AuthInRequestNotFoundInResponse(uint8,bool,uint256,bytes)",
+ authRequest.authType,
+ authRequest.isAnon,
+ authRequest.userId,
+ authRequest.extraData
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: authRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_AuthIsAnonAndUserIdNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withAuth({
+ auth: AuthBuilder.build({authType: AuthType.GITHUB, isAnon: true, userId: uint256(0xc0de)})
+ });
+ // we need to choose a different AuthType than AUthType.VAULT to be able to test if the userId error is thrown
+ // we also need to set the userId different from zero since isSelectableByUser is false
+ // it means that we are waiting for a userId in the response that actually means something so different from zero
+ // we set userId of the request to 0xf00 to be different from the one in the response
+ AuthRequest memory auth = sismoConnect.exposed_buildAuth({
+ authType: AuthType.GITHUB,
+ isOptional: false,
+ isSelectableByUser: false,
+ userId: uint256(0xf00)
+ });
+
+ vm.expectRevert(
+ abi.encodeWithSignature("AuthIsAnonAndUserIdNotFound(bool,uint256)", auth.isAnon, auth.userId)
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: auth,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_AuthTypeAndUserIdNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withAuth({
+ auth: AuthBuilder.build({authType: AuthType.VAULT, userId: uint256(bytes32("wrong-id"))})
+ });
+ // we need to choose a different AuthType than AUthType.VAULT to be able to test if the userId error is thrown
+ // we set userId of the request to 0xf00 to be different from the one in the response
+ AuthRequest memory auth = sismoConnect.exposed_buildAuth({
+ authType: AuthType.GITHUB,
+ userId: uint256(0xf00)
+ }); // wrong userId
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "AuthTypeAndUserIdNotFound(uint8,uint256)",
+ auth.authType,
+ auth.userId
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: auth,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_AuthUserIdNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withAuth({
+ auth: AuthBuilder.build({authType: AuthType.GITHUB, userId: uint256(bytes32("wrong-id"))})
+ });
+ // we need to choose a different AuthType than AUthType.VAULT to be able to test if the userId error is thrown
+ // we set userId of the request to 0xf00 to be different from the one in the response
+ AuthRequest memory auth = sismoConnect.exposed_buildAuth({
+ authType: AuthType.GITHUB,
+ userId: uint256(0xf00)
+ }); // wrong userId
+ vm.expectRevert(abi.encodeWithSignature("AuthUserIdNotFound(uint256)", auth.userId));
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: auth,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_AuthTypeAndIsAnonNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withAuth({
+ auth: AuthBuilder.build({authType: AuthType.VAULT, isAnon: true})
+ });
+ AuthRequest memory auth = sismoConnect.exposed_buildAuth({
+ authType: AuthType.GITHUB,
+ isAnon: false
+ });
+ vm.expectRevert(
+ abi.encodeWithSignature("AuthTypeAndIsAnonNotFound(uint8,bool)", auth.authType, auth.isAnon)
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: auth,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_AuthIsAnonNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withAuth({
+ auth: AuthBuilder.build({authType: AuthType.VAULT, isAnon: true})
+ });
+ AuthRequest memory auth = sismoConnect.exposed_buildAuth({
+ authType: AuthType.VAULT,
+ isAnon: false
+ });
+ vm.expectRevert(abi.encodeWithSignature("AuthIsAnonNotFound(bool)", auth.isAnon));
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: auth,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_AuthTypeNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withAuth({
+ auth: AuthBuilder.build({authType: AuthType.VAULT})
+ });
+ AuthRequest memory auth = sismoConnect.exposed_buildAuth({authType: AuthType.GITHUB});
+ vm.expectRevert(abi.encodeWithSignature("AuthTypeNotFound(uint8)", auth.authType));
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: auth,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_ClaimInRequestNotFoundInResponse() public {
+ // we expect a revert since no proofs are provided in the response
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.build();
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "ClaimInRequestNotFoundInResponse(uint8,bytes16,bytes16,uint256,bytes)",
+ claimRequest.claimType,
+ claimRequest.groupId,
+ claimRequest.groupTimestamp,
+ claimRequest.value,
+ claimRequest.extraData
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_ClaimGroupIdAndGroupTimestampNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withClaim({
+ claim: ClaimBuilder.build({groupId: "wrong-id", groupTimestamp: bytes16("fake-timestamp")})
+ });
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "ClaimGroupIdAndGroupTimestampNotFound(bytes16,bytes16)",
+ claimRequest.groupId,
+ claimRequest.groupTimestamp
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_ClaimTypeAndGroupTimestampNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withClaim({
+ claim: ClaimBuilder.build({
+ groupId: claimRequest.groupId,
+ groupTimestamp: bytes16("fake-timestamp"),
+ claimType: ClaimType.LTE
+ })
+ });
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "ClaimTypeAndGroupTimestampNotFound(uint8,bytes16)",
+ claimRequest.claimType,
+ claimRequest.groupTimestamp
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_ClaimGroupTimestampNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withClaim({
+ claim: ClaimBuilder.build({
+ groupId: claimRequest.groupId,
+ groupTimestamp: bytes16("wrong-timestamp")
+ })
+ });
+ invalidResponse.proofs[0].claims[0].groupTimestamp = bytes16("fake-timestamp");
+ vm.expectRevert(
+ abi.encodeWithSignature("ClaimGroupTimestampNotFound(bytes16)", claimRequest.groupTimestamp)
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_ClaimTypeAndGroupIdNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withClaim({
+ claim: ClaimBuilder.build({groupId: "wrong-id", claimType: ClaimType.LTE})
+ });
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "ClaimTypeAndGroupIdNotFound(uint8,bytes16)",
+ claimRequest.claimType,
+ claimRequest.groupId
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_ClaimGroupIdNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withClaim({
+ claim: ClaimBuilder.build({groupId: bytes16("wrong-group-id")})
+ });
+ vm.expectRevert(abi.encodeWithSignature("ClaimGroupIdNotFound(bytes16)", claimRequest.groupId));
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_ClaimTypeNotFound() public {
+ SismoConnectResponse memory invalidResponse = DEFAULT_RESPONSE.withClaim({
+ claim: ClaimBuilder.build({groupId: claimRequest.groupId, claimType: ClaimType.LTE})
+ });
+ vm.expectRevert(
+ abi.encodeWithSignature("ClaimTypeNotFound(uint8)", uint8(claimRequest.claimType))
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_OneAuthOneClaimOneSignature() public {
+ SismoConnectResponse memory validResponse = DEFAULT_RESPONSE
+ .withAuth({
+ auth: AuthBuilder.build({authType: AuthType.VAULT}),
+ provingScheme: DEFAULT_PROVING_SCHEME
+ })
+ .withClaim({
+ claim: ClaimBuilder.build({groupId: claimRequest.groupId}),
+ provingScheme: DEFAULT_PROVING_SCHEME
+ });
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(validResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ // helpers
+
+ function emptyResponse() private pure returns (SismoConnectResponse memory) {
+ return ResponseBuilder.empty();
+ }
+}
diff --git a/test/misc/UpgradeableExample.sol b/test/misc/UpgradeableExample.sol
new file mode 100644
index 0000000..67137f8
--- /dev/null
+++ b/test/misc/UpgradeableExample.sol
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
+import "src/SismoConnectLib.sol";
+
+contract UpgradeableExample is SismoConnect, Initializable {
+ bytes16[] private _groupIds;
+
+ constructor(
+ bytes16 appId,
+ bool isImpersonationMode,
+ bytes16 groupId
+ ) SismoConnect(buildConfig(appId, isImpersonationMode)) {
+ initialize(groupId);
+ }
+
+ function initialize(bytes16 groupId) public initializer {
+ _groupIds.push(groupId);
+ }
+
+ function addGroupId(bytes16 groupId) public {
+ _groupIds.push(groupId);
+ }
+
+ function getGroupIds() public view returns (bytes16[] memory) {
+ return _groupIds;
+ }
+
+ function exposed_buildSignature(
+ bytes memory message
+ ) external view returns (SignatureRequest memory) {
+ return buildSignature(message);
+ }
+
+ function exposed_verify(
+ bytes memory responseBytes,
+ SignatureRequest memory signature
+ ) external returns (SismoConnectVerifiedResult memory) {
+ ClaimRequest[] memory claims = new ClaimRequest[](_groupIds.length);
+ for (uint256 i = 0; i < _groupIds.length; i++) {
+ claims[i] = buildClaim(_groupIds[i]);
+ }
+ return verify({responseBytes: responseBytes, claims: claims, signature: signature});
+ }
+}
diff --git a/test/mocks/AddressesProviderMock.sol b/test/mocks/AddressesProviderMock.sol
new file mode 100644
index 0000000..3401bfe
--- /dev/null
+++ b/test/mocks/AddressesProviderMock.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: Unlicensed
+pragma solidity ^0.8.17;
+
+contract AddressesProviderMock {
+ mapping(bytes32 => address) private _contractAddresses;
+ string[] private _contractNames;
+
+ /**
+ * @dev Sets the address of a contract.
+ * @param contractAddress Address of the contract.
+ * @param contractName Name of the contract.
+ */
+ function set(address contractAddress, string memory contractName) public {
+ bytes32 contractNameHash = keccak256(abi.encodePacked(contractName));
+
+ if (_contractAddresses[contractNameHash] == address(0)) {
+ _contractNames.push(contractName);
+ }
+
+ _contractAddresses[contractNameHash] = contractAddress;
+ }
+
+ function get(string memory contractName) public view returns (address) {
+ bytes32 contractNameHash = keccak256(abi.encodePacked(contractName));
+
+ return _contractAddresses[contractNameHash];
+ }
+}
diff --git a/test/mocks/AvailableRootsRegistryMock.sol b/test/mocks/AvailableRootsRegistryMock.sol
new file mode 100644
index 0000000..b4ba969
--- /dev/null
+++ b/test/mocks/AvailableRootsRegistryMock.sol
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {IAvailableRootsRegistry} from "src/periphery/interfaces/IAvailableRootsRegistry.sol";
+
+contract AvailableRootsRegistryMock is IAvailableRootsRegistry {
+ mapping(uint256 => bool) public _roots;
+ bool internal _isRootAvailable;
+
+ constructor() {
+ _isRootAvailable = true;
+ }
+
+ function initialize(address) external {}
+
+ function isRootAvailable(uint256) external view returns (bool) {
+ return _isRootAvailable;
+ }
+
+ function registerRoot(uint256 root) external {
+ _roots[root] = true;
+ }
+
+ function unregisterRoot(uint256 root) external {
+ _roots[root] = false;
+ }
+
+ function switchIsRootAvailable() external {
+ _isRootAvailable = !_isRootAvailable;
+ }
+}
diff --git a/test/mocks/CommitmentMapperRegistryMock.sol b/test/mocks/CommitmentMapperRegistryMock.sol
new file mode 100644
index 0000000..d8b6f26
--- /dev/null
+++ b/test/mocks/CommitmentMapperRegistryMock.sol
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {ICommitmentMapperRegistry} from "src/periphery/interfaces/ICommitmentMapperRegistry.sol";
+
+contract CommitmentMapperRegistryMock is ICommitmentMapperRegistry {
+ uint256[2] public edDSAPubKey;
+
+ function initialize(address, uint256[2] memory) external {}
+
+ function updateCommitmentMapperEdDSAPubKey(uint256[2] memory newEdDSAPubKey) external {
+ edDSAPubKey = newEdDSAPubKey;
+ }
+
+ function getEdDSAPubKey() external view returns (uint256[2] memory) {
+ return edDSAPubKey;
+ }
+}
diff --git a/test/mocks/VerifierMock.sol b/test/mocks/VerifierMock.sol
new file mode 100644
index 0000000..7b4f9b1
--- /dev/null
+++ b/test/mocks/VerifierMock.sol
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/console.sol";
+import {IBaseVerifier} from "src/interfaces/IBaseVerifier.sol";
+import {Auth, ClaimType, AuthType, Claim, SismoConnectProof, VerifiedAuth, VerifiedClaim} from "src/utils/Structs.sol";
+
+contract VerifierMock is IBaseVerifier {
+ bytes32 public immutable VERSION = "mock-scheme";
+
+ function verify(
+ bytes16,
+ bytes16,
+ bool,
+ bytes memory,
+ SismoConnectProof memory sismoConnectProof
+ ) external pure override returns (VerifiedAuth memory, VerifiedClaim memory) {
+ // Verify Claim, Auth and SignedMessage validity by checking corresponding
+ // snarkProof public input
+ VerifiedAuth memory verifiedAuth;
+ VerifiedClaim memory verifiedClaim;
+ if (sismoConnectProof.auths.length == 1) {
+ // Get the Auth from the sismoConnectProof
+ // We only support one Auth in the hydra-s3 proving scheme
+ Auth memory auth = sismoConnectProof.auths[0];
+ verifiedAuth = VerifiedAuth({
+ authType: auth.authType,
+ isAnon: auth.isAnon,
+ userId: auth.userId,
+ extraData: auth.extraData,
+ proofData: hex""
+ });
+ }
+ if (sismoConnectProof.claims.length == 1) {
+ // Get the Claim from the sismoConnectProof
+ // We only support one Claim in the hydra-s3 proving scheme
+ Claim memory claim = sismoConnectProof.claims[0];
+ verifiedClaim = VerifiedClaim({
+ claimType: claim.claimType,
+ groupId: claim.groupId,
+ groupTimestamp: claim.groupTimestamp,
+ value: claim.value,
+ extraData: claim.extraData,
+ proofId: 0x0,
+ proofData: hex""
+ });
+ }
+
+ return (verifiedAuth, verifiedClaim);
+ }
+}
diff --git a/test/script/01_DeployAll.t.sol b/test/script/01_DeployAll.t.sol
new file mode 100644
index 0000000..8de6c59
--- /dev/null
+++ b/test/script/01_DeployAll.t.sol
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "forge-std/Test.sol";
+import "forge-std/console.sol";
+import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
+
+import "script/01_DeployAll.s.sol";
+import {DeployAvailableRootsRegistry} from "script/DeployAvailableRootsRegistry.s.sol";
+import {DeployCommitmentMapperRegistry} from "script/DeployCommitmentMapperRegistry.s.sol";
+import "script/BaseConfig.sol";
+
+contract DeployAllTest is Test, BaseDeploymentConfig {
+ ScriptTypes.DeployAllContracts contracts;
+
+ address immutable PROXY_ADMIN = address(1);
+ address immutable OWNER = address(2);
+ address immutable ROOTS_OWNER = address(3);
+
+ function setUp() public virtual {
+ _chainName = "test";
+ _checkIfEmpty = true;
+
+ DeployAll deploy = new DeployAll();
+
+ (bool success, bytes memory result) = address(deploy).delegatecall(
+ abi.encodeWithSelector(DeployAll.runFor.selector, "test")
+ );
+ require(success, "Deploy script did not run successfully!");
+ contracts = abi.decode(result, (ScriptTypes.DeployAllContracts));
+ }
+
+ function testAvailableRootsRegistryDeployed() public {
+ _expectDeployedWithProxy(address(contracts.availableRootsRegistry), PROXY_ADMIN);
+ assertEq(contracts.availableRootsRegistry.owner(), ROOTS_OWNER);
+ }
+
+ function testCommitmentMapperRegistryDeployed() public {
+ _expectDeployedWithProxy(address(contracts.commitmentMapperRegistry), PROXY_ADMIN);
+ assertEq(contracts.commitmentMapperRegistry.owner(), OWNER);
+ }
+
+ function testHydraS3Verifier() public {
+ _expectDeployedWithProxy(address(contracts.hydraS3Verifier), PROXY_ADMIN);
+ assertEq(
+ address(contracts.hydraS3Verifier.COMMITMENT_MAPPER_REGISTRY()),
+ address(contracts.commitmentMapperRegistry)
+ );
+ assertEq(
+ address(contracts.hydraS3Verifier.AVAILABLE_ROOTS_REGISTRY()),
+ address(contracts.availableRootsRegistry)
+ );
+ }
+
+ function testSismoConnectVerifier() public {
+ _expectDeployedWithProxy(address(contracts.sismoConnectVerifier), PROXY_ADMIN);
+ assertEq(
+ contracts.sismoConnectVerifier.getVerifier("hydra-s3.1"),
+ address(contracts.hydraS3Verifier)
+ );
+ assertEq(contracts.sismoConnectVerifier.owner(), OWNER);
+ }
+
+ function test_RemoveFile() public {
+ removeFile();
+ }
+
+ function _expectDeployedWithProxy(address proxy, address expectedAdmin) internal {
+ // Expect proxy is deployed behin a TransparentUpgradeableProxy proxy with the right admin
+ vm.prank(expectedAdmin);
+ (bool success, bytes memory result) = address(proxy).call(
+ abi.encodeWithSelector(TransparentUpgradeableProxy.admin.selector)
+ );
+ assertEq(success, true);
+ assertEq(abi.decode(result, (address)), PROXY_ADMIN);
+ }
+
+ function removeFile() internal {
+ console.log("Removing deploymentConfigFilePath", _deploymentConfigFilePath());
+
+ vm.removeFile(_deploymentConfigFilePath());
+ }
+}
diff --git a/test/utils/GroupLib.sol b/test/utils/GroupLib.sol
new file mode 100644
index 0000000..b5e325f
--- /dev/null
+++ b/test/utils/GroupLib.sol
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+struct Group {
+ AccountData[] accountsData;
+}
+
+struct AccountData {
+ address accountIdentifier;
+ uint256 value;
+}
+
+library GroupLib {
+ function build(AccountData[] memory accountsData) public pure returns (Group memory) {
+ return Group({accountsData: accountsData});
+ }
+}
diff --git a/test/utils/ResponseBuilderLib.sol b/test/utils/ResponseBuilderLib.sol
new file mode 100644
index 0000000..7b71c93
--- /dev/null
+++ b/test/utils/ResponseBuilderLib.sol
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import "src/utils/Structs.sol";
+import {ProofBuilder} from "src/utils/SismoConnectProofBuilder.sol";
+
+// We introduce an intermediate struct that will not store the proofs
+// This is useful to be able to store this struct in the a contract storage
+// We will then use different function to add the proofs and build the SismoConnectResponse struct
+struct ResponseWithoutProofs {
+ bytes16 appId;
+ bytes16 namespace;
+ bytes32 version;
+ bytes signedMessage;
+}
+
+// This library aims at building SismoConnectResponse structs with less overhead
+// than using the SismoConnectResponse struct directly
+// It also allows to build the SismoConnectResponse struct in multiple steps
+// by adding the proofs later, ensuring modularity and flexibility in the code
+library ResponseBuilder {
+ //////////////////////////////////
+ // Simple Field Initialization //
+ ////////////////////////////////
+
+ function withAppId(
+ SismoConnectResponse memory response,
+ bytes16 appId
+ ) external pure returns (SismoConnectResponse memory) {
+ response.appId = appId;
+ return response;
+ }
+
+ function withAppId(
+ ResponseWithoutProofs memory response,
+ bytes16 appId
+ ) external pure returns (ResponseWithoutProofs memory) {
+ response.appId = appId;
+ return response;
+ }
+
+ function withVersion(
+ SismoConnectResponse memory response,
+ bytes32 version
+ ) external pure returns (SismoConnectResponse memory) {
+ response.version = version;
+ return response;
+ }
+
+ function withVersion(
+ ResponseWithoutProofs memory response,
+ bytes32 version
+ ) external pure returns (ResponseWithoutProofs memory) {
+ response.version = version;
+ return response;
+ }
+
+ function withNamespace(
+ SismoConnectResponse memory response,
+ bytes16 namespace
+ ) external pure returns (SismoConnectResponse memory) {
+ response.namespace = namespace;
+ return response;
+ }
+
+ function withNamespace(
+ ResponseWithoutProofs memory response,
+ bytes16 namespace
+ ) external pure returns (ResponseWithoutProofs memory) {
+ response.namespace = namespace;
+ return response;
+ }
+
+ function withSignedMessage(
+ SismoConnectResponse memory response,
+ bytes memory signedMessage
+ ) external pure returns (SismoConnectResponse memory) {
+ response.signedMessage = signedMessage;
+ return response;
+ }
+
+ function withSignedMessage(
+ ResponseWithoutProofs memory response,
+ bytes memory signedMessage
+ ) external pure returns (ResponseWithoutProofs memory) {
+ response.signedMessage = signedMessage;
+ return response;
+ }
+
+ //////////////////////////////////
+ // Proof Initialization //
+ ////////////////////////////////
+
+ // the `build` function is used to build a valid Sismo Connect response from a ResponseWithoutProofs struct
+ // it just adds an empty array of proofs to the ResponseWithoutProofs struct
+ // it has a public visibility because it is used inside this library to transform a ResponseWithoutProofs struct into a SismoConnectResponse struct
+ // but it can also be used outside this library to build a SismoConnectResponse struct from a ResponseWithoutProofs struct
+ function build(
+ ResponseWithoutProofs memory response
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](0);
+ return
+ SismoConnectResponse({
+ appId: response.appId,
+ namespace: response.namespace,
+ version: response.version,
+ signedMessage: response.signedMessage,
+ proofs: proofs
+ });
+ }
+
+ function withAuth(
+ SismoConnectResponse memory response,
+ Auth memory auth,
+ bytes memory proofData,
+ bytes32 provingScheme
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({
+ auth: auth,
+ proofData: proofData,
+ provingScheme: provingScheme
+ });
+ response.proofs = proofs;
+ return response;
+ }
+
+ function withAuth(
+ SismoConnectResponse memory response,
+ Auth memory auth,
+ bytes memory proofData
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({auth: auth, proofData: proofData, provingScheme: ""});
+ response.proofs = proofs;
+ return response;
+ }
+
+ function withAuth(
+ SismoConnectResponse memory response,
+ Auth memory auth
+ ) external pure returns (SismoConnectResponse memory) {
+ return withAuth(response, auth, "");
+ }
+
+ function withAuth(
+ ResponseWithoutProofs memory response,
+ Auth memory auth,
+ bytes memory proofData,
+ bytes32 provingScheme
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({
+ auth: auth,
+ proofData: proofData,
+ provingScheme: provingScheme
+ });
+ SismoConnectResponse memory responseWithProofs = build(response);
+ responseWithProofs.proofs = proofs;
+ return responseWithProofs;
+ }
+
+ function withAuth(
+ ResponseWithoutProofs memory response,
+ Auth memory auth,
+ bytes memory proofData
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({auth: auth, proofData: proofData, provingScheme: ""});
+ SismoConnectResponse memory responseWithProofs = build(response);
+ responseWithProofs.proofs = proofs;
+ return responseWithProofs;
+ }
+
+ function withAuth(
+ ResponseWithoutProofs memory response,
+ Auth memory auth,
+ bytes32 provingScheme
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({auth: auth, proofData: "", provingScheme: provingScheme});
+ SismoConnectResponse memory responseWithProofs = build(response);
+ responseWithProofs.proofs = proofs;
+ return responseWithProofs;
+ }
+
+ function withAuth(
+ ResponseWithoutProofs memory response,
+ Auth memory auth
+ ) external pure returns (SismoConnectResponse memory) {
+ return withAuth({response: response, auth: auth, proofData: ""});
+ }
+
+ function withClaim(
+ SismoConnectResponse memory response,
+ Claim memory claim,
+ bytes memory proofData,
+ bytes32 provingScheme
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({
+ claim: claim,
+ proofData: proofData,
+ provingScheme: provingScheme
+ });
+ response.proofs = proofs;
+ return response;
+ }
+
+ function withClaim(
+ SismoConnectResponse memory response,
+ Claim memory claim,
+ bytes memory proofData
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({claim: claim, proofData: proofData, provingScheme: ""});
+ response.proofs = proofs;
+ return response;
+ }
+
+ function withClaim(
+ SismoConnectResponse memory response,
+ Claim memory claim,
+ bytes32 provingScheme
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({claim: claim, proofData: "", provingScheme: provingScheme});
+ response.proofs = proofs;
+ return response;
+ }
+
+ function withClaim(
+ SismoConnectResponse memory response,
+ Claim memory claim
+ ) external pure returns (SismoConnectResponse memory) {
+ return withClaim({response: response, claim: claim, proofData: ""});
+ }
+
+ function withClaim(
+ ResponseWithoutProofs memory response,
+ Claim memory claim,
+ bytes memory proofData
+ ) public pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({claim: claim, proofData: proofData});
+ SismoConnectResponse memory responseWithProofs = build(response);
+ responseWithProofs.proofs = proofs;
+ return responseWithProofs;
+ }
+
+ function withClaim(
+ ResponseWithoutProofs memory response,
+ Claim memory claim
+ ) external pure returns (SismoConnectResponse memory) {
+ return withClaim(response, claim, "");
+ }
+
+ ////////////////////////////////
+ // Empty structs //
+ //////////////////////////////
+
+ function emptyResponseWithoutProofs() external pure returns (ResponseWithoutProofs memory) {
+ return
+ ResponseWithoutProofs({
+ appId: bytes16(0),
+ namespace: bytes16(0),
+ version: bytes32(0),
+ signedMessage: ""
+ });
+ }
+
+ function empty() external pure returns (SismoConnectResponse memory) {
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](0);
+ return
+ SismoConnectResponse({
+ appId: bytes16(0),
+ namespace: bytes16(0),
+ version: bytes32(0),
+ signedMessage: "",
+ proofs: proofs
+ });
+ }
+}
diff --git a/test/verifiers/hydra-s3/HydraS3BaseTest.t.sol b/test/verifiers/hydra-s3/HydraS3BaseTest.t.sol
new file mode 100644
index 0000000..d4ece1e
--- /dev/null
+++ b/test/verifiers/hydra-s3/HydraS3BaseTest.t.sol
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.17;
+
+import {BaseTest} from "test/BaseTest.t.sol";
+import "src/verifiers/HydraS3Verifier.sol";
+import "test/verifiers/hydra-s3//HydraS3Proofs.sol";
+import {CommitmentMapperRegistryMock, ICommitmentMapperRegistry} from "test/mocks/CommitmentMapperRegistryMock.sol";
+import {AvailableRootsRegistryMock} from "test/mocks/AvailableRootsRegistryMock.sol";
+
+contract HydraS3BaseTest is BaseTest {
+ HydraS3Proofs immutable hydraS3Proofs = new HydraS3Proofs();
+ HydraS3Verifier hydraS3Verifier;
+ ICommitmentMapperRegistry commitmentMapperRegistry;
+ AvailableRootsRegistryMock availableRootsRegistry;
+
+ function setUp() public virtual override {
+ super.setUp();
+
+ commitmentMapperRegistry = new CommitmentMapperRegistryMock();
+ availableRootsRegistry = new AvailableRootsRegistryMock();
+
+ hydraS3Verifier = new HydraS3Verifier(
+ address(commitmentMapperRegistry),
+ address(availableRootsRegistry)
+ );
+
+ vm.startPrank(owner);
+ sismoConnectVerifier.registerVerifier(
+ hydraS3Verifier.HYDRA_S3_VERSION(),
+ address(hydraS3Verifier)
+ );
+ vm.stopPrank();
+
+ commitmentMapperRegistry.updateCommitmentMapperEdDSAPubKey(hydraS3Proofs.getEdDSAPubKey());
+ availableRootsRegistry.registerRoot(hydraS3Proofs.getRoot());
+ }
+}
diff --git a/test/verifiers/hydra-s3/HydraS3Proofs.sol b/test/verifiers/hydra-s3/HydraS3Proofs.sol
new file mode 100644
index 0000000..6bb5722
--- /dev/null
+++ b/test/verifiers/hydra-s3/HydraS3Proofs.sol
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.17;
+
+import "forge-std/console.sol";
+import "src/utils/Structs.sol";
+import {AuthBuilder} from "src/utils/AuthBuilder.sol";
+import {ClaimBuilder} from "src/utils/ClaimBuilder.sol";
+import {ProofBuilder} from "src/utils/SismoConnectProofBuilder.sol";
+import {ResponseBuilder} from "test/utils/ResponseBuilderLib.sol";
+import {ICommitmentMapperRegistry} from "test/mocks/CommitmentMapperRegistryMock.sol";
+
+contract HydraS3Proofs {
+ using ResponseBuilder for SismoConnectResponse;
+
+ // default value for Claim
+ bytes16 public constant DEFAULT_CLAIM_GROUP_TIMESTAMP = bytes16("latest");
+ uint256 public constant DEFAULT_CLAIM_VALUE = 1;
+ bytes16 public constant DEFAULT_CLAIM_GROUP_ID = "";
+ ClaimType public constant DEFAULT_CLAIM_TYPE = ClaimType.GTE;
+ bytes public constant DEFAULT_CLAIM_EXTRA_DATA = "";
+
+ // default values for Auth
+ bool public constant DEFAULT_AUTH_ANON_MODE = false;
+ uint256 public constant DEFAULT_AUTH_USER_ID = 0;
+ bytes public constant DEFAULT_AUTH_EXTRA_DATA = "";
+
+ // default values for MessageSignature
+ bytes public constant DEFAULT_MESSAGE_SIGNATURE_REQUEST = "MESSAGE_SELECTED_BY_USER";
+
+ // default value for appId
+ bytes16 public constant DEFAULT_APP_ID = 0x11b1de449c6c4adb0b5775b3868b28b3;
+ // default value for namespace
+ bytes16 public constant DEFAULT_NAMESPACE = bytes16(keccak256("main"));
+
+ // default value for version
+ bytes32 public constant DEFAULT_VERSION = bytes32("sismo-connect-v1.1");
+
+ // default proving scheme
+ bytes32 public constant DEFAULT_PROVING_SCHEME = bytes32("hydra-s3.1");
+
+ function getEdDSAPubKey() public pure returns (uint256[2] memory) {
+ return [
+ 0x07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb9,
+ 0x20706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa
+ ];
+ }
+
+ function getImpersonationEdDSAPubKey() public pure returns (uint256[2] memory) {
+ return [
+ 0x1801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b,
+ 0x057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b
+ ];
+ }
+
+ function getRoot() public pure returns (uint256) {
+ return 0x0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d85210;
+ }
+
+ // simple sismoConnect with 1 claim
+ function getResponseWithOneClaimAndSignature()
+ external
+ pure
+ returns (SismoConnectResponse memory response, bytes memory responseAsBytes)
+ {
+ return (
+ ResponseBuilder
+ .empty()
+ .withAppId(DEFAULT_APP_ID)
+ .withNamespace(DEFAULT_NAMESPACE)
+ .withVersion(DEFAULT_VERSION)
+ .withClaim({
+ claim: ClaimBuilder.build({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e}),
+ proofData: hex"2f9bbf1553b98848be543f1a3e0ac887c82d8927fc89e59e4bc0f46500b2f53803054cf63a56f54ee3116729939d5c285e4d6e0f2881f30b0d2c1ee2811ada090b5870dde9d003024c21122e122eac3d53aa9fc116159bf3385fce8fe194485f062384d38ebaac2bc59c1e74a86ab2b516b97a66df4160d6429bea6513d1942c291277ee22a603133f26d18b754867d40c059405a380252d30e8e1b6784c15a80770eee902fba2468672835e68512d6e2be18308e65b2ed62ddf8462877d70b002d8b41e2ebffee6ea7a520b4245211834c44c9ae158f18bfd52f922c8c7b70e2489f6b7d34333f5b5cf3482df7106cf69e8847284ef2fe00e227f2c52ab0d5b000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000",
+ provingScheme: DEFAULT_PROVING_SCHEME
+ })
+ .withSignedMessage({signedMessage: abi.encode(0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE)}),
+ // response as bytes
+ hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007def1d6d28d6bda49e69fa89ad75d160becba3ae0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000e9ed316946d3d98dfcd829a53ec9822e000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c02f9bbf1553b98848be543f1a3e0ac887c82d8927fc89e59e4bc0f46500b2f53803054cf63a56f54ee3116729939d5c285e4d6e0f2881f30b0d2c1ee2811ada090b5870dde9d003024c21122e122eac3d53aa9fc116159bf3385fce8fe194485f062384d38ebaac2bc59c1e74a86ab2b516b97a66df4160d6429bea6513d1942c291277ee22a603133f26d18b754867d40c059405a380252d30e8e1b6784c15a80770eee902fba2468672835e68512d6e2be18308e65b2ed62ddf8462877d70b002d8b41e2ebffee6ea7a520b4245211834c44c9ae158f18bfd52f922c8c7b70e2489f6b7d34333f5b5cf3482df7106cf69e8847284ef2fe00e227f2c52ab0d5b000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ );
+ }
+
+ // simple sismoConnect with 2 claims
+ function getResponseWithTwoClaimsAndSignature()
+ external
+ pure
+ returns (SismoConnectResponse memory response, bytes memory responseAsBytes)
+ {
+ Claim memory claim = ClaimBuilder.build({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+
+ Claim memory claimTwo = ClaimBuilder.build({groupId: 0x02d241fdb9d4330c564ffc0a36af05f6});
+
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](2);
+ proofs[0] = ProofBuilder.build({
+ claim: claim,
+ proofData: hex"112a90db82673ac2dc9d3b0c94fe4bdec60c54fc1f2fb9db24fd778939b0bc571e844e09218e08edf85ded69c70cf173b3973d1dc1861084214ed990f4a8940112e22fb69156b526f5d9205bdfb86fac13465ca6417e8d8358ec16ac9da5f3bc29bb9877f10cd882a788e79d10d60cb1c26a95f6fcfaac914b86f4e929bb29a6019aaf53837786c4cc6d4d94cb551fde1bfda52bd4baf84f5b7b683d6beb55d12f8826b3051c6766f1112dc12ee1121423f694d2549d87b2db3909e2db042f642a4e82e7ea049f01792bb8dd9db687c19aa2e63b47fb32d5bd61a808433cbd3028639724873b9591f0e850c0edfcfb854509f41f8b8e1f6247bf3338b795069a000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"
+ });
+ proofs[1] = ProofBuilder.build({
+ claim: claimTwo,
+ proofData: hex"1abb9a37eb98d68e994f4bcfd45b784ca2d6b4aa6d2aa77f5245681cafc79b82165e8c16c944d1a943a58fbf32a7be7c641a30d94c53e4d18695740c8a4b15cd06f95c66190ba95f2f4366f8c1b7582f8f9cfc4690674086cca42b1c55cb65b60c34dccd92e5fa17c49de842eb8e3bd70c09a1fba7e3e44e2543d280353b6dd919d06da5a98df5667bf2a41cc00329afc1aa0b2c1f9907539b2a784bb79f68bc0f5d9af52436adf7a02d1645eaa3f46e42e8c6944dba7c0dc94c2e4f3be3a86d164267c480df8bd1aca9195c89f2c6d06c13629aa41c3726f06d833a078781721317c863b582112f085883b36cd4f8e48288f0d2c02739a0a45ff6311a693e9e000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d852100f1d1d7e673892c9109c8b536253aa86d1d9dbd317ee37e71f22391e3a9fa5b3138cc656a4ed3352a074f68b57d684b33506d71ef40054fa928402c4897d14b8000000000000000000000000000000000000000000000000000000000000000102d241fdb9d4330c564ffc0a36af05f66c6174657374000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"
+ });
+
+ return (
+ SismoConnectResponse({
+ appId: 0x11b1de449c6c4adb0b5775b3868b28b3,
+ namespace: bytes16(keccak256("main")),
+ version: bytes32("sismo-connect-v1.1"),
+ signedMessage: abi.encode(0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE),
+ proofs: proofs
+ }),
+ // response as bytes
+ hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007def1d6d28d6bda49e69fa89ad75d160becba3ae00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000e9ed316946d3d98dfcd829a53ec9822e000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0112a90db82673ac2dc9d3b0c94fe4bdec60c54fc1f2fb9db24fd778939b0bc571e844e09218e08edf85ded69c70cf173b3973d1dc1861084214ed990f4a8940112e22fb69156b526f5d9205bdfb86fac13465ca6417e8d8358ec16ac9da5f3bc29bb9877f10cd882a788e79d10d60cb1c26a95f6fcfaac914b86f4e929bb29a6019aaf53837786c4cc6d4d94cb551fde1bfda52bd4baf84f5b7b683d6beb55d12f8826b3051c6766f1112dc12ee1121423f694d2549d87b2db3909e2db042f642a4e82e7ea049f01792bb8dd9db687c19aa2e63b47fb32d5bd61a808433cbd3028639724873b9591f0e850c0edfcfb854509f41f8b8e1f6247bf3338b795069a000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000002d241fdb9d4330c564ffc0a36af05f6000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c01abb9a37eb98d68e994f4bcfd45b784ca2d6b4aa6d2aa77f5245681cafc79b82165e8c16c944d1a943a58fbf32a7be7c641a30d94c53e4d18695740c8a4b15cd06f95c66190ba95f2f4366f8c1b7582f8f9cfc4690674086cca42b1c55cb65b60c34dccd92e5fa17c49de842eb8e3bd70c09a1fba7e3e44e2543d280353b6dd919d06da5a98df5667bf2a41cc00329afc1aa0b2c1f9907539b2a784bb79f68bc0f5d9af52436adf7a02d1645eaa3f46e42e8c6944dba7c0dc94c2e4f3be3a86d164267c480df8bd1aca9195c89f2c6d06c13629aa41c3726f06d833a078781721317c863b582112f085883b36cd4f8e48288f0d2c02739a0a45ff6311a693e9e000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d852100f1d1d7e673892c9109c8b536253aa86d1d9dbd317ee37e71f22391e3a9fa5b3138cc656a4ed3352a074f68b57d684b33506d71ef40054fa928402c4897d14b8000000000000000000000000000000000000000000000000000000000000000102d241fdb9d4330c564ffc0a36af05f66c6174657374000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ );
+ }
+
+ // simple sismoConnect with only auth
+ function getResponseWithOnlyOneAuthAndMessage()
+ external
+ pure
+ returns (SismoConnectResponse memory response, bytes memory responseAsBytes)
+ {
+ Auth memory auth = AuthBuilder.build({authType: AuthType.VAULT});
+
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({
+ auth: auth,
+ proofData: hex"138e0d99b4b1fff0128090b63d69da3ccb11b3241ede465119fe13e614e3995f21125ff7d8ff5acdd47a6955c78ecaa079fd4089399f4a92a427e15c3281d8660754ae52a95639d42f53c8b81ed49303a85734b3b9e95e338601ed84c2e8c9920828518d257cb789012f6b2f2c211b02e1062e6623b5aa50dd136eac4fc937ab2dcec087dbeeb3bfe12e255cb5751f6c2f4015a9017cd2f6fbf4a46dcba74eb6290e64a13eaae874d6f6cce1368495dadf20dd5adfb2c801d5cabafa2d078ede270724551d579b5c3d73744a96a8e8a723339d504ac50c71f0a005dca32868d20cdbe42ab4a27fa33ff7388dc1322ce5a2eb2cccf11aaa67a6a755f4ed3d2f1f000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d2ab71fb864979b71106135acfa84afc1d756cda74f8f258896f896b4864f025630423b4c502f1cd4179a425723bf1e15c843733af2ecdee9aef6a0451ef2db7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018202c14c40a8bc84b8fc8748836190f53fc45c66ad969c7bfa2a91afdd1ad8d01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ });
+
+ return (
+ SismoConnectResponse({
+ appId: 0x11b1de449c6c4adb0b5775b3868b28b3,
+ namespace: bytes16(keccak256("main")),
+ version: bytes32("sismo-connect-v1.1"),
+ signedMessage: abi.encode(0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE),
+ proofs: proofs
+ }),
+ // response as bytes
+ hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007def1d6d28d6bda49e69fa89ad75d160becba3ae0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000118202c14c40a8bc84b8fc8748836190f53fc45c66ad969c7bfa2a91afdd1ad8d00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0138e0d99b4b1fff0128090b63d69da3ccb11b3241ede465119fe13e614e3995f21125ff7d8ff5acdd47a6955c78ecaa079fd4089399f4a92a427e15c3281d8660754ae52a95639d42f53c8b81ed49303a85734b3b9e95e338601ed84c2e8c9920828518d257cb789012f6b2f2c211b02e1062e6623b5aa50dd136eac4fc937ab2dcec087dbeeb3bfe12e255cb5751f6c2f4015a9017cd2f6fbf4a46dcba74eb6290e64a13eaae874d6f6cce1368495dadf20dd5adfb2c801d5cabafa2d078ede270724551d579b5c3d73744a96a8e8a723339d504ac50c71f0a005dca32868d20cdbe42ab4a27fa33ff7388dc1322ce5a2eb2cccf11aaa67a6a755f4ed3d2f1f000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d2ab71fb864979b71106135acfa84afc1d756cda74f8f258896f896b4864f025630423b4c502f1cd4179a425723bf1e15c843733af2ecdee9aef6a0451ef2db7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018202c14c40a8bc84b8fc8748836190f53fc45c66ad969c7bfa2a91afdd1ad8d01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ );
+ }
+
+ // simple sismoConnect with one claim and one auth
+ function getResponseWithOneClaimOneAuthAndOneMessage()
+ external
+ pure
+ returns (SismoConnectResponse memory response, bytes memory responseAsBytes)
+ {
+ Claim memory claim = ClaimBuilder.build({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+
+ Auth memory auth = AuthBuilder.build({authType: AuthType.VAULT});
+
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](2);
+ proofs[0] = ProofBuilder.build({
+ claim: claim,
+ proofData: hex"0ca19971a2d025de05de77c2f1aeda6cc57424c7ac7b3237c90cdcd84412077a1886754c486cae08ea652c173ae1870debef85a80d95d6725e0b37256d695584107aa68653fb67722e07237654af11107d299618a7f312421c62522c76ba51d308540f29626f1443da6c11e54622b23222339ea6da09f8ac77ec315693f24b132925ca9016386c891aa3bac9797a9b43a3313bfd98629d6fb95d2417ae5534e0001017552d3d3e8911f5e5aa4384d8a6e1dfb385e585667626d0aeb9b0c8c95326d41320eb53032f108cf48fcbf17ecf166979272210647d09153113c56871fc165bc6274afbc88352572cfb118bda16a7ba1b99f24c37d1bd31c10f6b4d7607000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"
+ });
+ proofs[1] = ProofBuilder.build({
+ auth: auth,
+ proofData: hex"2dc5aba5f01c9d989e252e7c14662c0140e0e03cf7e646528c252d423cc72f1f03189aff86d2a4c1a5e14b886f75f51b4210087de5cab5fd39b5567f27eff9902adcb81f9e9f6739d563c61ea80f1602455def27a07a90bbaf1df87b1c01b89621c37053f086bf8b57446a88e15b5501f00a756fcfa57cbc4f3776a930de2b9102137447707533080a013ebde8fb887f8576cdcb9d65c4ed06422e3721c30eb11ebc69e9c11e192ca5c0b392492ad413dd7095705b9e66758dd39aed176511fa23ec1761e651c6d9cd300c48ba1daa3abc5a5c0df7ebbe2338d0bcf53fb2600015d397326c95eadd529aaafd249d9d8288f2aa83635311dda3dc2a1b81cd4c1c000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ });
+
+ return (
+ SismoConnectResponse({
+ appId: 0x11b1de449c6c4adb0b5775b3868b28b3,
+ namespace: bytes16(keccak256("main")),
+ version: bytes32("sismo-connect-v1.1"),
+ signedMessage: abi.encode(0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE),
+ proofs: proofs
+ }),
+ // response as bytes
+ hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007def1d6d28d6bda49e69fa89ad75d160becba3ae00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c02dc5aba5f01c9d989e252e7c14662c0140e0e03cf7e646528c252d423cc72f1f03189aff86d2a4c1a5e14b886f75f51b4210087de5cab5fd39b5567f27eff9902adcb81f9e9f6739d563c61ea80f1602455def27a07a90bbaf1df87b1c01b89621c37053f086bf8b57446a88e15b5501f00a756fcfa57cbc4f3776a930de2b9102137447707533080a013ebde8fb887f8576cdcb9d65c4ed06422e3721c30eb11ebc69e9c11e192ca5c0b392492ad413dd7095705b9e66758dd39aed176511fa23ec1761e651c6d9cd300c48ba1daa3abc5a5c0df7ebbe2338d0bcf53fb2600015d397326c95eadd529aaafd249d9d8288f2aa83635311dda3dc2a1b81cd4c1c000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000e9ed316946d3d98dfcd829a53ec9822e000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c00ca19971a2d025de05de77c2f1aeda6cc57424c7ac7b3237c90cdcd84412077a1886754c486cae08ea652c173ae1870debef85a80d95d6725e0b37256d695584107aa68653fb67722e07237654af11107d299618a7f312421c62522c76ba51d308540f29626f1443da6c11e54622b23222339ea6da09f8ac77ec315693f24b132925ca9016386c891aa3bac9797a9b43a3313bfd98629d6fb95d2417ae5534e0001017552d3d3e8911f5e5aa4384d8a6e1dfb385e585667626d0aeb9b0c8c95326d41320eb53032f108cf48fcbf17ecf166979272210647d09153113c56871fc165bc6274afbc88352572cfb118bda16a7ba1b99f24c37d1bd31c10f6b4d7607000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ );
+ }
+
+ function getResponseWithTwoClaimsOneAuthAndOneSignature()
+ external
+ pure
+ returns (SismoConnectResponse memory response, bytes memory responseAsBytes)
+ {
+ Claim memory claim = ClaimBuilder.build({groupId: 0xe9ed316946d3d98dfcd829a53ec9822e});
+
+ Claim memory claimTwo = ClaimBuilder.build({groupId: 0x02d241fdb9d4330c564ffc0a36af05f6});
+
+ Auth memory auth = AuthBuilder.build({authType: AuthType.VAULT});
+
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](3);
+ proofs[0] = ProofBuilder.build({
+ claim: claim,
+ proofData: hex"2d53f40dfd231e94db1a1d5759818fb65788cc5a586dd52a87086c6ef52c2ea5067f9e6672e0fad253a4fe3884a9474a86f76c452ffb70ce828f49ff271c157a212abb5dd8ad3ebe98c1df40799e224a0b6a91af68f97531f8987abd58abc3a10f93cb8848bbe50947bbc22b5c97b388ba7998cd532c20da56567f476b1e76a31105d06e1f880f4048a98a4df35b275375f27e6044dbb2cf04ccacdbe07b823e28afe9c052d68931c22f0e0fa54431072857eab1835faa2d675021facea397ca28d2278d4aa71184d6240498c2b30cad7270f561f8322338e7b93259560e7b6a1560ee42f01bc475cc1f4791f9cabd2c9061e1f4545030271fe81b0c076cb4e4000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"
+ });
+
+ proofs[1] = ProofBuilder.build({
+ claim: claimTwo,
+ proofData: hex"05b949d85f762a54b7400547132026c5d0995d671297872ebfb3dbac1917659f2755fb3f4599b1be254b810f9c973d8d539e56fb599f9d024508b5940a4334ab2368727d07b8fbaa568f5fa27a4cda0c0160243a010f1efcc0db7a6973b247620569ef4735403a355f762108a4d140aa0dc4b2333b8542438953e6f72dc57cce10c14af2d6f21dbcfe917df6e872277a928e5bc2760f3fc4e6a59466089cb23b2b1ecda73e41abed5fe373923efc6a5724a8a865f829d600afc22ad5a846b02a203c58db94f189f5e9d0805f37c30de93e0af2dc930fc138d20cc4b0655df11f0ef8a2c8bbec2d701c5ebb5caf18a04847748c43ef52efd9422effa8b23651fd000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d852100f1d1d7e673892c9109c8b536253aa86d1d9dbd317ee37e71f22391e3a9fa5b3138cc656a4ed3352a074f68b57d684b33506d71ef40054fa928402c4897d14b8000000000000000000000000000000000000000000000000000000000000000102d241fdb9d4330c564ffc0a36af05f66c6174657374000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"
+ });
+
+ proofs[2] = ProofBuilder.build({
+ auth: auth,
+ proofData: hex"2225b3a9e7f6ddd7774daf4578d38ba58a6d21db07b86ea3852d3e89157cba4200e73eae485f989e2a1a06c0c1b2567c38dd018a25bca5dbc8fdbab9e4bdf7990e94589641fead66343771f10429363a94cae1f25110153e6ed60be3e4aaec302c969077aa9383e862faa80d7399079c627a948c924fcfcae04f8191bb5f164d0253c2b4562cbed45c8d7a0bff785b7157101e957d912882f20a9e91b4a514b80269193c78b666a71cf497bf03d82a1a5938e01ad372cdea3deefb00450a5b1416fe1a4cef14962a2d79f59caedee4ad4a9420ae09b4b0971e59582fb254ddcc2c4a231ac34c6fb2caaeb8a558c1e30c26411503878185bd82728c6193e4ff4f000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ });
+
+ return (
+ SismoConnectResponse({
+ appId: 0x11b1de449c6c4adb0b5775b3868b28b3,
+ namespace: bytes16(keccak256("main")),
+ version: bytes32("sismo-connect-v1.1"),
+ signedMessage: abi.encode(0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE),
+ proofs: proofs
+ }),
+ // response as bytes
+ hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007def1d6d28d6bda49e69fa89ad75d160becba3ae0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000ee000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c02225b3a9e7f6ddd7774daf4578d38ba58a6d21db07b86ea3852d3e89157cba4200e73eae485f989e2a1a06c0c1b2567c38dd018a25bca5dbc8fdbab9e4bdf7990e94589641fead66343771f10429363a94cae1f25110153e6ed60be3e4aaec302c969077aa9383e862faa80d7399079c627a948c924fcfcae04f8191bb5f164d0253c2b4562cbed45c8d7a0bff785b7157101e957d912882f20a9e91b4a514b80269193c78b666a71cf497bf03d82a1a5938e01ad372cdea3deefb00450a5b1416fe1a4cef14962a2d79f59caedee4ad4a9420ae09b4b0971e59582fb254ddcc2c4a231ac34c6fb2caaeb8a558c1e30c26411503878185bd82728c6193e4ff4f000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000100200000000000000000000000000288480976500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c00d3916fb92997fc6d11ceac7618482759bbdee5134e9d90baf116ba3519c9ac003ddc52962996f3fba4559612dab2325a5b0955dcea7b47acca0cf09ec11077715d0c7554341e472f609caae810b38873fe00309bb2d45ec9a832d3495e4036a2522e15d49a09c52652fef43746de58ec7b1fd7b184c865c83e1388e094271b409ba20579e2d04accd56eb8e8a491ab9b4d34f99bfc72cd440617da672eed9051ee6ceeeeb8a777900d022714aff12d1226c32ce7878959335314ce025fcc1cd2e67c2299cf9706fe81e750b7169ac0997b670a655c3141cc3848a6c36262aa1268cc791f070169f6130083246044546114360f7717fc47a4038c470c2b0eb71000000000000000000000000100200000000000000000000000000288480976509f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000e9ed316946d3d98dfcd829a53ec9822e000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c02d53f40dfd231e94db1a1d5759818fb65788cc5a586dd52a87086c6ef52c2ea5067f9e6672e0fad253a4fe3884a9474a86f76c452ffb70ce828f49ff271c157a212abb5dd8ad3ebe98c1df40799e224a0b6a91af68f97531f8987abd58abc3a10f93cb8848bbe50947bbc22b5c97b388ba7998cd532c20da56567f476b1e76a31105d06e1f880f4048a98a4df35b275375f27e6044dbb2cf04ccacdbe07b823e28afe9c052d68931c22f0e0fa54431072857eab1835faa2d675021facea397ca28d2278d4aa71184d6240498c2b30cad7270f561f8322338e7b93259560e7b6a1560ee42f01bc475cc1f4791f9cabd2c9061e1f4545030271fe81b0c076cb4e4000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d8521004f81599b826fa9b715033e76e5b2fdda881352a9b61360022e30ee33ddccad90744e9b92802056c722ac4b31612e1b1de544d5b99481386b162a0b59862e0850000000000000000000000000000000000000000000000000000000000000001285bf79dc20d58e71b9712cb38c420b9cb91d3438c8e3dbaf07829b03ffffffc0000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000002d241fdb9d4330c564ffc0a36af05f6000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c005b949d85f762a54b7400547132026c5d0995d671297872ebfb3dbac1917659f2755fb3f4599b1be254b810f9c973d8d539e56fb599f9d024508b5940a4334ab2368727d07b8fbaa568f5fa27a4cda0c0160243a010f1efcc0db7a6973b247620569ef4735403a355f762108a4d140aa0dc4b2333b8542438953e6f72dc57cce10c14af2d6f21dbcfe917df6e872277a928e5bc2760f3fc4e6a59466089cb23b2b1ecda73e41abed5fe373923efc6a5724a8a865f829d600afc22ad5a846b02a203c58db94f189f5e9d0805f37c30de93e0af2dc930fc138d20cc4b0655df11f0ef8a2c8bbec2d701c5ebb5caf18a04847748c43ef52efd9422effa8b23651fd000000000000000000000000000000000000000000000000000000000000000009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d852100f1d1d7e673892c9109c8b536253aa86d1d9dbd317ee37e71f22391e3a9fa5b3138cc656a4ed3352a074f68b57d684b33506d71ef40054fa928402c4897d14b8000000000000000000000000000000000000000000000000000000000000000102d241fdb9d4330c564ffc0a36af05f66c6174657374000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+ );
+ }
+
+ function getResponseWithGitHubAuth()
+ external
+ pure
+ returns (SismoConnectResponse memory response, bytes memory responseAsBytes)
+ {
+ Auth memory auth = AuthBuilder.build({authType: AuthType.GITHUB});
+
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({
+ auth: auth,
+ proofData: hex"0dac2cbf2a79fbf0685feb4decc19d488741ab490e3a1d9bc7f188b117650cd81acd802e6ed6a5c7d1b82b43238e6c6b9ccc5ba466aa7a2edcf11916374b410f06acfd9ce499c4798e90170cd4ae34163e98f57c011b96ee4cab4a48e2bf276c01431be40bbdfa36bea2306300b12b33d5848b3ac2d537697b7bb49d20eadb09222be62294cfe98a8d9fc397d96a3d76b1baf55644ebcad35c9b29be6a0a6c542bb5308742a9bea4ff29f1732cfc0b1ac496dd7e2ab7f2f6f4e7760700cab6e4166218b204613db523550412311a5f58d3090138c70c38ba402c61bedd4fcaf1202bc490be5cab53595dc1359743004bc48c6db6fa7a9bb80c65cdc3d28fea54000000000000000000000000100100000000000000000000000000009999037009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
+ });
+
+ return (
+ SismoConnectResponse({
+ appId: 0x11b1de449c6c4adb0b5775b3868b28b3,
+ namespace: bytes16(keccak256("main")),
+ version: bytes32("sismo-connect-v1.1"),
+ signedMessage: abi.encode(0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE),
+ proofs: proofs
+ }),
+ // response as bytes
+ hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000200000000000000000000000007def1d6d28d6bda49e69fa89ad75d160becba3ae0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000100100000000000000000000000000009999037000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c00dac2cbf2a79fbf0685feb4decc19d488741ab490e3a1d9bc7f188b117650cd81acd802e6ed6a5c7d1b82b43238e6c6b9ccc5ba466aa7a2edcf11916374b410f06acfd9ce499c4798e90170cd4ae34163e98f57c011b96ee4cab4a48e2bf276c01431be40bbdfa36bea2306300b12b33d5848b3ac2d537697b7bb49d20eadb09222be62294cfe98a8d9fc397d96a3d76b1baf55644ebcad35c9b29be6a0a6c542bb5308742a9bea4ff29f1732cfc0b1ac496dd7e2ab7f2f6f4e7760700cab6e4166218b204613db523550412311a5f58d3090138c70c38ba402c61bedd4fcaf1202bc490be5cab53595dc1359743004bc48c6db6fa7a9bb80c65cdc3d28fea54000000000000000000000000100100000000000000000000000000009999037009f60d972df499264335faccfc437669a97ea2b6c97a1a7ddf3f0105eda34b1d07f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"
+ );
+ }
+
+ function getResponseWithGitHubAuthWithoutSignature()
+ external
+ pure
+ returns (SismoConnectResponse memory response, bytes memory responseAsBytes)
+ {
+ Auth memory auth = AuthBuilder.build({authType: AuthType.GITHUB});
+
+ SismoConnectProof[] memory proofs = new SismoConnectProof[](1);
+ proofs[0] = ProofBuilder.build({
+ auth: auth,
+ proofData: hex"14aa96fb34414b749bb4610bace69a3d3e9ed4b1af6137f7d1a3270590c696bb0074dc54bfd774a3185b445f2b1013bcefb8d8d1b98b186611829ae9ac59a44407b6fa1abaafa92b207d2bed2139ff1a6cd05f56ac2167f89a6b3a3180eceebb107f09ef3f109f1ac13560ed255b5605e340964f5fd6b96ae9e62634cd219d51233f679d2011810af86b8da940f2e3b8ba38716d0ab63a8aa6944c13dd6ec40d0c36d09c76572cc1dfffd527ca60c1828642782322a49ef6df921f0a57ecc65f2706ff429747a7b1dd72643a24dc9be189b0461f155fe5479bde1f78609fece82331e429f79401e878e826c36ada7d85053e00226dd49e6e76fb76ff7b2e43490000000000000000000000001001000000000000000000000000000099990370000000000000000000000000000000000000000000000000000000000000000007f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
+ });
+
+ return (
+ SismoConnectResponse({
+ appId: 0x11b1de449c6c4adb0b5775b3868b28b3,
+ namespace: bytes16(keccak256("main")),
+ version: bytes32("sismo-connect-v1.1"),
+ signedMessage: "",
+ proofs: proofs
+ }),
+ // response as bytes
+ hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000100100000000000000000000000000009999037000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c014aa96fb34414b749bb4610bace69a3d3e9ed4b1af6137f7d1a3270590c696bb0074dc54bfd774a3185b445f2b1013bcefb8d8d1b98b186611829ae9ac59a44407b6fa1abaafa92b207d2bed2139ff1a6cd05f56ac2167f89a6b3a3180eceebb107f09ef3f109f1ac13560ed255b5605e340964f5fd6b96ae9e62634cd219d51233f679d2011810af86b8da940f2e3b8ba38716d0ab63a8aa6944c13dd6ec40d0c36d09c76572cc1dfffd527ca60c1828642782322a49ef6df921f0a57ecc65f2706ff429747a7b1dd72643a24dc9be189b0461f155fe5479bde1f78609fece82331e429f79401e878e826c36ada7d85053e00226dd49e6e76fb76ff7b2e43490000000000000000000000001001000000000000000000000000000099990370000000000000000000000000000000000000000000000000000000000000000007f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"
+ );
+ }
+
+ function getCheatSheetResponse() external pure returns (bytes memory) {
+ return
+ hex"000000000000000000000000000000000000000000000000000000000000002032403ced4b65f2079eda77c84e7d2be600000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d49206c6f7665205369736d6f2100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000f80000000000000000000000000000000000000000000000000000000000000144000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001de000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000027a00000000000000000000000000000000000000000000000000000000000002c8000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000110915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c02ee756e8d291546c67b5573b9b751b5bd5a0dbcede35464ef2a6e2c14f11b033151164d686f667393f18dcd27584954f2126998bcbed6ed9b9982cd99069bb830d2e1f84055faad2b66fd81c5db45b47356df5f8a3e3c3f852b63ffb83579b25221a09032e42863c6847ff2dd1ad2843628b7cae34ce0eee41c2c95829526ba611abc4b47a83f51174c44304a3ec7fc5e0a4d2661c6e0516f1f932c5258d788a14165f2fac0ff540383b5d74113f799dc98b5e6bc9cad1d8c1706b8606ff7d400877d9fc97b985ab302afe17621dd1ede1379dc2671aeb791d104097ce7a2b7c2d27c3487bda0b24a491c70c021aee29840c77400e3612e6959cd78c1d29e55000000000000000000000000000000000000000000000000000000000000000001304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008ab1760889f26cbbf33a75fd2cf1696bfccdc9e600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c024d4b21c846468fc5e45041225279dbaf181db1d30c0ca47ba531e2139d9eaf7280d33b782823298589f29aaba714eea5acb96ebe2826de93f633d7f3c0a008f2f32d3204f8911a2bcfa70a0ef4e197b1807f8cfbb23f8e5686d79ccce4a40a10d7cf559488b27861bd1cc1b63275ccdceb49daaf8639ee099df558ceec868ed0edc00ae97888c6e213a4922f25c33e2e9de1d9a84f65101e071ac07297799eb2ca5e5cc67ee3d6c3a747ee9f0da812d8cbcb477a162dcabc40860092b8e4985049dded4313ca1c7fd8c2bb2341dc239b4c0b7db930ecc7e2b849e5dcdfe9317247dc2c6229691441432bffb6228a40d4096290a347bed1a215bf4203b6932a80000000000000000000000008ab1760889f26cbbf33a75fd2cf1696bfccdc9e61304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4c94a6091545e40fc9c3e0982aec8942e282f3800000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c005e9a85d4b9401511669228989a3ff0c30b5b9f459e900fc75d4ab9a70c49ef80e46b75f5cf3bccbf05d7af71f87fe8d132b7f85a1607b0bfd6e4feaa8213f9f1063f2f84a7ce96e52f5e43003dfab677a74c1ec96a1d626225a4033cde26ebc0e54e534d6de2002f1a08033821a7fd348fd0f9dae7e85e0796f76319ff8c8e5251c6201cecdbd21885dd4d341227cdbf8f7f5693146166d99192c0ada581d5924b9ebe2e3dd193f95bbfc462a64bddcce25b799936a919452a704138a60c35d1534cb185dc6762a446321ad3b0ac40720cde123c86d8ada6ed050b0c106adc81ee271099e4702a5925e134d668eea626c19b220a2c39dd16d0400168d99d791000000000000000000000000a4c94a6091545e40fc9c3e0982aec8942e282f381304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000100100000000000000000000000000003577409700000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0137081498c847bdc10ace33d22949bfc73b674d4812b66a8f53e878ddffc190f0cda340c783fd25566dfd14394dcc8fc9e7af60237bbec04d70b097721f7e6e70e0998b7010de2546274bb5c03238e5ffd2340c319ba85327f11e8dd0279f1f217e1c040a49739304d4025d7c42d97f2b41102d4b504b49693666d6fffae1ea5279e58b6b2a415acd5db0706921a85985d348386637463751a7de73448ac35fd215517307d716502bc580dff5ba4c8f484eeb7a1f2f9cc69f49052a09f6887b70803efb5635d81e2f07eb7ae6024bcd4ffd2b927209865e183747523f7d274c51464ceea457eb61b7c2a132177ec531842ceb568a51fe6a4e145a0f9a564a0ee00000000000000000000000010010000000000000000000000000000357740971304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100300000000000000000000000000087560811000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c01cab87335090f31f2c858c45dbe40ac1e3fd5eda4b584bbc8b8784991a5c9f91041986364178d5d6a6a9cfbe96e6679111feff038be558c436df97c113d8f10e25b99ceb0082c9df5bb7e90739e1c1f4d4588bae1169c88c5422356294e86b7e0b43cb521b0b664462993aea9666d18a84e6684afeed6ba49b0b42402b67685e0b82bfa1c7724f214cd6fd624e7300ab4372f955ebfd9b489aa935ed5e074eb2239b65a6f9f51888891d69f57ce2d4a6fd1a1594d77090edf526d16242feb4a2157bec5129edd6e86f43d73f12b2561250a8835cfa5eb1533f1a15d5d1513ca11129beec3cd8288b1beb42352734cb93173f72679402a51db226dbe1a01ce49900000000000000000000000010030000000000000000000000000008756081101304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000fae674b6cba3ff2f8ce2114defb200b1000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0068a54cba7e80eea17652e5399bac0f373a37289e19e4990f03b14f5304ba97b0e86c7b9ff626dad18a91068c36cfaca3b4bba8c23ccbd8aa89a50478632bb3808dac983625c650c8ee73594fd9b6cc609696db35f213f4efa3c7355436c61d9273d66565e35cd47df9763521fcb24813b0070b920aa7d13206d3f541540a4542ff6e85db5be75a22c067551f70000275568339f0e67155907ce6aaacdd9c35120e1c6f0752cb5565b7324847eadc5b568b60b356976f6194b59cddd32f72bcd0c60c6907df2d4e1dfc7fd7cafb77170d74deed3b60f4565d8814ad3345c489d2073030d081ad0615e2898c77db05842544e08d1909daffd4b1f51af41d0c1a600000000000000000000000000000000000000000000000000000000000000001304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d85210223889be50de6309c4a51edd039aa1fb882c9964a746581ff319bbe982debcf82efc4cc7c03398856dbf08377861fb15549f5a9137456a615d4da264e7d69cd4000000000000000000000000000000000000000000000000000000000000000108f0ec7865abde5ef350b4bd682b46dfa35deafb12d4cd29ac96341c4ffffffb000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001cde61966decb8600dfd0749bd371f12000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c02c7c25b4657897bdb2bc62112bdac39f1fcb4fd090b44a73b9e17125754d0f9a26321b26cb19ac752eb7f7557ef0b868d9e1c0cb22a6f3354d8bf1eae8efb02f2ea24f5c4265ed8439dfa93a3742164e91bad77e6fee1b2f88ecd7c58fbe802027f44df7403fb133ce8cc8c5fd23b458c4bc53c455727e28d753bfea20f1445d2182c405df59bec7da832b42cfa3edbbd48bdf42dbfb073950d13ee7b0a55f1c1d4eb48a63d9d4f67c61a932a830101e76b501cd1145ffc755d8d5450b554bbd2fbd2b04120d8ef1e5bd290b00ff4a25a917bccfa03f13da4f70e7d30ac792932e716a0f4c76aa9a197419c2125257cfcfd36fd4e7c7de28c145ec429e3c5a1700000000000000000000000000000000000000000000000000000000000000001304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d852101e7a3215d4d02e734fa653c5ca96357521ac260e6ba94a1f05c413b0143e15bd2113caea8c11ac1bdcde3d297ebd9f24df376b1ae881a18e62e49c81b5db8267000000000000000000000000000000000000000000000000000000000000000f1cde61966decb8600dfd0749bd371f126c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002fae674b6cba3ff2f8ce2114defb200b1000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c0107ecc33ddbb094a870b4f300a5fff992ce214effaf8e441b1d3de2d2b9ae0a012842d6a54fd89bc48444701e99eb26114f4bf767490bb13d0446f214c55ce7603ecc0efc47b9d2fe6683d856ddc141d234da6e80845263c4bcc1e823443da430c50c00649710842967c9755f99bafc7219a19fad38cce29f1bcf1316c1469061c0b6468c29704188ddece490bd2723cc392b4ca7b1f6501c6469236cb535bf61df114f50ba48448088c440823c7cf811003b2c1707f124d8ab2b262c7400c982b14db09cfabca6f7fd817457ae68a882cbd72c01839cc326408e938e3deb0140323af36a396c8b906ecfda2d92e82383e4693cef14d94a2b2b77f4b61b3859000000000000000000000000000000000000000000000000000000000000000001304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d85210223889be50de6309c4a51edd039aa1fb882c9964a746581ff319bbe982debcf82efc4cc7c03398856dbf08377861fb15549f5a9137456a615d4da264e7d69cd4000000000000000000000000000000000000000000000000000000000000000a08f0ec7865abde5ef350b4bd682b46dfa35deafb12d4cd29ac96341c4ffffffb000000000000000000000000000000000000000000000000000000000000000110915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000fae674b6cba3ff2f8ce2114defb200b1000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c02699914aaa5bb1b11b49261603cd894aee490c39b8ca5ea5c1625f05c60c3e2e2e4bef13a3cc0df3f3dc1bf5d601b699f4c2d94b1ca2b62622f91874f3a600832f057ff2148e63bc50db8c9f049e33929d195610f8b8a826d75941d2ef7c46ef1a108ab29c16b6498990fa5767f4e3594648c444a71dd16924366d03e1f31a9813f954aaf7916663320a9baa8de31cb14f3e4ce8fb7fc88d7ae2356f8d91404f1c21b77322002fdfcea7df847cf31f4dc7c4485d535392f4583aa67eb63bfcd214ca04a230eca28910992acf54cb9682f8b7a4240b193ccdd7ac081181e9ee3f1fbfc685affa356338b832c8c49dc2d33cafb950af2377e2ea73e53cc101020400000000000000000000000000000000000000000000000000000000000000001304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d85210223889be50de6309c4a51edd039aa1fb882c9964a746581ff319bbe982debcf82efc4cc7c03398856dbf08377861fb15549f5a9137456a615d4da264e7d69cd4000000000000000000000000000000000000000000000000000000000000000108f0ec7865abde5ef350b4bd682b46dfa35deafb12d4cd29ac96341c4ffffffb000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001cde61966decb8600dfd0749bd371f12000000000000000000000000000000006c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c01376d89c862093d8af4faece2845d584a7f5adbce6415f91185445053066db272b55dfb2d1f4d34239c3dde1e396bec29e5a1398dc9cc589a1c4a01dc6b5a190038bbde989bdaa41ae06c00e806e8b05698557a1ee2b7bcba05173cb72e5a22b2b4b2be01439457de5fbee80ca58c442b0a98239810cd611ab1db95e2806d81a194d33e4750fa3d1dc0417bc8c620935c888ad3a5af607fc4ccf21af83b539980c8017f171ea205708d7d16dd2d6968682c92a4f6aa60c4a2b397849c064f1d71f2c626c4108ab3566301144a75f0964791e8770d014da3c6b986cadc296763d19d3935c9924bd88b558920f376f4cd31833d1f69dcaa8b747bd8fab8a83305300000000000000000000000000000000000000000000000000000000000000001304dc6e4c90bc43f257c55a1c5ec90070d73f4356bca95b502a7bbc28d13a071801b584700a740f9576cc7e83745895452edc518a9ce60b430e1272fc4eb93b057cf80de4f8dd3e4c56f948f40c28c3acbeca71ef9f825597bf8cc059f1238b0d4f2a0d3c9c82fbdb9f118c948baa9d8c0b2f467855c6b4cb43a95631d852101e7a3215d4d02e734fa653c5ca96357521ac260e6ba94a1f05c413b0143e15bd2113caea8c11ac1bdcde3d297ebd9f24df376b1ae881a18e62e49c81b5db826700000000000000000000000000000000000000000000000000000000000000191cde61966decb8600dfd0749bd371f126c617465737400000000000000000000000000000000000000000000000000000000000000000000000000000000000010915e40a7c9ce7f97e81541c24893b4f714de4794fc4a3c71898cb9f25bb55f0fe61c3a8c717465050c08081b2efe7d66020da96e00293df4c354c783d06b6b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+ }
+}
diff --git a/test/verifiers/hydra-s3/HydraS3Verifier.t.sol b/test/verifiers/hydra-s3/HydraS3Verifier.t.sol
new file mode 100644
index 0000000..e8a7bfa
--- /dev/null
+++ b/test/verifiers/hydra-s3/HydraS3Verifier.t.sol
@@ -0,0 +1,521 @@
+// SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.17;
+
+import "forge-std/console.sol";
+import {HydraS3BaseTest} from "./HydraS3BaseTest.t.sol";
+import {SismoConnectHarness} from "test/harness/SismoConnectHarness.sol";
+import "src/SismoConnectLib.sol";
+import {HydraS3ProofData, HydraS3Lib, HydraS3ProofInput} from "src/verifiers/HydraS3Lib.sol";
+
+contract HydraS3VerifierTest is HydraS3BaseTest {
+ using HydraS3Lib for HydraS3ProofData;
+
+ SismoConnectHarness sismoConnect;
+ address user = 0x7def1d6D28D6bDa49E69fa89aD75d160BEcBa3AE;
+ bytes16 constant appId = 0x11b1de449c6c4adb0b5775b3868b28b3;
+ bytes16 constant groupId = 0xe9ed316946d3d98dfcd829a53ec9822e;
+
+ bool public DEFAULT_IS_IMPERSONATION_MODE = false;
+
+ ClaimRequest claimRequest;
+ AuthRequest authRequest;
+ SignatureRequest signature;
+
+ HydraS3ProofData snarkProof;
+
+ function setUp() public virtual override {
+ super.setUp();
+ sismoConnect = new SismoConnectHarness(appId, DEFAULT_IS_IMPERSONATION_MODE);
+ claimRequest = sismoConnect.exposed_buildClaim({groupId: groupId});
+ authRequest = sismoConnect.exposed_buildAuth({authType: AuthType.VAULT});
+ signature = sismoConnect.exposed_buildSignature({message: abi.encode(user)});
+ }
+
+ function test_RevertWith_InvalidVersionOfProvingScheme() public {
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ invalidResponse.proofs[0].provingScheme = bytes32("fake-proving-scheme");
+ // register the fake proving scheme to the HydraS3Verifier address i the SismoConnectVerifier contract
+ // if the proving scheme is not registered, it will revert without an error since the SismoConnectVerifier will not be able to find the verifier when routing
+ vm.prank(owner);
+ sismoConnectVerifier.registerVerifier(bytes32("fake-proving-scheme"), address(hydraS3Verifier));
+ vm.expectRevert(
+ abi.encodeWithSignature("InvalidVersion(bytes32)", bytes32("fake-proving-scheme"))
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_VaultNamespaceMismatch(uint256 invalidVaultNamespace) public {
+ // we force the invalidVaultNamespace to be different from the correct one
+ // while being a valid uint128
+ vm.assume(invalidVaultNamespace < 2 ** 128 - 1);
+ vm.assume(
+ invalidVaultNamespace !=
+ uint256(keccak256(abi.encodePacked(appId, bytes16(0)))) % HydraS3Lib.SNARK_FIELD
+ );
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOnlyOneAuthAndMessage();
+ // we change the vaultNamespace to be equal to a random one instead of the coorect appId
+ // vaultNamespace is at index 11 is in the snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 11,
+ invalidVaultNamespace
+ );
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "VaultNamespaceMismatch(uint256,uint256)",
+ snarkProof._getVaultNamespace(),
+ uint256(keccak256(abi.encodePacked(appId, bytes16(0)))) % HydraS3Lib.SNARK_FIELD
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: authRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_DestinationVerificationNotEnabled() public {
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOnlyOneAuthAndMessage();
+ // we change the authType to be equal to GITHUB instead of ANON
+ invalidResponse.proofs[0].auths[0] = Auth({
+ authType: AuthType.GITHUB,
+ isAnon: false,
+ isSelectableByUser: true,
+ userId: 0,
+ extraData: ""
+ });
+
+ // we change the authType to be equal to GITHUB instead of ANON, so it is the same as in the response and we can test the revert of the destinationVerificationEnabled
+ AuthRequest memory githubAuthRequest = sismoConnect.exposed_buildAuth({
+ authType: AuthType.GITHUB
+ });
+
+ // this should revert because the destinationVerificationEnabled is false and the AuthType is different from ANON
+ vm.expectRevert(abi.encodeWithSignature("DestinationVerificationNotEnabled()"));
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: githubAuthRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_CommitmentMapperPubKeyXMismatchWithAuth(
+ uint256 incorrectCommitmentMapperPubKeyX
+ ) public {
+ // we assume that the incorrectCommitmentMapperPubKeyX is different from the correct commitmentMapperPubKeyX when fuzzing
+ vm.assume(incorrectCommitmentMapperPubKeyX != hydraS3Proofs.getEdDSAPubKey()[0]);
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOnlyOneAuthAndMessage();
+ // we change the authType to be equal to GITHUB instead of ANON to be able to check the public key
+ invalidResponse.proofs[0].auths[0] = Auth({
+ authType: AuthType.GITHUB,
+ isAnon: false,
+ isSelectableByUser: true,
+ userId: 0,
+ extraData: ""
+ });
+ // we change the commitmentMapperPubKeyX to be equal to a random uint256 instead of the correct commitmentMapperPubKeyX
+ // commitmentMapperPubKeyX is at index 2 in the snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 2,
+ incorrectCommitmentMapperPubKeyX
+ );
+ // we change the destinationVerificationEnabled to be equal to true instead of false
+ // with an AuthType different from ANON, the destinationVerificationEnabled should be true
+ // destinationVerificationEnabled at index 13 in the snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(invalidResponse, 13, uint256(1)); // true
+
+ // we change the authType to be equal to GITHUB instead of ANON, so it is the same as in the response and we can test the revert of the destinationVerificationEnabled
+ AuthRequest memory githubAuthRequest = sismoConnect.exposed_buildAuth({
+ authType: AuthType.GITHUB
+ });
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "CommitmentMapperPubKeyMismatch(bytes32,bytes32,bytes32,bytes32)",
+ bytes32(hydraS3Proofs.getEdDSAPubKey()[0]),
+ bytes32(hydraS3Proofs.getEdDSAPubKey()[1]),
+ bytes32(incorrectCommitmentMapperPubKeyX),
+ bytes32(snarkProof._getCommitmentMapperPubKey()[1])
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: githubAuthRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_CommitmentMapperPubKeyYMismatchWithAuth(
+ uint256 incorrectCommitmentMapperPubKeyY
+ ) public {
+ // we assume that the incorrectCommitmentMapperPubKeyY is different from the correct commitmentMapperPubKeyY when fuzzing
+ vm.assume(incorrectCommitmentMapperPubKeyY != hydraS3Proofs.getEdDSAPubKey()[1]);
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOnlyOneAuthAndMessage();
+ // we change the authType to be equal to GITHUB instead of ANON to be able to check the public key
+ invalidResponse.proofs[0].auths[0] = Auth({
+ authType: AuthType.GITHUB,
+ isAnon: false,
+ isSelectableByUser: true,
+ userId: 0,
+ extraData: ""
+ });
+ // we change the commitmentMapperPubKeyY to be equal to a random uint256 instead of the correct commitmentMapperPubKeyY
+ // commitmentMapperPubKeyY is at index 3 in the snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 3,
+ incorrectCommitmentMapperPubKeyY
+ );
+ // we change the destinationVerificationEnabled to be equal to true instead of false
+ // with an AuthType different from ANON, the destinationVerificationEnabled should be true
+ invalidResponse = _changeProofDataInSismoConnectResponse(invalidResponse, 13, uint256(1)); // destinationVerificationEnabled at index 13 is equal to true
+
+ // we change the authType to be equal to GITHUB instead of ANON, so it is the same as in the response and we can test the revert of the destinationVerificationEnabled
+ AuthRequest memory githubAuthRequest = sismoConnect.exposed_buildAuth({
+ authType: AuthType.GITHUB
+ });
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "CommitmentMapperPubKeyMismatch(bytes32,bytes32,bytes32,bytes32)",
+ bytes32(hydraS3Proofs.getEdDSAPubKey()[0]),
+ bytes32(hydraS3Proofs.getEdDSAPubKey()[1]),
+ bytes32(snarkProof._getCommitmentMapperPubKey()[0]),
+ bytes32(incorrectCommitmentMapperPubKeyY)
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ auth: githubAuthRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_ClaimValueMismatch(uint256 invalidClaimValue) public {
+ // we force that the invalidClaimValue is different from the correct claimValue when fuzzing
+ vm.assume(invalidClaimValue != 1);
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ // claimValue is at index 7 in the snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(invalidResponse, 7, invalidClaimValue);
+ vm.expectRevert(abi.encodeWithSignature("ClaimValueMismatch()"));
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_RequestIdentifierMismatch(
+ uint256 incorrectRequestIdentifier
+ ) public {
+ uint256 correctRequestIdentifier = _encodeRequestIdentifier(
+ groupId,
+ bytes16("latest"),
+ appId,
+ bytes16(keccak256("main"))
+ );
+ // we force that the incorrectRequestIdentifier is different from the correct requestIdentifier when fuzzing
+ vm.assume(
+ incorrectRequestIdentifier !=
+ _encodeRequestIdentifier(groupId, bytes16("latest"), appId, bytes16(keccak256("main")))
+ );
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ // requestIdentifier is at index 5 in the snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 5,
+ incorrectRequestIdentifier
+ );
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "RequestIdentifierMismatch(uint256,uint256)",
+ incorrectRequestIdentifier,
+ correctRequestIdentifier
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_CommitmentMapperPubKeyXMismatchWithClaim(
+ uint256 incorrectCommitmentMapperPubKeyX
+ ) public {
+ // we assume that the incorrectCommitmentMapperPubKeyX is different from the correct commitmentMapperPubKeyX when fuzzing
+ vm.assume(incorrectCommitmentMapperPubKeyX != hydraS3Proofs.getEdDSAPubKey()[0]);
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ // commitmentMapperPubKeyX is at index 2 in snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 2,
+ incorrectCommitmentMapperPubKeyX
+ );
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "CommitmentMapperPubKeyMismatch(bytes32,bytes32,bytes32,bytes32)",
+ bytes32(hydraS3Proofs.getEdDSAPubKey()[0]),
+ bytes32(hydraS3Proofs.getEdDSAPubKey()[1]),
+ bytes32(incorrectCommitmentMapperPubKeyX),
+ bytes32(snarkProof._getCommitmentMapperPubKey()[1])
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+
+ // it should also revert whe in impersonation mode
+ SismoConnectHarness impersonationSismoConnect = new SismoConnectHarness(appId, true);
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "CommitmentMapperPubKeyMismatch(bytes32,bytes32,bytes32,bytes32)",
+ bytes32(hydraS3Proofs.getImpersonationEdDSAPubKey()[0]),
+ bytes32(hydraS3Proofs.getImpersonationEdDSAPubKey()[1]),
+ bytes32(incorrectCommitmentMapperPubKeyX),
+ bytes32(snarkProof._getCommitmentMapperPubKey()[1])
+ )
+ );
+ impersonationSismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_CommitmentMapperPubKeyYMismatchWithClaim(
+ uint256 incorrectCommitmentMapperPubKeyY
+ ) public {
+ // we assume that the incorrectCommitmentMapperPubKeyY is different from the correct commitmentMapperPubKeyY when fuzzing
+ vm.assume(incorrectCommitmentMapperPubKeyY != hydraS3Proofs.getEdDSAPubKey()[1]);
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ // commitmentMapperPubKeyY is at index 3 in the snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 3,
+ incorrectCommitmentMapperPubKeyY
+ );
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "CommitmentMapperPubKeyMismatch(bytes32,bytes32,bytes32,bytes32)",
+ bytes32(hydraS3Proofs.getEdDSAPubKey()[0]),
+ bytes32(hydraS3Proofs.getEdDSAPubKey()[1]),
+ bytes32(snarkProof._getCommitmentMapperPubKey()[0]),
+ bytes32(incorrectCommitmentMapperPubKeyY)
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+
+ // it should also revert whe in impersonation mode
+ SismoConnectHarness impersonationSismoConnect = new SismoConnectHarness(appId, true);
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "CommitmentMapperPubKeyMismatch(bytes32,bytes32,bytes32,bytes32)",
+ bytes32(hydraS3Proofs.getImpersonationEdDSAPubKey()[0]),
+ bytes32(hydraS3Proofs.getImpersonationEdDSAPubKey()[1]),
+ bytes32(snarkProof._getCommitmentMapperPubKey()[0]),
+ bytes32(incorrectCommitmentMapperPubKeyY)
+ )
+ );
+ impersonationSismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_SourceVerificationNotEnabled() public {
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ // we change the sourceVerificationEnabled to be equal to false instead of true
+ // sourceVerificationEnabled is at index 12 in snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(invalidResponse, 12, uint256(0));
+ vm.expectRevert(abi.encodeWithSignature("SourceVerificationNotEnabled()"));
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_RegistryTreeRootNotAvailable(
+ uint256 invalidRegistryTreeRoot
+ ) public {
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+
+ // we shift the return of the mocked AvailableRootsregistry contract to be always false
+ availableRootsRegistry.switchIsRootAvailable();
+ // registryTreeRoot is at index 4 in snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 4,
+ invalidRegistryTreeRoot
+ );
+ vm.expectRevert(
+ abi.encodeWithSignature("RegistryRootNotAvailable(uint256)", invalidRegistryTreeRoot)
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_AccountsTreeValueMismatch(
+ uint256 incorrectAccountsTreeValue
+ ) public {
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ uint256 correctAccountsTreeValue = abi
+ .decode(invalidResponse.proofs[0].proofData, (HydraS3ProofData))
+ ._getAccountsTreeValue();
+ // we assume that the incorrectAccountsTreeValue is different from the correct accountsTreeValue when fuzzing
+ vm.assume(incorrectAccountsTreeValue != correctAccountsTreeValue);
+ // accountsTreeValue is at index 8 in snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 8,
+ incorrectAccountsTreeValue
+ );
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "AccountsTreeValueMismatch(uint256,uint256)",
+ incorrectAccountsTreeValue,
+ correctAccountsTreeValue
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function test_RevertWith_ClaimTypeMismatch() public {
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ // we change the claimComparator to be equal to 1, the claimType should be EQ to not revert
+ // but we keep the claimType of GTE in the claimRequest
+ uint256 incorrectClaimComparator = 1;
+ // claimComparator is at index 9 in snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 9,
+ incorrectClaimComparator
+ );
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "ClaimTypeMismatch(uint256,uint256)",
+ incorrectClaimComparator,
+ claimRequest.claimType
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_InvalidExtraData(uint256 incorrectExtraData) public {
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ uint256 correctExtraData = abi
+ .decode(invalidResponse.proofs[0].proofData, (HydraS3ProofData))
+ ._getExtraData();
+ // we assume that the incorrectExtraData is different from the correct extraData when fuzzing
+ vm.assume(incorrectExtraData != correctExtraData);
+ // extraData is at index 1 in snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 1,
+ incorrectExtraData
+ );
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "InvalidExtraData(uint256,uint256)",
+ incorrectExtraData,
+ correctExtraData
+ )
+ );
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ function testFuzz_RevertWith_InvalidProof(uint256 incorrectProofIdentifier) public {
+ (SismoConnectResponse memory invalidResponse, ) = hydraS3Proofs
+ .getResponseWithOneClaimAndSignature();
+ uint256 correctProofIdentifier = abi
+ .decode(invalidResponse.proofs[0].proofData, (HydraS3ProofData))
+ ._getProofIdentifier();
+ vm.assume(incorrectProofIdentifier != correctProofIdentifier);
+ // we force the incorrectProofIdentifier to be less than the SNARK_FIELD
+ vm.assume(incorrectProofIdentifier < HydraS3Lib.SNARK_FIELD);
+ // proofIdentifier is at index 6 in snarkProof's inputs
+ invalidResponse = _changeProofDataInSismoConnectResponse(
+ invalidResponse,
+ 6,
+ incorrectProofIdentifier
+ );
+ vm.expectRevert(abi.encodeWithSignature("InvalidProof()"));
+ sismoConnect.exposed_verify({
+ responseBytes: abi.encode(invalidResponse),
+ claim: claimRequest,
+ signature: signature
+ });
+ }
+
+ ///////////////////////////
+ // Helper functions
+ ///////////////////////////
+
+ // this helper function is used to change the input at the specified index of the snark proof in the response
+ // the value is the new value of the input at the specified index
+ function _changeProofDataInSismoConnectResponse(
+ SismoConnectResponse memory response,
+ uint256 index,
+ uint256 value
+ ) internal returns (SismoConnectResponse memory) {
+ // Decode the snark proof from the sismoConnectProof
+ // This snark proof is specify to this proving scheme
+ snarkProof = abi.decode(response.proofs[0].proofData, (HydraS3ProofData));
+ // we change the input at the specified index to be different
+ snarkProof.input[index] = value;
+ response.proofs[0].proofData = abi.encode(snarkProof);
+ return response;
+ }
+
+ function _encodeRequestIdentifier(
+ bytes16 _groupId,
+ bytes16 groupTimestamp,
+ bytes16 _appId,
+ bytes16 namespace
+ ) internal pure returns (uint256) {
+ bytes32 groupSnapshotId = bytes32(abi.encodePacked(_groupId, groupTimestamp));
+ bytes32 serviceId = bytes32(abi.encodePacked(_appId, namespace));
+ return
+ uint256(keccak256(abi.encodePacked(serviceId, groupSnapshotId))) % HydraS3Lib.SNARK_FIELD;
+ }
+}
diff --git a/test/verifiers/mocks/VerifierMockBaseTest.t.sol b/test/verifiers/mocks/VerifierMockBaseTest.t.sol
new file mode 100644
index 0000000..413a790
--- /dev/null
+++ b/test/verifiers/mocks/VerifierMockBaseTest.t.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.17;
+
+import {BaseTest} from "test/BaseTest.t.sol";
+import {VerifierMock} from "test/mocks/VerifierMock.sol";
+
+contract VerifierMockBaseTest is BaseTest {
+ VerifierMock verifierMock;
+
+ function setUp() public virtual override {
+ super.setUp();
+
+ verifierMock = new VerifierMock();
+
+ vm.startPrank(owner);
+ sismoConnectVerifier.registerVerifier(verifierMock.VERSION(), address(verifierMock));
+ vm.stopPrank();
+ }
+}