@zentity/fhevm-contracts 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/abi/ComplianceRules.json +25 -16
  2. package/abi/CompliantERC20.json +30 -16
  3. package/abi/IdentityRegistry.json +496 -119
  4. package/contracts/compliance/ComplianceRules.sol +40 -189
  5. package/contracts/core/IdentityRegistry.sol +280 -232
  6. package/contracts/interfaces/IComplianceRules.sol +30 -0
  7. package/contracts/interfaces/IIdentityRegistry.sol +133 -159
  8. package/contracts/proxy/ERC1967Proxy.sol +6 -0
  9. package/contracts/test/MockFacilitator.sol +40 -0
  10. package/contracts/tokens/CompliantERC20.sol +28 -242
  11. package/deployments/hardhat/addresses.json +3 -8
  12. package/dist/index.d.ts +175 -9
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +44 -1
  15. package/package.json +1 -1
  16. package/typechain-types/@openzeppelin/contracts/access/Ownable.ts +153 -0
  17. package/typechain-types/@openzeppelin/contracts/access/Ownable2Step.ts +217 -0
  18. package/typechain-types/@openzeppelin/contracts/access/index.ts +5 -0
  19. package/typechain-types/@openzeppelin/contracts/index.ts +11 -0
  20. package/typechain-types/@openzeppelin/contracts/interfaces/IERC1967.ts +168 -0
  21. package/typechain-types/@openzeppelin/contracts/interfaces/IERC5267.ts +151 -0
  22. package/typechain-types/{contracts/tokens/CompliantERC20.sol/IComplianceChecker.ts → @openzeppelin/contracts/interfaces/draft-IERC1822.sol/IERC1822Proxiable.ts} +12 -17
  23. package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC1822.sol/index.ts +4 -0
  24. package/typechain-types/@openzeppelin/contracts/interfaces/index.ts +7 -0
  25. package/typechain-types/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.ts +105 -0
  26. package/typechain-types/@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.ts +69 -0
  27. package/typechain-types/@openzeppelin/contracts/proxy/ERC1967/index.ts +5 -0
  28. package/typechain-types/@openzeppelin/contracts/proxy/Proxy.ts +69 -0
  29. package/typechain-types/@openzeppelin/contracts/proxy/beacon/IBeacon.ts +90 -0
  30. package/typechain-types/@openzeppelin/contracts/proxy/beacon/index.ts +4 -0
  31. package/typechain-types/@openzeppelin/contracts/proxy/index.ts +8 -0
  32. package/typechain-types/@openzeppelin/contracts/utils/Address.ts +69 -0
  33. package/typechain-types/@openzeppelin/contracts/utils/Errors.ts +69 -0
  34. package/typechain-types/@openzeppelin/contracts/utils/Strings.ts +69 -0
  35. package/typechain-types/@openzeppelin/contracts/utils/cryptography/ECDSA.ts +69 -0
  36. package/typechain-types/@openzeppelin/contracts/utils/cryptography/index.ts +4 -0
  37. package/typechain-types/@openzeppelin/contracts/utils/index.ts +10 -0
  38. package/typechain-types/@openzeppelin/contracts/utils/math/SafeCast.ts +69 -0
  39. package/typechain-types/@openzeppelin/contracts/utils/math/index.ts +4 -0
  40. package/typechain-types/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.ts +251 -0
  41. package/typechain-types/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.ts +186 -0
  42. package/typechain-types/@openzeppelin/contracts-upgradeable/access/index.ts +5 -0
  43. package/typechain-types/@openzeppelin/contracts-upgradeable/index.ts +9 -0
  44. package/typechain-types/@openzeppelin/contracts-upgradeable/proxy/index.ts +5 -0
  45. package/typechain-types/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.ts +105 -0
  46. package/typechain-types/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.ts +196 -0
  47. package/typechain-types/@openzeppelin/contracts-upgradeable/proxy/utils/index.ts +5 -0
  48. package/typechain-types/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.ts +105 -0
  49. package/typechain-types/@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.ts +184 -0
  50. package/typechain-types/@openzeppelin/contracts-upgradeable/utils/cryptography/index.ts +4 -0
  51. package/typechain-types/@openzeppelin/contracts-upgradeable/utils/index.ts +6 -0
  52. package/typechain-types/@openzeppelin/index.ts +7 -0
  53. package/typechain-types/contracts/compliance/ComplianceRules.ts +18 -7
  54. package/typechain-types/contracts/core/IdentityRegistry.ts +493 -233
  55. package/typechain-types/contracts/index.ts +2 -0
  56. package/typechain-types/contracts/interfaces/IComplianceRules.ts +290 -0
  57. package/typechain-types/contracts/interfaces/IIdentityRegistry.ts +269 -341
  58. package/typechain-types/contracts/interfaces/index.ts +1 -0
  59. package/typechain-types/contracts/test/MockFacilitator.ts +187 -0
  60. package/typechain-types/contracts/test/index.ts +4 -0
  61. package/typechain-types/contracts/tokens/{CompliantERC20.sol/CompliantERC20.ts → CompliantERC20.ts} +19 -8
  62. package/typechain-types/contracts/tokens/index.ts +1 -2
  63. package/typechain-types/factories/@openzeppelin/contracts/access/Ownable2Step__factory.ts +138 -0
  64. package/typechain-types/factories/@openzeppelin/contracts/access/Ownable__factory.ts +96 -0
  65. package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +5 -0
  66. package/typechain-types/factories/@openzeppelin/contracts/index.ts +7 -0
  67. package/typechain-types/factories/@openzeppelin/contracts/interfaces/IERC1967__factory.ts +67 -0
  68. package/typechain-types/factories/@openzeppelin/contracts/interfaces/IERC5267__factory.ts +71 -0
  69. package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC1822.sol/IERC1822Proxiable__factory.ts +38 -0
  70. package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC1822.sol/index.ts +4 -0
  71. package/typechain-types/factories/@openzeppelin/contracts/interfaces/index.ts +6 -0
  72. package/typechain-types/factories/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy__factory.ts +144 -0
  73. package/typechain-types/factories/@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils__factory.ts +105 -0
  74. package/typechain-types/factories/@openzeppelin/contracts/proxy/ERC1967/index.ts +5 -0
  75. package/typechain-types/factories/@openzeppelin/contracts/proxy/Proxy__factory.ts +26 -0
  76. package/typechain-types/factories/@openzeppelin/contracts/proxy/beacon/IBeacon__factory.ts +35 -0
  77. package/typechain-types/factories/@openzeppelin/contracts/proxy/beacon/index.ts +4 -0
  78. package/typechain-types/factories/@openzeppelin/contracts/proxy/index.ts +6 -0
  79. package/typechain-types/factories/@openzeppelin/contracts/utils/Address__factory.ts +75 -0
  80. package/typechain-types/factories/@openzeppelin/contracts/utils/Errors__factory.ts +101 -0
  81. package/typechain-types/factories/@openzeppelin/contracts/utils/Strings__factory.ts +90 -0
  82. package/typechain-types/factories/@openzeppelin/contracts/utils/cryptography/ECDSA__factory.ts +91 -0
  83. package/typechain-types/factories/@openzeppelin/contracts/utils/cryptography/index.ts +4 -0
  84. package/typechain-types/factories/@openzeppelin/contracts/utils/index.ts +8 -0
  85. package/typechain-types/factories/@openzeppelin/contracts/utils/math/SafeCast__factory.ts +118 -0
  86. package/typechain-types/factories/@openzeppelin/contracts/utils/math/index.ts +4 -0
  87. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable__factory.ts +165 -0
  88. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable__factory.ts +122 -0
  89. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/access/index.ts +5 -0
  90. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/index.ts +6 -0
  91. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/proxy/index.ts +4 -0
  92. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable__factory.ts +48 -0
  93. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable__factory.ts +153 -0
  94. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/proxy/utils/index.ts +5 -0
  95. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable__factory.ts +48 -0
  96. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable__factory.ts +97 -0
  97. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/utils/cryptography/index.ts +4 -0
  98. package/typechain-types/factories/@openzeppelin/contracts-upgradeable/utils/index.ts +5 -0
  99. package/typechain-types/factories/@openzeppelin/index.ts +5 -0
  100. package/typechain-types/factories/contracts/compliance/ComplianceRules__factory.ts +26 -17
  101. package/typechain-types/factories/contracts/core/IdentityRegistry__factory.ts +493 -116
  102. package/typechain-types/factories/contracts/index.ts +1 -0
  103. package/typechain-types/factories/contracts/interfaces/IComplianceRules__factory.ts +193 -0
  104. package/typechain-types/factories/contracts/interfaces/IIdentityRegistry__factory.ts +236 -186
  105. package/typechain-types/factories/contracts/interfaces/index.ts +1 -0
  106. package/typechain-types/factories/contracts/test/MockFacilitator__factory.ts +194 -0
  107. package/typechain-types/factories/contracts/test/index.ts +4 -0
  108. package/typechain-types/factories/contracts/tokens/CompliantERC20__factory.ts +595 -0
  109. package/typechain-types/factories/contracts/tokens/index.ts +1 -1
  110. package/typechain-types/factories/index.ts +1 -0
  111. package/typechain-types/hardhat.d.ts +394 -16
  112. package/typechain-types/index.ts +48 -4
  113. package/deployments/hardhat/.chainId +0 -1
  114. package/typechain-types/contracts/tokens/CompliantERC20.sol/index.ts +0 -5
  115. package/typechain-types/factories/contracts/tokens/CompliantERC20.sol/CompliantERC20__factory.ts +0 -581
  116. package/typechain-types/factories/contracts/tokens/CompliantERC20.sol/IComplianceChecker__factory.ts +0 -44
  117. package/typechain-types/factories/contracts/tokens/CompliantERC20.sol/index.ts +0 -5
