mirror of
https://github.com/selfxyz/self.git
synced 2026-01-09 14:48:06 -05:00
add example contract how to integrate self verifier (#198)
This commit is contained in:
@@ -1,161 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.28;
|
||||
|
||||
import {IIdentityVerificationHubV1} from "../interfaces/IIdentityVerificationHubV1.sol";
|
||||
import {IVcAndDiscloseCircuitVerifier} from "../interfaces/IVcAndDiscloseCircuitVerifier.sol";
|
||||
import {IIdentityRegistryV1} from "../interfaces/IIdentityRegistryV1.sol";
|
||||
import {CircuitConstants} from "../constants/CircuitConstants.sol";
|
||||
import {IPassportAirdropRoot} from "../interfaces/IPassportAirdropRoot.sol";
|
||||
|
||||
/**
|
||||
* @title PassportAirdropRoot
|
||||
* @notice Abstract contract to manage passport airdrop functionality, including registration with vc and disclose proof.
|
||||
* @dev Provides the core registration logic and verification of proofs. Inherits from IPassportAirdropRoot.
|
||||
*/
|
||||
abstract contract PassportAirdropRoot is
|
||||
IPassportAirdropRoot
|
||||
{
|
||||
|
||||
// ====================================================
|
||||
// Storage Variables
|
||||
// ====================================================
|
||||
|
||||
/// @notice Expected scope for the proof verification.
|
||||
uint256 internal immutable _scope;
|
||||
/// @notice Expected attestation identifier for the identity behind the proof.
|
||||
uint256 internal immutable _attestationId;
|
||||
/// @notice Target root timestamp used for additional verification.
|
||||
uint256 internal immutable _targetRootTimestamp;
|
||||
|
||||
/// @notice Verification configuration settings.
|
||||
IPassportAirdropRoot.VerificationConfig internal _verificationConfig;
|
||||
|
||||
/// @notice Instance of the Identity Verification Hub.
|
||||
IIdentityVerificationHubV1 internal immutable _identityVerificationHub;
|
||||
/// @notice Instance of the Identity Registry.
|
||||
IIdentityRegistryV1 internal immutable _identityRegistry;
|
||||
|
||||
/// @notice Mapping recording used nullifiers to prevent double registration.
|
||||
mapping(uint256 => uint256) internal _nullifiers;
|
||||
/// @notice Mapping tracking registered user identifiers.
|
||||
mapping(uint256 => bool) internal _registeredUserIdentifiers;
|
||||
|
||||
// ====================================================
|
||||
// Events
|
||||
// ====================================================
|
||||
|
||||
/**
|
||||
* @notice Emitted when a new user identifier is successfully registered.
|
||||
* @param registeredUserIdentifier The user identifier that has been registered.
|
||||
* @param nullifier The nullifier associated with the registered commitment.
|
||||
*/
|
||||
event UserIdentifierRegistered(uint256 indexed registeredUserIdentifier, uint256 indexed nullifier);
|
||||
|
||||
// ====================================================
|
||||
// Errors
|
||||
// ====================================================
|
||||
|
||||
/// @dev Reverts if the provided nullifier has already been registered.
|
||||
error RegisteredNullifier();
|
||||
/// @dev Reverts if the attestation identifier in the proof is invalid.
|
||||
error InvalidAttestationId();
|
||||
/// @dev Reverts if the proof scope does not match the expected scope.
|
||||
error InvalidScope();
|
||||
/// @dev Reverts if the identity root timestamp is not valid.
|
||||
error InvalidTimestamp();
|
||||
/// @dev Reverts if the user identifier is not valid.
|
||||
error InvalidUserIdentifier();
|
||||
|
||||
/**
|
||||
* @notice Initializes the PassportAirdropRoot contract.
|
||||
* @dev Sets up the identity verification hub, identity registry, expected scope, attestation, and timestamp along with verification configuration.
|
||||
* @param identityVerificationHub The address of the Identity Verification Hub.
|
||||
* @param identityRegistry The address of the Identity Registry.
|
||||
* @param scope The expected proof scope.
|
||||
* @param attestationId The expected attestation identifier.
|
||||
* @param targetRootTimestamp The target timestamp for root verification (set to 0 to disable).
|
||||
* @param olderThanEnabled Flag indicating if the 'olderThan' attribute should be verified.
|
||||
* @param olderThan Value to compare against for 'olderThan' verification.
|
||||
* @param forbiddenCountriesEnabled Flag indicating if forbidden countries verification is enabled.
|
||||
* @param forbiddenCountriesListPacked Packed list of forbidden countries.
|
||||
* @param ofacEnabled Array of flags indicating if each OFAC verification is enabled.
|
||||
*/
|
||||
constructor(
|
||||
address identityVerificationHub,
|
||||
address identityRegistry,
|
||||
uint256 scope,
|
||||
uint256 attestationId,
|
||||
uint256 targetRootTimestamp,
|
||||
bool olderThanEnabled,
|
||||
uint256 olderThan,
|
||||
bool forbiddenCountriesEnabled,
|
||||
uint256[4] memory forbiddenCountriesListPacked,
|
||||
bool[3] memory ofacEnabled
|
||||
) {
|
||||
_identityVerificationHub = IIdentityVerificationHubV1(identityVerificationHub);
|
||||
_identityRegistry = IIdentityRegistryV1(identityRegistry);
|
||||
_scope = scope;
|
||||
_attestationId = attestationId;
|
||||
_targetRootTimestamp = targetRootTimestamp;
|
||||
_verificationConfig.olderThanEnabled = olderThanEnabled;
|
||||
_verificationConfig.olderThan = olderThan;
|
||||
_verificationConfig.forbiddenCountriesEnabled = forbiddenCountriesEnabled;
|
||||
_verificationConfig.forbiddenCountriesListPacked = forbiddenCountriesListPacked;
|
||||
_verificationConfig.ofacEnabled = ofacEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Internal function to register a user address based on a valid VC and Disclose proof.
|
||||
* @dev Verifies the proof against the expected scope, attestation identifier, and, if applicable,
|
||||
* ensures the identity commitment root was generated at the target timestamp. Records
|
||||
* the nullifier and marks the corresponding user identifier as registered.
|
||||
* @param proof The VC and Disclose proof containing public signals and proof data.
|
||||
* @return userIdentifier The user identifier extracted from the proof.
|
||||
*/
|
||||
function _registerAddress(
|
||||
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory proof
|
||||
)
|
||||
internal
|
||||
returns (uint256 userIdentifier)
|
||||
{
|
||||
if (_scope != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_SCOPE_INDEX]) {
|
||||
revert InvalidScope();
|
||||
}
|
||||
|
||||
if (_nullifiers[proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_NULLIFIER_INDEX]] != 0) {
|
||||
revert RegisteredNullifier();
|
||||
}
|
||||
|
||||
if (_attestationId != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_ATTESTATION_ID_INDEX]) {
|
||||
revert InvalidAttestationId();
|
||||
}
|
||||
|
||||
if (proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX] == 0) {
|
||||
revert InvalidUserIdentifier();
|
||||
}
|
||||
|
||||
IIdentityVerificationHubV1.VcAndDiscloseVerificationResult memory result = _identityVerificationHub.verifyVcAndDisclose(
|
||||
IIdentityVerificationHubV1.VcAndDiscloseHubProof({
|
||||
olderThanEnabled: _verificationConfig.olderThanEnabled,
|
||||
olderThan: _verificationConfig.olderThan,
|
||||
forbiddenCountriesEnabled: _verificationConfig.forbiddenCountriesEnabled,
|
||||
forbiddenCountriesListPacked: _verificationConfig.forbiddenCountriesListPacked,
|
||||
ofacEnabled: _verificationConfig.ofacEnabled,
|
||||
vcAndDiscloseProof: proof
|
||||
})
|
||||
);
|
||||
|
||||
if (_targetRootTimestamp != 0) {
|
||||
if (_identityRegistry.rootTimestamps(result.identityCommitmentRoot) != _targetRootTimestamp) {
|
||||
revert InvalidTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
_nullifiers[result.nullifier] = proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX];
|
||||
_registeredUserIdentifiers[proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX]] = true;
|
||||
|
||||
emit UserIdentifierRegistered(proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX], result.nullifier);
|
||||
|
||||
return proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX];
|
||||
}
|
||||
}
|
||||
110
contracts/contracts/abstract/SelfVerificationRoot.sol
Normal file
110
contracts/contracts/abstract/SelfVerificationRoot.sol
Normal file
@@ -0,0 +1,110 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.28;
|
||||
|
||||
import {IVcAndDiscloseCircuitVerifier} from "../interfaces/IVcAndDiscloseCircuitVerifier.sol";
|
||||
import {IIdentityVerificationHubV1} from "../interfaces/IIdentityVerificationHubV1.sol";
|
||||
import {ISelfVerificationRoot} from "../interfaces/ISelfVerificationRoot.sol";
|
||||
import {CircuitConstants} from "../constants/CircuitConstants.sol";
|
||||
|
||||
/**
|
||||
* @title SelfVerificationRoot
|
||||
* @notice Abstract base contract to be integrated with self's verification infrastructure
|
||||
* @dev Provides base functionality for verifying and disclosing identity credentials
|
||||
*/
|
||||
abstract contract SelfVerificationRoot is ISelfVerificationRoot {
|
||||
|
||||
// ====================================================
|
||||
// Storage Variables
|
||||
// ====================================================
|
||||
|
||||
/// @notice The scope value that proofs must match
|
||||
/// @dev Used to validate that submitted proofs match the expected scope
|
||||
uint256 internal _scope;
|
||||
|
||||
/// @notice The attestation ID that proofs must match
|
||||
/// @dev Used to validate that submitted proofs contain the correct attestation
|
||||
uint256 internal _attestationId;
|
||||
|
||||
/// @notice Configuration settings for the verification process
|
||||
/// @dev Contains settings for age verification, country restrictions, and OFAC checks
|
||||
ISelfVerificationRoot.VerificationConfig internal _verificationConfig;
|
||||
|
||||
/// @notice Reference to the identity verification hub contract
|
||||
/// @dev Immutable reference used for proof verification
|
||||
IIdentityVerificationHubV1 internal immutable _identityVerificationHub;
|
||||
|
||||
// ====================================================
|
||||
// Errors
|
||||
// ====================================================
|
||||
|
||||
/// @notice Error thrown when the proof's scope doesn't match the expected scope
|
||||
/// @dev Triggered in verifySelfProof when scope validation fails
|
||||
error InvalidScope();
|
||||
|
||||
/// @notice Error thrown when the proof's attestation ID doesn't match the expected ID
|
||||
/// @dev Triggered in verifySelfProof when attestation ID validation fails
|
||||
error InvalidAttestationId();
|
||||
|
||||
/**
|
||||
* @notice Initializes the SelfVerificationRoot contract.
|
||||
* @param identityVerificationHub The address of the Identity Verification Hub.
|
||||
* @param scope The expected proof scope for user registration.
|
||||
* @param attestationId The expected attestation identifier required in proofs.
|
||||
* @param olderThanEnabled Flag indicating if 'olderThan' verification is enabled.
|
||||
* @param olderThan Value for 'olderThan' verification.
|
||||
* @param forbiddenCountriesEnabled Flag indicating if forbidden countries verification is enabled.
|
||||
* @param forbiddenCountriesListPacked Packed list of forbidden countries.
|
||||
* @param ofacEnabled Array of flags indicating which OFAC checks are enabled. [passportNo, nameAndDob, nameAndYob]
|
||||
*/
|
||||
constructor(
|
||||
address identityVerificationHub,
|
||||
uint256 scope,
|
||||
uint256 attestationId,
|
||||
bool olderThanEnabled,
|
||||
uint256 olderThan,
|
||||
bool forbiddenCountriesEnabled,
|
||||
uint256[4] memory forbiddenCountriesListPacked,
|
||||
bool[3] memory ofacEnabled
|
||||
) {
|
||||
_identityVerificationHub = IIdentityVerificationHubV1(identityVerificationHub);
|
||||
_scope = scope;
|
||||
_attestationId = attestationId;
|
||||
_verificationConfig.olderThanEnabled = olderThanEnabled;
|
||||
_verificationConfig.olderThan = olderThan;
|
||||
_verificationConfig.forbiddenCountriesEnabled = forbiddenCountriesEnabled;
|
||||
_verificationConfig.forbiddenCountriesListPacked = forbiddenCountriesListPacked;
|
||||
_verificationConfig.ofacEnabled = ofacEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Verifies a self-proof
|
||||
* @dev Validates scope and attestation ID before performing verification through the identity hub
|
||||
* @param proof The proof data for verification and disclosure
|
||||
*/
|
||||
function verifySelfProof(
|
||||
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory proof
|
||||
)
|
||||
public
|
||||
virtual
|
||||
{
|
||||
if (_scope != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_SCOPE_INDEX]) {
|
||||
revert InvalidScope();
|
||||
}
|
||||
|
||||
if (_attestationId != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_ATTESTATION_ID_INDEX]) {
|
||||
revert InvalidAttestationId();
|
||||
}
|
||||
|
||||
_identityVerificationHub.verifyVcAndDisclose(
|
||||
IIdentityVerificationHubV1.VcAndDiscloseHubProof({
|
||||
olderThanEnabled: _verificationConfig.olderThanEnabled,
|
||||
olderThan: _verificationConfig.olderThan,
|
||||
forbiddenCountriesEnabled: _verificationConfig.forbiddenCountriesEnabled,
|
||||
forbiddenCountriesListPacked: _verificationConfig.forbiddenCountriesListPacked,
|
||||
ofacEnabled: _verificationConfig.ofacEnabled,
|
||||
vcAndDiscloseProof: proof
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,11 +3,12 @@ pragma solidity 0.8.28;
|
||||
|
||||
import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
|
||||
import {PassportAirdropRoot} from "../abstract/PassportAirdropRoot.sol";
|
||||
import {IPassportAirdropRoot} from "../interfaces/IPassportAirdropRoot.sol";
|
||||
import {SelfVerificationRoot} from "../abstract/SelfVerificationRoot.sol";
|
||||
import {ISelfVerificationRoot} from "../interfaces/ISelfVerificationRoot.sol";
|
||||
import {IIdentityVerificationHubV1} from "../interfaces/IIdentityVerificationHubV1.sol";
|
||||
import {IVcAndDiscloseCircuitVerifier} from "../interfaces/IVcAndDiscloseCircuitVerifier.sol";
|
||||
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import {CircuitConstants} from "../constants/CircuitConstants.sol";
|
||||
|
||||
/**
|
||||
* @title Airdrop (Experimental)
|
||||
@@ -16,7 +17,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
||||
* **WARNING:** This contract has not been audited and is NOT intended for production use.
|
||||
* @dev Inherits from PassportAirdropRoot for registration logic and Ownable for administrative control.
|
||||
*/
|
||||
contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
contract Airdrop is SelfVerificationRoot, Ownable {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
// ====================================================
|
||||
@@ -34,6 +35,9 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
/// @notice Indicates whether the claim phase is active.
|
||||
bool public isClaimOpen;
|
||||
|
||||
mapping(uint256 => uint256) internal _nullifiers;
|
||||
mapping(uint256 => bool) internal _registeredUserIdentifiers;
|
||||
|
||||
// ====================================================
|
||||
// Errors
|
||||
// ====================================================
|
||||
@@ -51,6 +55,9 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
/// @notice Reverts when a claim is attempted while claiming is not enabled.
|
||||
error ClaimNotOpen();
|
||||
|
||||
error RegisteredNullifier();
|
||||
error InvalidUserIdentifier();
|
||||
|
||||
// ====================================================
|
||||
// Events
|
||||
// ====================================================
|
||||
@@ -69,6 +76,8 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
/// @notice Emitted when the claim phase is closed.
|
||||
event ClaimClose();
|
||||
|
||||
event UserIdentifierRegistered(uint256 indexed registeredUserIdentifier, uint256 indexed nullifier);
|
||||
|
||||
// ====================================================
|
||||
// Constructor
|
||||
// ====================================================
|
||||
@@ -78,11 +87,9 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
* @dev Initializes the airdrop parameters, zero-knowledge verification configuration,
|
||||
* and sets the ERC20 token to be distributed.
|
||||
* @param _identityVerificationHub The address of the Identity Verification Hub.
|
||||
* @param _identityRegistry The address of the Identity Registry.
|
||||
* @param _scope The expected proof scope for user registration.
|
||||
* @param _attestationId The expected attestation identifier required in proofs.
|
||||
* @param _token The address of the ERC20 token for airdrop.
|
||||
* @param _targetRootTimestamp The target root timestamp for additional verification (0 to disable).
|
||||
* @param _olderThanEnabled Flag indicating if 'olderThan' verification is enabled.
|
||||
* @param _olderThan Value for 'olderThan' verification.
|
||||
* @param _forbiddenCountriesEnabled Flag indicating if forbidden countries verification is enabled.
|
||||
@@ -91,23 +98,19 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
*/
|
||||
constructor(
|
||||
address _identityVerificationHub,
|
||||
address _identityRegistry,
|
||||
uint256 _scope,
|
||||
uint256 _attestationId,
|
||||
address _token,
|
||||
uint256 _targetRootTimestamp,
|
||||
bool _olderThanEnabled,
|
||||
uint256 _olderThan,
|
||||
bool _forbiddenCountriesEnabled,
|
||||
uint256[4] memory _forbiddenCountriesListPacked,
|
||||
bool[3] memory _ofacEnabled
|
||||
)
|
||||
PassportAirdropRoot(
|
||||
SelfVerificationRoot(
|
||||
_identityVerificationHub,
|
||||
_identityRegistry,
|
||||
_scope,
|
||||
_attestationId,
|
||||
_targetRootTimestamp,
|
||||
_olderThanEnabled,
|
||||
_olderThan,
|
||||
_forbiddenCountriesEnabled,
|
||||
@@ -138,7 +141,7 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
* @param newVerificationConfig The new verification configuration.
|
||||
*/
|
||||
function setVerificationConfig(
|
||||
IPassportAirdropRoot.VerificationConfig memory newVerificationConfig
|
||||
ISelfVerificationRoot.VerificationConfig memory newVerificationConfig
|
||||
) external onlyOwner {
|
||||
_verificationConfig = newVerificationConfig;
|
||||
}
|
||||
@@ -184,13 +187,48 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
* @dev Reverts if the registration phase is not open.
|
||||
* @param proof The VC and Disclose proof data used to verify and register the user.
|
||||
*/
|
||||
function registerAddress(
|
||||
function verifySelfProof(
|
||||
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory proof
|
||||
) external {
|
||||
)
|
||||
public
|
||||
override
|
||||
{
|
||||
|
||||
if (!isRegistrationOpen) {
|
||||
revert RegistrationNotOpen();
|
||||
}
|
||||
_registerAddress(proof);
|
||||
|
||||
if (_scope != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_SCOPE_INDEX]) {
|
||||
revert InvalidScope();
|
||||
}
|
||||
|
||||
if (_attestationId != proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_ATTESTATION_ID_INDEX]) {
|
||||
revert InvalidAttestationId();
|
||||
}
|
||||
|
||||
if (_nullifiers[proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_NULLIFIER_INDEX]] != 0) {
|
||||
revert RegisteredNullifier();
|
||||
}
|
||||
|
||||
if (proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX] == 0) {
|
||||
revert InvalidUserIdentifier();
|
||||
}
|
||||
|
||||
IIdentityVerificationHubV1.VcAndDiscloseVerificationResult memory result = _identityVerificationHub.verifyVcAndDisclose(
|
||||
IIdentityVerificationHubV1.VcAndDiscloseHubProof({
|
||||
olderThanEnabled: _verificationConfig.olderThanEnabled,
|
||||
olderThan: _verificationConfig.olderThan,
|
||||
forbiddenCountriesEnabled: _verificationConfig.forbiddenCountriesEnabled,
|
||||
forbiddenCountriesListPacked: _verificationConfig.forbiddenCountriesListPacked,
|
||||
ofacEnabled: _verificationConfig.ofacEnabled,
|
||||
vcAndDiscloseProof: proof
|
||||
})
|
||||
);
|
||||
|
||||
_nullifiers[result.nullifier] = proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX];
|
||||
_registeredUserIdentifiers[proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX]] = true;
|
||||
|
||||
emit UserIdentifierRegistered(proof.pubSignals[CircuitConstants.VC_AND_DISCLOSE_USER_IDENTIFIER_INDEX], result.nullifier);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +260,7 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
* @notice Retrieves the current verification configuration.
|
||||
* @return The verification configuration used for registration.
|
||||
*/
|
||||
function getVerificationConfig() external view returns (IPassportAirdropRoot.VerificationConfig memory) {
|
||||
function getVerificationConfig() external view returns (ISelfVerificationRoot.VerificationConfig memory) {
|
||||
return _verificationConfig;
|
||||
}
|
||||
|
||||
@@ -266,7 +304,7 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
if (!MerkleProof.verify(merkleProof, merkleRoot, node)) revert InvalidProof();
|
||||
|
||||
// Mark as claimed and transfer tokens.
|
||||
_setClaimed(index);
|
||||
_setClaimed();
|
||||
IERC20(token).safeTransfer(msg.sender, amount);
|
||||
|
||||
emit Claimed(index, msg.sender, amount);
|
||||
@@ -279,9 +317,8 @@ contract Airdrop is PassportAirdropRoot, Ownable {
|
||||
/**
|
||||
* @notice Internal function to mark the caller as having claimed their tokens.
|
||||
* @dev Updates the claimed mapping.
|
||||
* @param index The index of the claim (unused in storage, provided for event consistency).
|
||||
*/
|
||||
function _setClaimed(uint256 index) internal {
|
||||
function _setClaimed() internal {
|
||||
claimed[msg.sender] = true;
|
||||
}
|
||||
}
|
||||
|
||||
20
contracts/contracts/interfaces/ISelfVerificationRoot.sol
Normal file
20
contracts/contracts/interfaces/ISelfVerificationRoot.sol
Normal file
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.28;
|
||||
|
||||
import {IVcAndDiscloseCircuitVerifier} from "./IVcAndDiscloseCircuitVerifier.sol";
|
||||
|
||||
interface ISelfVerificationRoot {
|
||||
|
||||
struct VerificationConfig {
|
||||
bool olderThanEnabled;
|
||||
uint256 olderThan;
|
||||
bool forbiddenCountriesEnabled;
|
||||
uint256[4] forbiddenCountriesListPacked;
|
||||
bool[3] ofacEnabled;
|
||||
}
|
||||
|
||||
function verifySelfProof(
|
||||
IVcAndDiscloseCircuitVerifier.VcAndDiscloseProof memory proof
|
||||
) external;
|
||||
|
||||
}
|
||||
@@ -68,18 +68,14 @@ describe("Airdrop", () => {
|
||||
commitment
|
||||
);
|
||||
|
||||
const root = await deployedActors.registry.getIdentityCommitmentMerkleRoot();
|
||||
const timestamp = await deployedActors.registry.rootTimestamps(root);
|
||||
countriesListPacked = splitHexFromBack(reverseBytes(Formatter.bytesToHexString(new Uint8Array(formatCountriesList(forbiddenCountriesList)))));
|
||||
|
||||
const airdropFactory = await ethers.getContractFactory("Airdrop");
|
||||
airdrop = await airdropFactory.connect(deployedActors.owner).deploy(
|
||||
deployedActors.hub.target,
|
||||
deployedActors.registry.target,
|
||||
castFromScope("test-airdrop"),
|
||||
ATTESTATION_ID.E_PASSPORT,
|
||||
token.target,
|
||||
timestamp,
|
||||
true,
|
||||
20,
|
||||
true,
|
||||
@@ -198,7 +194,7 @@ describe("Airdrop", () => {
|
||||
const { owner, user1 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
const tx = await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
|
||||
const tx = await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
|
||||
const receipt = await tx.wait();
|
||||
|
||||
const event = receipt?.logs.find(
|
||||
@@ -227,7 +223,7 @@ describe("Airdrop", () => {
|
||||
const { owner, user1 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).closeRegistration();
|
||||
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
|
||||
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
|
||||
.to.be.revertedWithCustomError(airdrop, "RegistrationNotOpen");
|
||||
});
|
||||
|
||||
@@ -246,7 +242,7 @@ describe("Airdrop", () => {
|
||||
);
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
|
||||
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
|
||||
.to.be.revertedWithCustomError(airdrop, "InvalidScope");
|
||||
});
|
||||
|
||||
@@ -254,8 +250,8 @@ describe("Airdrop", () => {
|
||||
const { owner, user1 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
|
||||
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
|
||||
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
|
||||
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
|
||||
.to.be.revertedWithCustomError(airdrop, "RegisteredNullifier");
|
||||
});
|
||||
|
||||
@@ -287,7 +283,7 @@ describe("Airdrop", () => {
|
||||
);
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
|
||||
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
|
||||
.to.be.revertedWithCustomError(airdrop, "InvalidAttestationId");
|
||||
});
|
||||
|
||||
@@ -310,58 +306,19 @@ describe("Airdrop", () => {
|
||||
);
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
|
||||
await expect(airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
|
||||
.to.be.revertedWithCustomError(airdrop, "InvalidUserIdentifier");
|
||||
});
|
||||
|
||||
it("should not able to register address when rootTimestamp is different", async () => {
|
||||
const {registry, owner, user1, mockPassport} = deployedActors;
|
||||
|
||||
const secondCommitment = generateCommitment(registerSecret, ATTESTATION_ID.INVALID_ATTESTATION_ID, mockPassport);
|
||||
await registry.devAddIdentityCommitment(
|
||||
ATTESTATION_ID.E_PASSPORT,
|
||||
nullifier,
|
||||
secondCommitment
|
||||
);
|
||||
|
||||
const hashFunction = (a: bigint, b: bigint) => poseidon2([a, b]);
|
||||
const invalidImt = new LeanIMT<bigint>(hashFunction);
|
||||
invalidImt.insert(BigInt(commitment));
|
||||
invalidImt.insert(BigInt(secondCommitment));
|
||||
|
||||
vcAndDiscloseProof = await generateVcAndDiscloseProof(
|
||||
registerSecret,
|
||||
BigInt(ATTESTATION_ID.E_PASSPORT).toString(),
|
||||
deployedActors.mockPassport,
|
||||
"test-airdrop",
|
||||
new Array(88).fill("1"),
|
||||
"1",
|
||||
invalidImt,
|
||||
"20",
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
forbiddenCountriesList,
|
||||
(await deployedActors.user1.getAddress()).slice(2)
|
||||
);
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await expect(airdrop.connect(user1).registerAddress(vcAndDiscloseProof))
|
||||
.to.be.revertedWithCustomError(airdrop, "InvalidTimestamp");
|
||||
});
|
||||
|
||||
it("should allow registration when targetRootTimestamp is 0", async () => {
|
||||
const { hub, registry, owner, user1 } = deployedActors;
|
||||
|
||||
const airdropFactory = await ethers.getContractFactory("Airdrop");
|
||||
const newAirdrop = await airdropFactory.connect(owner).deploy(
|
||||
hub.target,
|
||||
registry.target,
|
||||
castFromScope("test-airdrop"),
|
||||
ATTESTATION_ID.E_PASSPORT,
|
||||
token.target,
|
||||
0,
|
||||
true,
|
||||
20,
|
||||
true,
|
||||
@@ -371,34 +328,10 @@ describe("Airdrop", () => {
|
||||
await newAirdrop.waitForDeployment();
|
||||
|
||||
await newAirdrop.connect(owner).openRegistration();
|
||||
await expect(newAirdrop.connect(user1).registerAddress(vcAndDiscloseProof))
|
||||
await expect(newAirdrop.connect(user1).verifySelfProof(vcAndDiscloseProof))
|
||||
.to.not.be.reverted;
|
||||
});
|
||||
|
||||
it("should revert with InvalidTimestamp when root timestamp does not match", async () => {
|
||||
const { hub, registry, owner, user1 } = deployedActors;
|
||||
|
||||
const airdropFactory = await ethers.getContractFactory("Airdrop");
|
||||
const newAirdrop = await airdropFactory.connect(owner).deploy(
|
||||
hub.target,
|
||||
registry.target,
|
||||
castFromScope("test-airdrop"),
|
||||
ATTESTATION_ID.E_PASSPORT,
|
||||
token.target,
|
||||
123456789,
|
||||
true,
|
||||
20,
|
||||
true,
|
||||
countriesListPacked,
|
||||
[true, true, true],
|
||||
);
|
||||
await newAirdrop.waitForDeployment();
|
||||
|
||||
await newAirdrop.connect(owner).openRegistration();
|
||||
await expect(newAirdrop.connect(user1).registerAddress(vcAndDiscloseProof))
|
||||
.to.be.revertedWithCustomError(newAirdrop, "InvalidTimestamp");
|
||||
});
|
||||
|
||||
it("should return correct scope", async () => {
|
||||
const scope = await airdrop.getScope();
|
||||
expect(scope).to.equal(castFromScope("test-airdrop"));
|
||||
@@ -427,7 +360,7 @@ describe("Airdrop", () => {
|
||||
const { owner, user1 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
|
||||
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
|
||||
await airdrop.connect(owner).closeRegistration();
|
||||
|
||||
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
|
||||
@@ -464,7 +397,7 @@ describe("Airdrop", () => {
|
||||
const { owner, user1 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
|
||||
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
|
||||
|
||||
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
|
||||
const root = tree.getHexRoot();
|
||||
@@ -484,7 +417,7 @@ describe("Airdrop", () => {
|
||||
const { owner, user1 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
|
||||
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
|
||||
await airdrop.connect(owner).closeRegistration();
|
||||
|
||||
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
|
||||
@@ -504,7 +437,7 @@ describe("Airdrop", () => {
|
||||
const { owner, user1 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
|
||||
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
|
||||
await airdrop.connect(owner).closeRegistration();
|
||||
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
|
||||
const root = tree.getHexRoot();
|
||||
@@ -529,7 +462,7 @@ describe("Airdrop", () => {
|
||||
const { owner, user1 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
|
||||
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
|
||||
await airdrop.connect(owner).closeRegistration();
|
||||
const tree = new BalanceTree([{ account: await user1.getAddress(), amount: BigInt(1000000000000000000) }]);
|
||||
const root = tree.getHexRoot();
|
||||
@@ -550,7 +483,7 @@ describe("Airdrop", () => {
|
||||
const { owner, user1, user2 } = deployedActors;
|
||||
|
||||
await airdrop.connect(owner).openRegistration();
|
||||
await airdrop.connect(user1).registerAddress(vcAndDiscloseProof);
|
||||
await airdrop.connect(user1).verifySelfProof(vcAndDiscloseProof);
|
||||
await airdrop.connect(owner).closeRegistration();
|
||||
|
||||
const tree = new BalanceTree([
|
||||
|
||||
@@ -168,7 +168,6 @@ export async function generateVcAndDiscloseRawProof(
|
||||
forbiddenCountriesList,
|
||||
userIdentifier
|
||||
);
|
||||
console.log("forbiddenCountriesList: ", vcAndDiscloseCircuitInputs.forbidden_countries_list);
|
||||
|
||||
console.log(CYAN, "=== Start generateVcAndDiscloseRawProof ===", RESET);
|
||||
const startTime = performance.now();
|
||||
|
||||
2
sdk/tests/web-app/.env.sample
Normal file
2
sdk/tests/web-app/.env.sample
Normal file
@@ -0,0 +1,2 @@
|
||||
END_POINT=
|
||||
SCOPE=
|
||||
2
sdk/tests/web-app/.gitignore
vendored
2
sdk/tests/web-app/.gitignore
vendored
@@ -34,3 +34,5 @@ yarn-error.log*
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
.env
|
||||
Reference in New Issue
Block a user