Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
3928637 | 13 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
Semaphore
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {ISemaphore} from "./interfaces/ISemaphore.sol"; import {ISemaphoreVerifier} from "./interfaces/ISemaphoreVerifier.sol"; import {SemaphoreGroups} from "./base/SemaphoreGroups.sol"; import {MIN_DEPTH, MAX_DEPTH} from "./base/Constants.sol"; /// @title Semaphore /// @dev This contract uses the Semaphore base contracts to provide a complete service /// to allow admins to create and manage groups and their members to verify Semaphore proofs /// Group admins can add, update or remove group members, and can be an Ethereum account or a smart contract. /// This contract also assigns each new Merkle tree generated with a new root a duration (or an expiry) /// within which the proofs generated with that root can be validated. contract Semaphore is ISemaphore, SemaphoreGroups { ISemaphoreVerifier public verifier; /// @dev Gets a group id and returns the group parameters. mapping(uint256 => Group) public groups; /// @dev Counter to assign an incremental id to the groups. /// This counter is used to keep track of the number of groups created. uint256 public groupCounter; /// @dev Initializes the Semaphore verifier used to verify the user's ZK proofs. /// @param _verifier: Semaphore verifier addresse. constructor(ISemaphoreVerifier _verifier) { verifier = _verifier; } /// @dev See {SemaphoreGroups-_createGroup}. function createGroup() external override returns (uint256 groupId) { groupId = groupCounter++; _createGroup(groupId, msg.sender); groups[groupId].merkleTreeDuration = 1 hours; } /// @dev See {SemaphoreGroups-_createGroup}. function createGroup(address admin) external override returns (uint256 groupId) { groupId = groupCounter++; _createGroup(groupId, admin); groups[groupId].merkleTreeDuration = 1 hours; } /// @dev See {ISemaphore-createGroup}. function createGroup(address admin, uint256 merkleTreeDuration) external override returns (uint256 groupId) { groupId = groupCounter++; _createGroup(groupId, admin); groups[groupId].merkleTreeDuration = merkleTreeDuration; } /// @dev See {SemaphoreGroups-_updateGroupAdmin}. function updateGroupAdmin(uint256 groupId, address newAdmin) external override { _updateGroupAdmin(groupId, newAdmin); } /// @dev See {SemaphoreGroups- acceptGroupAdmin}. function acceptGroupAdmin(uint256 groupId) external override { _acceptGroupAdmin(groupId); } /// @dev See {ISemaphore-updateGroupMerkleTreeDuration}. function updateGroupMerkleTreeDuration( uint256 groupId, uint256 newMerkleTreeDuration ) external override onlyGroupAdmin(groupId) { uint256 oldMerkleTreeDuration = groups[groupId].merkleTreeDuration; groups[groupId].merkleTreeDuration = newMerkleTreeDuration; emit GroupMerkleTreeDurationUpdated(groupId, oldMerkleTreeDuration, newMerkleTreeDuration); } /// @dev See {SemaphoreGroups-_addMember}. function addMember(uint256 groupId, uint256 identityCommitment) external override { uint256 merkleTreeRoot = _addMember(groupId, identityCommitment); groups[groupId].merkleRootCreationDates[merkleTreeRoot] = block.timestamp; } /// @dev See {SemaphoreGroups-_addMembers}. function addMembers(uint256 groupId, uint256[] calldata identityCommitments) external override { uint256 merkleTreeRoot = _addMembers(groupId, identityCommitments); groups[groupId].merkleRootCreationDates[merkleTreeRoot] = block.timestamp; } /// @dev See {SemaphoreGroups-_updateMember}. function updateMember( uint256 groupId, uint256 identityCommitment, uint256 newIdentityCommitment, uint256[] calldata merkleProofSiblings ) external override { uint256 merkleTreeRoot = _updateMember(groupId, identityCommitment, newIdentityCommitment, merkleProofSiblings); groups[groupId].merkleRootCreationDates[merkleTreeRoot] = block.timestamp; } /// @dev See {SemaphoreGroups-_removeMember}. function removeMember( uint256 groupId, uint256 identityCommitment, uint256[] calldata merkleProofSiblings ) external override { uint256 merkleTreeRoot = _removeMember(groupId, identityCommitment, merkleProofSiblings); groups[groupId].merkleRootCreationDates[merkleTreeRoot] = block.timestamp; } /// @dev See {ISemaphore-validateProof}. function validateProof(uint256 groupId, SemaphoreProof calldata proof) external override { // The function will revert if the nullifier that is part of the proof, // was already used inside the group with id groupId. if (groups[groupId].nullifiers[proof.nullifier]) { revert Semaphore__YouAreUsingTheSameNullifierTwice(); } // The function will revert if the proof is not verified successfully. if (!verifyProof(groupId, proof)) { revert Semaphore__InvalidProof(); } // Saves the nullifier so that it cannot be used again to successfully verify a proof // that is part of the group with id groupId. groups[groupId].nullifiers[proof.nullifier] = true; emit ProofValidated( groupId, proof.merkleTreeDepth, proof.merkleTreeRoot, proof.nullifier, proof.message, proof.scope, proof.points ); } /// @dev See {ISemaphore-verifyProof}. function verifyProof( uint256 groupId, SemaphoreProof calldata proof ) public view override onlyExistingGroup(groupId) returns (bool) { // The function will revert if the Merkle tree depth is not supported. if (proof.merkleTreeDepth < MIN_DEPTH || proof.merkleTreeDepth > MAX_DEPTH) { revert Semaphore__MerkleTreeDepthIsNotSupported(); } // Gets the number of leaves in the Incremental Merkle Tree that represents the group // with id groupId which is the same as the number of members in the group groupId. uint256 merkleTreeSize = getMerkleTreeSize(groupId); // The function will revert if there are no members in the group. if (merkleTreeSize == 0) { revert Semaphore__GroupHasNoMembers(); } // Gets the Merkle root of the Incremental Merkle Tree that represents the group with id groupId. uint256 currentMerkleTreeRoot = getMerkleTreeRoot(groupId); // A proof could have used an old Merkle tree root. // https://github.com/semaphore-protocol/semaphore/issues/98 if (proof.merkleTreeRoot != currentMerkleTreeRoot) { uint256 merkleRootCreationDate = groups[groupId].merkleRootCreationDates[proof.merkleTreeRoot]; uint256 merkleTreeDuration = groups[groupId].merkleTreeDuration; if (merkleRootCreationDate == 0) { revert Semaphore__MerkleTreeRootIsNotPartOfTheGroup(); } if (block.timestamp > merkleRootCreationDate + merkleTreeDuration) { revert Semaphore__MerkleTreeRootIsExpired(); } } return verifier.verifyProof( [proof.points[0], proof.points[1]], [[proof.points[2], proof.points[3]], [proof.points[4], proof.points[5]]], [proof.points[6], proof.points[7]], [proof.merkleTreeRoot, proof.nullifier, _hash(proof.message), _hash(proof.scope)], proof.merkleTreeDepth ); } /// @dev Creates a keccak256 hash of a message compatible with the SNARK scalar modulus. /// @param message: Message to be hashed. /// @return Message digest. function _hash(uint256 message) private pure returns (uint256) { return uint256(keccak256(abi.encodePacked(message))) >> 8; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; uint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {PoseidonT3} from "poseidon-solidity/PoseidonT3.sol"; import {SNARK_SCALAR_FIELD} from "./Constants.sol"; struct LeanIMTData { // Tracks the current number of leaves in the tree. uint256 size; // Represents the current depth of the tree, which can increase as new leaves are inserted. uint256 depth; // A mapping from each level of the tree to the node value of the last even position at that level. // Used for efficient inserts, updates and root calculations. mapping(uint256 => uint256) sideNodes; // A mapping from leaf values to their respective indices in the tree. // This facilitates checks for leaf existence and retrieval of leaf positions. mapping(uint256 => uint256) leaves; } error WrongSiblingNodes(); error LeafGreaterThanSnarkScalarField(); error LeafCannotBeZero(); error LeafAlreadyExists(); error LeafDoesNotExist(); /// @title Lean Incremental binary Merkle tree. /// @dev The LeanIMT is an optimized version of the BinaryIMT. /// This implementation eliminates the use of zeroes, and make the tree depth dynamic. /// When a node doesn't have the right child, instead of using a zero hash as in the BinaryIMT, /// the node's value becomes that of its left child. Furthermore, rather than utilizing a static tree depth, /// it is updated based on the number of leaves in the tree. This approach /// results in the calculation of significantly fewer hashes, making the tree more efficient. library InternalLeanIMT { /// @dev Inserts a new leaf into the incremental merkle tree. /// The function ensures that the leaf is valid according to the /// constraints of the tree and then updates the tree's structure accordingly. /// @param self: A storage reference to the 'LeanIMTData' struct. /// @param leaf: The value of the new leaf to be inserted into the tree. /// @return The new hash of the node after the leaf has been inserted. function _insert(LeanIMTData storage self, uint256 leaf) internal returns (uint256) { if (leaf >= SNARK_SCALAR_FIELD) { revert LeafGreaterThanSnarkScalarField(); } else if (leaf == 0) { revert LeafCannotBeZero(); } else if (_has(self, leaf)) { revert LeafAlreadyExists(); } uint256 index = self.size; // Cache tree depth to optimize gas uint256 treeDepth = self.depth; // A new insertion can increase a tree's depth by at most 1, // and only if the number of leaves supported by the current // depth is less than the number of leaves to be supported after insertion. if (2 ** treeDepth < index + 1) { ++treeDepth; } self.depth = treeDepth; uint256 node = leaf; for (uint256 level = 0; level < treeDepth; ) { if ((index >> level) & 1 == 1) { node = PoseidonT3.hash([self.sideNodes[level], node]); } else { self.sideNodes[level] = node; } unchecked { ++level; } } self.size = ++index; self.sideNodes[treeDepth] = node; self.leaves[leaf] = index; return node; } /// @dev Inserts many leaves into the incremental merkle tree. /// The function ensures that the leaves are valid according to the /// constraints of the tree and then updates the tree's structure accordingly. /// @param self: A storage reference to the 'LeanIMTData' struct. /// @param leaves: The values of the new leaves to be inserted into the tree. /// @return The root after the leaves have been inserted. function _insertMany(LeanIMTData storage self, uint256[] calldata leaves) internal returns (uint256) { // Cache tree size to optimize gas uint256 treeSize = self.size; // Check that all the new values are correct to be added. for (uint256 i = 0; i < leaves.length; ) { if (leaves[i] >= SNARK_SCALAR_FIELD) { revert LeafGreaterThanSnarkScalarField(); } else if (leaves[i] == 0) { revert LeafCannotBeZero(); } else if (_has(self, leaves[i])) { revert LeafAlreadyExists(); } self.leaves[leaves[i]] = treeSize + 1 + i; unchecked { ++i; } } // Array to save the nodes that will be used to create the next level of the tree. uint256[] memory currentLevelNewNodes; currentLevelNewNodes = leaves; // Cache tree depth to optimize gas uint256 treeDepth = self.depth; // Calculate the depth of the tree after adding the new values. // Unlike the 'insert' function, we need a while here as // N insertions can increase the tree's depth more than once. while (2 ** treeDepth < treeSize + leaves.length) { ++treeDepth; } self.depth = treeDepth; // First index to change in every level. uint256 currentLevelStartIndex = treeSize; // Size of the level used to create the next level. uint256 currentLevelSize = treeSize + leaves.length; // The index where changes begin at the next level. uint256 nextLevelStartIndex = currentLevelStartIndex >> 1; // The size of the next level. uint256 nextLevelSize = ((currentLevelSize - 1) >> 1) + 1; for (uint256 level = 0; level < treeDepth; ) { // The number of nodes for the new level that will be created, // only the new values, not the entire level. uint256 numberOfNewNodes = nextLevelSize - nextLevelStartIndex; uint256[] memory nextLevelNewNodes = new uint256[](numberOfNewNodes); for (uint256 i = 0; i < numberOfNewNodes; ) { uint256 leftNode; // Assign the left node using the saved path or the position in the array. if ((i + nextLevelStartIndex) * 2 < currentLevelStartIndex) { leftNode = self.sideNodes[level]; } else { leftNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 - currentLevelStartIndex]; } uint256 rightNode; // Assign the right node if the value exists. if ((i + nextLevelStartIndex) * 2 + 1 < currentLevelSize) { rightNode = currentLevelNewNodes[(i + nextLevelStartIndex) * 2 + 1 - currentLevelStartIndex]; } uint256 parentNode; // Assign the parent node. // If it has a right child the result will be the hash(leftNode, rightNode) if not, // it will be the leftNode. if (rightNode != 0) { parentNode = PoseidonT3.hash([leftNode, rightNode]); } else { parentNode = leftNode; } nextLevelNewNodes[i] = parentNode; unchecked { ++i; } } // Update the `sideNodes` variable. // If `currentLevelSize` is odd, the saved value will be the last value of the array // if it is even and there are more than 1 element in `currentLevelNewNodes`, the saved value // will be the value before the last one. // If it is even and there is only one element, there is no need to save anything because // the correct value for this level was already saved before. if (currentLevelSize & 1 == 1) { self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 1]; } else if (currentLevelNewNodes.length > 1) { self.sideNodes[level] = currentLevelNewNodes[currentLevelNewNodes.length - 2]; } currentLevelStartIndex = nextLevelStartIndex; // Calculate the next level startIndex value. // It is the position of the parent node which is pos/2. nextLevelStartIndex >>= 1; // Update the next array that will be used to calculate the next level. currentLevelNewNodes = nextLevelNewNodes; currentLevelSize = nextLevelSize; // Calculate the size of the next level. // The size of the next level is (currentLevelSize - 1) / 2 + 1. nextLevelSize = ((nextLevelSize - 1) >> 1) + 1; unchecked { ++level; } } // Update tree size self.size = treeSize + leaves.length; // Update tree root self.sideNodes[treeDepth] = currentLevelNewNodes[0]; return currentLevelNewNodes[0]; } /// @dev Updates the value of an existing leaf and recalculates hashes /// to maintain tree integrity. /// @param self: A storage reference to the 'LeanIMTData' struct. /// @param oldLeaf: The value of the leaf that is to be updated. /// @param newLeaf: The new value that will replace the oldLeaf in the tree. /// @param siblingNodes: An array of sibling nodes that are necessary to recalculate the path to the root. /// @return The new hash of the updated node after the leaf has been updated. function _update( LeanIMTData storage self, uint256 oldLeaf, uint256 newLeaf, uint256[] calldata siblingNodes ) internal returns (uint256) { if (newLeaf >= SNARK_SCALAR_FIELD) { revert LeafGreaterThanSnarkScalarField(); } else if (!_has(self, oldLeaf)) { revert LeafDoesNotExist(); } else if (_has(self, newLeaf)) { revert LeafAlreadyExists(); } uint256 index = _indexOf(self, oldLeaf); uint256 node = newLeaf; uint256 oldRoot = oldLeaf; uint256 lastIndex = self.size - 1; uint256 i = 0; // Cache tree depth to optimize gas uint256 treeDepth = self.depth; for (uint256 level = 0; level < treeDepth; ) { if ((index >> level) & 1 == 1) { if (siblingNodes[i] >= SNARK_SCALAR_FIELD) { revert LeafGreaterThanSnarkScalarField(); } node = PoseidonT3.hash([siblingNodes[i], node]); oldRoot = PoseidonT3.hash([siblingNodes[i], oldRoot]); unchecked { ++i; } } else { if (index >> level != lastIndex >> level) { if (siblingNodes[i] >= SNARK_SCALAR_FIELD) { revert LeafGreaterThanSnarkScalarField(); } node = PoseidonT3.hash([node, siblingNodes[i]]); oldRoot = PoseidonT3.hash([oldRoot, siblingNodes[i]]); unchecked { ++i; } } else { self.sideNodes[i] = node; } } unchecked { ++level; } } if (oldRoot != _root(self)) { revert WrongSiblingNodes(); } self.sideNodes[treeDepth] = node; if (newLeaf != 0) { self.leaves[newLeaf] = self.leaves[oldLeaf]; } self.leaves[oldLeaf] = 0; return node; } /// @dev Removes a leaf from the tree by setting its value to zero. /// This function utilizes the update function to set the leaf's value /// to zero and update the tree's state accordingly. /// @param self: A storage reference to the 'LeanIMTData' struct. /// @param oldLeaf: The value of the leaf to be removed. /// @param siblingNodes: An array of sibling nodes required for updating the path to the root after removal. /// @return The new root hash of the tree after the leaf has been removed. function _remove( LeanIMTData storage self, uint256 oldLeaf, uint256[] calldata siblingNodes ) internal returns (uint256) { return _update(self, oldLeaf, 0, siblingNodes); } /// @dev Checks if a leaf exists in the tree. /// @param self: A storage reference to the 'LeanIMTData' struct. /// @param leaf: The value of the leaf to check for existence. /// @return A boolean value indicating whether the leaf exists in the tree. function _has(LeanIMTData storage self, uint256 leaf) internal view returns (bool) { return self.leaves[leaf] != 0; } /// @dev Retrieves the index of a given leaf in the tree. /// @param self: A storage reference to the 'LeanIMTData' struct. /// @param leaf: The value of the leaf whose index is to be found. /// @return The index of the specified leaf within the tree. If the leaf is not present, the function /// reverts with a custom error. function _indexOf(LeanIMTData storage self, uint256 leaf) internal view returns (uint256) { if (self.leaves[leaf] == 0) { revert LeafDoesNotExist(); } return self.leaves[leaf] - 1; } /// @dev Retrieves the root of the tree from the 'sideNodes' mapping using the /// current tree depth. /// @param self: A storage reference to the 'LeanIMTData' struct. /// @return The root hash of the tree. function _root(LeanIMTData storage self) internal view returns (uint256) { return self.sideNodes[self.depth]; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.23; /// @dev Minimum supported tree depth. uint8 constant MIN_DEPTH = 1; /// @dev Maximum supported tree depth. uint8 constant MAX_DEPTH = 32;
//SPDX-License-Identifier: MIT pragma solidity 0.8.23; import {ISemaphoreGroups} from "../interfaces/ISemaphoreGroups.sol"; import {InternalLeanIMT, LeanIMTData} from "@zk-kit/lean-imt.sol/InternalLeanIMT.sol"; /// @title Semaphore groups contract. /// @dev This contract allows you to create groups, add, remove and update members. /// You can use getters to obtain informations about groups (root, depth, number of leaves). abstract contract SemaphoreGroups is ISemaphoreGroups { using InternalLeanIMT for LeanIMTData; /// @dev Gets a group id and returns its tree data. /// The tree is an Incremental Merkle Tree /// which is called Lean Incremental Merkle Tree. mapping(uint256 => LeanIMTData) internal merkleTrees; /// @dev Gets a group id and returns its admin. /// The admin can be an Ethereum account or a smart contract. mapping(uint256 => address) internal admins; /// @dev Gets a group id and returns any pending admin. /// The pending admin can be an Ethereum account or a smart contract. mapping(uint256 => address) internal pendingAdmins; /// @dev Checks if the group admin is the transaction sender. /// @param groupId: Id of the group. modifier onlyGroupAdmin(uint256 groupId) { if (admins[groupId] != msg.sender) { revert Semaphore__CallerIsNotTheGroupAdmin(); } _; } /// @dev Checks if the group exists. /// @param groupId: Id of the group. modifier onlyExistingGroup(uint256 groupId) { if (admins[groupId] == address(0)) { revert Semaphore__GroupDoesNotExist(); } _; } /// @dev Creates a new group. Only the admin will be able to add or remove members. /// @param groupId: Id of the group. /// @param admin: Admin of the group. function _createGroup(uint256 groupId, address admin) internal virtual { admins[groupId] = admin; emit GroupCreated(groupId); emit GroupAdminUpdated(groupId, address(0), admin); } /// @dev Updates the group admin. In order for the new admin to actually be updated, /// they must explicitly accept by calling `_acceptGroupAdmin`. /// @param groupId: Id of the group. /// @param newAdmin: New admin of the group. function _updateGroupAdmin(uint256 groupId, address newAdmin) internal virtual onlyGroupAdmin(groupId) { pendingAdmins[groupId] = newAdmin; emit GroupAdminPending(groupId, msg.sender, newAdmin); } /// @dev Allows the new admin to accept to update the group admin with their address. /// @param groupId: Id of the group. function _acceptGroupAdmin(uint256 groupId) internal virtual { if (pendingAdmins[groupId] != msg.sender) { revert Semaphore__CallerIsNotThePendingGroupAdmin(); } address oldAdmin = admins[groupId]; admins[groupId] = msg.sender; delete pendingAdmins[groupId]; emit GroupAdminUpdated(groupId, oldAdmin, msg.sender); } /// @dev Adds an identity commitment to an existing group. /// @param groupId: Id of the group. /// @param identityCommitment: New identity commitment. /// @return merkleTreeRoot New root hash of the tree. function _addMember( uint256 groupId, uint256 identityCommitment ) internal virtual onlyGroupAdmin(groupId) returns (uint256 merkleTreeRoot) { uint256 index = getMerkleTreeSize(groupId); merkleTreeRoot = merkleTrees[groupId]._insert(identityCommitment); emit MemberAdded(groupId, index, identityCommitment, merkleTreeRoot); } /// @dev Adds new members to an existing group. /// @param groupId: Id of the group. /// @param identityCommitments: New identity commitments. /// @return merkleTreeRoot New root hash of the tree. function _addMembers( uint256 groupId, uint256[] calldata identityCommitments ) internal virtual onlyGroupAdmin(groupId) returns (uint256 merkleTreeRoot) { uint256 startIndex = getMerkleTreeSize(groupId); merkleTreeRoot = merkleTrees[groupId]._insertMany(identityCommitments); emit MembersAdded(groupId, startIndex, identityCommitments, merkleTreeRoot); } /// @dev Updates an identity commitment of an existing group. A proof of membership is /// needed to check if the node to be updated is part of the tree. /// @param groupId: Id of the group. /// @param oldIdentityCommitment: Existing identity commitment to be updated. /// @param newIdentityCommitment: New identity commitment. /// @param merkleProofSiblings: Array of the sibling nodes of the proof of membership. /// @return merkleTreeRoot New root hash of the tree. function _updateMember( uint256 groupId, uint256 oldIdentityCommitment, uint256 newIdentityCommitment, uint256[] calldata merkleProofSiblings ) internal virtual onlyGroupAdmin(groupId) returns (uint256 merkleTreeRoot) { uint256 index = merkleTrees[groupId]._indexOf(oldIdentityCommitment); merkleTreeRoot = merkleTrees[groupId]._update( oldIdentityCommitment, newIdentityCommitment, merkleProofSiblings ); emit MemberUpdated(groupId, index, oldIdentityCommitment, newIdentityCommitment, merkleTreeRoot); } /// @dev Removes an identity commitment from an existing group. A proof of membership is /// needed to check if the node to be deleted is part of the tree. /// @param groupId: Id of the group. /// @param identityCommitment: Existing identity commitment to be removed. /// @param merkleProofSiblings: Array of the sibling nodes of the proof of membership. /// @return merkleTreeRoot New root hash of the tree. function _removeMember( uint256 groupId, uint256 identityCommitment, uint256[] calldata merkleProofSiblings ) internal virtual onlyGroupAdmin(groupId) returns (uint256 merkleTreeRoot) { uint256 index = merkleTrees[groupId]._indexOf(identityCommitment); merkleTreeRoot = merkleTrees[groupId]._remove(identityCommitment, merkleProofSiblings); emit MemberRemoved(groupId, index, identityCommitment, merkleTreeRoot); } /// @dev See {ISemaphoreGroups-getGroupAdmin}. function getGroupAdmin(uint256 groupId) public view virtual override returns (address) { return admins[groupId]; } /// @dev See {ISemaphoreGroups-hasMember}. function hasMember(uint256 groupId, uint256 identityCommitment) public view virtual override returns (bool) { return merkleTrees[groupId]._has(identityCommitment); } /// @dev See {ISemaphoreGroups-indexOf}. function indexOf(uint256 groupId, uint256 identityCommitment) public view virtual override returns (uint256) { return merkleTrees[groupId]._indexOf(identityCommitment); } /// @dev See {ISemaphoreGroups-getMerkleTreeRoot}. function getMerkleTreeRoot(uint256 groupId) public view virtual override returns (uint256) { return merkleTrees[groupId]._root(); } /// @dev See {ISemaphoreGroups-getMerkleTreeDepth}. function getMerkleTreeDepth(uint256 groupId) public view virtual override returns (uint256) { return merkleTrees[groupId].depth; } /// @dev See {ISemaphoreGroups-getMerkleTreeSize}. function getMerkleTreeSize(uint256 groupId) public view virtual override returns (uint256) { return merkleTrees[groupId].size; } }
//SPDX-License-Identifier: MIT pragma solidity 0.8.23; /// @title Semaphore contract interface. interface ISemaphore { error Semaphore__GroupHasNoMembers(); error Semaphore__MerkleTreeDepthIsNotSupported(); error Semaphore__MerkleTreeRootIsExpired(); error Semaphore__MerkleTreeRootIsNotPartOfTheGroup(); error Semaphore__YouAreUsingTheSameNullifierTwice(); error Semaphore__InvalidProof(); /// It defines all the group parameters used by Semaphore.sol. struct Group { uint256 merkleTreeDuration; mapping(uint256 => uint256) merkleRootCreationDates; mapping(uint256 => bool) nullifiers; } /// It defines all the Semaphore proof parameters used by Semaphore.sol. struct SemaphoreProof { uint256 merkleTreeDepth; uint256 merkleTreeRoot; uint256 nullifier; uint256 message; uint256 scope; uint256[8] points; } /// @dev Event emitted when the Merkle tree duration of a group is updated. /// @param groupId: Id of the group. /// @param oldMerkleTreeDuration: Old Merkle tree duration of the group. /// @param newMerkleTreeDuration: New Merkle tree duration of the group. event GroupMerkleTreeDurationUpdated( uint256 indexed groupId, uint256 oldMerkleTreeDuration, uint256 newMerkleTreeDuration ); /// @dev Event emitted when a Semaphore proof is validated. /// @param groupId: Id of the group. /// @param merkleTreeDepth: Depth of the Merkle tree. /// @param merkleTreeRoot: Root of the Merkle tree. /// @param nullifier: Nullifier. /// @param message: Semaphore message. /// @param scope: Scope. /// @param points: Zero-knowledge points. event ProofValidated( uint256 indexed groupId, uint256 merkleTreeDepth, uint256 indexed merkleTreeRoot, uint256 nullifier, uint256 message, uint256 indexed scope, uint256[8] points ); /// @dev Returns the current value of the group counter. /// @return The current group counter value. function groupCounter() external view returns (uint256); /// @dev See {SemaphoreGroups-_createGroup}. function createGroup() external returns (uint256); /// @dev See {SemaphoreGroups-_createGroup}. function createGroup(address admin) external returns (uint256); /// @dev It creates a group with a custom Merkle tree duration. /// @param admin: Admin of the group. It can be an Ethereum account or a smart contract. /// @param merkleTreeDuration: Merkle tree duration. /// @return Id of the group. function createGroup(address admin, uint256 merkleTreeDuration) external returns (uint256); /// @dev See {SemaphoreGroups-_updateGroupAdmin}. function updateGroupAdmin(uint256 groupId, address newAdmin) external; /// @dev See {SemaphoreGroups-_acceptGroupAdmin}. function acceptGroupAdmin(uint256 groupId) external; /// @dev Updates the group Merkle tree duration. /// @param groupId: Id of the group. /// @param newMerkleTreeDuration: New Merkle tree duration. function updateGroupMerkleTreeDuration(uint256 groupId, uint256 newMerkleTreeDuration) external; /// @dev See {SemaphoreGroups-_addMember}. function addMember(uint256 groupId, uint256 identityCommitment) external; /// @dev See {SemaphoreGroups-_addMembers}. function addMembers(uint256 groupId, uint256[] calldata identityCommitments) external; /// @dev See {SemaphoreGroups-_updateMember}. function updateMember( uint256 groupId, uint256 oldIdentityCommitment, uint256 newIdentityCommitment, uint256[] calldata merkleProofSiblings ) external; /// @dev See {SemaphoreGroups-_removeMember}. function removeMember(uint256 groupId, uint256 identityCommitment, uint256[] calldata merkleProofSiblings) external; /// @dev Saves the nullifier hash to prevent double signaling and emits an event /// if the zero-knowledge proof is valid. /// @param groupId: Id of the group. /// @param proof: Semaphore zero-knowledge proof. function validateProof(uint256 groupId, SemaphoreProof calldata proof) external; /// @dev Verifies a zero-knowledge proof by returning true or false. /// @param groupId: Id of the group. /// @param proof: Semaphore zero-knowledge proof. function verifyProof(uint256 groupId, SemaphoreProof calldata proof) external view returns (bool); }
//SPDX-License-Identifier: MIT pragma solidity 0.8.23; /// @title SemaphoreGroups contract interface. interface ISemaphoreGroups { error Semaphore__GroupDoesNotExist(); error Semaphore__CallerIsNotTheGroupAdmin(); error Semaphore__CallerIsNotThePendingGroupAdmin(); /// @dev Event emitted when a new group is created. /// @param groupId: Id of the group. event GroupCreated(uint256 indexed groupId); /// @dev Event emitted when a new admin is assigned to a group. /// @param groupId: Id of the group. /// @param oldAdmin: Old admin of the group. /// @param newAdmin: New admin of the group. event GroupAdminUpdated(uint256 indexed groupId, address indexed oldAdmin, address indexed newAdmin); /// @dev Event emitted when a group admin is being updated. /// @param groupId: Id of the group. /// @param oldAdmin: Old admin of the group. /// @param newAdmin: New admin of the group. event GroupAdminPending(uint256 indexed groupId, address indexed oldAdmin, address indexed newAdmin); /// @dev Event emitted when a new identity commitment is added. /// @param groupId: Group id of the group. /// @param index: Merkle tree leaf index. /// @param identityCommitment: New identity commitment. /// @param merkleTreeRoot: New root hash of the tree. event MemberAdded(uint256 indexed groupId, uint256 index, uint256 identityCommitment, uint256 merkleTreeRoot); /// @dev Event emitted when many identity commitments are added at the same time. /// @param groupId: Group id of the group. /// @param startIndex: Index of the first element of the new identity commitments in the merkle tree. /// @param identityCommitments: The new identity commitments. /// @param merkleTreeRoot: New root hash of the tree. event MembersAdded( uint256 indexed groupId, uint256 startIndex, uint256[] identityCommitments, uint256 merkleTreeRoot ); /// @dev Event emitted when an identity commitment is updated. /// @param groupId: Group id of the group. /// @param index: Identity commitment index. /// @param identityCommitment: Existing identity commitment to be updated. /// @param newIdentityCommitment: New identity commitment. /// @param merkleTreeRoot: New root hash of the tree. event MemberUpdated( uint256 indexed groupId, uint256 index, uint256 identityCommitment, uint256 newIdentityCommitment, uint256 merkleTreeRoot ); /// @dev Event emitted when a new identity commitment is removed. /// @param groupId: Group id of the group. /// @param index: Identity commitment index. /// @param identityCommitment: Existing identity commitment to be removed. /// @param merkleTreeRoot: New root hash of the tree. event MemberRemoved(uint256 indexed groupId, uint256 index, uint256 identityCommitment, uint256 merkleTreeRoot); /// @dev Returns the address of the group admin. The group admin can be an Ethereum account or a smart contract. /// @param groupId: Id of the group. /// @return Address of the group admin. function getGroupAdmin(uint256 groupId) external view returns (address); /// @dev Returns true if a member exists in a group. /// @param groupId: Id of the group. /// @param identityCommitment: Identity commitment. /// @return True if the member exists, false otherwise. function hasMember(uint256 groupId, uint256 identityCommitment) external view returns (bool); /// @dev Returns the index of a member. /// @param groupId: Id of the group. /// @param identityCommitment: Identity commitment. /// @return Index of member. function indexOf(uint256 groupId, uint256 identityCommitment) external view returns (uint256); /// @dev Returns the last root hash of a group. /// @param groupId: Id of the group. /// @return Root hash of the group. function getMerkleTreeRoot(uint256 groupId) external view returns (uint256); /// @dev Returns the depth of the tree of a group. /// @param groupId: Id of the group. /// @return Depth of the group tree. function getMerkleTreeDepth(uint256 groupId) external view returns (uint256); /// @dev Returns the number of tree leaves of a group. /// @param groupId: Id of the group. /// @return Number of tree leaves. function getMerkleTreeSize(uint256 groupId) external view returns (uint256); }
//SPDX-License-Identifier: MIT pragma solidity 0.8.23; /// @title SemaphoreVerifier contract interface. interface ISemaphoreVerifier { /// @dev Returns true if the proof was successfully verified. /// @param _pA: Point A. /// @param _pB: Point B. /// @param _pC: Point C. /// @param _pubSignals: Public signals. /// @param merkleTreeDepth: Merkle tree depth. /// @return True if the proof was successfully verified, false otherwise. function verifyProof( uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[4] calldata _pubSignals, uint merkleTreeDepth ) external view returns (bool); }
/// SPDX-License-Identifier: MIT pragma solidity >=0.7.0; library PoseidonT3 { uint constant M00 = 0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118b; uint constant M01 = 0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771; uint constant M02 = 0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7; uint constant M10 = 0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0; uint constant M11 = 0x2e2419f9ec02ec394c9871c832963dc1b89d743c8c7b964029b2311687b1fe23; uint constant M12 = 0x176cc029695ad02582a70eff08a6fd99d057e12e58e7d7b6b16cdfabc8ee2911; // See here for a simplified implementation: https://github.com/vimwitch/poseidon-solidity/blob/e57becdabb65d99fdc586fe1e1e09e7108202d53/contracts/Poseidon.sol#L40 // Inspired by: https://github.com/iden3/circomlibjs/blob/v0.0.8/src/poseidon_slow.js function hash(uint[2] memory) public pure returns (uint) { assembly { let F := 21888242871839275222246405745257275088548364400416034343698204186575808495617 let M20 := 0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736d let M21 := 0x101071f0032379b697315876690f053d148d4e109f5fb065c8aacc55a0f89bfa let M22 := 0x19a3fc0a56702bf417ba7fee3802593fa644470307043f7773279cd71d25d5e0 // load the inputs from memory let state1 := add(mod(mload(0x80), F), 0x00f1445235f2148c5986587169fc1bcd887b08d4d00868df5696fff40956e864) let state2 := add(mod(mload(0xa0), F), 0x08dff3487e8ac99e1f29a058d0fa80b930c728730b7ab36ce879f3890ecf73f5) let scratch0 := mulmod(state1, state1, F) state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F) scratch0 := mulmod(state2, state2, F) state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F) scratch0 := add( 0x2f27be690fdaee46c3ce28f7532b13c856c35342c84bda6e20966310fadc01d0, add(add(15452833169820924772166449970675545095234312153403844297388521437673434406763, mulmod(state1, M10, F)), mulmod(state2, M20, F)) ) let scratch1 := add( 0x2b2ae1acf68b7b8d2416bebf3d4f6234b763fe04b8043ee48b8327bebca16cf2, add(add(18674271267752038776579386132900109523609358935013267566297499497165104279117, mulmod(state1, M11, F)), mulmod(state2, M21, F)) ) let scratch2 := add( 0x0319d062072bef7ecca5eac06f97d4d55952c175ab6b03eae64b44c7dbf11cfa, add(add(14817777843080276494683266178512808687156649753153012854386334860566696099579, mulmod(state1, M12, F)), mulmod(state2, M22, F)) ) let state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := mulmod(scratch1, scratch1, F) scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F) state0 := mulmod(scratch2, scratch2, F) scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F) state0 := add(0x28813dcaebaeaa828a376df87af4a63bc8b7bf27ad49c6298ef7b387bf28526d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x2727673b2ccbc903f181bf38e1c1d40d2033865200c352bc150928adddf9cb78, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x234ec45ca27727c2e74abd2b2a1494cd6efbd43e340587d6b8fb9e31e65cc632, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := mulmod(state1, state1, F) state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F) scratch0 := mulmod(state2, state2, F) state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F) scratch0 := add(0x15b52534031ae18f7f862cb2cf7cf760ab10a8150a337b1ccd99ff6e8797d428, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x0dc8fad6d9e4b35f5ed9a3d186b79ce38e0e8a8d1b58b132d701d4eecf68d1f6, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x1bcd95ffc211fbca600f705fad3fb567ea4eb378f62e1fec97805518a47e4d9c, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := mulmod(scratch1, scratch1, F) scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F) state0 := mulmod(scratch2, scratch2, F) scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F) state0 := add(0x10520b0ab721cadfe9eff81b016fc34dc76da36c2578937817cb978d069de559, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x1f6d48149b8e7f7d9b257d8ed5fbbaf42932498075fed0ace88a9eb81f5627f6, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x1d9655f652309014d29e00ef35a2089bfff8dc1c816f0dc9ca34bdb5460c8705, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x04df5a56ff95bcafb051f7b1cd43a99ba731ff67e47032058fe3d4185697cc7d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x0672d995f8fff640151b3d290cedaf148690a10a8c8424a7f6ec282b6e4be828, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x099952b414884454b21200d7ffafdd5f0c9a9dcc06f2708e9fc1d8209b5c75b9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x052cba2255dfd00c7c483143ba8d469448e43586a9b4cd9183fd0e843a6b9fa6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x0b8badee690adb8eb0bd74712b7999af82de55707251ad7716077cb93c464ddc, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x119b1590f13307af5a1ee651020c07c749c15d60683a8050b963d0a8e4b2bdd1, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x03150b7cd6d5d17b2529d36be0f67b832c4acfc884ef4ee5ce15be0bfb4a8d09, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x2cc6182c5e14546e3cf1951f173912355374efb83d80898abe69cb317c9ea565, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x005032551e6378c450cfe129a404b3764218cadedac14e2b92d2cd73111bf0f9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x233237e3289baa34bb147e972ebcb9516469c399fcc069fb88f9da2cc28276b5, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x05c8f4f4ebd4a6e3c980d31674bfbe6323037f21b34ae5a4e80c2d4c24d60280, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x0a7b1db13042d396ba05d818a319f25252bcf35ef3aeed91ee1f09b2590fc65b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x2a73b71f9b210cf5b14296572c9d32dbf156e2b086ff47dc5df542365a404ec0, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x1ac9b0417abcc9a1935107e9ffc91dc3ec18f2c4dbe7f22976a760bb5c50c460, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x12c0339ae08374823fabb076707ef479269f3e4d6cb104349015ee046dc93fc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x0b7475b102a165ad7f5b18db4e1e704f52900aa3253baac68246682e56e9a28e, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x037c2849e191ca3edb1c5e49f6e8b8917c843e379366f2ea32ab3aa88d7f8448, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x05a6811f8556f014e92674661e217e9bd5206c5c93a07dc145fdb176a716346f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x29a795e7d98028946e947b75d54e9f044076e87a7b2883b47b675ef5f38bd66e, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x20439a0c84b322eb45a3857afc18f5826e8c7382c8a1585c507be199981fd22f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x2e0ba8d94d9ecf4a94ec2050c7371ff1bb50f27799a84b6d4a2a6f2a0982c887, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x143fd115ce08fb27ca38eb7cce822b4517822cd2109048d2e6d0ddcca17d71c8, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x0c64cbecb1c734b857968dbbdcf813cdf8611659323dbcbfc84323623be9caf1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x028a305847c683f646fca925c163ff5ae74f348d62c2b670f1426cef9403da53, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x2e4ef510ff0b6fda5fa940ab4c4380f26a6bcb64d89427b824d6755b5db9e30c, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x0081c95bc43384e663d79270c956ce3b8925b4f6d033b078b96384f50579400e, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x2ed5f0c91cbd9749187e2fade687e05ee2491b349c039a0bba8a9f4023a0bb38, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x30509991f88da3504bbf374ed5aae2f03448a22c76234c8c990f01f33a735206, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x1c3f20fd55409a53221b7c4d49a356b9f0a1119fb2067b41a7529094424ec6ad, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x10b4e7f3ab5df003049514459b6e18eec46bb2213e8e131e170887b47ddcb96c, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x2a1982979c3ff7f43ddd543d891c2abddd80f804c077d775039aa3502e43adef, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x1c74ee64f15e1db6feddbead56d6d55dba431ebc396c9af95cad0f1315bd5c91, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x07533ec850ba7f98eab9303cace01b4b9e4f2e8b82708cfa9c2fe45a0ae146a0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x21576b438e500449a151e4eeaf17b154285c68f42d42c1808a11abf3764c0750, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x2f17c0559b8fe79608ad5ca193d62f10bce8384c815f0906743d6930836d4a9e, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x2d477e3862d07708a79e8aae946170bc9775a4201318474ae665b0b1b7e2730e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x162f5243967064c390e095577984f291afba2266c38f5abcd89be0f5b2747eab, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x2b4cb233ede9ba48264ecd2c8ae50d1ad7a8596a87f29f8a7777a70092393311, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x2c8fbcb2dd8573dc1dbaf8f4622854776db2eece6d85c4cf4254e7c35e03b07a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x1d6f347725e4816af2ff453f0cd56b199e1b61e9f601e9ade5e88db870949da9, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x204b0c397f4ebe71ebc2d8b3df5b913df9e6ac02b68d31324cd49af5c4565529, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x0c4cb9dc3c4fd8174f1149b3c63c3c2f9ecb827cd7dc25534ff8fb75bc79c502, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x174ad61a1448c899a25416474f4930301e5c49475279e0639a616ddc45bc7b54, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x1a96177bcf4d8d89f759df4ec2f3cde2eaaa28c177cc0fa13a9816d49a38d2ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x066d04b24331d71cd0ef8054bc60c4ff05202c126a233c1a8242ace360b8a30a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x2a4c4fc6ec0b0cf52195782871c6dd3b381cc65f72e02ad527037a62aa1bd804, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x13ab2d136ccf37d447e9f2e14a7cedc95e727f8446f6d9d7e55afc01219fd649, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x1121552fca26061619d24d843dc82769c1b04fcec26f55194c2e3e869acc6a9a, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x00ef653322b13d6c889bc81715c37d77a6cd267d595c4a8909a5546c7c97cff1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x0e25483e45a665208b261d8ba74051e6400c776d652595d9845aca35d8a397d3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x29f536dcb9dd7682245264659e15d88e395ac3d4dde92d8c46448db979eeba89, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x2a56ef9f2c53febadfda33575dbdbd885a124e2780bbea170e456baace0fa5be, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x1c8361c78eb5cf5decfb7a2d17b5c409f2ae2999a46762e8ee416240a8cb9af1, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x151aff5f38b20a0fc0473089aaf0206b83e8e68a764507bfd3d0ab4be74319c5, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x04c6187e41ed881dc1b239c88f7f9d43a9f52fc8c8b6cdd1e76e47615b51f100, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x13b37bd80f4d27fb10d84331f6fb6d534b81c61ed15776449e801b7ddc9c2967, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x01a5c536273c2d9df578bfbd32c17b7a2ce3664c2a52032c9321ceb1c4e8a8e4, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x2ab3561834ca73835ad05f5d7acb950b4a9a2c666b9726da832239065b7c3b02, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x1d4d8ec291e720db200fe6d686c0d613acaf6af4e95d3bf69f7ed516a597b646, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x041294d2cc484d228f5784fe7919fd2bb925351240a04b711514c9c80b65af1d, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x154ac98e01708c611c4fa715991f004898f57939d126e392042971dd90e81fc6, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x0b339d8acca7d4f83eedd84093aef51050b3684c88f8b0b04524563bc6ea4da4, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x0955e49e6610c94254a4f84cfbab344598f0e71eaff4a7dd81ed95b50839c82e, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x06746a6156eba54426b9e22206f15abca9a6f41e6f535c6f3525401ea0654626, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x0f18f5a0ecd1423c496f3820c549c27838e5790e2bd0a196ac917c7ff32077fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x04f6eeca1751f7308ac59eff5beb261e4bb563583ede7bc92a738223d6f76e13, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x2b56973364c4c4f5c1a3ec4da3cdce038811eb116fb3e45bc1768d26fc0b3758, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x123769dd49d5b054dcd76b89804b1bcb8e1392b385716a5d83feb65d437f29ef, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x2147b424fc48c80a88ee52b91169aacea989f6446471150994257b2fb01c63e9, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x0fdc1f58548b85701a6c5505ea332a29647e6f34ad4243c2ea54ad897cebe54d, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x12373a8251fea004df68abcf0f7786d4bceff28c5dbbe0c3944f685cc0a0b1f2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x21e4f4ea5f35f85bad7ea52ff742c9e8a642756b6af44203dd8a1f35c1a90035, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x16243916d69d2ca3dfb4722224d4c462b57366492f45e90d8a81934f1bc3b147, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x1efbe46dd7a578b4f66f9adbc88b4378abc21566e1a0453ca13a4159cac04ac2, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x07ea5e8537cf5dd08886020e23a7f387d468d5525be66f853b672cc96a88969a, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x05a8c4f9968b8aa3b7b478a30f9a5b63650f19a75e7ce11ca9fe16c0b76c00bc, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x20f057712cc21654fbfe59bd345e8dac3f7818c701b9c7882d9d57b72a32e83f, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x04a12ededa9dfd689672f8c67fee31636dcd8e88d01d49019bd90b33eb33db69, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x27e88d8c15f37dcee44f1e5425a51decbd136ce5091a6767e49ec9544ccd101a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x2feed17b84285ed9b8a5c8c5e95a41f66e096619a7703223176c41ee433de4d1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x1ed7cc76edf45c7c404241420f729cf394e5942911312a0d6972b8bd53aff2b8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x15742e99b9bfa323157ff8c586f5660eac6783476144cdcadf2874be45466b1a, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x1aac285387f65e82c895fc6887ddf40577107454c6ec0317284f033f27d0c785, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x25851c3c845d4790f9ddadbdb6057357832e2e7a49775f71ec75a96554d67c77, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x15a5821565cc2ec2ce78457db197edf353b7ebba2c5523370ddccc3d9f146a67, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x2411d57a4813b9980efa7e31a1db5966dcf64f36044277502f15485f28c71727, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x002e6f8d6520cd4713e335b8c0b6d2e647e9a98e12f4cd2558828b5ef6cb4c9b, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x2ff7bc8f4380cde997da00b616b0fcd1af8f0e91e2fe1ed7398834609e0315d2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x00b9831b948525595ee02724471bcd182e9521f6b7bb68f1e93be4febb0d3cbe, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x0a2f53768b8ebf6a86913b0e57c04e011ca408648a4743a87d77adbf0c9c3512, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x00248156142fd0373a479f91ff239e960f599ff7e94be69b7f2a290305e1198d, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x171d5620b87bfb1328cf8c02ab3f0c9a397196aa6a542c2350eb512a2b2bcda9, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x170a4f55536f7dc970087c7c10d6fad760c952172dd54dd99d1045e4ec34a808, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x29aba33f799fe66c2ef3134aea04336ecc37e38c1cd211ba482eca17e2dbfae1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x1e9bc179a4fdd758fdd1bb1945088d47e70d114a03f6a0e8b5ba650369e64973, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x1dd269799b660fad58f7f4892dfb0b5afeaad869a9c4b44f9c9e1c43bdaf8f09, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x22cdbc8b70117ad1401181d02e15459e7ccd426fe869c7c95d1dd2cb0f24af38, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x0ef042e454771c533a9f57a55c503fcefd3150f52ed94a7cd5ba93b9c7dacefd, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x11609e06ad6c8fe2f287f3036037e8851318e8b08a0359a03b304ffca62e8284, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x1166d9e554616dba9e753eea427c17b7fecd58c076dfe42708b08f5b783aa9af, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x2de52989431a859593413026354413db177fbf4cd2ac0b56f855a888357ee466, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x3006eb4ffc7a85819a6da492f3a8ac1df51aee5b17b8e89d74bf01cf5f71e9ad, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x2af41fbb61ba8a80fdcf6fff9e3f6f422993fe8f0a4639f962344c8225145086, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x119e684de476155fe5a6b41a8ebc85db8718ab27889e85e781b214bace4827c3, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x1835b786e2e8925e188bea59ae363537b51248c23828f047cff784b97b3fd800, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x28201a34c594dfa34d794996c6433a20d152bac2a7905c926c40e285ab32eeb6, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x083efd7a27d1751094e80fefaf78b000864c82eb571187724a761f88c22cc4e7, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x0b6f88a3577199526158e61ceea27be811c16df7774dd8519e079564f61fd13b, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x0ec868e6d15e51d9644f66e1d6471a94589511ca00d29e1014390e6ee4254f5b, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x2af33e3f866771271ac0c9b3ed2e1142ecd3e74b939cd40d00d937ab84c98591, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x0b520211f904b5e7d09b5d961c6ace7734568c547dd6858b364ce5e47951f178, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x0b2d722d0919a1aad8db58f10062a92ea0c56ac4270e822cca228620188a1d40, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x1f790d4d7f8cf094d980ceb37c2453e957b54a9991ca38bbe0061d1ed6e562d4, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x0171eb95dfbf7d1eaea97cd385f780150885c16235a2a6a8da92ceb01e504233, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x0c2d0e3b5fd57549329bf6885da66b9b790b40defd2c8650762305381b168873, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x1162fb28689c27154e5a8228b4e72b377cbcafa589e283c35d3803054407a18d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x2f1459b65dee441b64ad386a91e8310f282c5a92a89e19921623ef8249711bc0, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x1e6ff3216b688c3d996d74367d5cd4c1bc489d46754eb712c243f70d1b53cfbb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x01ca8be73832b8d0681487d27d157802d741a6f36cdc2a0576881f9326478875, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x1f7735706ffe9fc586f976d5bdf223dc680286080b10cea00b9b5de315f9650e, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x2522b60f4ea3307640a0c2dce041fba921ac10a3d5f096ef4745ca838285f019, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x23f0bee001b1029d5255075ddc957f833418cad4f52b6c3f8ce16c235572575b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x2bc1ae8b8ddbb81fcaac2d44555ed5685d142633e9df905f66d9401093082d59, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x0f9406b8296564a37304507b8dba3ed162371273a07b1fc98011fcd6ad72205f, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x2360a8eb0cc7defa67b72998de90714e17e75b174a52ee4acb126c8cd995f0a8, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x15871a5cddead976804c803cbaef255eb4815a5e96df8b006dcbbc2767f88948, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x193a56766998ee9e0a8652dd2f3b1da0362f4f54f72379544f957ccdeefb420f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x2a394a43934f86982f9be56ff4fab1703b2e63c8ad334834e4309805e777ae0f, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x1859954cfeb8695f3e8b635dcb345192892cd11223443ba7b4166e8876c0d142, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x04e1181763050e58013444dbcb99f1902b11bc25d90bbdca408d3819f4fed32b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x0fdb253dee83869d40c335ea64de8c5bb10eb82db08b5e8b1f5e5552bfd05f23, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x058cbe8a9a5027bdaa4efb623adead6275f08686f1c08984a9d7c5bae9b4f1c0, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x1382edce9971e186497eadb1aeb1f52b23b4b83bef023ab0d15228b4cceca59a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x03464990f045c6ee0819ca51fd11b0be7f61b8eb99f14b77e1e6634601d9e8b5, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x23f7bfc8720dc296fff33b41f98ff83c6fcab4605db2eb5aaa5bc137aeb70a58, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x0a59a158e3eec2117e6e94e7f0e9decf18c3ffd5e1531a9219636158bbaf62f2, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x06ec54c80381c052b58bf23b312ffd3ce2c4eba065420af8f4c23ed0075fd07b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x118872dc832e0eb5476b56648e867ec8b09340f7a7bcb1b4962f0ff9ed1f9d01, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x13d69fa127d834165ad5c7cba7ad59ed52e0b0f0e42d7fea95e1906b520921b1, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x169a177f63ea681270b1c6877a73d21bde143942fb71dc55fd8a49f19f10c77b, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x04ef51591c6ead97ef42f287adce40d93abeb032b922f66ffb7e9a5a7450544d, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x256e175a1dc079390ecd7ca703fb2e3b19ec61805d4f03ced5f45ee6dd0f69ec, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x30102d28636abd5fe5f2af412ff6004f75cc360d3205dd2da002813d3e2ceeb2, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x10998e42dfcd3bbf1c0714bc73eb1bf40443a3fa99bef4a31fd31be182fcc792, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x193edd8e9fcf3d7625fa7d24b598a1d89f3362eaf4d582efecad76f879e36860, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x18168afd34f2d915d0368ce80b7b3347d1c7a561ce611425f2664d7aa51f0b5d, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x29383c01ebd3b6ab0c017656ebe658b6a328ec77bc33626e29e2e95b33ea6111, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x10646d2f2603de39a1f4ae5e7771a64a702db6e86fb76ab600bf573f9010c711, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x0beb5e07d1b27145f575f1395a55bf132f90c25b40da7b3864d0242dcb1117fb, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x16d685252078c133dc0d3ecad62b5c8830f95bb2e54b59abdffbf018d96fa336, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x0a6abd1d833938f33c74154e0404b4b40a555bbbec21ddfafd672dd62047f01a, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x1a679f5d36eb7b5c8ea12a4c2dedc8feb12dffeec450317270a6f19b34cf1860, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x0980fb233bd456c23974d50e0ebfde4726a423eada4e8f6ffbc7592e3f1b93d6, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x161b42232e61b84cbf1810af93a38fc0cece3d5628c9282003ebacb5c312c72b, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x0ada10a90c7f0520950f7d47a60d5e6a493f09787f1564e5d09203db47de1a0b, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x1a730d372310ba82320345a29ac4238ed3f07a8a2b4e121bb50ddb9af407f451, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x2c8120f268ef054f817064c369dda7ea908377feaba5c4dffbda10ef58e8c556, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x1c7c8824f758753fa57c00789c684217b930e95313bcb73e6e7b8649a4968f70, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x2cd9ed31f5f8691c8e39e4077a74faa0f400ad8b491eb3f7b47b27fa3fd1cf77, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x23ff4f9d46813457cf60d92f57618399a5e022ac321ca550854ae23918a22eea, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x09945a5d147a4f66ceece6405dddd9d0af5a2c5103529407dff1ea58f180426d, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x188d9c528025d4c2b67660c6b771b90f7c7da6eaa29d3f268a6dd223ec6fc630, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x3050e37996596b7f81f68311431d8734dba7d926d3633595e0c0d8ddf4f0f47f, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x15af1169396830a91600ca8102c35c426ceae5461e3f95d89d829518d30afd78, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x1da6d09885432ea9a06d9f37f873d985dae933e351466b2904284da3320d8acc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := add(0x2796ea90d269af29f5f8acf33921124e4e4fad3dbe658945e546ee411ddaa9cb, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x202d7dd1da0f6b4b0325c8b3307742f01e15612ec8e9304a7cb0319e01d32d60, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x096d6790d05bb759156a952ba263d672a2d7f9c788f4c831a29dace4c0f8be5f, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := add(0x054efa1f65b0fce283808965275d877b438da23ce5b13e1963798cb1447d25a4, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x1b162f83d917e93edb3308c29802deb9d8aa690113b2e14864ccf6e18e4165f1, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x21e5241e12564dd6fd9f1cdd2a0de39eedfefc1466cc568ec5ceb745a0506edc, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := mulmod(scratch1, scratch1, F) scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F) state0 := mulmod(scratch2, scratch2, F) scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F) state0 := add(0x1cfb5662e8cf5ac9226a80ee17b36abecb73ab5f87e161927b4349e10e4bdf08, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x0f21177e302a771bbae6d8d1ecb373b62c99af346220ac0129c53f666eb24100, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x1671522374606992affb0dd7f71b12bec4236aede6290546bcef7e1f515c2320, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := mulmod(state1, state1, F) state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F) scratch0 := mulmod(state2, state2, F) state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F) scratch0 := add(0x0fa3ec5b9488259c2eb4cf24501bfad9be2ec9e42c5cc8ccd419d2a692cad870, add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F))) scratch1 := add(0x193c0e04e0bd298357cb266c1506080ed36edce85c648cc085e8c57b1ab54bba, add(add(mulmod(state0, M01, F), mulmod(state1, M11, F)), mulmod(state2, M21, F))) scratch2 := add(0x102adf8ef74735a27e9128306dcbc3c99f6f7291cd406578ce14ea2adaba68f8, add(add(mulmod(state0, M02, F), mulmod(state1, M12, F)), mulmod(state2, M22, F))) state0 := mulmod(scratch0, scratch0, F) scratch0 := mulmod(mulmod(state0, state0, F), scratch0, F) state0 := mulmod(scratch1, scratch1, F) scratch1 := mulmod(mulmod(state0, state0, F), scratch1, F) state0 := mulmod(scratch2, scratch2, F) scratch2 := mulmod(mulmod(state0, state0, F), scratch2, F) state0 := add(0x0fe0af7858e49859e2a54d6f1ad945b1316aa24bfbdd23ae40a6d0cb70c3eab1, add(add(mulmod(scratch0, M00, F), mulmod(scratch1, M10, F)), mulmod(scratch2, M20, F))) state1 := add(0x216f6717bbc7dedb08536a2220843f4e2da5f1daa9ebdefde8a5ea7344798d22, add(add(mulmod(scratch0, M01, F), mulmod(scratch1, M11, F)), mulmod(scratch2, M21, F))) state2 := add(0x1da55cc900f0d21f4a3e694391918a1b3c23b2ac773c6b3ef88e2e4228325161, add(add(mulmod(scratch0, M02, F), mulmod(scratch1, M12, F)), mulmod(scratch2, M22, F))) scratch0 := mulmod(state0, state0, F) state0 := mulmod(mulmod(scratch0, scratch0, F), state0, F) scratch0 := mulmod(state1, state1, F) state1 := mulmod(mulmod(scratch0, scratch0, F), state1, F) scratch0 := mulmod(state2, state2, F) state2 := mulmod(mulmod(scratch0, scratch0, F), state2, F) mstore(0x0, mod(add(add(mulmod(state0, M00, F), mulmod(state1, M10, F)), mulmod(state2, M20, F)), F)) return(0, 0x20) } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "poseidon-solidity/PoseidonT3.sol": { "PoseidonT3": "0xb43122ecb241dd50062641f089876679fd06599a" } } }
[{"inputs":[{"internalType":"contract ISemaphoreVerifier","name":"_verifier","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"LeafAlreadyExists","type":"error"},{"inputs":[],"name":"LeafCannotBeZero","type":"error"},{"inputs":[],"name":"LeafDoesNotExist","type":"error"},{"inputs":[],"name":"LeafGreaterThanSnarkScalarField","type":"error"},{"inputs":[],"name":"Semaphore__CallerIsNotTheGroupAdmin","type":"error"},{"inputs":[],"name":"Semaphore__CallerIsNotThePendingGroupAdmin","type":"error"},{"inputs":[],"name":"Semaphore__GroupDoesNotExist","type":"error"},{"inputs":[],"name":"Semaphore__GroupHasNoMembers","type":"error"},{"inputs":[],"name":"Semaphore__InvalidProof","type":"error"},{"inputs":[],"name":"Semaphore__MerkleTreeDepthIsNotSupported","type":"error"},{"inputs":[],"name":"Semaphore__MerkleTreeRootIsExpired","type":"error"},{"inputs":[],"name":"Semaphore__MerkleTreeRootIsNotPartOfTheGroup","type":"error"},{"inputs":[],"name":"Semaphore__YouAreUsingTheSameNullifierTwice","type":"error"},{"inputs":[],"name":"WrongSiblingNodes","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"GroupAdminPending","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"GroupAdminUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"}],"name":"GroupCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldMerkleTreeDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMerkleTreeDuration","type":"uint256"}],"name":"GroupMerkleTreeDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"identityCommitment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"merkleTreeRoot","type":"uint256"}],"name":"MemberAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"identityCommitment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"merkleTreeRoot","type":"uint256"}],"name":"MemberRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"identityCommitment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newIdentityCommitment","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"merkleTreeRoot","type":"uint256"}],"name":"MemberUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startIndex","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"identityCommitments","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"merkleTreeRoot","type":"uint256"}],"name":"MembersAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"merkleTreeDepth","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"merkleTreeRoot","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nullifier","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"message","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"scope","type":"uint256"},{"indexed":false,"internalType":"uint256[8]","name":"points","type":"uint256[8]"}],"name":"ProofValidated","type":"event"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"name":"acceptGroupAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"internalType":"uint256","name":"identityCommitment","type":"uint256"}],"name":"addMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"internalType":"uint256[]","name":"identityCommitments","type":"uint256[]"}],"name":"addMembers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint256","name":"merkleTreeDuration","type":"uint256"}],"name":"createGroup","outputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createGroup","outputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"createGroup","outputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"name":"getGroupAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"name":"getMerkleTreeDepth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"name":"getMerkleTreeRoot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"}],"name":"getMerkleTreeSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"groupCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"groups","outputs":[{"internalType":"uint256","name":"merkleTreeDuration","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"internalType":"uint256","name":"identityCommitment","type":"uint256"}],"name":"hasMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"internalType":"uint256","name":"identityCommitment","type":"uint256"}],"name":"indexOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"internalType":"uint256","name":"identityCommitment","type":"uint256"},{"internalType":"uint256[]","name":"merkleProofSiblings","type":"uint256[]"}],"name":"removeMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"internalType":"address","name":"newAdmin","type":"address"}],"name":"updateGroupAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"internalType":"uint256","name":"newMerkleTreeDuration","type":"uint256"}],"name":"updateGroupMerkleTreeDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"internalType":"uint256","name":"identityCommitment","type":"uint256"},{"internalType":"uint256","name":"newIdentityCommitment","type":"uint256"},{"internalType":"uint256[]","name":"merkleProofSiblings","type":"uint256[]"}],"name":"updateMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"components":[{"internalType":"uint256","name":"merkleTreeDepth","type":"uint256"},{"internalType":"uint256","name":"merkleTreeRoot","type":"uint256"},{"internalType":"uint256","name":"nullifier","type":"uint256"},{"internalType":"uint256","name":"message","type":"uint256"},{"internalType":"uint256","name":"scope","type":"uint256"},{"internalType":"uint256[8]","name":"points","type":"uint256[8]"}],"internalType":"struct ISemaphore.SemaphoreProof","name":"proof","type":"tuple"}],"name":"validateProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"contract ISemaphoreVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"components":[{"internalType":"uint256","name":"merkleTreeDepth","type":"uint256"},{"internalType":"uint256","name":"merkleTreeRoot","type":"uint256"},{"internalType":"uint256","name":"nullifier","type":"uint256"},{"internalType":"uint256","name":"message","type":"uint256"},{"internalType":"uint256","name":"scope","type":"uint256"},{"internalType":"uint256[8]","name":"points","type":"uint256[8]"}],"internalType":"struct ISemaphore.SemaphoreProof","name":"proof","type":"tuple"}],"name":"verifyProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5060405161201538038061201583398101604081905261002f91610054565b600380546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b611f82806100936000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c80636389e107116100b8578063a9961c941161007c578063a9961c94146102b5578063d0d898dd146102de578063d24924fe146102f1578063da3cda52146102fa578063dabc4d511461030d578063fcf0b6ec1461032057600080fd5b80636389e1071461022c5780636cdd32fe1461024f5780637ee35a0c1461026257806390509d441461028257806396324bd41461029557600080fd5b80634178c4d5116100ff5780634178c4d5146101c8578063456f4188146101db578063568ee826146101fe578063575185ed146102115780635c3f3b601461021957600080fd5b8063042453711461013c57806306dd8485146101515780631783efc3146101775780632b7ac3f31461018a5780632c880363146101b5575b600080fd5b61014f61014a3660046119e2565b610333565b005b61016461015f366004611a2e565b610366565b6040519081526020015b60405180910390f35b61014f610185366004611a2e565b610387565b60035461019d906001600160a01b031681565b6040516001600160a01b03909116815260200161016e565b6101646101c3366004611a6c565b6103b8565b61014f6101d6366004611a96565b6103f0565b6101ee6101e9366004611af7565b610427565b604051901515815260200161016e565b61014f61020c366004611b31565b61068c565b61016461069a565b610164610227366004611b5d565b6106d1565b61016461023a366004611b78565b60009081526020819052604090206001015490565b61014f61025d366004611b91565b61070a565b610164610270366004611b78565b60009081526020819052604090205490565b6101ee610290366004611a2e565b61073f565b6101646102a3366004611b78565b60046020526000908152604090205481565b61019d6102c3366004611b78565b6000908152600160205260409020546001600160a01b031690565b61014f6102ec366004611af7565b610761565b61016460055481565b61014f610308366004611b78565b61084b565b61016461031b366004611b78565b610857565b61014f61032e366004611a2e565b61087b565b600061034084848461090b565b600094855260046020908152604080872092875260019092019052909320429055505050565b600082815260208190526040812061037e90836109a9565b90505b92915050565b600061039383836109f6565b6000938452600460209081526040808620928652600190920190529092204290555050565b60058054600091826103c983611bfa565b9190505590506103d98184610a98565b600081815260046020526040902091909155919050565b60006103ff8686868686610b22565b6000968752600460209081526040808920928952600190920190529095204290555050505050565b60008281526001602052604081205483906001600160a01b031661045e5760405163029f057960e01b815260040160405180910390fd5b60018335108061046f575060208335115b1561048d5760405163767b278960e11b815260040160405180910390fd5b600084815260208190526040812054908190036104bd5760405163c8b02e0160e01b815260040160405180910390fd5b60006104c886610857565b90508085602001351461054d576000868152600460208181526040808420898301358552600181018352908420548a855292909152549091829003610520576040516326994ac360e11b815260040160405180910390fd5b61052a8183611c13565b42111561054a576040516309581a9960e41b815260040160405180910390fd5b50505b60035460408051808201825260a0880135815260c088013560208083019190915282516080808201855260e08b01358286019081526101008c0135606080850191909152908352855180870187526101208d013581526101408d01358186015283850152855180870187526101608d013581526101808d01358186015286519283018752848d013583528c870135948301949094526001600160a01b039096169563a23f019995929392820190610606908d0135610be9565b81526020016106188c60800135610be9565b90526040516001600160e01b031960e087901b16815261064194939291908c3590600401611c88565b602060405180830381865afa15801561065e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106829190611d1b565b9695505050505050565b6106968282610c20565b5050565b60058054600091826106ab83611bfa565b9190505590506106bb8133610a98565b6000818152600460205260409020610e10905590565b60058054600091826106e283611bfa565b9190505590506106f28183610a98565b6000818152600460205260409020610e109055919050565b600061071885858585610cb4565b60009586526004602090815260408088209288526001909201905290942042905550505050565b600082815260208181526040808320848452600301909152812054151561037e565b600082815260046020908152604080832084820135845260020190915290205460ff16156107a25760405163041162bd60e31b815260040160405180910390fd5b6107ac8282610427565b6107c95760405163012a9af160e61b815260040160405180910390fd5b6000828152600460209081526040808320848201358085526002909101835292819020805460ff1916600117905551608084013592918401359185917f0c32e14cfe81a05d371c248d22de6b7ae849e981b76a1f8842e7b6da73fc405a9161083f918735919060608901359060a08a0190611d44565b60405180910390a45050565b61085481610d72565b50565b60008181526020818152604080832060018101548452600201909152812054610381565b60008281526001602052604090205482906001600160a01b031633146108b4576040516317737e4f60e31b815260040160405180910390fd5b60008381526004602090815260409182902080549085905582518181529182018590529185917f264b2a8f6763c084235fe832ba903482b2ef1a521336881fc75b987c2dfd29c5910160405180910390a250505050565b60008381526001602052604081205484906001600160a01b03163314610944576040516317737e4f60e31b815260040160405180910390fd5b6000858152602081905260409020805490610960908686610e17565b9250857f61e5e8054e3daf084a0c6c646c065e8bf5e7ca4d5567bda942309bd1652f349d828787876040516109989493929190611d6c565b60405180910390a250509392505050565b600081815260038301602052604081205481036109d957604051631c811d5b60e21b815260040160405180910390fd5b600082815260038401602052604090205461037e90600190611db2565b60008281526001602052604081205483906001600160a01b03163314610a2f576040516317737e4f60e31b815260040160405180910390fd5b6000848152602081905260409020805490610a4a9085611344565b604080518381526020810187905290810182905290935085907f19239b3f93cd10558aaf11423af70c77763bf54f52bcc75bfa74d4d13548cde99060600160405180910390a2505092915050565b60008281526001602052604080822080546001600160a01b0319166001600160a01b0385161790555183917ff0adfb94eab6daf835deb69c5738fe636150c3dfd08094a76f39b963dc8cb05a91a26040516001600160a01b0382169060009084907f0ba83579a0e79193ef649b9f5a8759d35af086ba62a3e207b52e4a8ae30d49e3908390a45050565b60008581526001602052604081205486906001600160a01b03163314610b5b576040516317737e4f60e31b815260040160405180910390fd5b6000878152602081905260408120610b7390886109a9565b6000898152602081905260409020909150610b91908888888861150d565b60408051838152602081018a90529081018890526060810182905290935088907fea3588e4a2a0c93d6a0e69dfeaf7496f43ccccf02ad9ce0a5b7627cbca4b61b19060800160405180910390a2505095945050505050565b6000600882604051602001610c0091815260200190565b60408051601f198184030181529190528051602090910120901c92915050565b60008281526001602052604090205482906001600160a01b03163314610c59576040516317737e4f60e31b815260040160405180910390fd5b60008381526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590519091339186917f1018365553cce55d9cb02ef73e18cc9311894f3fe1d1eafd235ac2d26cd8ba5891a4505050565b60008481526001602052604081205485906001600160a01b03163314610ced576040516317737e4f60e31b815260040160405180910390fd5b6000868152602081905260408120610d0590876109a9565b6000888152602081905260409020909150610d229087878761197d565b604080518381526020810189905290810182905290935087907f3108849c053c77b8073a11256dffb5ffd5b55e93e105a355e1c9061db890d8719060600160405180910390a25050949350505050565b6000818152600260205260409020546001600160a01b03163314610da9576040516334c4245d60e01b815260040160405180910390fd5b60008181526001602090815260408083208054336001600160a01b031980831682179093556002909452828520805490921690915590516001600160a01b0390911692839185917f0ba83579a0e79193ef649b9f5a8759d35af086ba62a3e207b52e4a8ae30d49e391a45050565b8254600090815b83811015610f4857600080516020611f2d833981519152858583818110610e4757610e47611c26565b9050602002013510610e6c576040516361c0541760e11b815260040160405180910390fd5b848482818110610e7e57610e7e611c26565b90506020020135600003610ea5576040516314b48df160e11b815260040160405180910390fd5b610eda86868684818110610ebb57610ebb611c26565b9050602002013560009081526003919091016020526040902054151590565b15610ef8576040516312c50cad60e11b815260040160405180910390fd5b80610f04836001611c13565b610f0e9190611c13565b866003016000878785818110610f2657610f26611c26565b6020908102929092013583525081019190915260400160002055600101610e1e565b50606084848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050506001880154919250505b610f918584611c13565b610f9c826002611ea9565b1015610fb257610fab81611bfa565b9050610f87565b60018701819055826000610fc68783611c13565b9050600182811c90600090610fdb8185611db2565b610fe7911c6001611c13565b905060005b858110156112d85760006110008484611db2565b905060008167ffffffffffffffff81111561101d5761101d611eb5565b604051908082528060200260200182016040528015611046578160200160208202803683370190505b50905060005b82811015611203576000886110618884611c13565b61106c906002611ecb565b101561108f578f60020160008681526020019081526020016000205490506110cb565b8a8961109b8985611c13565b6110a6906002611ecb565b6110b09190611db2565b815181106110c0576110c0611c26565b602002602001015190505b6000886110d88985611c13565b6110e3906002611ecb565b6110ee906001611c13565b101561113b578b8a6111008a86611c13565b61110b906002611ecb565b611116906001611c13565b6111209190611db2565b8151811061113057611130611c26565b602002602001015190505b600081156111d357604080518082018252848152602081018490529051632b0aac7f60e11b815273b43122ecb241dd50062641f089876679fd06599a9163561558fe9161118b9190600401611ee2565b602060405180830381865af41580156111a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111cc9190611f13565b90506111d6565b50815b808585815181106111e9576111e9611c26565b60200260200101818152505083600101935050505061104c565b5085600116600103611254578860018a5161121e9190611db2565b8151811061122e5761122e611c26565b60200260200101518e60020160008581526020019081526020016000208190555061129f565b60018951111561129f578860028a5161126d9190611db2565b8151811061127d5761127d611c26565b60200260200101518e6002016000858152602001908152602001600020819055505b849650600185901c9450809850839550600180856112bd9190611db2565b6112c9911c6001611c13565b93508260010192505050610fec565b506112e38988611c13565b8b55855186906000906112f8576112f8611c26565b60200260200101518b6002016000878152602001908152602001600020819055508560008151811061132c5761132c611c26565b60200260200101519750505050505050509392505050565b6000600080516020611f2d8339815191528210611374576040516361c0541760e11b815260040160405180910390fd5b81600003611395576040516314b48df160e11b815260040160405180910390fd5b6000828152600384016020526040902054156113c4576040516312c50cad60e11b815260040160405180910390fd5b8254600180850154906113d8908390611c13565b6113e3826002611ea9565b10156113f5576113f281611bfa565b90505b600185018190558360005b828110156114d2578084901c6001166001036114b657604080518082018252600083815260028a0160209081529083902054825281018490529051632b0aac7f60e11b815273b43122ecb241dd50062641f089876679fd06599a9163561558fe9161146e9190600401611ee2565b602060405180830381865af415801561148b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114af9190611f13565b91506114ca565b600081815260028801602052604090208290555b600101611400565b506114dc83611bfa565b8087556000928352600287016020908152604080852084905596845260039097019096529390209390935550919050565b6000600080516020611f2d833981519152841061153d576040516361c0541760e11b815260040160405180910390fd5b600085815260038701602052604090205461156b57604051631c811d5b60e21b815260040160405180910390fd5b60008481526003870160205260409020541561159a576040516312c50cad60e11b815260040160405180910390fd5b60006115a687876109a9565b8754909150859087906000906115be90600190611db2565b60018b0154909150600090815b818110156118f4578087901c60011660010361177e57600080516020611f2d8339815191528a8a8581811061160257611602611c26565b9050602002013510611627576040516361c0541760e11b815260040160405180910390fd5b73b43122ecb241dd50062641f089876679fd06599a63561558fe60405180604001604052808d8d8881811061165e5761165e611c26565b905060200201358152602001898152506040518263ffffffff1660e01b815260040161168a9190611ee2565b602060405180830381865af41580156116a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cb9190611f13565b955073b43122ecb241dd50062641f089876679fd06599a63561558fe60405180604001604052808d8d8881811061170457611704611c26565b905060200201358152602001888152506040518263ffffffff1660e01b81526004016117309190611ee2565b602060405180830381865af415801561174d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117719190611f13565b94508260010192506118ec565b86811c84821c146118d857600080516020611f2d8339815191528a8a858181106117aa576117aa611c26565b90506020020135106117cf576040516361c0541760e11b815260040160405180910390fd5b73b43122ecb241dd50062641f089876679fd06599a63561558fe60405180604001604052808981526020018d8d8881811061180c5761180c611c26565b905060200201358152506040518263ffffffff1660e01b81526004016118329190611ee2565b602060405180830381865af415801561184f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118739190611f13565b955073b43122ecb241dd50062641f089876679fd06599a63561558fe60405180604001604052808881526020018d8d888181106118b2576118b2611c26565b905060200201358152506040518263ffffffff1660e01b81526004016117309190611ee2565b600083815260028e01602052604090208690555b6001016115cb565b5060018c0154600090815260028d016020526040902054841461192a57604051631fd4986360e11b815260040160405180910390fd5b600081815260028d0160205260409020859055891561195c5760008b815260038d016020526040808220548c83529120555b505050600088815260038a0160205260408120555091505095945050505050565b600061198d85856000868661150d565b95945050505050565b60008083601f8401126119a857600080fd5b50813567ffffffffffffffff8111156119c057600080fd5b6020830191508360208260051b85010111156119db57600080fd5b9250929050565b6000806000604084860312156119f757600080fd5b83359250602084013567ffffffffffffffff811115611a1557600080fd5b611a2186828701611996565b9497909650939450505050565b60008060408385031215611a4157600080fd5b50508035926020909101359150565b80356001600160a01b0381168114611a6757600080fd5b919050565b60008060408385031215611a7f57600080fd5b611a8883611a50565b946020939093013593505050565b600080600080600060808688031215611aae57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115611ada57600080fd5b611ae688828901611996565b969995985093965092949392505050565b6000808284036101c0811215611b0c57600080fd5b833592506101a0601f1982011215611b2357600080fd5b506020830190509250929050565b60008060408385031215611b4457600080fd5b82359150611b5460208401611a50565b90509250929050565b600060208284031215611b6f57600080fd5b61037e82611a50565b600060208284031215611b8a57600080fd5b5035919050565b60008060008060608587031215611ba757600080fd5b8435935060208501359250604085013567ffffffffffffffff811115611bcc57600080fd5b611bd887828801611996565b95989497509550505050565b634e487b7160e01b600052601160045260246000fd5b600060018201611c0c57611c0c611be4565b5060010190565b8082018082111561038157610381611be4565b634e487b7160e01b600052603260045260246000fd5b8060005b6002811015611c5f578151845260209384019390910190600101611c40565b50505050565b8060005b6004811015611c5f578151845260209384019390910190600101611c69565b6101a08101611c978288611c3c565b6040808301876000805b6002808210611cb05750611cea565b835185845b83811015611cd3578251825260209283019290910190600101611cb5565b505050938501935060209290920191600101611ca1565b5050505050611cfc60c0830186611c3c565b611d0a610100830185611c65565b826101808301529695505050505050565b600060208284031215611d2d57600080fd5b81518015158114611d3d57600080fd5b9392505050565b8481526020810184905260408101839052610160810161010083606084013795945050505050565b848152606060208201819052810183905260006001600160fb1b03841115611d9357600080fd5b8360051b80866080850137604083019390935250016080019392505050565b8181038181111561038157610381611be4565b600181815b80851115611e00578160001904821115611de657611de6611be4565b80851615611df357918102915b93841c9390800290611dca565b509250929050565b600082611e1757506001610381565b81611e2457506000610381565b8160018114611e3a5760028114611e4457611e60565b6001915050610381565b60ff841115611e5557611e55611be4565b50506001821b610381565b5060208310610133831016604e8410600b8410161715611e83575081810a610381565b611e8d8383611dc5565b8060001904821115611ea157611ea1611be4565b029392505050565b600061037e8383611e08565b634e487b7160e01b600052604160045260246000fd5b808202811582820484141761038157610381611be4565b60408101818360005b6002811015611f0a578151835260209283019290910190600101611eeb565b50505092915050565b600060208284031215611f2557600080fd5b505191905056fe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001a2646970667358221220164ddea4e67fb9956ad9d73065c0b85ecf9b8062f67bcc5be446364b9475660664736f6c63430008170033000000000000000000000000e538f9deee04a397decb1e7dc5d16fd6f123c043
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101375760003560e01c80636389e107116100b8578063a9961c941161007c578063a9961c94146102b5578063d0d898dd146102de578063d24924fe146102f1578063da3cda52146102fa578063dabc4d511461030d578063fcf0b6ec1461032057600080fd5b80636389e1071461022c5780636cdd32fe1461024f5780637ee35a0c1461026257806390509d441461028257806396324bd41461029557600080fd5b80634178c4d5116100ff5780634178c4d5146101c8578063456f4188146101db578063568ee826146101fe578063575185ed146102115780635c3f3b601461021957600080fd5b8063042453711461013c57806306dd8485146101515780631783efc3146101775780632b7ac3f31461018a5780632c880363146101b5575b600080fd5b61014f61014a3660046119e2565b610333565b005b61016461015f366004611a2e565b610366565b6040519081526020015b60405180910390f35b61014f610185366004611a2e565b610387565b60035461019d906001600160a01b031681565b6040516001600160a01b03909116815260200161016e565b6101646101c3366004611a6c565b6103b8565b61014f6101d6366004611a96565b6103f0565b6101ee6101e9366004611af7565b610427565b604051901515815260200161016e565b61014f61020c366004611b31565b61068c565b61016461069a565b610164610227366004611b5d565b6106d1565b61016461023a366004611b78565b60009081526020819052604090206001015490565b61014f61025d366004611b91565b61070a565b610164610270366004611b78565b60009081526020819052604090205490565b6101ee610290366004611a2e565b61073f565b6101646102a3366004611b78565b60046020526000908152604090205481565b61019d6102c3366004611b78565b6000908152600160205260409020546001600160a01b031690565b61014f6102ec366004611af7565b610761565b61016460055481565b61014f610308366004611b78565b61084b565b61016461031b366004611b78565b610857565b61014f61032e366004611a2e565b61087b565b600061034084848461090b565b600094855260046020908152604080872092875260019092019052909320429055505050565b600082815260208190526040812061037e90836109a9565b90505b92915050565b600061039383836109f6565b6000938452600460209081526040808620928652600190920190529092204290555050565b60058054600091826103c983611bfa565b9190505590506103d98184610a98565b600081815260046020526040902091909155919050565b60006103ff8686868686610b22565b6000968752600460209081526040808920928952600190920190529095204290555050505050565b60008281526001602052604081205483906001600160a01b031661045e5760405163029f057960e01b815260040160405180910390fd5b60018335108061046f575060208335115b1561048d5760405163767b278960e11b815260040160405180910390fd5b600084815260208190526040812054908190036104bd5760405163c8b02e0160e01b815260040160405180910390fd5b60006104c886610857565b90508085602001351461054d576000868152600460208181526040808420898301358552600181018352908420548a855292909152549091829003610520576040516326994ac360e11b815260040160405180910390fd5b61052a8183611c13565b42111561054a576040516309581a9960e41b815260040160405180910390fd5b50505b60035460408051808201825260a0880135815260c088013560208083019190915282516080808201855260e08b01358286019081526101008c0135606080850191909152908352855180870187526101208d013581526101408d01358186015283850152855180870187526101608d013581526101808d01358186015286519283018752848d013583528c870135948301949094526001600160a01b039096169563a23f019995929392820190610606908d0135610be9565b81526020016106188c60800135610be9565b90526040516001600160e01b031960e087901b16815261064194939291908c3590600401611c88565b602060405180830381865afa15801561065e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106829190611d1b565b9695505050505050565b6106968282610c20565b5050565b60058054600091826106ab83611bfa565b9190505590506106bb8133610a98565b6000818152600460205260409020610e10905590565b60058054600091826106e283611bfa565b9190505590506106f28183610a98565b6000818152600460205260409020610e109055919050565b600061071885858585610cb4565b60009586526004602090815260408088209288526001909201905290942042905550505050565b600082815260208181526040808320848452600301909152812054151561037e565b600082815260046020908152604080832084820135845260020190915290205460ff16156107a25760405163041162bd60e31b815260040160405180910390fd5b6107ac8282610427565b6107c95760405163012a9af160e61b815260040160405180910390fd5b6000828152600460209081526040808320848201358085526002909101835292819020805460ff1916600117905551608084013592918401359185917f0c32e14cfe81a05d371c248d22de6b7ae849e981b76a1f8842e7b6da73fc405a9161083f918735919060608901359060a08a0190611d44565b60405180910390a45050565b61085481610d72565b50565b60008181526020818152604080832060018101548452600201909152812054610381565b60008281526001602052604090205482906001600160a01b031633146108b4576040516317737e4f60e31b815260040160405180910390fd5b60008381526004602090815260409182902080549085905582518181529182018590529185917f264b2a8f6763c084235fe832ba903482b2ef1a521336881fc75b987c2dfd29c5910160405180910390a250505050565b60008381526001602052604081205484906001600160a01b03163314610944576040516317737e4f60e31b815260040160405180910390fd5b6000858152602081905260409020805490610960908686610e17565b9250857f61e5e8054e3daf084a0c6c646c065e8bf5e7ca4d5567bda942309bd1652f349d828787876040516109989493929190611d6c565b60405180910390a250509392505050565b600081815260038301602052604081205481036109d957604051631c811d5b60e21b815260040160405180910390fd5b600082815260038401602052604090205461037e90600190611db2565b60008281526001602052604081205483906001600160a01b03163314610a2f576040516317737e4f60e31b815260040160405180910390fd5b6000848152602081905260409020805490610a4a9085611344565b604080518381526020810187905290810182905290935085907f19239b3f93cd10558aaf11423af70c77763bf54f52bcc75bfa74d4d13548cde99060600160405180910390a2505092915050565b60008281526001602052604080822080546001600160a01b0319166001600160a01b0385161790555183917ff0adfb94eab6daf835deb69c5738fe636150c3dfd08094a76f39b963dc8cb05a91a26040516001600160a01b0382169060009084907f0ba83579a0e79193ef649b9f5a8759d35af086ba62a3e207b52e4a8ae30d49e3908390a45050565b60008581526001602052604081205486906001600160a01b03163314610b5b576040516317737e4f60e31b815260040160405180910390fd5b6000878152602081905260408120610b7390886109a9565b6000898152602081905260409020909150610b91908888888861150d565b60408051838152602081018a90529081018890526060810182905290935088907fea3588e4a2a0c93d6a0e69dfeaf7496f43ccccf02ad9ce0a5b7627cbca4b61b19060800160405180910390a2505095945050505050565b6000600882604051602001610c0091815260200190565b60408051601f198184030181529190528051602090910120901c92915050565b60008281526001602052604090205482906001600160a01b03163314610c59576040516317737e4f60e31b815260040160405180910390fd5b60008381526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590519091339186917f1018365553cce55d9cb02ef73e18cc9311894f3fe1d1eafd235ac2d26cd8ba5891a4505050565b60008481526001602052604081205485906001600160a01b03163314610ced576040516317737e4f60e31b815260040160405180910390fd5b6000868152602081905260408120610d0590876109a9565b6000888152602081905260409020909150610d229087878761197d565b604080518381526020810189905290810182905290935087907f3108849c053c77b8073a11256dffb5ffd5b55e93e105a355e1c9061db890d8719060600160405180910390a25050949350505050565b6000818152600260205260409020546001600160a01b03163314610da9576040516334c4245d60e01b815260040160405180910390fd5b60008181526001602090815260408083208054336001600160a01b031980831682179093556002909452828520805490921690915590516001600160a01b0390911692839185917f0ba83579a0e79193ef649b9f5a8759d35af086ba62a3e207b52e4a8ae30d49e391a45050565b8254600090815b83811015610f4857600080516020611f2d833981519152858583818110610e4757610e47611c26565b9050602002013510610e6c576040516361c0541760e11b815260040160405180910390fd5b848482818110610e7e57610e7e611c26565b90506020020135600003610ea5576040516314b48df160e11b815260040160405180910390fd5b610eda86868684818110610ebb57610ebb611c26565b9050602002013560009081526003919091016020526040902054151590565b15610ef8576040516312c50cad60e11b815260040160405180910390fd5b80610f04836001611c13565b610f0e9190611c13565b866003016000878785818110610f2657610f26611c26565b6020908102929092013583525081019190915260400160002055600101610e1e565b50606084848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050506001880154919250505b610f918584611c13565b610f9c826002611ea9565b1015610fb257610fab81611bfa565b9050610f87565b60018701819055826000610fc68783611c13565b9050600182811c90600090610fdb8185611db2565b610fe7911c6001611c13565b905060005b858110156112d85760006110008484611db2565b905060008167ffffffffffffffff81111561101d5761101d611eb5565b604051908082528060200260200182016040528015611046578160200160208202803683370190505b50905060005b82811015611203576000886110618884611c13565b61106c906002611ecb565b101561108f578f60020160008681526020019081526020016000205490506110cb565b8a8961109b8985611c13565b6110a6906002611ecb565b6110b09190611db2565b815181106110c0576110c0611c26565b602002602001015190505b6000886110d88985611c13565b6110e3906002611ecb565b6110ee906001611c13565b101561113b578b8a6111008a86611c13565b61110b906002611ecb565b611116906001611c13565b6111209190611db2565b8151811061113057611130611c26565b602002602001015190505b600081156111d357604080518082018252848152602081018490529051632b0aac7f60e11b815273b43122ecb241dd50062641f089876679fd06599a9163561558fe9161118b9190600401611ee2565b602060405180830381865af41580156111a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111cc9190611f13565b90506111d6565b50815b808585815181106111e9576111e9611c26565b60200260200101818152505083600101935050505061104c565b5085600116600103611254578860018a5161121e9190611db2565b8151811061122e5761122e611c26565b60200260200101518e60020160008581526020019081526020016000208190555061129f565b60018951111561129f578860028a5161126d9190611db2565b8151811061127d5761127d611c26565b60200260200101518e6002016000858152602001908152602001600020819055505b849650600185901c9450809850839550600180856112bd9190611db2565b6112c9911c6001611c13565b93508260010192505050610fec565b506112e38988611c13565b8b55855186906000906112f8576112f8611c26565b60200260200101518b6002016000878152602001908152602001600020819055508560008151811061132c5761132c611c26565b60200260200101519750505050505050509392505050565b6000600080516020611f2d8339815191528210611374576040516361c0541760e11b815260040160405180910390fd5b81600003611395576040516314b48df160e11b815260040160405180910390fd5b6000828152600384016020526040902054156113c4576040516312c50cad60e11b815260040160405180910390fd5b8254600180850154906113d8908390611c13565b6113e3826002611ea9565b10156113f5576113f281611bfa565b90505b600185018190558360005b828110156114d2578084901c6001166001036114b657604080518082018252600083815260028a0160209081529083902054825281018490529051632b0aac7f60e11b815273b43122ecb241dd50062641f089876679fd06599a9163561558fe9161146e9190600401611ee2565b602060405180830381865af415801561148b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114af9190611f13565b91506114ca565b600081815260028801602052604090208290555b600101611400565b506114dc83611bfa565b8087556000928352600287016020908152604080852084905596845260039097019096529390209390935550919050565b6000600080516020611f2d833981519152841061153d576040516361c0541760e11b815260040160405180910390fd5b600085815260038701602052604090205461156b57604051631c811d5b60e21b815260040160405180910390fd5b60008481526003870160205260409020541561159a576040516312c50cad60e11b815260040160405180910390fd5b60006115a687876109a9565b8754909150859087906000906115be90600190611db2565b60018b0154909150600090815b818110156118f4578087901c60011660010361177e57600080516020611f2d8339815191528a8a8581811061160257611602611c26565b9050602002013510611627576040516361c0541760e11b815260040160405180910390fd5b73b43122ecb241dd50062641f089876679fd06599a63561558fe60405180604001604052808d8d8881811061165e5761165e611c26565b905060200201358152602001898152506040518263ffffffff1660e01b815260040161168a9190611ee2565b602060405180830381865af41580156116a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cb9190611f13565b955073b43122ecb241dd50062641f089876679fd06599a63561558fe60405180604001604052808d8d8881811061170457611704611c26565b905060200201358152602001888152506040518263ffffffff1660e01b81526004016117309190611ee2565b602060405180830381865af415801561174d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117719190611f13565b94508260010192506118ec565b86811c84821c146118d857600080516020611f2d8339815191528a8a858181106117aa576117aa611c26565b90506020020135106117cf576040516361c0541760e11b815260040160405180910390fd5b73b43122ecb241dd50062641f089876679fd06599a63561558fe60405180604001604052808981526020018d8d8881811061180c5761180c611c26565b905060200201358152506040518263ffffffff1660e01b81526004016118329190611ee2565b602060405180830381865af415801561184f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118739190611f13565b955073b43122ecb241dd50062641f089876679fd06599a63561558fe60405180604001604052808881526020018d8d888181106118b2576118b2611c26565b905060200201358152506040518263ffffffff1660e01b81526004016117309190611ee2565b600083815260028e01602052604090208690555b6001016115cb565b5060018c0154600090815260028d016020526040902054841461192a57604051631fd4986360e11b815260040160405180910390fd5b600081815260028d0160205260409020859055891561195c5760008b815260038d016020526040808220548c83529120555b505050600088815260038a0160205260408120555091505095945050505050565b600061198d85856000868661150d565b95945050505050565b60008083601f8401126119a857600080fd5b50813567ffffffffffffffff8111156119c057600080fd5b6020830191508360208260051b85010111156119db57600080fd5b9250929050565b6000806000604084860312156119f757600080fd5b83359250602084013567ffffffffffffffff811115611a1557600080fd5b611a2186828701611996565b9497909650939450505050565b60008060408385031215611a4157600080fd5b50508035926020909101359150565b80356001600160a01b0381168114611a6757600080fd5b919050565b60008060408385031215611a7f57600080fd5b611a8883611a50565b946020939093013593505050565b600080600080600060808688031215611aae57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115611ada57600080fd5b611ae688828901611996565b969995985093965092949392505050565b6000808284036101c0811215611b0c57600080fd5b833592506101a0601f1982011215611b2357600080fd5b506020830190509250929050565b60008060408385031215611b4457600080fd5b82359150611b5460208401611a50565b90509250929050565b600060208284031215611b6f57600080fd5b61037e82611a50565b600060208284031215611b8a57600080fd5b5035919050565b60008060008060608587031215611ba757600080fd5b8435935060208501359250604085013567ffffffffffffffff811115611bcc57600080fd5b611bd887828801611996565b95989497509550505050565b634e487b7160e01b600052601160045260246000fd5b600060018201611c0c57611c0c611be4565b5060010190565b8082018082111561038157610381611be4565b634e487b7160e01b600052603260045260246000fd5b8060005b6002811015611c5f578151845260209384019390910190600101611c40565b50505050565b8060005b6004811015611c5f578151845260209384019390910190600101611c69565b6101a08101611c978288611c3c565b6040808301876000805b6002808210611cb05750611cea565b835185845b83811015611cd3578251825260209283019290910190600101611cb5565b505050938501935060209290920191600101611ca1565b5050505050611cfc60c0830186611c3c565b611d0a610100830185611c65565b826101808301529695505050505050565b600060208284031215611d2d57600080fd5b81518015158114611d3d57600080fd5b9392505050565b8481526020810184905260408101839052610160810161010083606084013795945050505050565b848152606060208201819052810183905260006001600160fb1b03841115611d9357600080fd5b8360051b80866080850137604083019390935250016080019392505050565b8181038181111561038157610381611be4565b600181815b80851115611e00578160001904821115611de657611de6611be4565b80851615611df357918102915b93841c9390800290611dca565b509250929050565b600082611e1757506001610381565b81611e2457506000610381565b8160018114611e3a5760028114611e4457611e60565b6001915050610381565b60ff841115611e5557611e55611be4565b50506001821b610381565b5060208310610133831016604e8410600b8410161715611e83575081810a610381565b611e8d8383611dc5565b8060001904821115611ea157611ea1611be4565b029392505050565b600061037e8383611e08565b634e487b7160e01b600052604160045260246000fd5b808202811582820484141761038157610381611be4565b60408101818360005b6002811015611f0a578151835260209283019290910190600101611eeb565b50505092915050565b600060208284031215611f2557600080fd5b505191905056fe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001a2646970667358221220164ddea4e67fb9956ad9d73065c0b85ecf9b8062f67bcc5be446364b9475660664736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e538f9deee04a397decb1e7dc5d16fd6f123c043
-----Decoded View---------------
Arg [0] : _verifier (address): 0xe538f9DeeE04A397decb1E7dc5D16fD6f123c043
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000e538f9deee04a397decb1e7dc5d16fd6f123c043
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.