@@ -0,0 +1,30 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.27;
3
+
4
+ import {ebool} from "@fhevm/solidity/lib/FHE.sol";
5
+
6
+ /// @title IComplianceRules
7
+ /// @notice Interface for the compliance aggregation contract
8
+ interface IComplianceRules {
9
+ event MinComplianceLevelUpdated(uint8 indexed newLevel);
10
+ event ComplianceChecked(address indexed user);
11
+ event AuthorizedCallerUpdated(address indexed caller, bool indexed allowed);
12
+
13
+ error CallerNotAuthorized();
14
+ error AccessProhibited();
15
+
16
+ /// @notice Check if user passes compliance (level + blacklist)
17
+ function checkCompliance(address user) external returns (ebool);
18
+
19
+ /// @notice Check compliance with additional country restriction
20
+ function checkComplianceWithCountry(address user, uint16 allowedCountry) external returns (ebool);
21
+
22
+ /// @notice Get the last cached compliance result
23
+ function getComplianceResult(address user) external view returns (ebool);
24
+
25
+ /// @notice Whether a cached compliance result exists
26
+ function hasComplianceResult(address user) external view returns (bool);
27
+
28
+ function minComplianceLevel() external view returns (uint8);
29
+ function authorizedCallers(address caller) external view returns (bool);
30
+ }
@@ -1,88 +1,62 @@
1
1
  // SPDX-License-Identifier: MIT
