Files
smom-dbis-138/contracts/compliance/IndyVerifier.sol
2026-03-02 12:14:09 -08:00

177 lines
5.1 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
/**
* @title IndyVerifier
* @notice Verifies Hyperledger Indy credentials before allowing bridge operations
* @dev Uses zero-knowledge proofs for privacy-preserving credential verification
*/
contract IndyVerifier is AccessControl {
bytes32 public constant VERIFIER_ROLE = keccak256("VERIFIER_ROLE");
bytes32 public constant ISSUER_ROLE = keccak256("ISSUER_ROLE");
enum CredentialType {
KYC,
AccreditedInvestor,
Institution,
Jurisdiction,
Compliance
}
struct CredentialSchema {
string schemaId; // Indy schema ID
string credDefId; // Credential definition ID
bool required;
CredentialType credType;
uint256 minScore; // Minimum verification score (0-100)
}
struct VerificationResult {
bool verified;
uint256 score;
uint256 verifiedAt;
string proofId;
}
mapping(address => mapping(CredentialType => VerificationResult)) public userCredentials;
mapping(CredentialType => CredentialSchema) public schemas;
mapping(string => bool) public verifiedProofs; // proofId => verified
event CredentialVerified(
address indexed user,
CredentialType credType,
uint256 score,
string proofId
);
event CredentialRevoked(
address indexed user,
CredentialType credType
);
event SchemaRegistered(
CredentialType credType,
string schemaId,
string credDefId
);
constructor(address admin) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(VERIFIER_ROLE, admin);
_grantRole(ISSUER_ROLE, admin);
}
/**
* @notice Register credential schema
*/
function registerSchema(
CredentialType credType,
string calldata schemaId,
string calldata credDefId,
bool required,
uint256 minScore
) external onlyRole(ISSUER_ROLE) {
schemas[credType] = CredentialSchema({
schemaId: schemaId,
credDefId: credDefId,
required: required,
credType: credType,
minScore: minScore
});
emit SchemaRegistered(credType, schemaId, credDefId);
}
/**
* @notice Verify credential proof (called by oracle/agent)
* @dev Off-chain: Verify ZK proof with Indy
* On-chain: Store verification result
*/
function verifyCredentialProof(
address user,
CredentialType credType,
bytes calldata zkProof,
uint256 score,
string calldata proofId
) external onlyRole(VERIFIER_ROLE) returns (bool) {
require(bytes(schemas[credType].schemaId).length > 0, "Schema not registered");
require(!verifiedProofs[proofId], "Proof already used");
require(score >= schemas[credType].minScore, "Score too low");
// Mark proof as used (prevent replay)
verifiedProofs[proofId] = true;
// Store verification result
userCredentials[user][credType] = VerificationResult({
verified: true,
score: score,
verifiedAt: block.timestamp,
proofId: proofId
});
emit CredentialVerified(user, credType, score, proofId);
return true;
}
/**
* @notice Check if user has required credential
*/
function hasCredential(
address user,
CredentialType credType
) external view returns (bool) {
VerificationResult memory result = userCredentials[user][credType];
if (!result.verified) return false;
CredentialSchema memory schema = schemas[credType];
return result.score >= schema.minScore;
}
/**
* @notice Get credential verification details
*/
function getCredentialDetails(
address user,
CredentialType credType
) external view returns (VerificationResult memory) {
return userCredentials[user][credType];
}
/**
* @notice Revoke credential (for compliance)
*/
function revokeCredential(
address user,
CredentialType credType
) external onlyRole(VERIFIER_ROLE) {
delete userCredentials[user][credType];
emit CredentialRevoked(user, credType);
}
/**
* @notice Batch verify credentials (for efficiency)
*/
function batchVerifyCredentials(
address[] calldata users,
CredentialType[] calldata credTypes,
bytes[] calldata zkProofs,
uint256[] calldata scores,
string[] calldata proofIds
) external onlyRole(VERIFIER_ROLE) {
require(
users.length == credTypes.length &&
credTypes.length == zkProofs.length &&
zkProofs.length == scores.length &&
scores.length == proofIds.length,
"Array length mismatch"
);
for (uint256 i = 0; i < users.length; i++) {
this.verifyCredentialProof(users[i], credTypes[i], zkProofs[i], scores[i], proofIds[i]);
}
}
}