{ "language": "Solidity", "sources": { "@appliedzkp/semaphore-contracts/base/SemaphoreConstants.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" }, "@appliedzkp/semaphore-contracts/base/SemaphoreCore.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../interfaces/ISemaphoreCore.sol\";\nimport \"../interfaces/IVerifier.sol\";\n\n/// @title Semaphore core contract.\n/// @notice Minimal code to allow users to signal their endorsement of an arbitrary string.\n/// @dev The following code verifies that the proof is correct and saves the hash of the\n/// nullifier to prevent double-signaling. External nullifier and Merkle trees (i.e. groups) must be\n/// managed externally.\ncontract SemaphoreCore is ISemaphoreCore {\n /// @dev Gets a nullifier hash and returns true or false.\n /// It is used to prevent double-signaling.\n mapping(uint256 => bool) internal nullifierHashes;\n\n /// @dev Asserts that no nullifier already exists and if the zero-knowledge proof is valid.\n /// Otherwise it reverts.\n /// @param signal: Semaphore signal.\n /// @param root: Root of the Merkle tree.\n /// @param nullifierHash: Nullifier hash.\n /// @param externalNullifier: External nullifier.\n /// @param proof: Zero-knowledge proof.\n /// @param verifier: Verifier address.\n function _verifyProof(\n bytes32 signal,\n uint256 root,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof,\n IVerifier verifier\n ) internal view {\n require(!nullifierHashes[nullifierHash], \"SemaphoreCore: you cannot use the same nullifier twice\");\n\n uint256 signalHash = _hashSignal(signal);\n\n verifier.verifyProof(\n [proof[0], proof[1]],\n [[proof[2], proof[3]], [proof[4], proof[5]]],\n [proof[6], proof[7]],\n [root, nullifierHash, signalHash, externalNullifier]\n );\n }\n\n /// @dev Stores the nullifier hash to prevent double-signaling.\n /// Attention! Remember to call it when you verify a proof if you\n /// need to prevent double-signaling.\n /// @param nullifierHash: Semaphore nullifier hash.\n function _saveNullifierHash(uint256 nullifierHash) internal {\n nullifierHashes[nullifierHash] = true;\n }\n\n /// @dev Creates a keccak256 hash of the signal.\n /// @param signal: Semaphore signal.\n /// @return Hash of the signal.\n function _hashSignal(bytes32 signal) private pure returns (uint256) {\n return uint256(keccak256(abi.encodePacked(signal))) >> 8;\n }\n}\n" }, "@appliedzkp/semaphore-contracts/interfaces/ISemaphoreCore.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title SemaphoreCore interface.\n/// @dev Interface of SemaphoreCore contract.\ninterface ISemaphoreCore {\n /// @notice Emitted when a proof is verified correctly and a new nullifier hash is added.\n /// @param nullifierHash: Hash of external and identity nullifiers.\n event NullifierHashAdded(uint256 nullifierHash);\n}\n" }, "@appliedzkp/semaphore-contracts/interfaces/IVerifier.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title Verifier interface.\n/// @dev Interface of Verifier contract.\ninterface IVerifier {\n function verifyProof(\n uint256[2] memory a,\n uint256[2][2] memory b,\n uint256[2] memory c,\n uint256[4] memory input\n ) external view;\n}\n" }, "@interep/contracts/IInterep.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title Interep interface.\n/// @dev Interface of a Interep contract.\ninterface IInterep {\n struct Verifier {\n address contractAddress;\n uint8 merkleTreeDepth;\n }\n\n struct Group {\n bytes32 provider;\n bytes32 name;\n uint256 root;\n uint8 depth;\n }\n\n /// @dev Emitted when a Semaphore proof is verified.\n /// @param groupId: Id of the group.\n /// @param signal: Semaphore signal.\n event ProofVerified(uint256 indexed groupId, bytes32 signal);\n\n /// @dev Emitted when an Interep group is updated.\n /// @param groupId: Id of the group.\n /// @param provider: Provider of the group.\n /// @param name: Name of the group.\n /// @param root: Root hash of the tree.\n /// @param depth: Depth of the tree.\n event GroupUpdated(\n uint256 groupId,\n bytes32 indexed provider,\n bytes32 indexed name,\n uint256 root,\n uint8 indexed depth\n );\n\n /// @dev Updates the Interep groups.\n /// @param groups: List of Interep groups.\n function updateGroups(Group[] calldata groups) external;\n\n /// @dev Saves the nullifier hash to avoid double signaling and emits an event\n /// if the zero-knowledge proof is valid.\n /// @param groupId: Id of the group.\n /// @param signal: Semaphore signal.\n /// @param nullifierHash: Nullifier hash.\n /// @param externalNullifier: External nullifier.\n /// @param proof: Zero-knowledge proof.\n function verifyProof(\n uint256 groupId,\n bytes32 signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof\n ) external;\n\n /// @dev Returns the root hash of an Interep group.\n /// @param groupId: Id of the group.\n /// @return Root hash of the group.\n function getRoot(uint256 groupId) external view returns (uint256);\n\n /// @dev Returns the tree depth of an Interep group.\n /// @param groupId: Id of the group.\n /// @return Tree depth of the group.\n function getDepth(uint256 groupId) external view returns (uint8);\n}\n" }, "@interep/contracts/Interep.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"./IInterep.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@appliedzkp/semaphore-contracts/interfaces/IVerifier.sol\";\nimport \"@appliedzkp/semaphore-contracts/base/SemaphoreCore.sol\";\nimport \"@appliedzkp/semaphore-contracts/base/SemaphoreConstants.sol\";\n\n/// @title Interep\n/// @dev Interep is a collection of reputation Semaphore groups in which members\n/// can prove their Web2 reputation (or their membership in a group) without revealing their identity.\n/// Each Interep group is actually a Merkle tree, whose leaves represent the members of the group.\n/// Interep groups are saved off-chain but the Merkle tree roots of those groups are saved on-chain\n/// at regular intervals, so that users can verify their Semaphore ZK proof on-chain with this contract.\ncontract Interep is IInterep, Ownable, SemaphoreCore {\n /// @dev Gets a tree depth and returns its verifier address.\n mapping(uint8 => IVerifier) public verifiers;\n\n /// @dev Gets a group id and returns the group data.\n mapping(uint256 => Group) public groups;\n\n /// @dev Checks if there is a verifier for the given tree depth.\n /// @param depth: Depth of the tree.\n modifier onlySupportedDepth(uint8 depth) {\n require(address(verifiers[depth]) != address(0), \"Interep: tree depth is not supported\");\n _;\n }\n\n /// @dev Initializes the Semaphore verifiers used to verify the user's ZK proofs.\n /// @param _verifiers: List of Semaphore verifiers (address and related Merkle tree depth).\n constructor(Verifier[] memory _verifiers) {\n for (uint8 i = 0; i < _verifiers.length; i++) {\n verifiers[_verifiers[i].merkleTreeDepth] = IVerifier(_verifiers[i].contractAddress);\n }\n }\n\n /// @dev See {IInterep-updateGroups}.\n function updateGroups(Group[] calldata _groups) external override onlyOwner {\n for (uint8 i = 0; i < _groups.length; i++) {\n uint256 groupId = uint256(keccak256(abi.encodePacked(_groups[i].provider, _groups[i].name))) %\n SNARK_SCALAR_FIELD;\n\n _updateGroup(groupId, _groups[i]);\n }\n }\n\n /// @dev See {IInterep-verifyProof}.\n function verifyProof(\n uint256 groupId,\n bytes32 signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof\n ) external override {\n uint256 root = getRoot(groupId);\n uint8 depth = getDepth(groupId);\n\n require(depth != 0, \"Interep: group does not exist\");\n\n IVerifier verifier = verifiers[depth];\n\n _verifyProof(signal, root, nullifierHash, externalNullifier, proof, verifier);\n\n _saveNullifierHash(nullifierHash);\n\n emit ProofVerified(groupId, signal);\n }\n\n /// @dev See {IInterep-getRoot}.\n function getRoot(uint256 groupId) public view override returns (uint256) {\n return groups[groupId].root;\n }\n\n /// @dev See {IInterep-getDepth}.\n function getDepth(uint256 groupId) public view override returns (uint8) {\n return groups[groupId].depth;\n }\n\n /// @dev Updates an Interep group.\n /// @param groupId: Id of the group.\n /// @param group: Group data.\n function _updateGroup(uint256 groupId, Group calldata group) private onlySupportedDepth(group.depth) {\n groups[groupId] = group;\n\n emit GroupUpdated(groupId, group.provider, group.name, group.root, group.depth);\n }\n}\n" }, "@openzeppelin/contracts/access/Ownable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" }, "@openzeppelin/contracts/utils/Context.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" }, "@semaphore-protocol/contracts/base/SemaphoreConstants.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n" }, "@semaphore-protocol/contracts/base/SemaphoreCore.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../interfaces/ISemaphoreCore.sol\";\nimport \"../interfaces/IVerifier.sol\";\n\n/// @title Semaphore core contract.\n/// @notice Minimal code to allow users to signal their endorsement of an arbitrary string.\n/// @dev The following code verifies that the proof is correct and saves the hash of the\n/// nullifier to prevent double-signaling. External nullifier and Merkle trees (i.e. groups) must be\n/// managed externally.\ncontract SemaphoreCore is ISemaphoreCore {\n /// @dev Gets a nullifier hash and returns true or false.\n /// It is used to prevent double-signaling.\n mapping(uint256 => bool) internal nullifierHashes;\n\n /// @dev Asserts that no nullifier already exists and if the zero-knowledge proof is valid.\n /// Otherwise it reverts.\n /// @param signal: Semaphore signal.\n /// @param root: Root of the Merkle tree.\n /// @param nullifierHash: Nullifier hash.\n /// @param externalNullifier: External nullifier.\n /// @param proof: Zero-knowledge proof.\n /// @param verifier: Verifier address.\n function _verifyProof(\n bytes32 signal,\n uint256 root,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof,\n IVerifier verifier\n ) internal view {\n require(!nullifierHashes[nullifierHash], \"SemaphoreCore: you cannot use the same nullifier twice\");\n\n uint256 signalHash = _hashSignal(signal);\n\n verifier.verifyProof(\n [proof[0], proof[1]],\n [[proof[2], proof[3]], [proof[4], proof[5]]],\n [proof[6], proof[7]],\n [root, nullifierHash, signalHash, externalNullifier]\n );\n }\n\n /// @dev Stores the nullifier hash to prevent double-signaling.\n /// Attention! Remember to call it when you verify a proof if you\n /// need to prevent double-signaling.\n /// @param nullifierHash: Semaphore nullifier hash.\n function _saveNullifierHash(uint256 nullifierHash) internal {\n nullifierHashes[nullifierHash] = true;\n }\n\n /// @dev Creates a keccak256 hash of the signal.\n /// @param signal: Semaphore signal.\n /// @return Hash of the signal.\n function _hashSignal(bytes32 signal) private pure returns (uint256) {\n return uint256(keccak256(abi.encodePacked(signal))) >> 8;\n }\n}\n" }, "@semaphore-protocol/contracts/interfaces/ISemaphoreCore.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title SemaphoreCore interface.\n/// @dev Interface of SemaphoreCore contract.\ninterface ISemaphoreCore {\n /// @notice Emitted when a proof is verified correctly and a new nullifier hash is added.\n /// @param nullifierHash: Hash of external and identity nullifiers.\n event NullifierHashAdded(uint256 nullifierHash);\n}\n" }, "@semaphore-protocol/contracts/interfaces/IVerifier.sol": { "content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title Verifier interface.\n/// @dev Interface of Verifier contract.\ninterface IVerifier {\n function verifyProof(\n uint256[2] memory a,\n uint256[2][2] memory b,\n uint256[2] memory c,\n uint256[4] memory input\n ) external view;\n}\n" }, "@semaphore-protocol/contracts/verifiers/Verifier20.sol": { "content": "//\n// Copyright 2017 Christian Reitwiessner\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n//\n// 2019 OKIMS\n// ported to solidity 0.6\n// fixed linter warnings\n// added requiere error messages\n//\n// 2021 Remco Bloemen\n// cleaned up code\n// added InvalidProve() error\n// always revert with InvalidProof() on invalid proof\n// make Pairing strict\n//\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.4;\n\nlibrary Pairing {\n error InvalidProof();\n\n // The prime q in the base field F_q for G1\n uint256 constant BASE_MODULUS = 21888242871839275222246405745257275088696311157297823662689037894645226208583;\n\n // The prime moludus of the scalar field of G1.\n uint256 constant SCALAR_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n\n struct G1Point {\n uint256 X;\n uint256 Y;\n }\n\n // Encoding of field elements is: X[0] * z + X[1]\n struct G2Point {\n uint256[2] X;\n uint256[2] Y;\n }\n\n /// @return the generator of G1\n function P1() internal pure returns (G1Point memory) {\n return G1Point(1, 2);\n }\n\n /// @return the generator of G2\n function P2() internal pure returns (G2Point memory) {\n return\n G2Point(\n [\n 11559732032986387107991004021392285783925812861821192530917403151452391805634,\n 10857046999023057135944570762232829481370756359578518086990519993285655852781\n ],\n [\n 4082367875863433681332203403145435568316851327593401208105741076214120093531,\n 8495653923123431417604973247489272438418190587263600148770280649306958101930\n ]\n );\n }\n\n /// @return r the negation of p, i.e. p.addition(p.negate()) should be zero.\n function negate(G1Point memory p) internal pure returns (G1Point memory r) {\n if (p.X == 0 && p.Y == 0) return G1Point(0, 0);\n // Validate input or revert\n if (p.X >= BASE_MODULUS || p.Y >= BASE_MODULUS) revert InvalidProof();\n // We know p.Y > 0 and p.Y < BASE_MODULUS.\n return G1Point(p.X, BASE_MODULUS - p.Y);\n }\n\n /// @return r the sum of two points of G1\n function addition(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) {\n // By EIP-196 all input is validated to be less than the BASE_MODULUS and form points\n // on the curve.\n uint256[4] memory input;\n input[0] = p1.X;\n input[1] = p1.Y;\n input[2] = p2.X;\n input[3] = p2.Y;\n bool success;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60)\n }\n if (!success) revert InvalidProof();\n }\n\n /// @return r the product of a point on G1 and a scalar, i.e.\n /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p.\n function scalar_mul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) {\n // By EIP-196 the values p.X and p.Y are verified to less than the BASE_MODULUS and\n // form a valid point on the curve. But the scalar is not verified, so we do that explicitelly.\n if (s >= SCALAR_MODULUS) revert InvalidProof();\n uint256[3] memory input;\n input[0] = p.X;\n input[1] = p.Y;\n input[2] = s;\n bool success;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)\n }\n if (!success) revert InvalidProof();\n }\n\n /// Asserts the pairing check\n /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1\n /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should succeed\n function pairingCheck(G1Point[] memory p1, G2Point[] memory p2) internal view {\n // By EIP-197 all input is verified to be less than the BASE_MODULUS and form elements in their\n // respective groups of the right order.\n if (p1.length != p2.length) revert InvalidProof();\n uint256 elements = p1.length;\n uint256 inputSize = elements * 6;\n uint256[] memory input = new uint256[](inputSize);\n for (uint256 i = 0; i < elements; i++) {\n input[i * 6 + 0] = p1[i].X;\n input[i * 6 + 1] = p1[i].Y;\n input[i * 6 + 2] = p2[i].X[0];\n input[i * 6 + 3] = p2[i].X[1];\n input[i * 6 + 4] = p2[i].Y[0];\n input[i * 6 + 5] = p2[i].Y[1];\n }\n uint256[1] memory out;\n bool success;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)\n }\n if (!success || out[0] != 1) revert InvalidProof();\n }\n}\n\ncontract Verifier20 {\n using Pairing for *;\n\n struct VerifyingKey {\n Pairing.G1Point alfa1;\n Pairing.G2Point beta2;\n Pairing.G2Point gamma2;\n Pairing.G2Point delta2;\n Pairing.G1Point[] IC;\n }\n\n struct Proof {\n Pairing.G1Point A;\n Pairing.G2Point B;\n Pairing.G1Point C;\n }\n\n function verifyingKey() internal pure returns (VerifyingKey memory vk) {\n vk.alfa1 = Pairing.G1Point(\n 20491192805390485299153009773594534940189261866228447918068658471970481763042,\n 9383485363053290200918347156157836566562967994039712273449902621266178545958\n );\n\n vk.beta2 = Pairing.G2Point(\n [4252822878758300859123897981450591353533073413197771768651442665752259397132, 6375614351688725206403948262868962793625744043794305715222011528459656738731],\n [21847035105528745403288232691147584728191162732299865338377159692350059136679, 10505242626370262277552901082094356697409835680220590971873171140371331206856]\n );\n\n vk.gamma2 = Pairing.G2Point(\n [11559732032986387107991004021392285783925812861821192530917403151452391805634, 10857046999023057135944570762232829481370756359578518086990519993285655852781],\n [4082367875863433681332203403145435568316851327593401208105741076214120093531, 8495653923123431417604973247489272438418190587263600148770280649306958101930]\n );\n\n vk.delta2 = Pairing.G2Point(\n [18976133691706015337908381757202123182841901611067930614519324084182946094218, 1382518990777992893805140303684642328066746531257780279226677247567004248173],\n [6627710380771660558660627878547223719795356903257079198333641681330388499309, 21806956747910197517744499423107239699428979652113081469385876768212706694581]\n );\n\n vk.IC = new Pairing.G1Point[](5);\n\n \n vk.IC[0] = Pairing.G1Point(\n 19918517214839406678907482305035208173510172567546071380302965459737278553528,\n 7151186077716310064777520690144511885696297127165278362082219441732663131220\n );\n \n vk.IC[1] = Pairing.G1Point(\n 690581125971423619528508316402701520070153774868732534279095503611995849608,\n 21271996888576045810415843612869789314680408477068973024786458305950370465558\n );\n \n vk.IC[2] = Pairing.G1Point(\n 16461282535702132833442937829027913110152135149151199860671943445720775371319,\n 2814052162479976678403678512565563275428791320557060777323643795017729081887\n );\n \n vk.IC[3] = Pairing.G1Point(\n 4319780315499060392574138782191013129592543766464046592208884866569377437627,\n 13920930439395002698339449999482247728129484070642079851312682993555105218086\n );\n \n vk.IC[4] = Pairing.G1Point(\n 3554830803181375418665292545416227334138838284686406179598687755626325482686,\n 5951609174746846070367113593675211691311013364421437923470787371738135276998\n );\n \n }\n\n /// @dev Verifies a Semaphore proof. Reverts with InvalidProof if the proof is invalid.\n function verifyProof(\n uint[2] memory a,\n uint[2][2] memory b,\n uint[2] memory c,\n uint[4] memory input\n ) public view {\n // If the values are not in the correct range, the Pairing contract will revert.\n Proof memory proof;\n proof.A = Pairing.G1Point(a[0], a[1]);\n proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]);\n proof.C = Pairing.G1Point(c[0], c[1]);\n\n VerifyingKey memory vk = verifyingKey();\n\n // Compute the linear combination vk_x of inputs times IC\n if (input.length + 1 != vk.IC.length) revert Pairing.InvalidProof();\n Pairing.G1Point memory vk_x = vk.IC[0];\n vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[1], input[0]));\n vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[2], input[1]));\n vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[3], input[2]));\n vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[4], input[3]));\n\n // Check pairing\n Pairing.G1Point[] memory p1 = new Pairing.G1Point[](4);\n Pairing.G2Point[] memory p2 = new Pairing.G2Point[](4);\n p1[0] = Pairing.negate(proof.A);\n p2[0] = proof.B;\n p1[1] = vk.alfa1;\n p2[1] = vk.beta2;\n p1[2] = vk_x;\n p2[2] = vk.gamma2;\n p1[3] = proof.C;\n p2[3] = vk.delta2;\n Pairing.pairingCheck(p1, p2);\n }\n}\n" }, "contracts/InterepTest.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"@interep/contracts/IInterep.sol\";\nimport \"@semaphore-protocol/contracts/interfaces/IVerifier.sol\";\nimport \"@semaphore-protocol/contracts/base/SemaphoreCore.sol\";\nimport \"@semaphore-protocol/contracts/base/SemaphoreConstants.sol\";\n\ncontract InterepTest is IInterep, SemaphoreCore {\n /// @dev Gets a tree depth and returns its verifier address.\n mapping(uint8 => IVerifier) public verifiers;\n\n mapping(uint256 => Group) public groups;\n\n /// @dev Checks if there is a verifier for the given tree depth.\n /// @param depth: Depth of the tree.\n modifier onlySupportedDepth(uint8 depth) {\n require(\n address(verifiers[depth]) != address(0),\n \"Interep: tree depth is not supported\"\n );\n _;\n }\n\n /// @dev Initializes the Semaphore verifiers used to verify the user's ZK proofs.\n /// @param _verifiers: List of Semaphore verifiers (address and related Merkle tree depth).\n constructor(Verifier[] memory _verifiers) {\n for (uint8 i = 0; i < _verifiers.length; i++) {\n verifiers[_verifiers[i].merkleTreeDepth] = IVerifier(\n _verifiers[i].contractAddress\n );\n }\n }\n\n /// @dev See {IInterep-updateGroups}.\n function updateGroups(Group[] calldata _groups) external override {\n for (uint8 i = 0; i < _groups.length; i++) {\n uint256 groupId = uint256(\n keccak256(\n abi.encodePacked(_groups[i].provider, _groups[i].name)\n )\n ) % SNARK_SCALAR_FIELD;\n\n _updateGroup(groupId, _groups[i]);\n }\n }\n\n /// @dev See {IInterep-getRoot}.\n function getRoot(uint256 groupId) public view override returns (uint256) {\n return groups[groupId].root;\n }\n\n /// @dev See {IInterep-getDepth}.\n function getDepth(uint256 groupId) public view override returns (uint8) {\n return groups[groupId].depth;\n }\n\n /// @dev Updates an Interep group.\n /// @param groupId: Id of the group.\n /// @param group: Group data.\n function _updateGroup(uint256 groupId, Group calldata group) private {\n groups[groupId] = group;\n\n emit GroupUpdated(\n groupId,\n group.provider,\n group.name,\n group.root,\n group.depth\n );\n }\n\n /// @dev See {IInterep-verifyProof}.\n function verifyProof(\n uint256 groupId,\n bytes32 signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof\n ) external override {\n uint256 root = getRoot(groupId);\n uint8 depth = getDepth(groupId);\n\n require(depth != 0, \"Interep: group does not exist\");\n\n IVerifier verifier = verifiers[depth];\n\n _verifyProof(\n signal,\n root,\n nullifierHash,\n externalNullifier,\n proof,\n verifier\n );\n\n // NOTE: After @interep/contracts is updated to use @semaphore-protocol/contracts v2,6.1, the logic to saveNullifierHash will change\n // ref: https://github.com/semaphore-protocol/semaphore/blob/68779e90a0db120d9c36143c5f48ca6fd1a2a159/packages/contracts/contracts/interfaces/ISemaphore.sol#L23\n // https://github.com/semaphore-protocol/semaphore/blob/68779e90a0db120d9c36143c5f48ca6fd1a2a159/packages/contracts/contracts/Semaphore.sol#L162-L171\n // Till then, downgrading semaphore-protocol/contracts to v2.0.0\n _saveNullifierHash(nullifierHash);\n\n emit ProofVerified(groupId, signal);\n }\n}\n" }, "contracts/PoseidonHasher.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\ninterface IPoseidonHasher {\n function hash(uint256 input) external pure returns (uint256 result);\n\n function identity() external pure returns (uint256);\n}\n\ncontract PoseidonHasher is IPoseidonHasher {\n uint256 constant Q =\n 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n uint256 constant C0 =\n 4417881134626180770308697923359573201005643519861877412381846989312604493735;\n uint256 constant C1 =\n 5433650512959517612316327474713065966758808864213826738576266661723522780033;\n uint256 constant C2 =\n 13641176377184356099764086973022553863760045607496549923679278773208775739952;\n uint256 constant C3 =\n 17949713444224994136330421782109149544629237834775211751417461773584374506783;\n uint256 constant C4 =\n 13765628375339178273710281891027109699578766420463125835325926111705201856003;\n uint256 constant C5 =\n 19179513468172002314585757290678967643352171735526887944518845346318719730387;\n uint256 constant C6 =\n 5157412437176756884543472904098424903141745259452875378101256928559722612176;\n uint256 constant C7 =\n 535160875740282236955320458485730000677124519901643397458212725410971557409;\n uint256 constant C8 =\n 1050793453380762984940163090920066886770841063557081906093018330633089036729;\n uint256 constant C9 =\n 10665495010329663932664894101216428400933984666065399374198502106997623173873;\n uint256 constant C10 =\n 19965634623406616956648724894636666805991993496469370618546874926025059150737;\n uint256 constant C11 =\n 13007250030070838431593222885902415182312449212965120303174723305710127422213;\n uint256 constant C12 =\n 16877538715074991604507979123743768693428157847423939051086744213162455276374;\n uint256 constant C13 =\n 18211747749504876135588847560312685184956239426147543810126553367063157141465;\n uint256 constant C14 =\n 18151553319826126919739798892854572062191241985315767086020821632812331245635;\n uint256 constant C15 =\n 19957033149976712666746140949846950406660099037474791840946955175819555930825;\n uint256 constant C16 =\n 3469514863538261843186854830917934449567467100548474599735384052339577040841;\n uint256 constant C17 =\n 989698510043911779243192466312362856042600749099921773896924315611668507708;\n uint256 constant C18 =\n 12568377015646290945235387813564567111330046038050864455358059568128000172201;\n uint256 constant C19 =\n 20856104135605479600325529349246932565148587186338606236677138505306779314172;\n uint256 constant C20 =\n 8206918720503535523121349917159924938835810381723474192155637697065780938424;\n uint256 constant C21 =\n 1309058477013932989380617265069188723120054926187607548493110334522527703566;\n uint256 constant C22 =\n 14076116939332667074621703729512195584105250395163383769419390236426287710606;\n uint256 constant C23 =\n 10153498892749751942204288991871286290442690932856658983589258153608012428674;\n uint256 constant C24 =\n 18202499207234128286137597834010475797175973146805180988367589376893530181575;\n uint256 constant C25 =\n 12739388830157083522877690211447248168864006284243907142044329113461613743052;\n uint256 constant C26 =\n 15123358710467780770838026754240340042441262572309759635224051333176022613949;\n uint256 constant C27 =\n 19925004701844594370904593774447343836015483888496504201331110250494635362184;\n uint256 constant C28 =\n 10352416606816998476681131583320899030072315953910679608943150613208329645891;\n uint256 constant C29 =\n 10567371822366244361703342347428230537114808440249611395507235283708966113221;\n uint256 constant C30 =\n 5635498582763880627392290206431559361272660937399944184533035305989295959602;\n uint256 constant C31 =\n 11866432933224219174041051738704352719163271639958083608224676028593315904909;\n uint256 constant C32 =\n 5795020705294401441272215064554385591292330721703923167136157291459784140431;\n uint256 constant C33 =\n 9482202378699252817564375087302794636287866584767523335624368774856230692758;\n uint256 constant C34 =\n 4245237636894546151746468406560945873445548423466753843402086544922216329298;\n uint256 constant C35 =\n 12000500941313982757584712677991730019124834399479314697467598397927435905133;\n uint256 constant C36 =\n 7596790274058425558167520209857956363736666939016807569082239187494363541787;\n uint256 constant C37 =\n 2484867918246116343205467273440098378820186751202461278013576281097918148877;\n uint256 constant C38 =\n 18312645949449997391810445935615409295369169383463185688973803378104013950190;\n uint256 constant C39 =\n 15320686572748723004980855263301182130424010735782762814513954166519592552733;\n uint256 constant C40 =\n 12618438900597948888520621062416758747872180395546164387827245287017031303859;\n uint256 constant C41 =\n 17438141672027706116733201008397064011774368832458707512367404736905021019585;\n uint256 constant C42 =\n 6374197807230665998865688675365359100400438034755781666913068586172586548950;\n uint256 constant C43 =\n 2189398913433273865510950346186699930188746169476472274335177556702504595264;\n uint256 constant C44 =\n 6268495580028970231803791523870131137294646402347399003576649137450213034606;\n uint256 constant C45 =\n 17896250365994900261202920044129628104272791547990619503076839618914047059275;\n uint256 constant C46 =\n 13692156312448722528008862371944543449350293305158722920787736248435893008873;\n uint256 constant C47 =\n 15234446864368744483209945022439268713300180233589581910497691316744177619376;\n uint256 constant C48 =\n 1572426502623310766593681563281600503979671244997798691029595521622402217227;\n uint256 constant C49 =\n 80103447810215150918585162168214870083573048458555897999822831203653996617;\n uint256 constant C50 =\n 8228820324013669567851850635126713973797711779951230446503353812192849106342;\n uint256 constant C51 =\n 5375851433746509614045812476958526065449377558695752132494533666370449415873;\n uint256 constant C52 =\n 12115998939203497346386774317892338270561208357481805380546938146796257365018;\n uint256 constant C53 =\n 9764067909645821279940531410531154041386008396840887338272986634350423466622;\n uint256 constant C54 =\n 8538708244538850542384936174629541085495830544298260335345008245230827876882;\n uint256 constant C55 =\n 7140127896620013355910287215441004676619168261422440177712039790284719613114;\n uint256 constant C56 =\n 14297402962228458726038826185823085337698917275385741292940049024977027409762;\n uint256 constant C57 =\n 6667115556431351074165934212337261254608231545257434281887966406956835140819;\n uint256 constant C58 =\n 20226761165244293291042617464655196752671169026542832236139342122602741090001;\n uint256 constant C59 =\n 12038289506489256655759141386763477208196694421666339040483042079632134429119;\n uint256 constant C60 =\n 19027757334170818571203982241812412991528769934917288000224335655934473717551;\n uint256 constant C61 =\n 16272152964456553579565580463468069884359929612321610357528838696790370074720;\n uint256 constant C62 =\n 2500392889689246014710135696485946334448570271481948765283016105301740284071;\n uint256 constant C63 =\n 8595254970528530312401637448610398388203855633951264114100575485022581946023;\n uint256 constant C64 =\n 11635945688914011450976408058407206367914559009113158286982919675551688078198;\n uint256 constant C65 =\n 614739068603482619581328040478536306925147663946742687395148680260956671871;\n uint256 constant C66 =\n 18692271780377861570175282183255720350972693125537599213951106550953176268753;\n uint256 constant C67 =\n 4987059230784976306647166378298632695585915319042844495357753339378260807164;\n uint256 constant C68 =\n 21851403978498723616722415377430107676258664746210815234490134600998983955497;\n uint256 constant C69 =\n 9830635451186415300891533983087800047564037813328875992115573428596207326204;\n uint256 constant C70 =\n 4842706106434537116860242620706030229206345167233200482994958847436425185478;\n uint256 constant C71 =\n 6422235064906823218421386871122109085799298052314922856340127798647926126490;\n uint256 constant C72 =\n 4564364104986856861943331689105797031330091877115997069096365671501473357846;\n uint256 constant C73 =\n 1944043894089780613038197112872830569538541856657037469098448708685350671343;\n uint256 constant C74 =\n 21179865974855950600518216085229498748425990426231530451599322283119880194955;\n uint256 constant C75 =\n 14296697761894107574369608843560006996183955751502547883167824879840894933162;\n uint256 constant C76 =\n 12274619649702218570450581712439138337725246879938860735460378251639845671898;\n uint256 constant C77 =\n 16371396450276899401411886674029075408418848209575273031725505038938314070356;\n uint256 constant C78 =\n 3702561221750983937578095019779188631407216522704543451228773892695044653565;\n uint256 constant C79 =\n 19721616877735564664624984774636557499099875603996426215495516594530838681980;\n uint256 constant C80 =\n 6383350109027696789969911008057747025018308755462287526819231672217685282429;\n uint256 constant C81 =\n 20860583956177367265984596617324237471765572961978977333122281041544719622905;\n uint256 constant C82 =\n 5766390934595026947545001478457407504285452477687752470140790011329357286275;\n uint256 constant C83 =\n 4043175758319898049344746138515323336207420888499903387536875603879441092484;\n uint256 constant C84 =\n 15579382179133608217098622223834161692266188678101563820988612253342538956534;\n uint256 constant C85 =\n 1864640783252634743892105383926602930909039567065240010338908865509831749824;\n uint256 constant C86 =\n 15943719865023133586707144161652035291705809358178262514871056013754142625673;\n uint256 constant C87 =\n 2326415993032390211558498780803238091925402878871059708106213703504162832999;\n uint256 constant C88 =\n 19995326402773833553207196590622808505547443523750970375738981396588337910289;\n uint256 constant C89 =\n 5143583711361588952673350526320181330406047695593201009385718506918735286622;\n uint256 constant C90 =\n 15436006486881920976813738625999473183944244531070780793506388892313517319583;\n uint256 constant C91 =\n 16660446760173633166698660166238066533278664023818938868110282615200613695857;\n uint256 constant C92 =\n 4966065365695755376133119391352131079892396024584848298231004326013366253934;\n uint256 constant C93 =\n 20683781957411705574951987677641476019618457561419278856689645563561076926702;\n uint256 constant C94 =\n 17280836839165902792086432296371645107551519324565649849400948918605456875699;\n uint256 constant C95 =\n 17045635513701208892073056357048619435743564064921155892004135325530808465371;\n uint256 constant C96 =\n 17055032967194400710390142791334572297458033582458169295920670679093585707295;\n uint256 constant C97 =\n 15727174639569115300068198908071514334002742825679221638729902577962862163505;\n uint256 constant C98 =\n 1001755657610446661315902885492677747789366510875120894840818704741370398633;\n uint256 constant C99 =\n 18638547332826171619311285502376343504539399518545103511265465604926625041234;\n uint256 constant C100 =\n 6751954224763196429755298529194402870632445298969935050224267844020826420799;\n uint256 constant C101 =\n 3526747115904224771452549517614107688674036840088422555827581348280834879405;\n uint256 constant C102 =\n 15705897908180497062880001271426561999724005008972544196300715293701537574122;\n uint256 constant C103 =\n 574386695213920937259007343820417029802510752426579750428758189312416867750;\n uint256 constant C104 =\n 15973040855000600860816974646787367136127946402908768408978806375685439868553;\n uint256 constant C105 =\n 20934130413948796333037139460875996342810005558806621330680156931816867321122;\n uint256 constant C106 =\n 6918585327145564636398173845411579411526758237572034236476079610890705810764;\n uint256 constant C107 =\n 14158163500813182062258176233162498241310167509137716527054939926126453647182;\n uint256 constant C108 =\n 4164602626597695668474100217150111342272610479949122406544277384862187287433;\n uint256 constant C109 =\n 12146526846507496913615390662823936206892812880963914267275606265272996025304;\n uint256 constant C110 =\n 10153527926900017763244212043512822363696541810586522108597162891799345289938;\n uint256 constant C111 =\n 13564663485965299104296214940873270349072051793008946663855767889066202733588;\n uint256 constant C112 =\n 5612449256997576125867742696783020582952387615430650198777254717398552960096;\n uint256 constant C113 =\n 12151885480032032868507892738683067544172874895736290365318623681886999930120;\n uint256 constant C114 =\n 380452237704664384810613424095477896605414037288009963200982915188629772177;\n uint256 constant C115 =\n 9067557551252570188533509616805287919563636482030947363841198066124642069518;\n uint256 constant C116 =\n 21280306817619711661335268484199763923870315733198162896599997188206277056900;\n uint256 constant C117 =\n 5567165819557297006750252582140767993422097822227408837378089569369734876257;\n uint256 constant C118 =\n 10411936321072105429908396649383171465939606386380071222095155850987201580137;\n uint256 constant C119 =\n 21338390051413922944780864872652000187403217966653363270851298678606449622266;\n uint256 constant C120 =\n 12156296560457833712186127325312904760045212412680904475497938949653569234473;\n uint256 constant C121 =\n 4271647814574748734312113971565139132510281260328947438246615707172526380757;\n uint256 constant C122 =\n 9061738206062369647211128232833114177054715885442782773131292534862178874950;\n uint256 constant C123 =\n 10134551893627587797380445583959894183158393780166496661696555422178052339133;\n uint256 constant C124 =\n 8932270237664043612366044102088319242789325050842783721780970129656616386103;\n uint256 constant C125 =\n 3339412934966886386194449782756711637636784424032779155216609410591712750636;\n uint256 constant C126 =\n 9704903972004596791086522314847373103670545861209569267884026709445485704400;\n uint256 constant C127 =\n 17467570179597572575614276429760169990940929887711661192333523245667228809456;\n uint256 constant M00 =\n 2910766817845651019878574839501801340070030115151021261302834310722729507541;\n uint256 constant M01 =\n 19727366863391167538122140361473584127147630672623100827934084310230022599144;\n uint256 constant M10 =\n 5776684794125549462448597414050232243778680302179439492664047328281728356345;\n uint256 constant M11 =\n 8348174920934122550483593999453880006756108121341067172388445916328941978568;\n\n function hash(\n uint256 input\n ) external pure override returns (uint256 result) {\n return _hash(input);\n }\n\n function _hash(uint256 input) internal pure returns (uint256 result) {\n assembly {\n // Poseidon parameters should be t = 2, RF = 8, RP = 56\n\n // We load the characteristic\n let q := Q\n\n // In zerokit implementation, if we pass inp = [a0,a1,..,an] to Poseidon what is effectively hashed is [0,a0,a1,..,an]\n // Note that a sequence of MIX-ARK involves 3 Bn254 field additions before the mulmod happens. Worst case we have a value corresponding to 2*(p-1) which is less than 2^256 and hence doesn't overflow\n //ROUND 0 - FULL\n let s0 := C0\n let s1 := add(input, C1)\n // SBOX\n let t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n t := mulmod(s1, s1, q)\n s1 := mulmod(mulmod(t, t, q), s1, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 1 - FULL\n s0 := add(s0, C2)\n s1 := add(s1, C3)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n t := mulmod(s1, s1, q)\n s1 := mulmod(mulmod(t, t, q), s1, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 2 - FULL\n s0 := add(s0, C4)\n s1 := add(s1, C5)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n t := mulmod(s1, s1, q)\n s1 := mulmod(mulmod(t, t, q), s1, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 3 - FULL\n s0 := add(s0, C6)\n s1 := add(s1, C7)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n t := mulmod(s1, s1, q)\n s1 := mulmod(mulmod(t, t, q), s1, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 4 - PARTIAL\n s0 := add(s0, C8)\n s1 := add(s1, C9)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 5 - PARTIAL\n s0 := add(s0, C10)\n s1 := add(s1, C11)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 6 - PARTIAL\n s0 := add(s0, C12)\n s1 := add(s1, C13)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 7 - PARTIAL\n s0 := add(s0, C14)\n s1 := add(s1, C15)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 8 - PARTIAL\n s0 := add(s0, C16)\n s1 := add(s1, C17)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 9 - PARTIAL\n s0 := add(s0, C18)\n s1 := add(s1, C19)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 10 - PARTIAL\n s0 := add(s0, C20)\n s1 := add(s1, C21)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 11 - PARTIAL\n s0 := add(s0, C22)\n s1 := add(s1, C23)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 12 - PARTIAL\n s0 := add(s0, C24)\n s1 := add(s1, C25)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 13 - PARTIAL\n s0 := add(s0, C26)\n s1 := add(s1, C27)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 14 - PARTIAL\n s0 := add(s0, C28)\n s1 := add(s1, C29)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 15 - PARTIAL\n s0 := add(s0, C30)\n s1 := add(s1, C31)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 16 - PARTIAL\n s0 := add(s0, C32)\n s1 := add(s1, C33)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 17 - PARTIAL\n s0 := add(s0, C34)\n s1 := add(s1, C35)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 18 - PARTIAL\n s0 := add(s0, C36)\n s1 := add(s1, C37)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 19 - PARTIAL\n s0 := add(s0, C38)\n s1 := add(s1, C39)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 20 - PARTIAL\n s0 := add(s0, C40)\n s1 := add(s1, C41)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 21 - PARTIAL\n s0 := add(s0, C42)\n s1 := add(s1, C43)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 22 - PARTIAL\n s0 := add(s0, C44)\n s1 := add(s1, C45)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 23 - PARTIAL\n s0 := add(s0, C46)\n s1 := add(s1, C47)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 24 - PARTIAL\n s0 := add(s0, C48)\n s1 := add(s1, C49)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 25 - PARTIAL\n s0 := add(s0, C50)\n s1 := add(s1, C51)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 26 - PARTIAL\n s0 := add(s0, C52)\n s1 := add(s1, C53)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 27 - PARTIAL\n s0 := add(s0, C54)\n s1 := add(s1, C55)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 28 - PARTIAL\n s0 := add(s0, C56)\n s1 := add(s1, C57)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 29 - PARTIAL\n s0 := add(s0, C58)\n s1 := add(s1, C59)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 30 - PARTIAL\n s0 := add(s0, C60)\n s1 := add(s1, C61)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 31 - PARTIAL\n s0 := add(s0, C62)\n s1 := add(s1, C63)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 32 - PARTIAL\n s0 := add(s0, C64)\n s1 := add(s1, C65)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 33 - PARTIAL\n s0 := add(s0, C66)\n s1 := add(s1, C67)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 34 - PARTIAL\n s0 := add(s0, C68)\n s1 := add(s1, C69)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 35 - PARTIAL\n s0 := add(s0, C70)\n s1 := add(s1, C71)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 36 - PARTIAL\n s0 := add(s0, C72)\n s1 := add(s1, C73)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 37 - PARTIAL\n s0 := add(s0, C74)\n s1 := add(s1, C75)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 38 - PARTIAL\n s0 := add(s0, C76)\n s1 := add(s1, C77)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 39 - PARTIAL\n s0 := add(s0, C78)\n s1 := add(s1, C79)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 40 - PARTIAL\n s0 := add(s0, C80)\n s1 := add(s1, C81)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 41 - PARTIAL\n s0 := add(s0, C82)\n s1 := add(s1, C83)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 42 - PARTIAL\n s0 := add(s0, C84)\n s1 := add(s1, C85)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 43 - PARTIAL\n s0 := add(s0, C86)\n s1 := add(s1, C87)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 44 - PARTIAL\n s0 := add(s0, C88)\n s1 := add(s1, C89)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 45 - PARTIAL\n s0 := add(s0, C90)\n s1 := add(s1, C91)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 46 - PARTIAL\n s0 := add(s0, C92)\n s1 := add(s1, C93)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 47 - PARTIAL\n s0 := add(s0, C94)\n s1 := add(s1, C95)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 48 - PARTIAL\n s0 := add(s0, C96)\n s1 := add(s1, C97)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 49 - PARTIAL\n s0 := add(s0, C98)\n s1 := add(s1, C99)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 50 - PARTIAL\n s0 := add(s0, C100)\n s1 := add(s1, C101)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 51 - PARTIAL\n s0 := add(s0, C102)\n s1 := add(s1, C103)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 52 - PARTIAL\n s0 := add(s0, C104)\n s1 := add(s1, C105)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 53 - PARTIAL\n s0 := add(s0, C106)\n s1 := add(s1, C107)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 54 - PARTIAL\n s0 := add(s0, C108)\n s1 := add(s1, C109)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 55 - PARTIAL\n s0 := add(s0, C110)\n s1 := add(s1, C111)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 56 - PARTIAL\n s0 := add(s0, C112)\n s1 := add(s1, C113)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 57 - PARTIAL\n s0 := add(s0, C114)\n s1 := add(s1, C115)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 58 - PARTIAL\n s0 := add(s0, C116)\n s1 := add(s1, C117)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 59 - PARTIAL\n s0 := add(s0, C118)\n s1 := add(s1, C119)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 60 - FULL\n s0 := add(s0, C120)\n s1 := add(s1, C121)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n t := mulmod(s1, s1, q)\n s1 := mulmod(mulmod(t, t, q), s1, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 61 - FULL\n s0 := add(s0, C122)\n s1 := add(s1, C123)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n t := mulmod(s1, s1, q)\n s1 := mulmod(mulmod(t, t, q), s1, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 62 - FULL\n s0 := add(s0, C124)\n s1 := add(s1, C125)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n t := mulmod(s1, s1, q)\n s1 := mulmod(mulmod(t, t, q), s1, q)\n // MIX\n t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))\n s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))\n s0 := t\n\n //ROUND 63 - FULL\n s0 := add(s0, C126)\n s1 := add(s1, C127)\n // SBOX\n t := mulmod(s0, s0, q)\n s0 := mulmod(mulmod(t, t, q), s0, q)\n t := mulmod(s1, s1, q)\n s1 := mulmod(mulmod(t, t, q), s1, q)\n // MIX\n s0 := mod(add(mulmod(s0, M00, q), mulmod(s1, M01, q)), q)\n\n result := s0\n }\n }\n\n function identity() external pure override returns (uint256) {\n return _identity();\n }\n\n // The hash of 0\n function _identity() internal pure returns (uint256) {\n return\n 0x2a09a9fd93c590c26b91effbb2499f07e8f7aa12e2b4940a3aed2411cb65e11c;\n }\n}\n" }, "contracts/Rln.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {IPoseidonHasher} from \"./PoseidonHasher.sol\";\nimport {IValidGroupStorage} from \"./ValidGroupStorage.sol\";\nimport {IInterep} from \"@interep/contracts/IInterep.sol\";\n\ncontract RLN {\n uint256 public immutable MEMBERSHIP_DEPOSIT;\n uint256 public immutable DEPTH;\n uint256 public immutable SET_SIZE;\n\n uint256 public idCommitmentIndex;\n mapping(uint256 => uint256) public stakedAmounts;\n mapping(uint256 => bool) public members;\n\n IPoseidonHasher public poseidonHasher;\n IValidGroupStorage public validGroupStorage;\n IInterep public interep;\n\n event MemberRegistered(uint256 idCommitment, uint256 index);\n event MemberWithdrawn(uint256 idCommitment);\n\n constructor(\n uint256 membershipDeposit,\n uint256 depth,\n address _poseidonHasher,\n address _validGroupStorage\n ) {\n MEMBERSHIP_DEPOSIT = membershipDeposit;\n DEPTH = depth;\n SET_SIZE = 1 << depth;\n poseidonHasher = IPoseidonHasher(_poseidonHasher);\n validGroupStorage = IValidGroupStorage(_validGroupStorage);\n interep = IInterep(validGroupStorage.interep());\n }\n\n function register(uint256 idCommitment) external payable {\n require(\n msg.value == MEMBERSHIP_DEPOSIT,\n \"RLN, register: membership deposit is not satisfied\"\n );\n _register(idCommitment, msg.value);\n }\n\n /// @dev Registers a member via a valid Interep Semaphore group.\n /// @param groupId: Id of the group.\n /// @param signal: Semaphore signal.\n /// @param nullifierHash: Nullifier hash.\n /// @param externalNullifier: External nullifier.\n /// @param proof: Zero-knowledge proof.\n /// @param idCommitment: ID Commitment of the member.\n function register(\n uint256 groupId,\n bytes32 signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof,\n uint256 idCommitment\n ) external {\n require(\n validGroupStorage.isValidGroup(groupId),\n \"RLN, register: invalid interep group\"\n );\n interep.verifyProof(\n groupId,\n signal,\n nullifierHash,\n externalNullifier,\n proof\n );\n _register(idCommitment, 0);\n }\n\n function registerBatch(uint256[] calldata idCommitments) external payable {\n uint256 idCommitmentlen = idCommitments.length;\n require(\n idCommitmentIndex + idCommitmentlen <= SET_SIZE,\n \"RLN, registerBatch: set is full\"\n );\n require(\n msg.value == MEMBERSHIP_DEPOSIT * idCommitmentlen,\n \"RLN, registerBatch: membership deposit is not satisfied\"\n );\n for (uint256 i = 0; i < idCommitmentlen; i++) {\n _register(idCommitments[i], msg.value / idCommitmentlen);\n }\n }\n\n function _register(uint256 idCommitment, uint256 stake) internal {\n require(\n !members[idCommitment],\n \"RLN, _register: member already registered\"\n );\n require(idCommitmentIndex < SET_SIZE, \"RLN, register: set is full\");\n if (stake != 0) {\n members[idCommitment] = true;\n stakedAmounts[idCommitment] = stake;\n } else {\n members[idCommitment] = true;\n stakedAmounts[idCommitment] = 0;\n }\n emit MemberRegistered(idCommitment, idCommitmentIndex);\n idCommitmentIndex += 1;\n }\n\n function withdrawBatch(\n uint256[] calldata secrets,\n address payable[] calldata receivers\n ) external {\n uint256 batchSize = secrets.length;\n require(batchSize != 0, \"RLN, withdrawBatch: batch size zero\");\n require(\n batchSize == secrets.length,\n \"RLN, withdrawBatch: batch size mismatch secrets\"\n );\n require(\n batchSize == receivers.length,\n \"RLN, withdrawBatch: batch size mismatch receivers\"\n );\n for (uint256 i = 0; i < batchSize; i++) {\n _withdraw(secrets[i], receivers[i]);\n }\n }\n\n function withdraw(uint256 secret, address payable receiver) external {\n _withdraw(secret, receiver);\n }\n\n function withdraw(uint256 secret) external {\n _withdraw(secret);\n }\n\n function _withdraw(uint256 secret, address payable receiver) internal {\n // derive idCommitment\n uint256 idCommitment = hash(secret);\n\n // check if member is registered\n require(members[idCommitment], \"RLN, _withdraw: member not registered\");\n\n // check if member has stake\n require(\n stakedAmounts[idCommitment] != 0,\n \"RLN, _withdraw: member has no stake\"\n );\n\n require(\n receiver != address(0),\n \"RLN, _withdraw: empty receiver address\"\n );\n\n // refund deposit\n (bool sent, ) = receiver.call{value: stakedAmounts[idCommitment]}(\"\");\n require(sent, \"transfer failed\");\n\n // delete member\n members[idCommitment] = false;\n stakedAmounts[idCommitment] = 0;\n\n emit MemberWithdrawn(idCommitment);\n }\n\n function _withdraw(uint256 secret) internal {\n // derive idCommitment\n uint256 idCommitment = hash(secret);\n\n // check if member is registered\n require(members[idCommitment], \"RLN, _withdraw: member not registered\");\n\n require(stakedAmounts[idCommitment] == 0, \"RLN, _withdraw: staked\");\n\n // delete member\n members[idCommitment] = false;\n\n emit MemberWithdrawn(idCommitment);\n }\n\n function hash(uint256 input) internal view returns (uint256) {\n return poseidonHasher.hash(input);\n }\n}\n" }, "contracts/ValidGroupStorage.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"@interep/contracts/Interep.sol\";\n\ninterface IValidGroupStorage {\n function isValidGroup(uint256 groupId) external view returns (bool);\n\n function interep() external view returns (address);\n}\n\ncontract ValidGroupStorage {\n mapping(uint256 => bool) public validGroups;\n\n Interep public interep;\n\n struct Group {\n bytes32 provider;\n bytes32 name;\n }\n\n constructor(address _interep, Group[] memory _groups) {\n interep = Interep(_interep);\n for (uint8 i = 0; i < _groups.length; i++) {\n uint256 groupId = uint256(\n keccak256(\n abi.encodePacked(_groups[i].provider, _groups[i].name)\n )\n ) % SNARK_SCALAR_FIELD;\n (bytes32 provider, bytes32 name, , ) = interep.groups(groupId);\n if (provider == _groups[i].provider && name == _groups[i].name) {\n validGroups[groupId] = true;\n } else {\n revert(\"[ValidGroupStorage] Invalid group\");\n }\n }\n }\n\n function isValidGroup(uint256 _groupId) public view returns (bool) {\n return validGroups[_groupId];\n }\n}\n" }, "contracts/Verifier.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\nimport \"@semaphore-protocol/contracts/verifiers/Verifier20.sol\";\n" }, "contracts/VerifierTest.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\ncontract VerifierTest {\n function verifyProof(\n uint[2] memory a,\n uint[2][2] memory b,\n uint[2] memory c,\n uint[4] memory input\n ) public view {}\n}\n" } }, "settings": { "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers", "metadata", "devdoc", "userdoc", "storageLayout", "evm.gasEstimates" ], "": ["ast"] } }, "metadata": { "useLiteralContent": true } } }