2
+ // solhint-disable func-name-mixedcase
2
3
  pragma solidity ^0.8.27;
3
4
 
4
5
  import {euint8, euint16, ebool, externalEuint8, externalEuint16, externalEbool} from "@fhevm/solidity/lib/FHE.sol";
5
6
 
6
- /**
7
- * @title IIdentityRegistry
8
- * @author Gustavo Valverde
9
- * @notice Interface for the IdentityRegistry contract
10
- * @dev Part of zentity-fhevm-contracts - Builder Track
11
- *
12
- * @custom:category identity
13
- * @custom:concept Interface for encrypted identity storage and verification
14
- * @custom:difficulty intermediate
15
- */
7
+ /// @title IIdentityRegistry
8
+ /// @author Gustavo Valverde
9
+ /// @notice Interface for the on-chain encrypted identity registry with EIP-712 permits,
10
+ /// per-attribute selective grants, and x402 compliance oracle surface
16
11
  interface IIdentityRegistry {
12
+ // ============ Enums ============
13
+
14
+ /// @notice Purpose of an attribute access grant (on-chain equivalent of OAuth scopes)
15
+ enum Purpose {
16
+ COMPLIANCE_CHECK,
17
+ AGE_VERIFICATION,
18
+ NATIONALITY_CHECK,
19
+ TRANSFER_GATING,
20
+ AUDIT
21
+ }
22
+
17
23
  // ============ Events ============
18
24
 
19
- /// @notice Emitted when a new registrar is authorized
20
- /// @param registrar Address of the authorized registrar
21
- event RegistrarAdded(address indexed registrar);
22
-
23
- /// @notice Emitted when a registrar's authorization is revoked
24
- /// @param registrar Address of the removed registrar
25
- event RegistrarRemoved(address indexed registrar);
26
-
27
- /// @notice Emitted when an identity is attested on-chain
28
- /// @param user Address of the attested user
29
- /// @param registrar Address of the registrar who performed attestation
30
- event IdentityAttested(address indexed user, address indexed registrar);
31
-
32
- /// @notice Emitted when an identity is attested on-chain with metadata
33
- /// @param user Address of the attested user
34
- /// @param registrar Address of the registrar who performed attestation
35
- /// @param attestationId Monotonic attestation identifier for the user
36
- /// @param timestamp Unix timestamp of attestation
37
- event IdentityAttestedDetailed(
38
- address indexed user,
39
- address indexed registrar,
40
- uint256 indexed attestationId,
41
- uint256 timestamp
42
- );
25
+ /// @notice Emitted when an identity is attested via registrar permit
26
+ event IdentityAttested(address indexed user);
43
27
 
44
28
  /// @notice Emitted when an identity attestation is revoked
45
- /// @param user Address whose attestation was revoked
46
29
  event IdentityRevoked(address indexed user);
47
30
 
48
- /// @notice Emitted when an identity attestation is revoked with metadata
49
- /// @param user Address whose attestation was revoked
50
- /// @param registrar Address of the registrar who performed the revocation
51
- /// @param attestationId Attestation identifier that was revoked
52
- /// @param timestamp Unix timestamp of revocation
53
- event IdentityRevokedDetailed(
31
+ /// @notice Emitted when a user grants per-attribute access to a grantee
32
+ event AttributeAccessGranted(
54
33
  address indexed user,
55
- address indexed registrar,
56
- uint256 indexed attestationId,
57
- uint256 timestamp
34
+ address indexed grantee,
35
+ uint8 attributeMask,
36
+ Purpose purpose
58
37
  );
59
38
 
60
- /// @notice Emitted when a user grants access to their encrypted data
61
- /// @param user Address of the user granting access
62
- /// @param grantee Address receiving access permission
63
- event AccessGranted(address indexed user, address indexed grantee);
64
-
65
- /// @notice Emitted when ownership transfer is initiated
66
- /// @param currentOwner Current owner address
67
- /// @param pendingOwner Address that can accept ownership
68
- event OwnershipTransferStarted(address indexed currentOwner, address indexed pendingOwner);
69
-
70
- /// @notice Emitted when ownership transfer is completed
71
- /// @param previousOwner Previous owner address
72
- /// @param newOwner New owner address
73
- event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
39
+ /// @notice Emitted when a registrar is added or removed
40
+ event RegistrarUpdated(address indexed registrar, bool status);
41
+
42
+ // ============ Structs ============
43
+
44
+ /// @notice Registrar-signed permit data for user-submitted attestation
45
+ struct AttestPermitData {
46
+ uint8 birthYearOffset;
47
+ uint16 countryCode;
48
+ uint8 complianceLevel;
49
+ bool isBlacklisted;
50
+ bytes32 proofSetHash;
51
+ uint32 policyVersion;
52
+ uint256 deadline;
53
+ uint8 v;
54
+ bytes32 r;
55
+ bytes32 s;
56
+ }
74
57
 
75
58
  // ============ Errors ============
76
59
 
77
- /// @notice Thrown when caller is not the contract owner
78
- error OnlyOwner();
79
-
80
- /// @notice Thrown when caller is not the pending owner
81
- error OnlyPendingOwner();
82
-
83
- /// @notice Thrown when new owner is the zero address
84
- error InvalidOwner();
85
-
86
60
  /// @notice Thrown when caller is not an authorized registrar
87
61
  error OnlyRegistrar();
88
62
 
@@ -92,27 +66,32 @@ interface IIdentityRegistry {
92
66
  /// @notice Thrown when attempting to attest an already-attested user
93
67
  error AlreadyAttested();
94
68
 
95
- // ============ Registrar Management ============
69
+ /// @notice Thrown when the EIP-712 permit signature is invalid
70
+ error InvalidPermit();
96
71
 
97
- /// @notice Add a new authorized registrar
98
- /// @param registrar Address to authorize as registrar
99
- function addRegistrar(address registrar) external;
72
+ /// @notice Thrown when the permit deadline has passed
73
+ error PermitExpired();
100
74
 
101
- /// @notice Remove an authorized registrar
102
- /// @param registrar Address to remove from registrars
103
- function removeRegistrar(address registrar) external;
75
+ /// @notice Thrown when an address argument is the zero address
76
+ error ZeroAddress();
104
77
 
105
- // ============ Identity Attestation ============
78
+ /// @notice Thrown when caller lacks FHE permission for encrypted data
79
+ error AccessProhibited();
106
80
 
107
- /// @notice Attest a user's encrypted identity data on-chain
108
- /// @param user Address of the user being attested
109
- /// @param encBirthYearOffset Encrypted birth year offset (years since 1900)
110
- /// @param encCountryCode Encrypted ISO 3166-1 numeric country code
111
- /// @param encComplianceLevel Encrypted compliance verification level (0-3)
112
- /// @param encIsBlacklisted Encrypted blacklist status
113
- /// @param inputProof FHE proof for encrypted inputs
114
- function attestIdentity(
115
- address user,
81
+ // ============ Attestation with Permit ============
82
+
83
+ /// @notice Attest identity using a registrar-signed EIP-712 permit
84
+ /// @dev The user submits this transaction with their own FHE-encrypted values.
85
+ /// The contract verifies the registrar's signature over the plaintext values
86
+ /// and stores the user's encrypted values. Nonce is auto-incremented.
87
+ /// @param permit Registrar-signed permit containing plaintext values + ECDSA signature
88
+ /// @param encBirthYearOffset FHE-encrypted birth year offset
89
+ /// @param encCountryCode FHE-encrypted country code
90
+ /// @param encComplianceLevel FHE-encrypted compliance level
91
+ /// @param encIsBlacklisted FHE-encrypted blacklist status
92
+ /// @param inputProof FHE input proof binding encrypted values to (contract, user)
93
+ function attestWithPermit(
94
+ AttestPermitData calldata permit,
116
95
  externalEuint8 encBirthYearOffset,
117
96
  externalEuint16 encCountryCode,
118
97
  externalEuint8 encComplianceLevel,
@@ -120,107 +99,102 @@ interface IIdentityRegistry {
120
99
  bytes calldata inputProof
121
100
  ) external;
122
101
 
123
- /// @notice Revoke a user's identity attestation
124
- /// @param user Address of the user to revoke
125
- function revokeIdentity(address user) external;
102
+ // ============ Revocation ============
126
103
 
127
- // ============ Encrypted Queries ============
104
+ /// @notice Revoke caller's own attestation (user self-revocation)
105
+ function revokeIdentity() external;
128
106
 
129
- /// @notice Get user's encrypted birth year offset
130
- /// @param user Address of the user
131
- /// @return Encrypted birth year offset (years since 1900)
132
- function getBirthYearOffset(address user) external view returns (euint8);
107
+ /// @notice Revoke a user's attestation (registrar-only)
108
+ /// @param user Address of the user to revoke
109
+ function revokeIdentityFor(address user) external;
133
110
 
134
- /// @notice Get user's encrypted country code
135
- /// @param user Address of the user
136
- /// @return Encrypted ISO 3166-1 numeric country code
137
- function getCountryCode(address user) external view returns (euint16);
111
+ // ============ Per-Attribute Access Grants ============
138
112
 
139
- /// @notice Get user's encrypted compliance level
140
- /// @param user Address of the user
141
- /// @return Encrypted compliance (KYC) verification level (0-3)
142
- function getComplianceLevel(address user) external view returns (euint8);
113
+ /// @notice Grant FHE access to specific attributes for a stated purpose
114
+ /// @param grantee Address receiving access permission
115
+ /// @param attributeMask Bitmask: 0x01=birthYear, 0x02=country, 0x04=compliance, 0x08=blacklist
116
+ /// @param purpose Why access is needed (on-chain audit trail)
117
+ function grantAttributeAccess(address grantee, uint8 attributeMask, Purpose purpose) external;
143
118
 
144
- /// @notice Get user's encrypted blacklist status
145
- /// @param user Address of the user
146
- /// @return Encrypted blacklist status (true if blacklisted)
147
- function getBlacklistStatus(address user) external view returns (ebool);
119
+ /// @notice Grant FHE access to all attributes (convenience wrapper)
120
+ /// @param grantee Address receiving access permission
121
+ function grantAccessTo(address grantee) external;
148
122
 
149
- // ============ Verification Helpers ============
123
+ // ============ Compliance Checks (x402 Oracle Surface) ============
150
124
 
151
- /// @notice Check if user has minimum compliance level (encrypted comparison)
152
- /// @param user Address of the user
125
+ /// @notice Combined compliance check: level >= minLevel AND not blacklisted
126
+ /// @dev State-mutating (FHE comparisons). Stores and returns encrypted result.
127
+ /// x402 facilitators compose this inline:
128
+ /// `euint64 amt = FHE.select(registry.checkCompliance(payer, 2), amount, zero);`
129
+ /// @param user Address to check
153
130
  /// @param minLevel Minimum compliance level required
154
- /// @return Encrypted boolean result of comparison
131
+ /// @return Encrypted boolean: true if compliant
132
+ function checkCompliance(address user, uint8 minLevel) external returns (ebool);
133
+
134
+ /// @notice Check if user meets minimum compliance level
135
+ /// @param user Address to check
136
+ /// @param minLevel Minimum level required
137
+ /// @return Encrypted boolean result
155
138
  function hasMinComplianceLevel(address user, uint8 minLevel) external returns (ebool);
156
139
 
157
- /// @notice Check if user is from a specific country (encrypted comparison)
158
- /// @param user Address of the user
159
- /// @param country ISO 3166-1 numeric country code to check
160
- /// @return Encrypted boolean result of comparison
140
+ /// @notice Check if user is from a specific country
141
+ /// @param user Address to check
142
+ /// @param country ISO 3166-1 numeric country code
143
+ /// @return Encrypted boolean result
161
144
  function isFromCountry(address user, uint16 country) external returns (ebool);
162
145
 
163
- /// @notice Check if user is not blacklisted (encrypted)
164
- /// @param user Address of the user
146
+ /// @notice Check if user is not blacklisted
147
+ /// @param user Address to check
165
148
  /// @return Encrypted boolean (true if NOT blacklisted)
166
149
  function isNotBlacklisted(address user) external returns (ebool);
167
150
 
168
- // ============ Access Control ============
151
+ // ============ View Getters ============
169
152
 
170
- /// @notice Grant a contract access to caller's encrypted identity data
171
- /// @param grantee Address to grant access to
172
- function grantAccessTo(address grantee) external;
173
-
174
- /// @notice Check if a user has been attested
175
- /// @param user Address of the user
176
- /// @return True if user has valid attestation
153
+ /// @notice Check if a user has a valid attestation
177
154
  function isAttested(address user) external view returns (bool);
178
155
 
179
- // ============ Public State ============
156
+ /// @notice Get user's encrypted birth year offset (caller must have FHE ACL access)
157
+ function getBirthYearOffset(address user) external view returns (euint8);
180
158
 
181
- /// @notice Get the contract owner address
182
- /// @return Owner address
183
- function owner() external view returns (address);
159
+ /// @notice Get user's encrypted country code (caller must have FHE ACL access)
160
+ function getCountryCode(address user) external view returns (euint16);
184
161
 
185
- /// @notice Get the pending owner address
186
- /// @return Pending owner address
187
- function pendingOwner() external view returns (address);
162
+ /// @notice Get user's encrypted compliance level (caller must have FHE ACL access)
163
+ function getComplianceLevel(address user) external view returns (euint8);
188
164
 
189
- /// @notice Initiate transfer of contract ownership
190
- /// @param newOwner Address that can accept ownership
191
- function transferOwnership(address newOwner) external;
165
+ /// @notice Get user's encrypted blacklist status (caller must have FHE ACL access)
166
+ function getBlacklistStatus(address user) external view returns (ebool);
192
167
 
193
- /// @notice Accept ownership transfer
194
- function acceptOwnership() external;
168
+ /// @notice Get the proof set hash for a user's attestation
169
+ function getProofSetHash(address user) external view returns (bytes32);
195
170
 
196
- /// @notice Check if an address is an authorized registrar
197
- /// @param registrar Address to check
198
- /// @return True if address is authorized registrar
199
- function registrars(address registrar) external view returns (bool);
171
+ /// @notice Get the policy version for a user's attestation
172
+ function getPolicyVersion(address user) external view returns (uint32);
173
+
174
+ /// @notice Get the attribute mask granted to a grantee by a user
175
+ function getGrantedAttributes(address user, address grantee) external view returns (uint8);
176
+
177
+ /// @notice Get the current attestation ID for a user (0 if not attested)
178
+ function currentAttestationId(address user) external view returns (uint256);
200
179
 
201
180
  /// @notice Get the timestamp when a user was attested
202
- /// @param user Address of the user
203
- /// @return Unix timestamp of attestation (0 if not attested)
204
181
  function attestationTimestamp(address user) external view returns (uint256);
205
182
 
206
- /// @notice Get the current attestation id for a user (0 if not attested)
207
- /// @param user Address of the user
208
- /// @return Current attestation id
209
- function currentAttestationId(address user) external view returns (uint256);
183
+ /// @notice Get the EIP-712 nonce for a user (for permit construction)
184
+ function nonces(address user) external view returns (uint256);
185
+
186
+ /// @notice Check if an address is an authorized registrar
187
+ function registrars(address registrar) external view returns (bool);
188
+
189
+ /// @notice Get a previously stored verification result
190
+ /// @param key The result key (keccak256 of check parameters)
191
+ function getVerificationResult(bytes32 key) external view returns (ebool);
192
+
193
+ // ============ Constants ============
210
194
 
211
- /// @notice Get the latest attestation id ever issued for a user
212
- /// @param user Address of the user
213
- /// @return Latest attestation id
214
- function latestAttestationId(address user) external view returns (uint256);
215
-
216
- /// @notice Get attestation metadata for a user and attestation id
217
- /// @param user Address of the user
218
- /// @param attestationId Attestation identifier to query
219
- /// @return timestamp Unix timestamp of attestation
220
- /// @return revokedAt Unix timestamp of revocation (0 if not revoked)
221
- /// @return registrar Registrar who performed the attestation
222
- function getAttestationMetadata(
223
- address user,
224
- uint256 attestationId
225
- ) external view returns (uint256 timestamp, uint256 revokedAt, address registrar);
195
+ function ATTR_BIRTH_YEAR() external pure returns (uint8);
196
+ function ATTR_COUNTRY() external pure returns (uint8);
197
+ function ATTR_COMPLIANCE() external pure returns (uint8);
198
+ function ATTR_BLACKLIST() external pure returns (uint8);
199
+ function ATTR_ALL() external pure returns (uint8);
226
200
  }
@@ -0,0 +1,6 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // solhint-disable no-unused-import
3
+ pragma solidity ^0.8.27;
4
+
5
+ // Import to make hardhat-deploy aware of the ERC1967Proxy artifact
6
+ import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
@@ -0,0 +1,40 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.27;
3
+
4
+ import {FHE, ebool} from "@fhevm/solidity/lib/FHE.sol";
5
+ import {ZamaEthereumConfig} from "@fhevm/solidity/config/ZamaConfig.sol";
6
+ import {IIdentityRegistry} from "../interfaces/IIdentityRegistry.sol";
7
+
8
+ /// @title MockFacilitator
9
+ /// @notice Simulates an x402 facilitator verifying compliance before settlement
10
+ /// @dev Demonstrates the checkCompliance + FHE.select pattern for x402 integration
11
+ contract MockFacilitator is ZamaEthereumConfig {
12
+ IIdentityRegistry public immutable registry;
13
+ uint8 public requiredLevel;
14
+
15
+ /// @notice Result of the last settlement attempt
16
+ mapping(address payer => ebool result) public settlementResults;
17
+
18
+ event SettlementAttempted(address indexed payer);
19
+
20
+ constructor(address _registry, uint8 _requiredLevel) {
21
+ registry = IIdentityRegistry(_registry);
22
+ requiredLevel = _requiredLevel;
23
+ }
24
+
25
+ /// @notice Simulates x402 settlement with inline compliance check
26
+ /// @dev This is the pattern x402 facilitators would use:
27
+ /// 1. Check compliance via registry
28
+ /// 2. Use FHE.select to conditionally process the amount
29
+ function settleWithCompliance(address payer) external returns (ebool) {
30
+ ebool compliant = registry.checkCompliance(payer, requiredLevel);
31
+
32
+ // Store result for test verification
33
+ settlementResults[payer] = compliant;
34
+ FHE.allowThis(compliant);
35
+ FHE.allow(compliant, msg.sender);
36
+
37
+ emit SettlementAttempted(payer);
38
+ return compliant;
39
+ }
40
+ }