diff --git a/packages/contracts/contracts/gatekeepers/MerkleProofGatekeeper.sol b/packages/contracts/contracts/gatekeepers/MerkleProofGatekeeper.sol new file mode 100644 index 000000000..3d8ea6501 --- /dev/null +++ b/packages/contracts/contracts/gatekeepers/MerkleProofGatekeeper.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; + +import { SignUpGatekeeper } from "./SignUpGatekeeper.sol"; + +/// @title MerkleProofGatekeeper +/// @notice A gatekeeper contract which allows users to sign up to MACI +/// only if they are part of the tree +contract MerkleProofGatekeeper is SignUpGatekeeper, Ownable(msg.sender) { + // the merkle tree root + bytes32 public immutable root; + + /// @notice the reference to the MACI contract + address public maci; + + // a mapping of addresses that have already registered + mapping(address => bool) public registeredAddresses; + + /// @notice custom errors + error InvalidProof(); + error AlreadyRegistered(); + error OnlyMACI(); + error ZeroAddress(); + error InvalidRoot(); + + /// @notice Deploy an instance of MerkleProofGatekeeper + /// @param _root The tree root + constructor(bytes32 _root) payable { + if (_root == bytes32(0)) revert InvalidRoot(); + root = _root; + } + + /// @notice Adds an uninitialised MACI instance to allow for token signups + /// @param _maci The MACI contract interface to be stored + function setMaciInstance(address _maci) public override onlyOwner { + if (_maci == address(0)) revert ZeroAddress(); + maci = _maci; + } + + /// @notice Register an user based on being part of the tree + /// @dev Throw if the proof is not valid or the user has already been registered + /// @param _user The user's Ethereum address. + /// @param _data The proof that the user is part of the tree. + function register(address _user, bytes memory _data) public override { + // ensure that the caller is the MACI contract + if (maci != msg.sender) revert OnlyMACI(); + + bytes32[] memory proof = abi.decode(_data, (bytes32[])); + + // ensure that the user has not been registered yet + if (registeredAddresses[_user]) revert AlreadyRegistered(); + + // register the user so it cannot be called again with the same one + registeredAddresses[_user] = true; + + // get the leaf + bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(_user)))); + + // check the proof + if (!MerkleProof.verify(proof, root, leaf)) revert InvalidProof(); + } + + /// @notice Get the trait of the gatekeeper + /// @return The type of the gatekeeper + function getTrait() public pure override returns (string memory) { + return "MerkleProof"; + } +} diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 683f64cc1..bd9a5b6b4 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -154,6 +154,7 @@ "@nomicfoundation/hardhat-ethers": "^3.0.6", "@nomicfoundation/hardhat-toolbox": "^5.0.0", "@openzeppelin/contracts": "^5.0.2", + "@openzeppelin/merkle-tree": "^1.0.7", "circomlibjs": "^0.1.7", "ethers": "^6.13.2", "hardhat": "^2.22.8", diff --git a/packages/contracts/tests/MerkleProofGatekeeper.test.ts b/packages/contracts/tests/MerkleProofGatekeeper.test.ts new file mode 100644 index 000000000..6f86b9829 --- /dev/null +++ b/packages/contracts/tests/MerkleProofGatekeeper.test.ts @@ -0,0 +1,124 @@ +import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; +import { expect } from "chai"; +import { AbiCoder, Signer, ZeroAddress, encodeBytes32String } from "ethers"; +import { Keypair } from "maci-domainobjs"; + +import { deployContract } from "../ts/deploy"; +import { getDefaultSigner, getSigners, generateMerkleTree } from "../ts/utils"; +import { MerkleProofGatekeeper, MACI } from "../typechain-types"; + +import { STATE_TREE_DEPTH, initialVoiceCreditBalance } from "./constants"; +import { deployTestContracts } from "./utils"; + +describe("MerkleProof Gatekeeper", () => { + let merkleProofGatekeeper: MerkleProofGatekeeper; + let signer: Signer; + let signerAddress: string; + let tree: StandardMerkleTree; + let validProof: string[]; + + const allowedAddress = [ + ["0x2fbca3862a7d99486c61e0275b6f5660180fb1b3"], + ["0x70564145fa8e8a15348ef0190e6b7c07a2120462"], + ["0x27cfc88640089f340aeaec182baff0ddf15b1b37"], + ["0xccde65cf4e39a2d28b50e3030fdab60c463fe215"], + ["0x9bae2cfa33280a8332da9a3bd589f91935b12804"], + ]; + + const invalidRoot = encodeBytes32String(""); + const invalidProof = ["0x0000000000000000000000000000000000000000000000000000000000000000"]; + + const user = new Keypair(); + + before(async () => { + signer = await getDefaultSigner(); + signerAddress = await signer.getAddress(); + allowedAddress.push([signerAddress]); + tree = generateMerkleTree(allowedAddress); + merkleProofGatekeeper = await deployContract("MerkleProofGatekeeper", signer, true, tree.root); + }); + + describe("Deployment", () => { + it("The gatekeeper should be deployed correctly", async () => { + expect(merkleProofGatekeeper).to.not.eq(undefined); + expect(await merkleProofGatekeeper.getAddress()).to.not.eq(ZeroAddress); + }); + + it("should fail to deploy when the root is not valid", async () => { + await expect(deployContract("MerkleProofGatekeeper", signer, true, invalidRoot)).to.be.revertedWithCustomError( + merkleProofGatekeeper, + "InvalidRoot", + ); + }); + }); + + describe("MerkleProofGatekeeper", () => { + let maciContract: MACI; + + before(async () => { + const r = await deployTestContracts({ + initialVoiceCreditBalance, + stateTreeDepth: STATE_TREE_DEPTH, + signer, + gatekeeper: merkleProofGatekeeper, + }); + + maciContract = r.maciContract; + validProof = tree.getProof([signerAddress]); + }); + + it("sets MACI instance correctly", async () => { + const maciAddress = await maciContract.getAddress(); + await merkleProofGatekeeper.setMaciInstance(maciAddress).then((tx) => tx.wait()); + + expect(await merkleProofGatekeeper.maci()).to.eq(maciAddress); + }); + + it("should fail to set MACI instance when the caller is not the owner", async () => { + const [, secondSigner] = await getSigners(); + await expect( + merkleProofGatekeeper.connect(secondSigner).setMaciInstance(signerAddress), + ).to.be.revertedWithCustomError(merkleProofGatekeeper, "OwnableUnauthorizedAccount"); + }); + + it("should fail to set MACI instance when the MACI instance is not valid", async () => { + await expect(merkleProofGatekeeper.setMaciInstance(ZeroAddress)).to.be.revertedWithCustomError( + merkleProofGatekeeper, + "ZeroAddress", + ); + }); + + it("should throw when the proof is invalid)", async () => { + await merkleProofGatekeeper.setMaciInstance(signerAddress).then((tx) => tx.wait()); + + await expect( + merkleProofGatekeeper.register(signerAddress, AbiCoder.defaultAbiCoder().encode(["bytes32[]"], [invalidProof])), + ).to.be.revertedWithCustomError(merkleProofGatekeeper, "InvalidProof"); + }); + + it("should register a user if the register function is called with the valid data", async () => { + await merkleProofGatekeeper.setMaciInstance(await maciContract.getAddress()).then((tx) => tx.wait()); + + // signup via MACI + const tx = await maciContract.signUp( + user.pubKey.asContractParam(), + AbiCoder.defaultAbiCoder().encode(["bytes32[]"], [validProof]), + AbiCoder.defaultAbiCoder().encode(["uint256"], [1]), + ); + + const receipt = await tx.wait(); + + expect(receipt?.status).to.eq(1); + }); + + it("should prevent signing up twice", async () => { + await expect( + maciContract.signUp( + user.pubKey.asContractParam(), + AbiCoder.defaultAbiCoder().encode(["bytes32[]"], [validProof]), + AbiCoder.defaultAbiCoder().encode(["uint256"], [1]), + ), + ).to.be.revertedWithCustomError(merkleProofGatekeeper, "AlreadyRegistered"); + }); + }); +}); diff --git a/packages/contracts/ts/utils.ts b/packages/contracts/ts/utils.ts index 359c9b2a9..bd2def241 100644 --- a/packages/contracts/ts/utils.ts +++ b/packages/contracts/ts/utils.ts @@ -1,3 +1,5 @@ +import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; + import type { Action, SnarkProof, Groth16Proof } from "./types"; import type { Ownable } from "../typechain-types"; import type { BigNumberish, FeeData, Network, Signer } from "ethers"; @@ -143,3 +145,7 @@ export const transferOwnership = async ( export function asHex(value: BigNumberish): string { return `0x${BigInt(value).toString(16)}`; } + +export function generateMerkleTree(elements: string[][]): StandardMerkleTree { + return StandardMerkleTree.of(elements, ["address"]); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 41b8f7080..9b2eaf2cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -125,7 +125,7 @@ importers: dependencies: '@docusaurus/core': specifier: ^3.5.1 - version: 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + version: 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/preset-classic': specifier: ^3.5.1 version: 3.5.1(@algolia/client-search@4.23.3)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.14.0)(typescript@5.5.4) @@ -348,6 +348,9 @@ importers: '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.0.2 + '@openzeppelin/merkle-tree': + specifier: ^1.0.7 + version: 1.0.7 circomlibjs: specifier: ^0.1.7 version: 0.1.7 @@ -2411,6 +2414,9 @@ packages: '@openzeppelin/contracts@5.0.2': resolution: {integrity: sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==} + '@openzeppelin/merkle-tree@1.0.7': + resolution: {integrity: sha512-i93t0YYv6ZxTCYU3CdO5Q+DXK0JH10A4dCBOMlzYbX+ujTXm+k1lXiEyVqmf94t3sqmv8sm/XT5zTa0+efnPgQ==} + '@peculiar/asn1-schema@2.3.8': resolution: {integrity: sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==} @@ -11552,6 +11558,97 @@ snapshots: - vue-template-compiler - webpack-cli + '@docusaurus/core@3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': + dependencies: + '@babel/core': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-transform-runtime': 7.24.7(@babel/core@7.24.7) + '@babel/preset-env': 7.24.7(@babel/core@7.24.7) + '@babel/preset-react': 7.24.7(@babel/core@7.24.7) + '@babel/preset-typescript': 7.24.7(@babel/core@7.24.7) + '@babel/runtime': 7.24.7 + '@babel/runtime-corejs3': 7.24.7 + '@babel/traverse': 7.24.7 + '@docusaurus/cssnano-preset': 3.5.1 + '@docusaurus/logger': 3.5.1 + '@docusaurus/mdx-loader': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/utils': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) + '@docusaurus/utils-common': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) + '@docusaurus/utils-validation': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) + autoprefixer: 10.4.19(postcss@8.4.38) + babel-loader: 9.1.3(@babel/core@7.24.7)(webpack@5.92.1) + babel-plugin-dynamic-import-node: 2.3.3 + boxen: 6.2.1 + chalk: 4.1.2 + chokidar: 3.6.0 + clean-css: 5.3.3 + cli-table3: 0.6.5 + combine-promises: 1.2.0 + commander: 5.1.0 + copy-webpack-plugin: 11.0.0(webpack@5.92.1) + core-js: 3.37.1 + css-loader: 6.11.0(webpack@5.92.1) + css-minimizer-webpack-plugin: 5.0.1(clean-css@5.3.3)(webpack@5.92.1) + cssnano: 6.1.2(postcss@8.4.38) + del: 6.1.1 + detect-port: 1.6.1 + escape-html: 1.0.3 + eta: 2.2.0 + eval: 0.1.8 + file-loader: 6.2.0(webpack@5.92.1) + fs-extra: 11.2.0 + html-minifier-terser: 7.2.0 + html-tags: 3.3.1 + html-webpack-plugin: 5.6.0(webpack@5.92.1) + leven: 3.1.0 + lodash: 4.17.21 + mini-css-extract-plugin: 2.9.0(webpack@5.92.1) + p-map: 4.0.0 + postcss: 8.4.38 + postcss-loader: 7.3.4(postcss@8.4.38)(typescript@5.5.4)(webpack@5.92.1) + prompts: 2.4.2 + react: 18.3.1 + react-dev-utils: 12.0.1(eslint@8.57.0)(typescript@5.5.4)(webpack@5.92.1) + react-dom: 18.3.1(react@18.3.1) + react-helmet-async: 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' + react-loadable-ssr-addon-v5-slorber: 1.0.1(@docusaurus/react-loadable@6.0.0(react@18.3.1))(webpack@5.92.1) + react-router: 5.3.4(react@18.3.1) + react-router-config: 5.1.1(react-router@5.3.4(react@18.3.1))(react@18.3.1) + react-router-dom: 5.3.4(react@18.3.1) + rtl-detect: 1.1.2 + semver: 7.6.2 + serve-handler: 6.1.5 + shelljs: 0.8.5 + terser-webpack-plugin: 5.3.10(webpack@5.92.1) + tslib: 2.6.3 + update-notifier: 6.0.2 + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.92.1))(webpack@5.92.1) + webpack: 5.92.1 + webpack-bundle-analyzer: 4.10.2 + webpack-dev-server: 4.15.2(webpack@5.92.1) + webpack-merge: 5.10.0 + webpackbar: 5.0.2(webpack@5.92.1) + transitivePeerDependencies: + - '@docusaurus/types' + - '@parcel/css' + - '@rspack/core' + - '@swc/core' + - '@swc/css' + - bufferutil + - csso + - debug + - esbuild + - eslint + - lightningcss + - supports-color + - typescript + - uglify-js + - utf-8-validate + - vue-template-compiler + - webpack-cli + '@docusaurus/cssnano-preset@3.5.1': dependencies: cssnano-preset-advanced: 6.1.2(postcss@8.4.38) @@ -11639,7 +11736,7 @@ snapshots: '@docusaurus/plugin-content-blog@3.5.1(@docusaurus/plugin-content-docs@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/logger': 3.5.1 '@docusaurus/mdx-loader': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/plugin-content-docs': 3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) @@ -11684,7 +11781,7 @@ snapshots: '@docusaurus/logger': 3.5.1 '@docusaurus/mdx-loader': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/module-type-aliases': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/theme-common': 3.5.1(@docusaurus/plugin-content-docs@3.5.1(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/theme-common': 3.5.1(@docusaurus/plugin-content-docs@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/types': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) '@docusaurus/utils-common': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) @@ -11719,7 +11816,7 @@ snapshots: '@docusaurus/plugin-content-docs@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/logger': 3.5.1 '@docusaurus/mdx-loader': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/module-type-aliases': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -11758,7 +11855,7 @@ snapshots: '@docusaurus/plugin-content-pages@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/mdx-loader': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/types': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) @@ -11788,7 +11885,7 @@ snapshots: '@docusaurus/plugin-debug@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/types': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) fs-extra: 11.2.0 @@ -11816,7 +11913,7 @@ snapshots: '@docusaurus/plugin-google-analytics@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/types': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) react: 18.3.1 @@ -11842,7 +11939,7 @@ snapshots: '@docusaurus/plugin-google-gtag@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/types': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) '@types/gtag.js': 0.0.12 @@ -11869,7 +11966,7 @@ snapshots: '@docusaurus/plugin-google-tag-manager@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/types': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) react: 18.3.1 @@ -11895,7 +11992,7 @@ snapshots: '@docusaurus/plugin-sitemap@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/logger': 3.5.1 '@docusaurus/types': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) @@ -11926,7 +12023,7 @@ snapshots: '@docusaurus/preset-classic@3.5.1(@algolia/client-search@4.23.3)(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.14.0)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/plugin-content-blog': 3.5.1(@docusaurus/plugin-content-docs@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/plugin-content-docs': 3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/plugin-content-pages': 3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) @@ -11969,7 +12066,7 @@ snapshots: '@docusaurus/theme-classic@3.5.1(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/mdx-loader': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/module-type-aliases': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/plugin-content-blog': 3.5.1(@docusaurus/plugin-content-docs@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) @@ -12015,32 +12112,6 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/theme-common@3.5.1(@docusaurus/plugin-content-docs@3.5.1(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': - dependencies: - '@docusaurus/mdx-loader': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) - '@docusaurus/module-type-aliases': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-docs': 3.5.1(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) - '@docusaurus/utils': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.4) - '@docusaurus/utils-common': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - '@types/history': 4.7.11 - '@types/react': 18.3.3 - '@types/react-router-config': 5.0.11 - clsx: 2.1.1 - parse-numeric-range: 1.3.0 - prism-react-renderer: 2.4.0(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - tslib: 2.6.3 - utility-types: 3.11.0 - transitivePeerDependencies: - - '@docusaurus/types' - - '@swc/core' - - esbuild - - supports-color - - typescript - - uglify-js - - webpack-cli - '@docusaurus/theme-common@3.5.1(@docusaurus/plugin-content-docs@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: '@docusaurus/mdx-loader': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) @@ -12070,7 +12141,7 @@ snapshots: '@docusaurus/theme-search-algolia@3.5.1(@algolia/client-search@4.23.3)(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.14.0)(typescript@5.5.4)': dependencies: '@docsearch/react': 3.6.0(@algolia/client-search@4.23.3)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.14.0) - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/logger': 3.5.1 '@docusaurus/plugin-content-docs': 3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@docusaurus/theme-common': 3.5.1(@docusaurus/plugin-content-docs@3.5.1(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) @@ -13528,6 +13599,13 @@ snapshots: '@openzeppelin/contracts@5.0.2': {} + '@openzeppelin/merkle-tree@1.0.7': + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@peculiar/asn1-schema@2.3.8': dependencies: asn1js: 3.0.5 @@ -14700,7 +14778,7 @@ snapshots: axios@1.7.2: dependencies: - follow-redirects: 1.15.6(debug@4.3.6) + follow-redirects: 1.15.6(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -16057,7 +16135,7 @@ snapshots: docusaurus-plugin-matomo@0.0.8(@docusaurus/core@3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)): dependencies: - '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(debug@4.3.6)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@docusaurus/core': 3.5.1(@docusaurus/types@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) dom-converter@0.2.0: dependencies: @@ -17931,6 +18009,18 @@ snapshots: transitivePeerDependencies: - supports-color + http-proxy-middleware@2.0.6(@types/express@4.17.21): + dependencies: + '@types/http-proxy': 1.17.14 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.7 + optionalDependencies: + '@types/express': 4.17.21 + transitivePeerDependencies: + - debug + http-proxy-middleware@2.0.6(@types/express@4.17.21)(debug@4.3.6): dependencies: '@types/http-proxy': 1.17.14 @@ -17943,6 +18033,14 @@ snapshots: transitivePeerDependencies: - debug + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.6(debug@4.3.4) + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + http-proxy@1.18.1(debug@4.3.6): dependencies: eventemitter3: 4.0.7 @@ -22939,6 +23037,46 @@ snapshots: - supports-color - utf-8-validate + webpack-dev-server@4.15.2(webpack@5.92.1): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.21 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.7 + '@types/sockjs': 0.3.36 + '@types/ws': 8.5.10 + ansi-html-community: 0.0.8 + bonjour-service: 1.2.1 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.7.4 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.19.2 + graceful-fs: 4.2.11 + html-entities: 2.5.2 + http-proxy-middleware: 2.0.6(@types/express@4.17.21) + ipaddr.js: 2.2.0 + launch-editor: 2.6.1 + open: 8.4.2 + p-retry: 4.6.2 + rimraf: 3.0.2 + schema-utils: 4.2.0 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 5.3.4(webpack@5.92.1) + ws: 8.17.1 + optionalDependencies: + webpack: 5.92.1 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + webpack-merge@5.10.0: dependencies: clone-deep: 4.0.1