mirror of
https://github.com/logos-messaging/OpChan.git
synced 2026-01-04 13:53:11 +00:00
149 lines
5.1 KiB
Solidity
149 lines
5.1 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
struct ProofVerificationParams {
|
|
bytes32 vkeyHash;
|
|
bytes proof;
|
|
bytes32[] publicInputs;
|
|
bytes committedInputs;
|
|
uint256[] committedInputCounts;
|
|
uint256 validityPeriodInSeconds;
|
|
string domain;
|
|
string scope;
|
|
bool devMode;
|
|
}
|
|
|
|
interface IZKPassportVerifier {
|
|
// Verify the proof
|
|
function verifyProof(ProofVerificationParams calldata params) external returns (bool verified, bytes32 uniqueIdentifier);
|
|
|
|
function verifyScopes(bytes32[] calldata publicInputs, string calldata domain, string calldata scope) external view returns (bool);
|
|
}
|
|
|
|
interface IZKVerifier {
|
|
function verifyProof(ProofVerificationParams calldata params) external returns (bool verified, bytes32 uniqueIdentifier);
|
|
}
|
|
|
|
/**
|
|
* @title ZKPassportVerifier
|
|
* @notice Simplified contract to store verification outputs for adult status, country, and gender
|
|
*/
|
|
contract ZKPassportVerifier {
|
|
// Structure to store user verification data
|
|
struct Verification {
|
|
bool initialized; // Whether the user has set their verification data
|
|
bool adult; // Whether user is 18+
|
|
string country; // User's country of nationality
|
|
string gender; // User's gender
|
|
}
|
|
|
|
// Mapping from user address to their verification data
|
|
mapping(address => Verification) public verifications;
|
|
|
|
// Mapping to track used unique identifiers per wallet
|
|
// This prevents cross-wallet correlation while maintaining Sybil resistance
|
|
mapping(address => mapping(bytes32 => bool)) public walletUniqueIdentifiers;
|
|
|
|
// Address of the ZKVerifier contract
|
|
IZKVerifier public zkVerifier;
|
|
|
|
/**
|
|
* @notice Constructor that sets the ZKVerifier contract address
|
|
* @param _zkVerifier Address of the ZKVerifier contract
|
|
*/
|
|
constructor(address _zkVerifier) {
|
|
require(_zkVerifier != address(0), "Invalid ZKVerifier address");
|
|
zkVerifier = IZKVerifier(_zkVerifier);
|
|
}
|
|
|
|
// Event emitted when verification data is updated
|
|
event VerificationUpdated(
|
|
address indexed user,
|
|
bool adult,
|
|
string country,
|
|
string gender
|
|
);
|
|
|
|
/**
|
|
* @notice Update verification data for the sender
|
|
* @param adult Whether the sender is 18+
|
|
* @param country The sender's country of nationality
|
|
* @param gender The sender's gender
|
|
* @param params Proof verification parameters
|
|
*/
|
|
function setVerification(
|
|
bool adult,
|
|
string calldata country,
|
|
string calldata gender,
|
|
ProofVerificationParams calldata params
|
|
) external {
|
|
// Verify the proof first using the ZKVerifier contract
|
|
(bool verified, bytes32 uniqueIdentifier) = zkVerifier.verifyProof(params);
|
|
|
|
// Revert if proof is not valid
|
|
require(verified, "Proof verification failed");
|
|
|
|
// Always enforce wallet-scoped uniqueness
|
|
require(!walletUniqueIdentifiers[msg.sender][uniqueIdentifier], "Unique identifier already used by this wallet");
|
|
|
|
// Mark this unique identifier as used by this wallet
|
|
walletUniqueIdentifiers[msg.sender][uniqueIdentifier] = true;
|
|
|
|
// Store the verification data
|
|
verifications[msg.sender] = Verification({
|
|
initialized: true,
|
|
adult: adult,
|
|
country: country,
|
|
gender: gender
|
|
});
|
|
|
|
emit VerificationUpdated(msg.sender, adult, country, gender);
|
|
}
|
|
|
|
/**
|
|
* @notice Update verification data without requiring a new proof
|
|
* @param adult Whether the sender is 18+
|
|
* @param country The sender's country of nationality
|
|
* @param gender The sender's gender
|
|
*/
|
|
function updateVerification(
|
|
bool adult,
|
|
string calldata country,
|
|
string calldata gender,
|
|
ProofVerificationParams calldata params
|
|
) external {
|
|
// Verify the proof first using the ZKVerifier contract
|
|
(bool verified, bytes32 uniqueIdentifier) = zkVerifier.verifyProof(params);
|
|
|
|
// Revert if proof is not valid
|
|
require(verified, "Proof verification failed");
|
|
|
|
// Always enforce wallet-scoped uniqueness
|
|
require(walletUniqueIdentifiers[msg.sender][uniqueIdentifier], "Unique identifier already used by this wallet");
|
|
|
|
// Update the verification data
|
|
verifications[msg.sender] = Verification({
|
|
initialized: true,
|
|
adult: adult,
|
|
country: country,
|
|
gender: gender
|
|
});
|
|
|
|
emit VerificationUpdated(msg.sender, adult, country, gender);
|
|
}
|
|
|
|
/**
|
|
* @notice Get verification data for a user
|
|
* @param user The address of the user
|
|
* @return adult Whether the user is 18+
|
|
* @return country The user's country of nationality
|
|
* @return gender The user's gender
|
|
*/
|
|
function getVerification(address user)
|
|
external view
|
|
returns (bool, bool, string memory, string memory)
|
|
{
|
|
Verification storage verification = verifications[user];
|
|
return (verification.initialized, verification.adult, verification.country, verification.gender);
|
|
}
|
|
} |