rln-interep-contract/deployments/goerli/solcInputs/340bcf47b11a05607e785a46710a077f.json

64 lines
54 KiB
JSON
Raw Normal View History

2022-11-25 12:07:06 +05:30
{
"language": "Solidity",
"sources": {
"@appliedzkp/semaphore-contracts/base/SemaphoreConstants.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nuint256 constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n"
},
"@appliedzkp/semaphore-contracts/base/SemaphoreCore.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"../interfaces/ISemaphoreCore.sol\";\nimport \"../interfaces/IVerifier.sol\";\n\n/// @title Semaphore core contract.\n/// @notice Minimal code to allow users to signal their endorsement of an arbitrary string.\n/// @dev The following code verifies that the proof is correct and saves the hash of the\n/// nullifier to prevent double-signaling. External nullifier and Merkle trees (i.e. groups) must be\n/// managed externally.\ncontract SemaphoreCore is ISemaphoreCore {\n /// @dev Gets a nullifier hash and returns true or false.\n /// It is used to prevent double-signaling.\n mapping(uint256 => bool) internal nullifierHashes;\n\n /// @dev Asserts that no nullifier already exists and if the zero-knowledge proof is valid.\n /// Otherwise it reverts.\n /// @param signal: Semaphore signal.\n /// @param root: Root of the Merkle tree.\n /// @param nullifierHash: Nullifier hash.\n /// @param externalNullifier: External nullifier.\n /// @param proof: Zero-knowledge proof.\n /// @param verifier: Verifier address.\n function _verifyProof(\n bytes32 signal,\n uint256 root,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof,\n IVerifier verifier\n ) internal view {\n require(!nullifierHashes[nullifierHash], \"SemaphoreCore: you cannot use the same nullifier twice\");\n\n uint256 signalHash = _hashSignal(signal);\n\n verifier.verifyProof(\n [proof[0], proof[1]],\n [[proof[2], proof[3]], [proof[4], proof[5]]],\n [proof[6], proof[7]],\n [root, nullifierHash, signalHash, externalNullifier]\n );\n }\n\n /// @dev Stores the nullifier hash to prevent double-signaling.\n /// Attention! Remember to call it when you verify a proof if you\n /// need to prevent double-signaling.\n /// @param nullifierHash: Semaphore nullifier hash.\n function _saveNullifierHash(uint256 nullifierHash) internal {\n nullifierHashes[nullifierHash] = true;\n }\n\n /// @dev Creates a keccak256 hash of the signal.\n /// @param signal: Semaphore signal.\n /// @return Hash of the signal.\n function _hashSignal(bytes32 signal) private pure returns (uint256) {\n return uint256(keccak256(abi.encodePacked(signal))) >> 8;\n }\n}\n"
},
"@appliedzkp/semaphore-contracts/interfaces/ISemaphoreCore.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title SemaphoreCore interface.\n/// @dev Interface of SemaphoreCore contract.\ninterface ISemaphoreCore {\n /// @notice Emitted when a proof is verified correctly and a new nullifier hash is added.\n /// @param nullifierHash: Hash of external and identity nullifiers.\n event NullifierHashAdded(uint256 nullifierHash);\n}\n"
},
"@appliedzkp/semaphore-contracts/interfaces/IVerifier.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title Verifier interface.\n/// @dev Interface of Verifier contract.\ninterface IVerifier {\n function verifyProof(\n uint256[2] memory a,\n uint256[2][2] memory b,\n uint256[2] memory c,\n uint256[4] memory input\n ) external view;\n}\n"
},
"@interep/contracts/IInterep.sol": {
"content": "//SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @title Interep interface.\n/// @dev Interface of a Interep contract.\ninterface IInterep {\n struct Verifier {\n address contractAddress;\n uint8 merkleTreeDepth;\n }\n\n struct Group {\n bytes32 provider;\n bytes32 name;\n uint256 root;\n uint8 depth;\n }\n\n /// @dev Emitted when a Semaphore proof is verified.\n /// @param groupId: Id of the group.\n /// @param signal: Semaphore signal.\n event ProofVerified(uint256 indexed groupId, bytes32 signal);\n\n /// @dev Emitted when an Interep group is updated.\n /// @param groupId: Id of the group.\n /// @param provider: Provider of the group.\n /// @param name: Name of the group.\n /// @param root: Root hash of the tree.\n /// @param depth: Depth of the tree.\n event GroupUpdated(\n uint256 groupId,\n bytes32 indexed provider,\n bytes32 indexed name,\n uint256 root,\n uint8 indexed depth\n );\n\n /// @dev Updates the Interep groups.\n /// @param groups: List of Interep groups.\n function updateGroups(Group[] calldata groups) external;\n\n /// @dev Saves the nullifier hash to avoid double signaling and emits an event\n /// if the zero-knowledge proof is valid.\n /// @param groupId: Id of the group.\n /// @param signal: Semaphore signal.\n /// @param nullifierHash: Nullifier hash.\n /// @param externalNullifier: External nullifier.\n /// @param proof: Zero-knowledge proof.\n function verifyProof(\n uint256 groupId,\n bytes32 signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof\n ) external;\n\n /// @dev Returns the root hash of an Interep group.\n /// @param groupId: Id of the group.\n /// @return Root hash of the group.\n function getRoot(uint256 groupId) external view returns (uint256);\n\n /// @dev Returns the tree depth of an Interep group.\n /// @param groupId: Id of the group.\n /// @return Tree depth of the group.\n function getDepth(uint256 groupId) external view returns (uint8);\n}\n"
},
"@interep/contracts/Interep.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"./IInterep.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@appliedzkp/semaphore-contracts/interfaces/IVerifier.sol\";\nimport \"@appliedzkp/semaphore-contracts/base/SemaphoreCore.sol\";\nimport \"@appliedzkp/semaphore-contracts/base/SemaphoreConstants.sol\";\n\n/// @title Interep\n/// @dev Interep is a collection of reputation Semaphore groups in which members\n/// can prove their Web2 reputation (or their membership in a group) without revealing their identity.\n/// Each Interep group is actually a Merkle tree, whose leaves represent the members of the group.\n/// Interep groups are saved off-chain but the Merkle tree roots of those groups are saved on-chain\n/// at regular intervals, so that users can verify their Semaphore ZK proof on-chain with this contract.\ncontract Interep is IInterep, Ownable, SemaphoreCore {\n /// @dev Gets a tree depth and returns its verifier address.\n mapping(uint8 => IVerifier) public verifiers;\n\n /// @dev Gets a group id and returns the group data.\n mapping(uint256 => Group) public groups;\n\n /// @dev Checks if there is a verifier for the given tree depth.\n /// @param depth: Depth of the tree.\n modifier onlySupportedDepth(uint8 depth) {\n require(address(verifiers[depth]) != address(0), \"Interep: tree depth is not supported\");\n _;\n }\n\n /// @dev Initializes the Semaphore verifiers used to verify the user's ZK proofs.\n /// @param _verifiers: List of Semaphore verifiers (address and related Merkle tree depth).\n constructor(Verifier[] memory _verifiers) {\n for (uint8 i = 0; i < _verifiers.length; i++) {\n verifiers[_verifiers[i].merkleTreeDepth] = IVerifier(_verifiers[i].contractAddress);\n }\n }\n\n /// @dev See {IInterep-updateGroups}.\n function updateGroups(Group[] calldata _groups) external override onlyOwner {\n for (uint8 i = 0; i < _groups.length; i++) {\n uint256 groupId = uint256(keccak256(abi.encodePacked(_groups[i].provider, _groups[i].name))) %\n SNARK_SCALAR_FIELD;\n\n _updateGroup(groupId, _groups[i]);\n }\n }\n\n /// @dev See {IInterep-verifyProof}.\n function verifyProof(\n uint256 groupId,\n bytes32 signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof\n ) external override {\n uint256 root = getRoot(groupId);\n uint8 depth = getDepth(groupId);\n\n require(depth != 0, \"Interep: group does not exist\");\n\n IVerifier verifier = verifiers[depth];\n\n _verifyProof(signal, root, nullifierHash, externalNullifier, proof, verifier);\n\n _saveNullifierHash(nullifierHash);\n\n emit ProofVerified(groupId, signal);\n }\n\n /// @dev See {IInterep-getRoot}.\n function getRoot(uint256 groupId) public view override returns (uint256) {\n return groups[groupId].root;\n }\n\n /// @dev See {IInterep-getDepth}.\n function getDepth(uint256 groupId) public view override returns (uint8) {\n return groups[groupId].depth;\n }\n\n /// @dev Updates an Interep group.\n /// @param groupId: Id of the group.\n /// @param group: Group data.\n function _updateGroup(uint256 groupId, Group calldata group) private onlySupportedDepth(group.depth) {\n groups[groupId] = group;\n\n emit GroupUpdated(groupId, group.provider, group.name, group.root, group.depth);\n }\n}\n"
},
"@openzeppelin/contracts/access/Ownable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n"
},
"@openzeppelin/contracts/utils/Context.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n"
},
"contracts/PoseidonHasher.sol": {
"content": "pragma solidity 0.8.15;\n\ninterface IPoseidonHasher {\n\tfunction hash(uint256 input) external pure returns (uint256 result);\n\n\tfunction identity() external pure returns (uint256);\n}\n\ncontract PoseidonHasher is IPoseidonHasher {\n\tuint256 constant Q = 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n\tuint256 constant C0 = 4417881134626180770308697923359573201005643519861877412381846989312604493735;\n\tuint256 constant C1 = 5433650512959517612316327474713065966758808864213826738576266661723522780033;\n\tuint256 constant C2 = 13641176377184356099764086973022553863760045607496549923679278773208775739952;\n\tuint256 constant C3 = 17949713444224994136330421782109149544629237834775211751417461773584374506783;\n\tuint256 constant C4 = 13765628375339178273710281891027109699578766420463125835325926111705201856003;\n\tuint256 constant C5 = 19179513468172002314585757290678967643352171735526887944518845346318719730387;\n\tuint256 constant C6 = 5157412437176756884543472904098424903141745259452875378101256928559722612176;\n\tuint256 constant C7 = 535160875740282236955320458485730000677124519901643397458212725410971557409;\n\tuint256 constant C8 = 1050793453380762984940163090920066886770841063557081906093018330633089036729;\n\tuint256 constant C9 = 10665495010329663932664894101216428400933984666065399374198502106997623173873;\n\tuint256 constant C10 = 19965634623406616956648724894636666805991993496469370618546874926025059150737;\n\tuint256 constant C11 = 13007250030070838431593222885902415182312449212965120303174723305710127422213;\n\tuint256 constant C12 = 16877538715074991604507979123743768693428157847423939051086744213162455276374;\n\tuint256 constant C13 = 18211747749504876135588847560312685184956239426147543810126553367063157141465;\n\tuint256 constant C14 = 18151553319826126919739798892854572062191241985315767086020821632812331245635;\n\tuint256 constant C15 = 19957033149976712666746140949846950406660099037474791840946955175819555930825;\n\tuint256 constant C16 = 3469514863538261843186854830917934449567467100548474599735384052339577040841;\n\tuint256 constant C17 = 989698510043911779243192466312362856042600749099921773896924315611668507708;\n\tuint256 constant C18 = 12568377015646290945235387813564567111330046038050864455358059568128000172201;\n\tuint256 constant C19 = 20856104135605479600325529349246932565148587186338606236677138505306779314172;\n\tuint256 constant C20 = 8206918720503535523121349917159924938835810381723474192155637697065780938424;\n\tuint256 constant C21 = 1309058477013932989380617265069188723120054926187607548493110334522527703566;\n\tuint256 constant C22 = 14076116939332667074621703729512195584105250395163383769419390236426287710606;\n\tuint256 constant C23 = 10153498892749751942204288991871286290442690932856658983589258153608012428674;\n\tuint256 constant C24 = 18202499207234128286137597834010475797175973146805180988367589376893530181575;\n\tuint256 constant C25 = 12739388830157083522877690211447248168864006284243907142044329113461613743052;\n\tuint256 constant C26 = 15123358710467780770838026754240340042441262572309759635224051333176022613949;\n\tuint256 constant C27 = 19925004701844594370904593774447343836015483888496504201331110250494635362184;\n\tuint256 constant C28 = 10352416606816998476681131583320899030072315953910679608943150613208329645891;\n\tuint256 constant C29 = 10567371822366244361703342347428230537114808440249611395507235283708966113221;\n\tuint256 constant C30 = 5635498582763880627392290206431559361272660937399944184533035305989295959602;\n\tuint256 constant C31 = 11866432933224219174041051738704352719163271639958083608224676028593315904909;\n\tuint256 constant C32 = 5795020705294401441272215064554385591292330721703923167136157291459784140431;\n\tuint256 constant C33 = 9482202378699252817564375087302794636287866584767523335624368774856230692758;\n\tuint256 constant C34 = 4245237636894546151746468406560945873445548423466753843402086544922216329298;\n\tuint256 constant C35 = 1200050094131398275758471267799173001912483439947931
},
"contracts/Rln.sol": {
2022-12-02 15:25:17 +05:30
"content": "pragma solidity 0.8.15;\n\nimport {IPoseidonHasher} from \"./PoseidonHasher.sol\";\nimport {IValidGroupStorage} from \"./ValidGroupStorage.sol\";\nimport {IInterep} from \"@interep/contracts/IInterep.sol\";\n\ncontract RLN {\n uint256 public immutable MEMBERSHIP_DEPOSIT;\n uint256 public immutable DEPTH;\n uint256 public immutable SET_SIZE;\n\n uint256 public pubkeyIndex = 0;\n mapping(uint256 => uint256) public members;\n\n IPoseidonHasher public poseidonHasher;\n IValidGroupStorage public validGroupStorage;\n IInterep public interep;\n\n event MemberRegistered(uint256 pubkey, uint256 index);\n event MemberWithdrawn(uint256 pubkey, uint256 index);\n\n constructor(\n uint256 membershipDeposit,\n uint256 depth,\n address _poseidonHasher,\n address _validGroupStorage\n ) {\n MEMBERSHIP_DEPOSIT = membershipDeposit;\n DEPTH = depth;\n SET_SIZE = 1 << depth;\n poseidonHasher = IPoseidonHasher(_poseidonHasher);\n validGroupStorage = IValidGroupStorage(_validGroupStorage);\n interep = IInterep(validGroupStorage.interep());\n }\n\n function register(uint256 pubkey) external payable {\n require(pubkeyIndex < SET_SIZE, \"RLN, register: set is full\");\n require(\n msg.value == MEMBERSHIP_DEPOSIT,\n \"RLN, register: membership deposit is not satisfied\"\n );\n _register(pubkey);\n }\n\n function register(\n uint256 groupId,\n string calldata signal,\n uint256 nullifierHash,\n uint256 externalNullifier,\n uint256[8] calldata proof,\n uint256 pubkey\n ) external {\n require(\n validGroupStorage.isValidGroup(groupId),\n \"RLN, register: invalid interep group\"\n );\n require(pubkeyIndex < SET_SIZE, \"RLN, register: set is full\");\n // TODO: verify proof\n _register(pubkey);\n }\n\n function registerBatch(uint256[] calldata pubkeys) external payable {\n uint256 pubkeylen = pubkeys.length;\n require(\n pubkeyIndex + pubkeylen <= SET_SIZE,\n \"RLN, registerBatch: set is full\"\n );\n require(\n msg.value == MEMBERSHIP_DEPOSIT * pubkeylen,\n \"RLN, registerBatch: membership deposit is not satisfied\"\n );\n for (uint256 i = 0; i < pubkeylen; i++) {\n _register(pubkeys[i]);\n }\n }\n\n function _register(uint256 pubkey) internal {\n members[pubkeyIndex] = pubkey;\n emit MemberRegistered(pubkey, pubkeyIndex);\n pubkeyIndex += 1;\n }\n\n function withdrawBatch(\n uint256[] calldata secrets,\n uint256[] calldata pubkeyIndexes,\n address payable[] calldata receivers\n ) external {\n uint256 batchSize = secrets.length;\n require(batchSize != 0, \"RLN, withdrawBatch: batch size zero\");\n require(\n batchSize == pubkeyIndexes.length,\n \"RLN, withdrawBatch: batch size mismatch pubkey indexes\"\n );\n require(\n batchSize == receivers.length,\n \"RLN, withdrawBatch: batch size mismatch receivers\"\n );\n for (uint256 i = 0; i < batchSize; i++) {\n _withdraw(secrets[i], pubkeyIndexes[i], receivers[i]);\n }\n }\n\n function withdraw(\n uint256 secret,\n uint256 _pubkeyIndex,\n address payable receiver\n ) external {\n _withdraw(secret, _pubkeyIndex, receiver);\n }\n\n function _withdraw(\n uint256 secret,\n uint256 _pubkeyIndex,\n address payable receiver\n ) internal {\n require(\n _pubkeyIndex < SET_SIZE,\n \"RLN, _withdraw: invalid pubkey index\"\n );\n require(\n members[_pubkeyIndex] != 0,\n \"RLN, _withdraw: member doesn't exist\"\n );\n require(\n receiver != address(0),\n \"RLN, _withdraw: empty receiver address\"\n
2022-11-25 12:07:06 +05:30
},
"contracts/ValidGroupStorage.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"@interep/contracts/Interep.sol\";\n\ninterface IValidGroupStorage {\n function isValidGroup(uint256 groupId) external view returns (bool);\n\n function interep() external view returns (address);\n}\n\ncontract ValidGroupStorage {\n mapping(uint256 => bool) public validGroups;\n\n Interep public interep;\n\n struct Group {\n bytes32 provider;\n bytes32 name;\n }\n\n constructor(address _interep, Group[] memory _groups) {\n interep = Interep(_interep);\n for (uint8 i = 0; i < _groups.length; i++) {\n uint256 groupId = uint256(\n keccak256(\n abi.encodePacked(_groups[i].provider, _groups[i].name)\n )\n ) % SNARK_SCALAR_FIELD;\n (bytes32 provider, bytes32 name, , ) = interep.groups(groupId);\n if (provider == _groups[i].provider && name == _groups[i].name) {\n validGroups[groupId] = true;\n } else {\n revert(\"[ValidGroupStorage] Invalid group\");\n }\n }\n }\n\n function isValidGroup(uint256 _groupId) public view returns (bool) {\n return validGroups[_groupId];\n }\n}\n"
}
},
"settings": {
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata",
"devdoc",
"userdoc",
"storageLayout",
"evm.gasEstimates"
],
2022-12-02 15:25:17 +05:30
"": ["ast"]
2022-11-25 12:07:06 +05:30
}
},
"metadata": {
"useLiteralContent": true
}
}
2022-12-02 15:25:17 +05:30
}