salmanch123 commited on
Commit
60050be
·
0 Parent(s):

feat: push fixed compilation tsconfig

Browse files
.gitignore ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ node_modules
2
+ cache
3
+ artifacts
4
+ typechain-types
5
+ .env
6
+ coverage
7
+ coverage.json
8
+ *.log
Dockerfile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:22-alpine
2
+
3
+ WORKDIR /app
4
+
5
+ # Install build dependencies for native modules
6
+ RUN apk add --no-cache python3 make g++
7
+
8
+ # Copy dependency mappings and install
9
+ COPY package*.json ./
10
+ RUN npm install
11
+
12
+ # Copy all project files
13
+ COPY . .
14
+
15
+ # Compile TS files to dist/
16
+ RUN npx tsc
17
+
18
+ # Expose port (HF requires this for Docker spaces)
19
+ EXPOSE 7860
20
+
21
+ # Run the compiled javascript directly for instant boot
22
+ CMD ["node", "dist/scripts/oracle_service.js"]
README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: CipherTrust Oracle
3
+ emoji: 🛡️
4
+ colorFrom: yellow
5
+ colorTo: indigo
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ # CipherTrust Telemetry Oracle Daemon
11
+
12
+ Background telemetry oracle for the CipherTrust FHE protocol.
contracts/AgentIdentityRegistry.sol ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.24;
3
+
4
+ /// @title AgentIdentityRegistry
5
+ /// @notice Lightweight, ERC-8004-inspired identity registry for autonomous agents and
6
+ /// robots. This is NOT a claim of full ERC-8004 compliance -- it borrows the standard's
7
+ /// core idea (a portable, on-chain identity record for an autonomous agent, decoupled
8
+ /// from any single application) so CipherTrust's underwriting data, and any other
9
+ /// confidential protocol, can be composed against the same agent identity instead of
10
+ /// re-deriving one per app.
11
+ contract AgentIdentityRegistry {
12
+ struct Identity {
13
+ address operator;
14
+ string agentType; // e.g. "trading-bot", "delivery-robot", "drone", "depin-device"
15
+ string metadataURI; // off-chain JSON: hardware attestation, manufacturer, firmware hash, etc.
16
+ uint256 registeredAt;
17
+ bool active;
18
+ }
19
+
20
+ address public admin;
21
+ uint256 public nextIdentityId;
22
+ mapping(uint256 => Identity) public identities;
23
+ mapping(uint256 => mapping(address => bool)) public delegatedOperators;
24
+
25
+ event IdentityRegistered(uint256 indexed identityId, address indexed operator, string agentType);
26
+ event IdentityDeactivated(uint256 indexed identityId);
27
+ event OperatorDelegated(uint256 indexed identityId, address indexed delegate);
28
+
29
+ modifier onlyOperator(uint256 identityId) {
30
+ require(
31
+ identities[identityId].operator == msg.sender || delegatedOperators[identityId][msg.sender],
32
+ "AgentIdentityRegistry: not operator"
33
+ );
34
+ _;
35
+ }
36
+
37
+ constructor() {
38
+ admin = msg.sender;
39
+ }
40
+
41
+ function registerIdentity(
42
+ address operator,
43
+ string calldata agentType,
44
+ string calldata metadataURI
45
+ ) external returns (uint256 identityId) {
46
+ identityId = nextIdentityId++;
47
+ identities[identityId] = Identity({
48
+ operator: operator,
49
+ agentType: agentType,
50
+ metadataURI: metadataURI,
51
+ registeredAt: block.timestamp,
52
+ active: true
53
+ });
54
+ emit IdentityRegistered(identityId, operator, agentType);
55
+ }
56
+
57
+ function delegateOperator(uint256 identityId, address delegate) external onlyOperator(identityId) {
58
+ delegatedOperators[identityId][delegate] = true;
59
+ emit OperatorDelegated(identityId, delegate);
60
+ }
61
+
62
+ function deactivate(uint256 identityId) external onlyOperator(identityId) {
63
+ identities[identityId].active = false;
64
+ emit IdentityDeactivated(identityId);
65
+ }
66
+
67
+ function isActiveOperator(uint256 identityId, address who) external view returns (bool) {
68
+ Identity storage id_ = identities[identityId];
69
+ return id_.active && (id_.operator == who || delegatedOperators[identityId][who]);
70
+ }
71
+ }
contracts/CipherAuth.sol ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.24;
3
+
4
+ import {FHE, euint64, ebool, externalEuint64} from "@fhevm/solidity/lib/FHE.sol";
5
+ import {SepoliaConfig} from "@fhevm/solidity/config/ZamaConfig.sol";
6
+
7
+ contract CipherAuth is SepoliaConfig {
8
+ // FHE-MFA Biometric Authentication State
9
+ mapping(address => euint64[3]) private _registeredBiometrics;
10
+ mapping(address => bool) private _hasBiometrics;
11
+ uint32 public maxBiometricDrift = 15; // Manhattan distance tolerance
12
+ mapping(address => bool) public biometricAuthPassed;
13
+ mapping(uint256 => address) public biometricRequestUser;
14
+
15
+ // FHE-Guard: Spam Filtering State
16
+ mapping(address => uint32) public spamThreshold;
17
+ mapping(address => uint256) public inboxCount;
18
+ mapping(address => uint256) public spamInboxCount;
19
+ mapping(uint256 => address) public spamCheckRequestUser;
20
+
21
+ // FHE-Guard: Passwordless Auth State
22
+ mapping(address => euint64) private _masterSecret;
23
+ mapping(address => bool) private _hasSecret;
24
+ mapping(address => uint64) public activeAuthChallenge;
25
+ mapping(address => bool) public authPassed;
26
+ mapping(uint256 => address) public authRequests;
27
+
28
+ // FHE-Passport: Biometric Uniqueness State
29
+ uint256 public passportCount;
30
+ mapping(uint256 => euint64[3]) private _passportDatabase;
31
+ mapping(address => bool) public hasPassport;
32
+ mapping(uint256 => address) public passportRequests;
33
+ mapping(address => bool) public passportUnique;
34
+ mapping(uint256 => euint64[3]) private _pendingPassportTemplates;
35
+ uint256 public nextTierRequestId = 1;
36
+
37
+ // FHE-Aegis: AI Agent Behavior Drift State
38
+ mapping(uint256 => euint64[3]) private _agentBaselines;
39
+ mapping(uint256 => bool) private _hasBaseline;
40
+ uint32 public maxBehaviorDrift = 1000; // squared Euclidean distance threshold
41
+ mapping(uint256 => bool) public agentBehaviorCompromised;
42
+ mapping(uint256 => uint256) public behaviorRequests;
43
+
44
+ event BiometricsRegistered(address indexed user);
45
+ event BiometricsVerified(address indexed user, bool success);
46
+ event MessageSpamChecked(address indexed recipient, bool isSpam);
47
+ event AuthSecretRegistered(address indexed user);
48
+ event AuthChallengeGenerated(address indexed user, uint64 challenge);
49
+ event AuthVerified(address indexed user, bool success);
50
+ event PassportCheckRequested(address indexed user, uint256 indexed requestId);
51
+ event PassportRegistered(address indexed user, bool success, uint256 passportId);
52
+ event AgentBaselineRegistered(uint256 indexed agentId);
53
+ event BehaviorCheckRequested(uint256 indexed agentId, uint256 indexed requestId);
54
+ event BehaviorChecked(uint256 indexed agentId, bool compromised);
55
+
56
+ // FHE-MFA: Biometric Authentication Implementation
57
+ function registerBiometricSignature(
58
+ externalEuint64 hX,
59
+ externalEuint64 hY,
60
+ externalEuint64 hZ,
61
+ bytes calldata inputProof
62
+ ) external {
63
+ _registeredBiometrics[msg.sender][0] = FHE.fromExternal(hX, inputProof);
64
+ _registeredBiometrics[msg.sender][1] = FHE.fromExternal(hY, inputProof);
65
+ _registeredBiometrics[msg.sender][2] = FHE.fromExternal(hZ, inputProof);
66
+ _hasBiometrics[msg.sender] = true;
67
+
68
+ FHE.allowThis(_registeredBiometrics[msg.sender][0]);
69
+ FHE.allowThis(_registeredBiometrics[msg.sender][1]);
70
+ FHE.allowThis(_registeredBiometrics[msg.sender][2]);
71
+ FHE.allow(_registeredBiometrics[msg.sender][0], msg.sender);
72
+ FHE.allow(_registeredBiometrics[msg.sender][1], msg.sender);
73
+ FHE.allow(_registeredBiometrics[msg.sender][2], msg.sender);
74
+
75
+ emit BiometricsRegistered(msg.sender);
76
+ }
77
+
78
+ function requestBiometricAuth(
79
+ externalEuint64 hX,
80
+ externalEuint64 hY,
81
+ externalEuint64 hZ,
82
+ bytes calldata inputProof
83
+ ) external returns (uint256 requestId) {
84
+ address user = msg.sender;
85
+ require(_hasBiometrics[user]);
86
+
87
+ euint64 x = FHE.fromExternal(hX, inputProof);
88
+ euint64 y = FHE.fromExternal(hY, inputProof);
89
+ euint64 z = FHE.fromExternal(hZ, inputProof);
90
+
91
+ euint64 dX = FHE.select(FHE.lt(x, _registeredBiometrics[user][0]), FHE.sub(_registeredBiometrics[user][0], x), FHE.sub(x, _registeredBiometrics[user][0]));
92
+ euint64 dY = FHE.select(FHE.lt(y, _registeredBiometrics[user][1]), FHE.sub(_registeredBiometrics[user][1], y), FHE.sub(y, _registeredBiometrics[user][1]));
93
+ euint64 dZ = FHE.select(FHE.lt(z, _registeredBiometrics[user][2]), FHE.sub(_registeredBiometrics[user][2], z), FHE.sub(z, _registeredBiometrics[user][2]));
94
+
95
+ euint64 totalDist = FHE.add(FHE.add(dX, dY), dZ);
96
+ ebool isValid = FHE.le(totalDist, FHE.asEuint64(maxBiometricDrift));
97
+ FHE.allowThis(isValid);
98
+
99
+ bytes32[] memory cts = new bytes32[](1);
100
+ cts[0] = ebool.unwrap(isValid);
101
+
102
+ requestId = FHE.requestDecryption(cts, this.fulfillBiometricAuth.selector);
103
+ biometricRequestUser[requestId] = user;
104
+
105
+ biometricAuthPassed[user] = false;
106
+ emit BiometricsVerified(user, false);
107
+ }
108
+
109
+ function fulfillBiometricAuth(
110
+ uint256 requestId,
111
+ bytes memory cleartexts,
112
+ bytes memory decryptionProof
113
+ ) external {
114
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
115
+
116
+ bool success = abi.decode(cleartexts, (bool));
117
+ address user = biometricRequestUser[requestId];
118
+ delete biometricRequestUser[requestId];
119
+
120
+ biometricAuthPassed[user] = success;
121
+ emit BiometricsVerified(user, success);
122
+ }
123
+
124
+ // FHE-Guard: Spam Filtering Implementation
125
+ function setSpamThreshold(uint32 threshold) external {
126
+ spamThreshold[msg.sender] = threshold;
127
+ }
128
+
129
+ function checkMessageSpam(
130
+ address recipient,
131
+ externalEuint64 wA,
132
+ externalEuint64 wB,
133
+ externalEuint64 wC,
134
+ bytes calldata inputProof
135
+ ) external returns (uint256 requestId) {
136
+ if (spamThreshold[recipient] == 0) {
137
+ spamThreshold[recipient] = 15; // default threshold
138
+ }
139
+
140
+ euint64 scoreA = FHE.fromExternal(wA, inputProof);
141
+ euint64 scoreB = FHE.fromExternal(wB, inputProof);
142
+ euint64 scoreC = FHE.fromExternal(wC, inputProof);
143
+
144
+ euint64 totalScore = FHE.add(FHE.add(scoreA, scoreB), scoreC);
145
+ ebool isSpam = FHE.gt(totalScore, FHE.asEuint64(spamThreshold[recipient]));
146
+
147
+ FHE.allowThis(isSpam);
148
+
149
+ bytes32[] memory cts = new bytes32[](1);
150
+ cts[0] = ebool.unwrap(isSpam);
151
+
152
+ requestId = FHE.requestDecryption(cts, this.fulfillSpamCheck.selector);
153
+ spamCheckRequestUser[requestId] = recipient;
154
+ }
155
+
156
+ function fulfillSpamCheck(
157
+ uint256 requestId,
158
+ bytes memory cleartexts,
159
+ bytes memory decryptionProof
160
+ ) external {
161
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
162
+
163
+ bool isSpam = abi.decode(cleartexts, (bool));
164
+ address recipient = spamCheckRequestUser[requestId];
165
+ delete spamCheckRequestUser[requestId];
166
+
167
+ if (isSpam) {
168
+ spamInboxCount[recipient]++;
169
+ } else {
170
+ inboxCount[recipient]++;
171
+ }
172
+
173
+ emit MessageSpamChecked(recipient, isSpam);
174
+ }
175
+
176
+ // FHE-Pass: Challenge-Response Implementation
177
+ function registerAuthSecret(
178
+ externalEuint64 hSecret,
179
+ bytes calldata inputProof
180
+ ) external {
181
+ _masterSecret[msg.sender] = FHE.fromExternal(hSecret, inputProof);
182
+ _hasSecret[msg.sender] = true;
183
+
184
+ FHE.allowThis(_masterSecret[msg.sender]);
185
+ FHE.allow(_masterSecret[msg.sender], msg.sender);
186
+
187
+ emit AuthSecretRegistered(msg.sender);
188
+ }
189
+
190
+ function generateAuthChallenge(uint64 seedChallenge) external returns (uint64) {
191
+ require(_hasSecret[msg.sender]);
192
+ activeAuthChallenge[msg.sender] = seedChallenge;
193
+ emit AuthChallengeGenerated(msg.sender, seedChallenge);
194
+ return seedChallenge;
195
+ }
196
+
197
+ function verifyAuthChallenge(
198
+ externalEuint64 hResponse,
199
+ bytes calldata inputProof
200
+ ) external returns (uint256 requestId) {
201
+ address user = msg.sender;
202
+ require(_hasSecret[user]);
203
+ require(activeAuthChallenge[user] != 0);
204
+
205
+ euint64 response = FHE.fromExternal(hResponse, inputProof);
206
+ euint64 challengeVal = FHE.asEuint64(activeAuthChallenge[user]);
207
+ euint64 expected = FHE.add(_masterSecret[user], challengeVal);
208
+
209
+ ebool isValid = FHE.eq(response, expected);
210
+ FHE.allowThis(isValid);
211
+
212
+ bytes32[] memory cts = new bytes32[](1);
213
+ cts[0] = ebool.unwrap(isValid);
214
+
215
+ requestId = FHE.requestDecryption(cts, this.fulfillAuthCheck.selector);
216
+ authRequests[requestId] = user;
217
+
218
+ authPassed[user] = false;
219
+ emit AuthVerified(user, false);
220
+ }
221
+
222
+ function fulfillAuthCheck(
223
+ uint256 requestId,
224
+ bytes memory cleartexts,
225
+ bytes memory decryptionProof
226
+ ) external {
227
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
228
+
229
+ bool success = abi.decode(cleartexts, (bool));
230
+ address user = authRequests[requestId];
231
+ delete authRequests[requestId];
232
+
233
+ authPassed[user] = success;
234
+ emit AuthVerified(user, success);
235
+ }
236
+
237
+ // FHE-Passport: Biometric Uniqueness Check Implementation
238
+ function requestPassportRegistration(
239
+ externalEuint64 hX,
240
+ externalEuint64 hY,
241
+ externalEuint64 hZ,
242
+ bytes calldata inputProof
243
+ ) external returns (uint256 requestId) {
244
+ address user = msg.sender;
245
+ require(!hasPassport[user]);
246
+
247
+ euint64 x = FHE.fromExternal(hX, inputProof);
248
+ euint64 y = FHE.fromExternal(hY, inputProof);
249
+ euint64 z = FHE.fromExternal(hZ, inputProof);
250
+
251
+ uint256 nextReqId = nextTierRequestId++;
252
+ _pendingPassportTemplates[nextReqId][0] = x;
253
+ _pendingPassportTemplates[nextReqId][1] = y;
254
+ _pendingPassportTemplates[nextReqId][2] = z;
255
+
256
+ FHE.allowThis(_pendingPassportTemplates[nextReqId][0]);
257
+ FHE.allowThis(_pendingPassportTemplates[nextReqId][1]);
258
+ FHE.allowThis(_pendingPassportTemplates[nextReqId][2]);
259
+
260
+ ebool isUnique = FHE.asEbool(true);
261
+
262
+ for (uint256 i = 0; i < passportCount; i++) {
263
+ euint64 dX = FHE.select(FHE.lt(x, _passportDatabase[i][0]), FHE.sub(_passportDatabase[i][0], x), FHE.sub(x, _passportDatabase[i][0]));
264
+ euint64 dY = FHE.select(FHE.lt(y, _passportDatabase[i][1]), FHE.sub(_passportDatabase[i][1], y), FHE.sub(y, _passportDatabase[i][1]));
265
+ euint64 dZ = FHE.select(FHE.lt(z, _passportDatabase[i][2]), FHE.sub(_passportDatabase[i][2], z), FHE.sub(z, _passportDatabase[i][2]));
266
+
267
+ euint64 dist = FHE.add(FHE.add(dX, dY), dZ);
268
+ ebool duplicate = FHE.le(dist, FHE.asEuint64(10));
269
+ isUnique = FHE.and(isUnique, FHE.not(duplicate));
270
+ }
271
+
272
+ FHE.allowThis(isUnique);
273
+
274
+ bytes32[] memory cts = new bytes32[](1);
275
+ cts[0] = ebool.unwrap(isUnique);
276
+
277
+ requestId = FHE.requestDecryption(cts, this.fulfillPassportCheck.selector);
278
+ passportRequests[requestId] = user;
279
+ }
280
+
281
+ function fulfillPassportCheck(
282
+ uint256 requestId,
283
+ bytes memory cleartexts,
284
+ bytes memory decryptionProof
285
+ ) external {
286
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
287
+
288
+ bool unique = abi.decode(cleartexts, (bool));
289
+ address user = passportRequests[requestId];
290
+ delete passportRequests[requestId];
291
+
292
+ if (unique) {
293
+ uint256 id = passportCount++;
294
+ _passportDatabase[id][0] = _pendingPassportTemplates[requestId][0];
295
+ _passportDatabase[id][1] = _pendingPassportTemplates[requestId][1];
296
+ _passportDatabase[id][2] = _pendingPassportTemplates[requestId][2];
297
+
298
+ FHE.allowThis(_passportDatabase[id][0]);
299
+ FHE.allowThis(_passportDatabase[id][1]);
300
+ FHE.allowThis(_passportDatabase[id][2]);
301
+
302
+ hasPassport[user] = true;
303
+ passportUnique[user] = true;
304
+ emit PassportRegistered(user, true, id);
305
+ } else {
306
+ passportUnique[user] = false;
307
+ emit PassportRegistered(user, false, 0);
308
+ }
309
+ }
310
+
311
+ // FHE-Aegis: Behavioral Anomaly Detector Implementation
312
+ function registerAgentBaseline(
313
+ uint256 agentId,
314
+ externalEuint64 hT,
315
+ externalEuint64 hF,
316
+ externalEuint64 hC,
317
+ bytes calldata inputProof
318
+ ) external {
319
+ _agentBaselines[agentId][0] = FHE.fromExternal(hT, inputProof);
320
+ _agentBaselines[agentId][1] = FHE.fromExternal(hF, inputProof);
321
+ _agentBaselines[agentId][2] = FHE.fromExternal(hC, inputProof);
322
+ _hasBaseline[agentId] = true;
323
+
324
+ FHE.allowThis(_agentBaselines[agentId][0]);
325
+ FHE.allowThis(_agentBaselines[agentId][1]);
326
+ FHE.allowThis(_agentBaselines[agentId][2]);
327
+
328
+ emit AgentBaselineRegistered(agentId);
329
+ }
330
+
331
+ function evaluateAgentBehavior(
332
+ uint256 agentId,
333
+ externalEuint64 hT,
334
+ externalEuint64 hF,
335
+ externalEuint64 hC,
336
+ bytes calldata inputProof
337
+ ) external returns (uint256 requestId) {
338
+ require(_hasBaseline[agentId]);
339
+
340
+ euint64 oT = FHE.fromExternal(hT, inputProof);
341
+ euint64 oF = FHE.fromExternal(hF, inputProof);
342
+ euint64 oC = FHE.fromExternal(hC, inputProof);
343
+
344
+ euint64 bT = _agentBaselines[agentId][0];
345
+ euint64 bF = _agentBaselines[agentId][1];
346
+ euint64 bC = _agentBaselines[agentId][2];
347
+
348
+ euint64 diffT = FHE.select(FHE.lt(oT, bT), FHE.sub(bT, oT), FHE.sub(oT, bT));
349
+ euint64 diffF = FHE.select(FHE.lt(oF, bF), FHE.sub(bF, oF), FHE.sub(oF, bF));
350
+ euint64 diffC = FHE.select(FHE.lt(oC, bC), FHE.sub(bC, oC), FHE.sub(oC, bC));
351
+
352
+ euint64 drift = FHE.add(
353
+ FHE.add(FHE.mul(diffT, diffT), FHE.mul(diffF, diffF)),
354
+ FHE.mul(diffC, diffC)
355
+ );
356
+
357
+ ebool isCompromised = FHE.gt(drift, FHE.asEuint64(maxBehaviorDrift));
358
+ FHE.allowThis(isCompromised);
359
+
360
+ bytes32[] memory cts = new bytes32[](1);
361
+ cts[0] = ebool.unwrap(isCompromised);
362
+
363
+ requestId = FHE.requestDecryption(cts, this.fulfillBehaviorCheck.selector);
364
+ behaviorRequests[requestId] = agentId;
365
+
366
+ emit BehaviorCheckRequested(agentId, requestId);
367
+ }
368
+
369
+ function fulfillBehaviorCheck(
370
+ uint256 requestId,
371
+ bytes memory cleartexts,
372
+ bytes memory decryptionProof
373
+ ) external {
374
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
375
+
376
+ bool isCompromised = abi.decode(cleartexts, (bool));
377
+ uint256 agentId = behaviorRequests[requestId];
378
+ delete behaviorRequests[requestId];
379
+
380
+ agentBehaviorCompromised[agentId] = isCompromised;
381
+ emit BehaviorChecked(agentId, isCompromised);
382
+ }
383
+ }
contracts/CipherTrust.sol ADDED
@@ -0,0 +1,824 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.24;
3
+
4
+ import {FHE, euint64, ebool, externalEuint64} from "@fhevm/solidity/lib/FHE.sol";
5
+ import {SepoliaConfig} from "@fhevm/solidity/config/ZamaConfig.sol";
6
+
7
+ interface IReputationBadge {
8
+ function mintOrUpgrade(uint256 agentId, address operator, uint8 tier) external;
9
+ function tierOf(uint256 agentId) external view returns (uint8);
10
+ }
11
+
12
+ interface IInsurancePool {
13
+ function receivePenalty(uint256 agentId) external payable;
14
+ function delegateCredit(uint256 agentId, uint256 amount) external;
15
+ function repayCredit(uint256 agentId) external payable;
16
+ }
17
+
18
+ /**
19
+ * @title CipherTrust
20
+ * @notice Confidential underwriting protocol for autonomous agents & robots.
21
+ *
22
+ * Autonomous AI trading bots, delivery robots, drone fleets, and DePIN devices
23
+ * increasingly hold funds and execute tasks without human supervision. There is
24
+ * no confidential way today to score their reliability and price the
25
+ * collateral/insurance they must post -- any naive on-chain reputation system
26
+ * leaks competitively sensitive operational data (uptime, error rates, routes,
27
+ * strategy performance) to rivals, because blockchains are public by default.
28
+ *
29
+ * CipherTrust computes a rolling trust score and a required collateral bond
30
+ * entirely under Fully Homomorphic Encryption. Operators, insurers, and task
31
+ * marketplaces can rely on the *outcome* (bond tier, sufficiency check)
32
+ * without ever seeing the raw encrypted telemetry that produced it.
33
+ *
34
+ * v0.2 additions (see docs/COMPETITIVE_ANALYSIS.md for why these were added):
35
+ * - Multi-oracle quorum: telemetry only affects the score once N independent
36
+ * oracles agree within a round, reducing single-oracle trust assumptions.
37
+ * - Async confidential slashing: an oracle can request a confidential SLA
38
+ * breach check; the breach flag is decrypted via Zama's public-decrypt +
39
+ * signature-verification flow before any penalty is applied on-chain.
40
+ * - Optional composability hooks into a soulbound ReputationBadge (public,
41
+ * selectively-revealed trust tier) and an InsurancePool (LP yield funded
42
+ * by slashing penalties), so other protocols can build on CipherTrust's
43
+ * output without ever touching an agent's raw telemetry.
44
+ *
45
+ * NOTE: this is an MVP scaffold. Verify every FHE.* call (especially the
46
+ * makePubliclyDecryptable / checkSignatures async-decrypt flow) against the
47
+ * exact current version of fhevm-solidity pinned in package.json before
48
+ * deploying to a live network -- the FHE Solidity API surface evolves
49
+ * between releases, and this flow has not yet been compiled/tested.
50
+ */
51
+ contract CipherTrust is SepoliaConfig {
52
+ address public admin;
53
+ uint256 public nextAgentId;
54
+
55
+ struct Agent {
56
+ address operator;
57
+ bool registered;
58
+ bool active;
59
+ uint256 identityId; // optional link into AgentIdentityRegistry, 0 if unset
60
+ euint64 trustScore; // encrypted, 0-1000 scale
61
+ euint64 requiredBond; // encrypted, wei
62
+ uint256 postedBond; // public collateral currently deposited (wei)
63
+ ebool bondSufficient; // encrypted boolean: postedBond >= requiredBond
64
+ uint256 breachCount; // public count of confirmed SLA breaches
65
+ uint256 trustScoreVar; // estimation uncertainty variance, initialized to 100 (public)
66
+ euint64 liquidationThreshold; // encrypted minimum trust score before liquidation
67
+ uint256 delegatedBond; // public delegated bond amount borrowed from the pool (wei)
68
+ uint256 interestAccumulated; // public interest accumulated (wei)
69
+ uint256 lastInterestUpdateTime; // timestamp of the last yield accrual
70
+ }
71
+
72
+ struct Task {
73
+ uint256 agentId;
74
+ address client;
75
+ uint256 coverageLimit; // maximum ETH coverage (wei)
76
+ bool active;
77
+ }
78
+
79
+ struct Lease {
80
+ address lessee;
81
+ uint256 agentId;
82
+ uint256 hardwareId;
83
+ uint256 requiredBond; // underwriting bond (wei)
84
+ uint256 startTimestamp;
85
+ bool active;
86
+ }
87
+
88
+ uint256 public nextTaskId = 1;
89
+ mapping(uint256 => Task) public tasks;
90
+
91
+ uint256 public nextLeaseId = 1;
92
+ mapping(uint256 => Lease) public leases;
93
+ mapping(address => uint256) public userActiveLeaseId;
94
+ mapping(uint256 => uint256) public claimRequestTask; // decryption requestId => taskId
95
+ mapping(uint256 => uint256) public agentActiveTaskId; // agentId => active taskId (0 if none)
96
+
97
+ struct PendingRound {
98
+ uint32 count;
99
+ bool initialized;
100
+ euint64 sumCompletion;
101
+ euint64 sumUptime;
102
+ euint64 sumLatency;
103
+ euint64 sumError;
104
+ }
105
+
106
+ mapping(uint256 => Agent) private _agents;
107
+ mapping(address => bool) public authorizedOracles;
108
+ mapping(address => bool) public authorizedUnderwriters;
109
+
110
+ // FHE-Stream: Confidential Staking Yields & Payroll Streams
111
+ struct SalaryStream {
112
+ euint64 flowRate;
113
+ uint256 lastClaimBlock;
114
+ bool active;
115
+ }
116
+ mapping(address => SalaryStream) private _salaryStreams;
117
+ mapping(uint256 => address) public streamRequests;
118
+
119
+ mapping(uint256 => PendingRound) private _pendingRounds; // agentId => in-flight quorum round
120
+ mapping(uint256 => uint256) public currentRoundId; // agentId => round id
121
+ mapping(uint256 => mapping(address => uint256)) private _oracleLastRound; // agentId => oracle => last round id + 1 submitted
122
+ uint32 public quorumThreshold = 1; // number of independent oracles required per round
123
+
124
+ uint256 public nextTierRequestId = 1;
125
+ mapping(uint256 => uint256) public tierRequestAgent;
126
+ mapping(uint256 => bytes32) public tierRequestHandle;
127
+
128
+ uint256 public nextSlashRequestId = 1;
129
+ mapping(uint256 => uint256) public slashRequestAgent;
130
+ mapping(uint256 => bytes32) public slashRequestHandle;
131
+
132
+ uint256 public nextLiquidationRequestId = 1;
133
+ mapping(uint256 => uint256) public liquidationRequestAgent;
134
+
135
+ IReputationBadge public reputationBadge;
136
+ IInsurancePool public insurancePool;
137
+
138
+ // FHE-ML Neural Perceptron Weights (Underwriter Configurable)
139
+ uint32 public weightCompletion = 40;
140
+ uint32 public weightUptime = 30;
141
+ uint32 public weightLatency = 15;
142
+ uint32 public weightError = 80;
143
+ uint32 public neuronBias = 200;
144
+ uint32 public maxNeuralRiskThreshold = 1200; // ReLU risk limit
145
+
146
+ uint64 private constant W_COMPLETION = 40;
147
+ uint64 private constant W_UPTIME = 30;
148
+ uint64 private constant W_LATENCY = 15;
149
+ uint64 private constant W_ERROR = 15;
150
+
151
+ uint64 private constant HIGH_TRUST_THRESHOLD = 750;
152
+ uint64 private constant MED_TRUST_THRESHOLD = 400;
153
+
154
+ uint64 private constant HIGH_TRUST_BOND = uint64(0.1 ether);
155
+ uint64 private constant MED_TRUST_BOND = uint64(1 ether);
156
+ uint64 private constant LOW_TRUST_BOND = uint64(5 ether);
157
+
158
+ uint256 private constant SLASH_BPS = 1000; // 10% of posted bond
159
+ uint256 private constant ORACLE_VAR = 50;
160
+ uint256 private constant PREMIUM_PER_VAR_WEI = 0.04 ether; // 0.04 ETH per unit of variance
161
+
162
+ event AgentRegistered(uint256 indexed agentId, address indexed operator, uint256 identityId);
163
+ event OracleAuthorized(address indexed oracle);
164
+ event UnderwriterAuthorized(address indexed underwriter);
165
+ event TelemetrySubmitted(uint256 indexed agentId, address indexed oracle, uint256 roundId);
166
+ event ScoreUpdated(uint256 indexed agentId, uint256 roundId);
167
+ event BondDeposited(uint256 indexed agentId, uint256 amount, uint256 totalPosted);
168
+ event BondWithdrawn(uint256 indexed agentId, uint256 amount);
169
+ event TierRevealRequested(uint256 indexed agentId, uint256 indexed requestId);
170
+ event TierRevealed(uint256 indexed agentId, uint64 tierCode);
171
+ event SlashCheckRequested(uint256 indexed agentId, uint256 indexed requestId);
172
+ event SlashCheckFulfilled(uint256 indexed agentId, bool breached);
173
+ event AgentSlashed(uint256 indexed agentId, uint256 penalty);
174
+ event AgentLiquidated(uint256 indexed agentId, uint256 slashedAmount);
175
+ event LiquidationCheckRequested(uint256 indexed agentId, uint256 indexed requestId);
176
+ event TaskRegistered(uint256 indexed taskId, uint256 indexed agentId, address indexed client, uint256 coverageLimit);
177
+ event ClaimPaid(uint256 indexed taskId, uint256 indexed agentId, address indexed client, uint256 payoutAmount);
178
+ event NeuronWeightsUpdated(uint32 wComp, uint32 wUpt, uint32 wLat, uint32 wErr, uint32 bias, uint32 threshold);
179
+ event ReputationBadgeSet(address indexed badge);
180
+ event InsurancePoolSet(address indexed pool);
181
+ event LeaseRequested(uint256 indexed leaseId, address indexed lessee, uint256 hardwareId, uint256 requiredBond);
182
+ event LeaseSettled(uint256 indexed leaseId, address indexed lessee, uint256 hardwareId, bool success, uint256 payout);
183
+ event SalaryStreamCreated(address indexed recipient);
184
+ event StreamClaimRequested(address indexed recipient, uint256 indexed requestId);
185
+ event StreamClaimed(address indexed recipient, uint256 amount);
186
+
187
+ modifier onlyAdmin() {
188
+ require(msg.sender == admin);
189
+ _;
190
+ }
191
+
192
+ modifier onlyOracle() {
193
+ require(authorizedOracles[msg.sender]);
194
+ _;
195
+ }
196
+
197
+ modifier onlyAgentOperator(uint256 agentId) {
198
+ require(_agents[agentId].operator == msg.sender);
199
+ _;
200
+ }
201
+
202
+ constructor() {
203
+ admin = msg.sender;
204
+ }
205
+
206
+ function setQuorumThreshold(uint32 threshold) external onlyAdmin {
207
+ require(threshold >= 1);
208
+ quorumThreshold = threshold;
209
+ }
210
+
211
+ function setReputationBadge(address badge) external onlyAdmin {
212
+ require(address(reputationBadge) == address(0));
213
+ reputationBadge = IReputationBadge(badge);
214
+ emit ReputationBadgeSet(badge);
215
+ }
216
+
217
+ function setInsurancePool(address pool) external onlyAdmin {
218
+ require(address(insurancePool) == address(0));
219
+ insurancePool = IInsurancePool(pool);
220
+ emit InsurancePoolSet(pool);
221
+ }
222
+
223
+ function authorizeOracle(address oracle) external onlyAdmin {
224
+ authorizedOracles[oracle] = true;
225
+ emit OracleAuthorized(oracle);
226
+ }
227
+
228
+ function authorizeUnderwriter(address underwriter) external onlyAdmin {
229
+ authorizedUnderwriters[underwriter] = true;
230
+ emit UnderwriterAuthorized(underwriter);
231
+ }
232
+
233
+ /// @notice Register a new autonomous agent/robot under a given operator.
234
+ /// @param identityId optional AgentIdentityRegistry id (0 if not using the registry).
235
+ function registerAgent(address operator, uint256 identityId) external onlyAdmin returns (uint256 agentId) {
236
+ agentId = nextAgentId++;
237
+ Agent storage a = _agents[agentId];
238
+ a.operator = operator;
239
+ a.registered = true;
240
+ a.active = true;
241
+ a.identityId = identityId;
242
+ a.trustScore = FHE.asEuint64(500); // neutral starting score
243
+ a.trustScoreVar = 100;
244
+ a.liquidationThreshold = FHE.asEuint64(300);
245
+ a.requiredBond = _deriveBond(a.trustScore, 100);
246
+ a.delegatedBond = 0;
247
+ a.interestAccumulated = 0;
248
+ a.lastInterestUpdateTime = block.timestamp;
249
+
250
+ FHE.allowThis(a.trustScore);
251
+ FHE.allowThis(a.requiredBond);
252
+ FHE.allowThis(a.liquidationThreshold);
253
+ FHE.allow(a.trustScore, operator);
254
+ FHE.allow(a.requiredBond, operator);
255
+ FHE.allow(a.liquidationThreshold, operator);
256
+
257
+ emit AgentRegistered(agentId, operator, identityId);
258
+ }
259
+
260
+ /// @notice Submit fully-encrypted telemetry for a completed task. Only
261
+ /// authorized oracles may call this. The submission only affects the
262
+ /// agent's score once `quorumThreshold` independent oracles have
263
+ /// submitted within the current round.
264
+ function submitTelemetry(
265
+ uint256 agentId,
266
+ externalEuint64 completionScoreA,
267
+ externalEuint64 completionScoreB,
268
+ externalEuint64 uptimeScore,
269
+ externalEuint64 latencyScore,
270
+ externalEuint64 errorScore,
271
+ bytes calldata inputProof
272
+ ) external onlyOracle {
273
+ Agent storage a = _agents[agentId];
274
+ require(a.registered && a.active);
275
+
276
+ uint256 roundId = currentRoundId[agentId];
277
+ require(_oracleLastRound[agentId][msg.sender] != roundId + 1);
278
+ _oracleLastRound[agentId][msg.sender] = roundId + 1;
279
+
280
+ euint64 compA = FHE.fromExternal(completionScoreA, inputProof);
281
+ euint64 compB = FHE.fromExternal(completionScoreB, inputProof);
282
+ euint64 uptime = FHE.fromExternal(uptimeScore, inputProof);
283
+ euint64 latency = FHE.fromExternal(latencyScore, inputProof);
284
+ euint64 errorP = FHE.fromExternal(errorScore, inputProof);
285
+
286
+ // Compute absolute differences for anomaly detection (Completion only)
287
+ ebool compAltB = FHE.lt(compA, compB);
288
+ euint64 compDiff = FHE.select(compAltB, FHE.sub(compB, compA), FHE.sub(compA, compB));
289
+ ebool compAnomaly = FHE.gt(compDiff, FHE.asEuint64(2));
290
+
291
+ // Apply sensor fusion outlier filter
292
+ euint64 completion = FHE.select(compAnomaly, FHE.asEuint64(0), FHE.div(FHE.add(compA, compB), 2));
293
+ uptime = FHE.select(compAnomaly, FHE.asEuint64(0), uptime);
294
+ latency = FHE.select(compAnomaly, FHE.asEuint64(0), latency);
295
+ errorP = FHE.select(compAnomaly, FHE.asEuint64(10), errorP);
296
+
297
+ PendingRound storage round = _pendingRounds[agentId];
298
+ if (!round.initialized) {
299
+ round.sumCompletion = completion;
300
+ round.sumUptime = uptime;
301
+ round.sumLatency = latency;
302
+ round.sumError = errorP;
303
+ round.initialized = true;
304
+ } else {
305
+ round.sumCompletion = FHE.add(round.sumCompletion, completion);
306
+ round.sumUptime = FHE.add(round.sumUptime, uptime);
307
+ round.sumLatency = FHE.add(round.sumLatency, latency);
308
+ round.sumError = FHE.add(round.sumError, errorP);
309
+ }
310
+ round.count += 1;
311
+ FHE.allowThis(round.sumCompletion);
312
+ FHE.allowThis(round.sumUptime);
313
+ FHE.allowThis(round.sumLatency);
314
+ FHE.allowThis(round.sumError);
315
+
316
+ emit TelemetrySubmitted(agentId, msg.sender, roundId);
317
+
318
+ if (round.count >= quorumThreshold) {
319
+ euint64 avgCompletion = FHE.div(round.sumCompletion, quorumThreshold);
320
+ euint64 avgUptime = FHE.div(round.sumUptime, quorumThreshold);
321
+ euint64 avgLatency = FHE.div(round.sumLatency, quorumThreshold);
322
+ euint64 avgError = FHE.div(round.sumError, quorumThreshold);
323
+
324
+ _applyScoreUpdate(agentId, avgCompletion, avgUptime, avgLatency, avgError);
325
+
326
+ delete _pendingRounds[agentId];
327
+ currentRoundId[agentId] = roundId + 1;
328
+ emit ScoreUpdated(agentId, roundId);
329
+ }
330
+ }
331
+
332
+ function _applyScoreUpdate(
333
+ uint256 agentId,
334
+ euint64 completion,
335
+ euint64 uptime,
336
+ euint64 latency,
337
+ euint64 errorP
338
+ ) private {
339
+ Agent storage a = _agents[agentId];
340
+
341
+ euint64 weightedObs = FHE.add(
342
+ FHE.add(FHE.mul(completion, W_COMPLETION), FHE.mul(uptime, W_UPTIME)),
343
+ FHE.mul(latency, W_LATENCY)
344
+ );
345
+ euint64 penalty = FHE.mul(errorP, W_ERROR);
346
+
347
+ ebool obsUnderflow = FHE.lt(weightedObs, penalty);
348
+ euint64 x_obs = FHE.select(obsUnderflow, FHE.asEuint64(0), FHE.sub(weightedObs, penalty));
349
+
350
+ // Bayesian Update for variance and weights
351
+ uint256 oldVar = a.trustScoreVar;
352
+ uint256 newVar = (oldVar * ORACLE_VAR) / (oldVar + ORACLE_VAR);
353
+ if (newVar < 10) {
354
+ newVar = 10;
355
+ }
356
+ a.trustScoreVar = newVar;
357
+
358
+ uint256 alpha = (ORACLE_VAR * 100) / (oldVar + ORACLE_VAR);
359
+ uint256 beta = (oldVar * 100) / (oldVar + ORACLE_VAR);
360
+
361
+ // Weighted FHE score update
362
+ euint64 term1 = FHE.mul(a.trustScore, uint64(alpha));
363
+ euint64 term2 = FHE.mul(x_obs, uint64(beta));
364
+ euint64 newScore = FHE.div(FHE.add(term1, term2), 100);
365
+
366
+ a.trustScore = newScore;
367
+ a.requiredBond = _deriveBond(newScore, newVar);
368
+
369
+ uint256 dt = block.timestamp - a.lastInterestUpdateTime;
370
+ a.lastInterestUpdateTime = block.timestamp;
371
+ if (dt > 0 && a.delegatedBond > 0) {
372
+ uint256 apr = 500; // default 5% APR
373
+ if (address(reputationBadge) != address(0)) {
374
+ uint8 tier = reputationBadge.tierOf(agentId);
375
+ if (tier == 3) apr = 100;
376
+ else if (tier == 2) apr = 500;
377
+ else if (tier == 1) apr = 2500;
378
+ }
379
+ uint256 interestAcc = (a.delegatedBond * apr * dt) / 8640000000;
380
+ a.interestAccumulated += interestAcc;
381
+ }
382
+
383
+ euint64 totalCollateral = FHE.add(FHE.asEuint64(uint64(_clampToU64(a.postedBond))), FHE.asEuint64(uint64(_clampToU64(a.delegatedBond))));
384
+ a.bondSufficient = FHE.ge(totalCollateral, a.requiredBond);
385
+
386
+ FHE.allowThis(a.trustScore);
387
+ FHE.allowThis(a.requiredBond);
388
+ FHE.allowThis(a.bondSufficient);
389
+ FHE.allow(a.trustScore, a.operator);
390
+ FHE.allow(a.requiredBond, a.operator);
391
+ // On-chain FHE Perceptron (Confidential AI Model Inference)
392
+ euint64 positiveRisk = FHE.add(
393
+ FHE.add(FHE.mul(latency, weightLatency), FHE.mul(errorP, weightError)),
394
+ FHE.asEuint64(neuronBias)
395
+ );
396
+ euint64 negativeRisk = FHE.add(
397
+ FHE.mul(completion, weightCompletion),
398
+ FHE.mul(uptime, weightUptime)
399
+ );
400
+
401
+ ebool riskUnderflow = FHE.lt(positiveRisk, negativeRisk);
402
+ euint64 neuralRisk = FHE.select(riskUnderflow, FHE.asEuint64(0), FHE.sub(positiveRisk, negativeRisk));
403
+ ebool isNeuralBreach = FHE.gt(neuralRisk, FHE.asEuint64(maxNeuralRiskThreshold));
404
+
405
+ ebool breachedLimit = FHE.or(FHE.lt(newScore, a.liquidationThreshold), isNeuralBreach);
406
+ euint64 severity = FHE.sub(FHE.asEuint64(1000), newScore);
407
+
408
+ bytes32[] memory cts = new bytes32[](2);
409
+ cts[0] = ebool.unwrap(breachedLimit);
410
+ cts[1] = euint64.unwrap(severity);
411
+
412
+ uint256 reqId = FHE.requestDecryption(cts, this.fulfillLiquidation.selector);
413
+ liquidationRequestAgent[reqId] = agentId;
414
+ emit LiquidationCheckRequested(agentId, reqId);
415
+ }
416
+
417
+ /// @dev Confidential decision-tree: three bond tiers selected entirely
418
+ /// under encryption via FHE.select, plus a dynamic uncertainty premium.
419
+ function _deriveBond(euint64 score, uint256 variance) private returns (euint64) {
420
+ ebool highTrust = FHE.ge(score, FHE.asEuint64(HIGH_TRUST_THRESHOLD));
421
+ ebool medTrust = FHE.ge(score, FHE.asEuint64(MED_TRUST_THRESHOLD));
422
+
423
+ euint64 baseBond = FHE.select(medTrust, FHE.asEuint64(MED_TRUST_BOND), FHE.asEuint64(LOW_TRUST_BOND));
424
+ baseBond = FHE.select(highTrust, FHE.asEuint64(HIGH_TRUST_BOND), baseBond);
425
+
426
+ uint256 premium = variance * PREMIUM_PER_VAR_WEI;
427
+ return FHE.add(baseBond, FHE.asEuint64(uint64(premium)));
428
+ }
429
+
430
+ function _clampToU64(uint256 value) private pure returns (uint256) {
431
+ uint256 maxU64 = type(uint64).max;
432
+ return value > maxU64 ? maxU64 : value;
433
+ }
434
+
435
+ /// @notice Operator posts native-token collateral for an agent.
436
+ function depositBond(uint256 agentId) external payable onlyAgentOperator(agentId) {
437
+ require(msg.value > 0);
438
+ Agent storage a = _agents[agentId];
439
+ a.postedBond += msg.value;
440
+ a.bondSufficient = FHE.ge(FHE.asEuint64(uint64(_clampToU64(a.postedBond))), a.requiredBond);
441
+ FHE.allowThis(a.bondSufficient);
442
+ FHE.allow(a.bondSufficient, a.operator);
443
+ emit BondDeposited(agentId, msg.value, a.postedBond);
444
+ }
445
+
446
+ /// @notice Operator withdraws excess collateral. Confidential sufficiency
447
+ /// should be re-checked off-chain via the relayer SDK before withdrawing,
448
+ /// since the exact required bond stays encrypted on-chain.
449
+ function withdrawBond(uint256 agentId, uint256 amount) external onlyAgentOperator(agentId) {
450
+ Agent storage a = _agents[agentId];
451
+ require(amount <= a.postedBond);
452
+ a.postedBond -= amount;
453
+ a.bondSufficient = FHE.ge(FHE.asEuint64(uint64(_clampToU64(a.postedBond))), a.requiredBond);
454
+ FHE.allowThis(a.bondSufficient);
455
+ FHE.allow(a.bondSufficient, a.operator);
456
+ payable(msg.sender).transfer(amount);
457
+ emit BondWithdrawn(agentId, amount);
458
+ }
459
+
460
+ /// @notice Grant an authorized underwriter/insurer read access to an
461
+ /// agent's encrypted trust score, required bond, and sufficiency flag --
462
+ /// without exposing the raw telemetry that produced them.
463
+ function grantUnderwriterAccess(uint256 agentId, address underwriter) external onlyAgentOperator(agentId) {
464
+ require(authorizedUnderwriters[underwriter]);
465
+ Agent storage a = _agents[agentId];
466
+ FHE.allow(a.trustScore, underwriter);
467
+ FHE.allow(a.requiredBond, underwriter);
468
+ FHE.allow(a.bondSufficient, underwriter);
469
+ }
470
+
471
+ /// @notice Operator opts in to publicly reveal only the *tier* (Low/Medium/High)
472
+ /// of their agent's trust score -- never the exact score -- so a soulbound
473
+ /// ReputationBadge can be minted/upgraded. This is a selective disclosure,
474
+ /// not a default: the raw score stays encrypted unless the operator calls this.
475
+ function requestTierReveal(uint256 agentId) external onlyAgentOperator(agentId) returns (uint256 requestId) {
476
+ Agent storage a = _agents[agentId];
477
+ ebool highTrust = FHE.ge(a.trustScore, FHE.asEuint64(HIGH_TRUST_THRESHOLD));
478
+ ebool medTrust = FHE.ge(a.trustScore, FHE.asEuint64(MED_TRUST_THRESHOLD));
479
+ euint64 tierCode = FHE.select(highTrust, FHE.asEuint64(3), FHE.select(medTrust, FHE.asEuint64(2), FHE.asEuint64(1)));
480
+
481
+ bytes32[] memory cts = new bytes32[](1);
482
+ cts[0] = euint64.unwrap(tierCode);
483
+ requestId = FHE.requestDecryption(cts, this.fulfillTierReveal.selector);
484
+
485
+ tierRequestAgent[requestId] = agentId;
486
+ emit TierRevealRequested(agentId, requestId);
487
+ }
488
+
489
+ /// @notice Called with the Zama KMS's decrypted cleartext + proof (via the
490
+ /// relayer SDK's public-decrypt flow) to finalize a tier reveal.
491
+ function fulfillTierReveal(uint256 requestId, bytes memory cleartexts, bytes memory decryptionProof) external {
492
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
493
+
494
+ uint64 tierCode = abi.decode(cleartexts, (uint64));
495
+ uint256 agentId = tierRequestAgent[requestId];
496
+ delete tierRequestAgent[requestId];
497
+
498
+ if (address(reputationBadge) != address(0)) {
499
+ reputationBadge.mintOrUpgrade(agentId, _agents[agentId].operator, uint8(tierCode));
500
+ }
501
+ emit TierRevealed(agentId, tierCode);
502
+ }
503
+
504
+ /// @notice An authorized oracle flags a possible SLA breach with an
505
+ /// encrypted 0/1 signal. Nothing happens on-chain until the flag is
506
+ /// confidentially checked and revealed via fulfillSlashCheck.
507
+ function requestSlashCheck(
508
+ uint256 agentId,
509
+ externalEuint64 breachSignal,
510
+ bytes calldata inputProof
511
+ ) external onlyOracle returns (uint256 requestId) {
512
+ Agent storage a = _agents[agentId];
513
+ require(a.registered);
514
+
515
+ euint64 signal = FHE.fromExternal(breachSignal, inputProof);
516
+ ebool breached = FHE.eq(signal, FHE.asEuint64(1));
517
+
518
+ bytes32[] memory cts = new bytes32[](1);
519
+ cts[0] = ebool.unwrap(breached);
520
+ requestId = FHE.requestDecryption(cts, this.fulfillSlashCheck.selector);
521
+
522
+ slashRequestAgent[requestId] = agentId;
523
+ emit SlashCheckRequested(agentId, requestId);
524
+ }
525
+
526
+ /// @notice Finalizes a slash check using the Zama KMS's decrypted
527
+ /// cleartext + proof. If breached, 10% of the posted bond is slashed and
528
+ /// forwarded to the InsurancePool (if configured) as LP yield.
529
+ function fulfillSlashCheck(uint256 requestId, bytes memory cleartexts, bytes memory decryptionProof) external {
530
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
531
+
532
+ bool breached = abi.decode(cleartexts, (bool));
533
+ uint256 agentId = slashRequestAgent[requestId];
534
+ delete slashRequestAgent[requestId];
535
+
536
+ if (breached) {
537
+ Agent storage a = _agents[agentId];
538
+ uint256 penalty = (a.postedBond * SLASH_BPS) / 10000;
539
+ if (penalty > 0) {
540
+ a.postedBond -= penalty;
541
+ a.breachCount += 1;
542
+ a.bondSufficient = FHE.ge(FHE.asEuint64(uint64(_clampToU64(a.postedBond))), a.requiredBond);
543
+ FHE.allowThis(a.bondSufficient);
544
+ FHE.allow(a.bondSufficient, a.operator);
545
+
546
+ if (address(insurancePool) != address(0)) {
547
+ insurancePool.receivePenalty{value: penalty}(agentId);
548
+ }
549
+ emit AgentSlashed(agentId, penalty);
550
+ }
551
+ }
552
+ emit SlashCheckFulfilled(agentId, breached);
553
+ }
554
+
555
+ /// @notice Finalizes a liquidation check using the Zama KMS's decrypted
556
+ /// cleartext + proof. If breached, the agent is deactivated and its remaining
557
+ /// posted bond is fully slashed to the InsurancePool.
558
+ function fulfillLiquidation(uint256 requestId, bytes memory cleartexts, bytes memory decryptionProof) external {
559
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
560
+
561
+ (bool breached, uint256 severity) = abi.decode(cleartexts, (bool, uint256));
562
+ uint256 agentId = liquidationRequestAgent[requestId];
563
+ delete liquidationRequestAgent[requestId];
564
+
565
+ if (breached) {
566
+ Agent storage a = _agents[agentId];
567
+ a.active = false;
568
+
569
+ uint256 selfBond = a.postedBond;
570
+ uint256 borrowedBond = a.delegatedBond;
571
+
572
+ a.postedBond = 0;
573
+ a.delegatedBond = 0;
574
+ a.bondSufficient = FHE.asEbool(false);
575
+ FHE.allowThis(a.bondSufficient);
576
+ FHE.allow(a.bondSufficient, a.operator);
577
+
578
+ uint256 totalBond = selfBond + borrowedBond;
579
+ uint256 payoutAmount = 0;
580
+ uint256 taskId = agentActiveTaskId[agentId];
581
+
582
+ if (taskId > 0 && tasks[taskId].active) {
583
+ payoutAmount = (tasks[taskId].coverageLimit * severity) / 1000;
584
+ if (payoutAmount > totalBond) {
585
+ payoutAmount = totalBond;
586
+ }
587
+
588
+ Task storage t = tasks[taskId];
589
+ t.active = false;
590
+ agentActiveTaskId[agentId] = 0;
591
+
592
+ if (payoutAmount > 0) {
593
+ payable(t.client).transfer(payoutAmount);
594
+ emit ClaimPaid(taskId, agentId, t.client, payoutAmount);
595
+ }
596
+ }
597
+
598
+ uint256 remainder = totalBond - payoutAmount;
599
+ if (remainder > 0) {
600
+ if (address(insurancePool) != address(0)) {
601
+ insurancePool.receivePenalty{value: remainder}(agentId);
602
+ }
603
+ emit AgentLiquidated(agentId, remainder);
604
+ }
605
+ }
606
+ }
607
+
608
+ function getAgent(uint256 agentId)
609
+ external
610
+ view
611
+ returns (address operator, bool registered, bool active, uint256 postedBond, uint256 breachCount, uint256 identityId, uint256 trustScoreVar)
612
+ {
613
+ Agent storage a = _agents[agentId];
614
+ return (a.operator, a.registered, a.active, a.postedBond, a.breachCount, a.identityId, a.trustScoreVar);
615
+ }
616
+
617
+ function getEncryptedTrustScore(uint256 agentId) external view returns (euint64) {
618
+ return _agents[agentId].trustScore;
619
+ }
620
+
621
+ function getEncryptedRequiredBond(uint256 agentId) external view returns (euint64) {
622
+ return _agents[agentId].requiredBond;
623
+ }
624
+
625
+ function getEncryptedBondSufficiency(uint256 agentId) external view returns (ebool) {
626
+ return _agents[agentId].bondSufficient;
627
+ }
628
+
629
+ function getDelegatedBond(uint256 agentId) external view returns (uint256) {
630
+ return _agents[agentId].delegatedBond;
631
+ }
632
+
633
+ function getInterestAccumulated(uint256 agentId) external view returns (uint256) {
634
+ return _agents[agentId].interestAccumulated;
635
+ }
636
+
637
+ event CreditDelegated(uint256 indexed agentId, uint256 amount);
638
+ event InterestRepaid(uint256 indexed agentId, uint256 amount);
639
+
640
+ function requestCreditDelegation(uint256 agentId, uint256 amount) external {
641
+ Agent storage a = _agents[agentId];
642
+ require(msg.sender == a.operator);
643
+ require(a.registered && a.active);
644
+ require(address(insurancePool) != address(0));
645
+
646
+ insurancePool.delegateCredit(agentId, amount);
647
+
648
+ a.delegatedBond += amount;
649
+ euint64 totalCollateral = FHE.add(FHE.asEuint64(uint64(_clampToU64(a.postedBond))), FHE.asEuint64(uint64(_clampToU64(a.delegatedBond))));
650
+ a.bondSufficient = FHE.ge(totalCollateral, a.requiredBond);
651
+
652
+ FHE.allowThis(a.bondSufficient);
653
+ FHE.allow(a.bondSufficient, a.operator);
654
+
655
+ emit CreditDelegated(agentId, amount);
656
+ }
657
+
658
+ function repayInterest(uint256 agentId) external payable {
659
+ Agent storage a = _agents[agentId];
660
+ require(a.registered && a.active);
661
+ require(msg.value > 0);
662
+
663
+ if (msg.value >= a.interestAccumulated) {
664
+ a.interestAccumulated = 0;
665
+ } else {
666
+ a.interestAccumulated -= msg.value;
667
+ }
668
+
669
+ insurancePool.repayCredit{value: msg.value}(agentId);
670
+
671
+ emit InterestRepaid(agentId, msg.value);
672
+ }
673
+
674
+ function registerUnderwrittenTask(uint256 agentId, address client, uint256 coverageLimit) external returns (uint256 taskId) {
675
+ Agent storage a = _agents[agentId];
676
+ require(msg.sender == a.operator || msg.sender == admin);
677
+ require(a.registered && a.active);
678
+ require(agentActiveTaskId[agentId] == 0);
679
+
680
+ uint256 totalCollateral = a.postedBond + a.delegatedBond;
681
+ require(totalCollateral >= coverageLimit);
682
+
683
+ taskId = nextTaskId++;
684
+ Task storage t = tasks[taskId];
685
+ t.agentId = agentId;
686
+ t.client = client;
687
+ t.coverageLimit = coverageLimit;
688
+ t.active = true;
689
+
690
+ agentActiveTaskId[agentId] = taskId;
691
+
692
+ emit TaskRegistered(taskId, agentId, client, coverageLimit);
693
+ }
694
+
695
+ function deactivateAgent(uint256 agentId) external onlyAdmin {
696
+ _agents[agentId].active = false;
697
+ }
698
+
699
+ function updateNeuronWeights(
700
+ uint32 wComp,
701
+ uint32 wUpt,
702
+ uint32 wLat,
703
+ uint32 wErr,
704
+ uint32 bias,
705
+ uint32 threshold
706
+ ) external onlyAdmin {
707
+ weightCompletion = wComp;
708
+ weightUptime = wUpt;
709
+ weightLatency = wLat;
710
+ weightError = wErr;
711
+ neuronBias = bias;
712
+ maxNeuralRiskThreshold = threshold;
713
+
714
+ emit NeuronWeightsUpdated(wComp, wUpt, wLat, wErr, bias, threshold);
715
+ }
716
+
717
+ function requestLeaseHardware(
718
+ uint256 agentId,
719
+ uint256 hardwareId,
720
+ uint256 leaseBond
721
+ ) external returns (uint256 leaseId) {
722
+ Agent storage a = _agents[agentId];
723
+ require(msg.sender == a.operator);
724
+ require(a.registered && a.active);
725
+ require(address(reputationBadge) != address(0));
726
+ require(address(insurancePool) != address(0));
727
+ require(userActiveLeaseId[msg.sender] == 0);
728
+
729
+ uint8 tier = reputationBadge.tierOf(agentId);
730
+ require(tier >= 2);
731
+
732
+ insurancePool.delegateCredit(agentId, leaseBond);
733
+
734
+ leaseId = nextLeaseId++;
735
+ Lease storage l = leases[leaseId];
736
+ l.lessee = msg.sender;
737
+ l.agentId = agentId;
738
+ l.hardwareId = hardwareId;
739
+ l.requiredBond = leaseBond;
740
+ l.startTimestamp = block.timestamp;
741
+ l.active = true;
742
+
743
+ userActiveLeaseId[msg.sender] = leaseId;
744
+
745
+ emit LeaseRequested(leaseId, msg.sender, hardwareId, leaseBond);
746
+ }
747
+
748
+ function settleLeaseHardware(uint256 leaseId, bool success) external onlyAdmin {
749
+ Lease storage l = leases[leaseId];
750
+ require(l.active);
751
+
752
+ l.active = false;
753
+ userActiveLeaseId[l.lessee] = 0;
754
+
755
+ uint256 payout = 0;
756
+ if (!success) {
757
+ payout = l.requiredBond;
758
+ payable(admin).transfer(payout);
759
+ } else {
760
+ insurancePool.repayCredit{value: l.requiredBond}(l.agentId);
761
+ }
762
+
763
+ emit LeaseSettled(leaseId, l.lessee, l.hardwareId, success, payout);
764
+ }
765
+
766
+ // FHE-Stream: Confidential Salary & Yield Streaming Implementation
767
+ function createSalaryStream(
768
+ address recipient,
769
+ externalEuint64 hRate,
770
+ bytes calldata inputProof
771
+ ) external onlyAdmin {
772
+ require(!_salaryStreams[recipient].active);
773
+
774
+ _salaryStreams[recipient].flowRate = FHE.fromExternal(hRate, inputProof);
775
+ _salaryStreams[recipient].lastClaimBlock = block.number;
776
+ _salaryStreams[recipient].active = true;
777
+
778
+ FHE.allow(_salaryStreams[recipient].flowRate, recipient);
779
+ FHE.allowThis(_salaryStreams[recipient].flowRate);
780
+
781
+ emit SalaryStreamCreated(recipient);
782
+ }
783
+
784
+ function claimSalaryStream() external returns (uint256 requestId) {
785
+ address recipient = msg.sender;
786
+ SalaryStream storage stream = _salaryStreams[recipient];
787
+ require(stream.active);
788
+ require(block.number > stream.lastClaimBlock);
789
+
790
+ uint256 blocksAccrued = block.number - stream.lastClaimBlock;
791
+ stream.lastClaimBlock = block.number;
792
+
793
+ euint64 accrued = FHE.mul(stream.flowRate, uint64(blocksAccrued));
794
+ FHE.allowThis(accrued);
795
+
796
+ bytes32[] memory cts = new bytes32[](1);
797
+ cts[0] = euint64.unwrap(accrued);
798
+
799
+ requestId = FHE.requestDecryption(cts, this.fulfillStreamClaim.selector);
800
+ streamRequests[requestId] = recipient;
801
+
802
+ emit StreamClaimRequested(recipient, requestId);
803
+ }
804
+
805
+ function fulfillStreamClaim(
806
+ uint256 requestId,
807
+ bytes memory cleartexts,
808
+ bytes memory decryptionProof
809
+ ) external {
810
+ FHE.checkSignatures(requestId, cleartexts, decryptionProof);
811
+
812
+ uint256 amount = abi.decode(cleartexts, (uint256));
813
+ address recipient = streamRequests[requestId];
814
+ delete streamRequests[requestId];
815
+
816
+ if (amount > 0) {
817
+ payable(recipient).transfer(amount);
818
+ }
819
+
820
+ emit StreamClaimed(recipient, amount);
821
+ }
822
+
823
+ receive() external payable {}
824
+ }
contracts/InsurancePool.sol ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.24;
3
+
4
+ /// @title InsurancePool
5
+ /// @notice Composable underwriting-yield pool. Liquidity providers stake native token and
6
+ /// earn a share of every confidential slashing penalty collected by CipherTrust when an
7
+ /// autonomous agent breaches its SLA. This is a deliberately plain, fully transparent DeFi
8
+ /// primitive that composes with CipherTrust's confidential risk engine without ever needing
9
+ /// to see any agent's encrypted telemetry or trust score -- a concrete demonstration of
10
+ /// Season 3's "Composable Privacy" theme.
11
+ contract InsurancePool {
12
+ address public admin;
13
+ address public cipherTrust;
14
+
15
+ uint256 public totalShares;
16
+ uint256 public totalAssets;
17
+ mapping(address => uint256) public sharesOf;
18
+
19
+ event Staked(address indexed provider, uint256 amount, uint256 shares);
20
+ event Withdrawn(address indexed provider, uint256 amount, uint256 shares);
21
+ event PenaltyReceived(uint256 indexed agentId, uint256 amount);
22
+ event CipherTrustSet(address indexed cipherTrust);
23
+ event CreditDelegated(uint256 indexed agentId, uint256 amount);
24
+ event CreditRepaid(uint256 indexed agentId, uint256 amount);
25
+
26
+ modifier onlyAdmin() {
27
+ require(msg.sender == admin, "InsurancePool: not admin");
28
+ _;
29
+ }
30
+
31
+ modifier onlyCipherTrust() {
32
+ require(msg.sender == cipherTrust, "InsurancePool: not CipherTrust");
33
+ _;
34
+ }
35
+
36
+ constructor() {
37
+ admin = msg.sender;
38
+ }
39
+
40
+ function setCipherTrust(address cipherTrust_) external onlyAdmin {
41
+ require(cipherTrust == address(0), "InsurancePool: already set");
42
+ cipherTrust = cipherTrust_;
43
+ emit CipherTrustSet(cipherTrust_);
44
+ }
45
+
46
+ function stake() external payable returns (uint256 shares) {
47
+ require(msg.value > 0, "InsurancePool: zero stake");
48
+ shares = totalShares == 0 ? msg.value : (msg.value * totalShares) / totalAssets;
49
+ totalShares += shares;
50
+ totalAssets += msg.value;
51
+ sharesOf[msg.sender] += shares;
52
+ emit Staked(msg.sender, msg.value, shares);
53
+ }
54
+
55
+ function withdraw(uint256 shares) external {
56
+ require(shares > 0 && shares <= sharesOf[msg.sender], "InsurancePool: bad shares");
57
+ uint256 amount = (shares * totalAssets) / totalShares;
58
+ sharesOf[msg.sender] -= shares;
59
+ totalShares -= shares;
60
+ totalAssets -= amount;
61
+ payable(msg.sender).transfer(amount);
62
+ emit Withdrawn(msg.sender, amount, shares);
63
+ }
64
+
65
+ /// @notice Called by CipherTrust when a confidential SLA breach results in a slashing
66
+ /// penalty. The pool grows in value for existing stakers without minting new shares --
67
+ /// this is the pool's yield.
68
+ function receivePenalty(uint256 agentId) external payable onlyCipherTrust {
69
+ totalAssets += msg.value;
70
+ emit PenaltyReceived(agentId, msg.value);
71
+ }
72
+
73
+ function pricePerShare() external view returns (uint256) {
74
+ if (totalShares == 0) return 1e18;
75
+ return (totalAssets * 1e18) / totalShares;
76
+ }
77
+
78
+ function delegateCredit(uint256 agentId, uint256 amount) external onlyCipherTrust {
79
+ require(totalAssets >= amount, "InsurancePool: insufficient assets for credit delegation");
80
+ totalAssets -= amount;
81
+ payable(cipherTrust).transfer(amount);
82
+ emit CreditDelegated(agentId, amount);
83
+ }
84
+
85
+ function repayCredit(uint256 agentId) external payable onlyCipherTrust {
86
+ totalAssets += msg.value;
87
+ emit CreditRepaid(agentId, msg.value);
88
+ }
89
+ }
contracts/ReputationBadge.sol ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.24;
3
+
4
+ import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
5
+
6
+ /// @title ReputationBadge
7
+ /// @notice Soulbound (non-transferable) ERC-721 badge representing an autonomous agent's
8
+ /// *publicly revealed* trust tier -- never the exact encrypted score. CipherTrust's core
9
+ /// contract calls mintOrUpgrade only after the operator opts in to a confidential tier
10
+ /// reveal, so the badge is a public, composable attestation that other protocols
11
+ /// (insurers, marketplaces, DAOs) can check with a single view call, with zero on-chain
12
+ /// exposure of the underlying telemetry or exact score.
13
+ contract ReputationBadge is ERC721 {
14
+ enum Tier {
15
+ Unrated,
16
+ Low,
17
+ Medium,
18
+ High
19
+ }
20
+
21
+ address public admin;
22
+ address public cipherTrust;
23
+ mapping(uint256 => Tier) public tierOf; // agentId => tier
24
+ mapping(uint256 => bool) private _minted;
25
+
26
+ event CipherTrustSet(address indexed cipherTrust);
27
+ event BadgeUpgraded(uint256 indexed agentId, Tier tier);
28
+
29
+ modifier onlyAdmin() {
30
+ require(msg.sender == admin, "ReputationBadge: not admin");
31
+ _;
32
+ }
33
+
34
+ modifier onlyCipherTrust() {
35
+ require(msg.sender == cipherTrust, "ReputationBadge: not CipherTrust");
36
+ _;
37
+ }
38
+
39
+ constructor() ERC721("CipherTrust Reputation Badge", "CTRUST") {
40
+ admin = msg.sender;
41
+ }
42
+
43
+ function setCipherTrust(address cipherTrust_) external onlyAdmin {
44
+ require(cipherTrust == address(0), "ReputationBadge: already set");
45
+ cipherTrust = cipherTrust_;
46
+ emit CipherTrustSet(cipherTrust_);
47
+ }
48
+
49
+ function mintOrUpgrade(uint256 agentId, address operator, uint8 tier) external onlyCipherTrust {
50
+ if (!_minted[agentId]) {
51
+ _minted[agentId] = true;
52
+ _safeMint(operator, agentId);
53
+ }
54
+ tierOf[agentId] = Tier(tier);
55
+ emit BadgeUpgraded(agentId, Tier(tier));
56
+ }
57
+
58
+ function tokenURI(uint256 tokenId) public view override returns (string memory) {
59
+ _requireOwned(tokenId);
60
+ Tier tier = tierOf[tokenId];
61
+ string memory tierName = tier == Tier.High ? "High" : tier == Tier.Medium ? "Medium" : tier == Tier.Low
62
+ ? "Low"
63
+ : "Unrated";
64
+ return
65
+ string(
66
+ abi.encodePacked(
67
+ "data:application/json;utf8,{\"name\":\"CipherTrust Agent #",
68
+ _toString(tokenId),
69
+ "\",\"attributes\":[{\"trait_type\":\"Trust Tier\",\"value\":\"",
70
+ tierName,
71
+ "\"}]}"
72
+ )
73
+ );
74
+ }
75
+
76
+ function _update(address to, uint256 tokenId, address auth) internal override returns (address) {
77
+ address from = _ownerOf(tokenId);
78
+ require(from == address(0) || to == address(0), "ReputationBadge: soulbound, non-transferable");
79
+ return super._update(to, tokenId, auth);
80
+ }
81
+
82
+ function _toString(uint256 value) internal pure returns (string memory) {
83
+ if (value == 0) return "0";
84
+ uint256 temp = value;
85
+ uint256 digits;
86
+ while (temp != 0) {
87
+ digits++;
88
+ temp /= 10;
89
+ }
90
+ bytes memory buffer = new bytes(digits);
91
+ while (value != 0) {
92
+ digits -= 1;
93
+ buffer[digits] = bytes1(uint8(48 + (value % 10)));
94
+ value /= 10;
95
+ }
96
+ return string(buffer);
97
+ }
98
+ }
hardhat.config.ts ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { HardhatUserConfig } from "hardhat/config";
2
+ import "@nomicfoundation/hardhat-toolbox";
3
+ // import "@fhevm/hardhat-plugin";
4
+ import * as dotenv from "dotenv";
5
+
6
+ dotenv.config();
7
+
8
+ const PRIVATE_KEY = process.env.PRIVATE_KEY ?? "";
9
+ const SEPOLIA_RPC_URL = process.env.SEPOLIA_RPC_URL ?? "";
10
+
11
+ const config: HardhatUserConfig = {
12
+ solidity: {
13
+ version: "0.8.24",
14
+ settings: {
15
+ optimizer: {
16
+ enabled: true,
17
+ runs: 1,
18
+ details: {
19
+ yul: true,
20
+ yulDetails: {
21
+ stackAllocation: true
22
+ }
23
+ }
24
+ },
25
+ evmVersion: "cancun",
26
+ viaIR: true,
27
+ },
28
+ },
29
+ networks: {
30
+ hardhat: {
31
+ allowUnlimitedContractSize: true,
32
+ },
33
+ sepolia: {
34
+ url: SEPOLIA_RPC_URL,
35
+ accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
36
+ chainId: 11155111,
37
+ },
38
+ baseSepolia: {
39
+ url: "https://sepolia.base.org",
40
+ accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
41
+ chainId: 84532,
42
+ },
43
+ },
44
+ };
45
+
46
+ export default config;
package.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "cipherpool-fhevm",
3
+ "version": "0.2.0",
4
+ "description": "CipherTrust: confidential underwriting protocol for autonomous agents & robots, built on Zama's fhEVM.",
5
+ "license": "MIT",
6
+ "scripts": {
7
+ "compile": "hardhat compile",
8
+ "test": "hardhat test",
9
+ "deploy:sepolia": "hardhat run scripts/deploy.ts --network sepolia"
10
+ },
11
+ "devDependencies": {
12
+ "@fhevm/hardhat-plugin": "^0.1.0",
13
+ "@fhevm/solidity": "^0.8.0",
14
+ "@fhevm/mock-utils": "0.1.0",
15
+ "@zama-fhe/oracle-solidity": "^0.1.0",
16
+ "@zama-fhe/relayer-sdk": "^0.2.0",
17
+ "@nomicfoundation/hardhat-chai-matchers": "^2.0.0",
18
+ "@nomicfoundation/hardhat-ethers": "^3.0.0",
19
+ "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0",
20
+ "@nomicfoundation/hardhat-ignition": "^0.15.0",
21
+ "@nomicfoundation/ignition-core": "^0.15.0",
22
+ "@nomicfoundation/hardhat-network-helpers": "^1.0.0",
23
+ "@nomicfoundation/hardhat-toolbox": "^5.0.0",
24
+ "@nomicfoundation/hardhat-verify": "^2.0.0",
25
+ "@typechain/ethers-v6": "^0.5.0",
26
+ "@typechain/hardhat": "^9.0.0",
27
+ "@types/chai": "^4.2.0",
28
+ "@types/mocha": "^10.0.10",
29
+ "chai": "^4.2.0",
30
+ "dotenv": "^16.4.5",
31
+ "hardhat": "^2.22.0",
32
+ "hardhat-gas-reporter": "^1.0.8",
33
+ "solidity-coverage": "^0.8.1",
34
+ "ts-node": "^10.9.2",
35
+ "typechain": "^8.3.0",
36
+ "typescript": "^5.5.0"
37
+ },
38
+ "dependencies": {
39
+ "@openzeppelin/contracts": "^5.0.2",
40
+ "ethers": "^6.13.0"
41
+ }
42
+ }
scripts/deploy.ts ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ethers } from "hardhat";
2
+
3
+ async function main() {
4
+ const [deployer] = await ethers.getSigners();
5
+ console.log("Deploying CipherTrust with account:", deployer.address);
6
+
7
+ const CipherTrust = await ethers.getContractFactory("CipherTrust");
8
+ const cipherTrust = await CipherTrust.deploy();
9
+ console.log("CipherTrust deploy tx sent. Hash:", cipherTrust.deploymentTransaction()?.hash);
10
+ await cipherTrust.waitForDeployment();
11
+ console.log("CipherTrust deployed to:", await cipherTrust.getAddress());
12
+
13
+ const CipherAuth = await ethers.getContractFactory("CipherAuth");
14
+ const cipherAuth = await CipherAuth.deploy();
15
+ console.log("CipherAuth deploy tx sent. Hash:", cipherAuth.deploymentTransaction()?.hash);
16
+ await cipherAuth.waitForDeployment();
17
+ console.log("CipherAuth deployed to:", await cipherAuth.getAddress());
18
+ }
19
+
20
+ main().catch((error) => {
21
+ console.error(error);
22
+ process.exitCode = 1;
23
+ });
scripts/deploy_auth.ts ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ethers } from "hardhat";
2
+
3
+ async function main() {
4
+ const [deployer] = await ethers.getSigners();
5
+ console.log("Deploying CipherAuth with account:", deployer.address);
6
+
7
+ const CipherAuth = await ethers.getContractFactory("CipherAuth");
8
+ const cipherAuth = await CipherAuth.deploy();
9
+ console.log("CipherAuth deploy tx sent. Hash:", cipherAuth.deploymentTransaction()?.hash);
10
+ await cipherAuth.waitForDeployment();
11
+ console.log("CipherAuth deployed to:", await cipherAuth.getAddress());
12
+ }
13
+
14
+ main().catch((error) => {
15
+ console.error(error);
16
+ process.exitCode = 1;
17
+ });
scripts/optimize_contract.js ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const filePath = path.join(__dirname, '../contracts/CipherTrust.sol');
5
+ let code = fs.readFileSync(filePath, 'utf8');
6
+
7
+ console.log("Original code length:", code.length);
8
+
9
+ // Robust replacement of require with strings
10
+ // Matches require(expression, "string") even with nested parentheses inside expression
11
+ let count = 0;
12
+ code = code.replace(/require\s*\(([^;]+?),\s*"[^"]+?"\s*\)/g, (match, p1) => {
13
+ count++;
14
+ return `require(${p1.trim()})`;
15
+ });
16
+
17
+ console.log(`Replaced ${count} require statements.`);
18
+
19
+ fs.writeFileSync(filePath, code);
20
+ console.log("Optimization complete.");
scripts/oracle_service.ts ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ethers } from "hardhat";
2
+ import * as dotenv from "dotenv";
3
+ import * as http from "http";
4
+
5
+ dotenv.config();
6
+
7
+ // HF Spaces compatibility: Respond to health check pings on port 7860
8
+ const port = process.env.PORT || 7860;
9
+ http.createServer((req, res) => {
10
+ res.writeHead(200, { "Content-Type": "text/plain" });
11
+ res.end("CipherTrust Oracle Daemon is Running!\n");
12
+ }).listen(port, () => {
13
+ console.log(`HF Health Check Server listening on port ${port}`);
14
+ });
15
+
16
+ async function main() {
17
+ const cipherTrustAddress = process.env.CIPHERTRUST_ADDRESS;
18
+ if (!cipherTrustAddress) {
19
+ console.error("Error: CIPHERTRUST_ADDRESS environment variable not set.");
20
+ process.exit(1);
21
+ }
22
+
23
+ console.log("======================================================================");
24
+ const provider = new ethers.JsonRpcProvider(process.env.RPC_URL || process.env.SEPOLIA_RPC_URL || "http://localhost:8545");
25
+ const wallet = new ethers.Wallet(process.env.PRIVATE_KEY || "", provider);
26
+ console.log(`Starting CipherTrust Telemetry Oracle Daemon: ${wallet.address}`);
27
+ console.log(`Target Protocol Contract Address: ${cipherTrustAddress}`);
28
+ console.log("======================================================================");
29
+
30
+ // Core execution loop
31
+ while (true) {
32
+ try {
33
+ console.log(`[${new Date().toLocaleTimeString()}] Fetching agent telemetry coordinates...`);
34
+
35
+ // Simulate real-time physical drone telemetry
36
+ const x = Math.floor(Math.random() * 80) + 10;
37
+ const y = Math.floor(Math.random() * 80) + 10;
38
+
39
+ // Compute correct distance squares to beacons: A(10,10), B(90,10), C(50,80)
40
+ const distA = Math.pow(x - 10, 2) + Math.pow(y - 10, 2);
41
+ const distB = Math.pow(x - 90, 2) + Math.pow(y - 10, 2);
42
+ const distC = Math.pow(x - 50, 2) + Math.pow(y - 80, 2);
43
+
44
+ console.log(`Generated Coordinates: (${x}, ${y}) | DistSq: A=${distA}, B=${distB}, C=${distC}`);
45
+ console.log("Pushing telemetry update successfully simulated.");
46
+ } catch (e) {
47
+ console.error("Error in oracle execution loop:", e);
48
+ }
49
+
50
+ // Wait for next telemetry submission round (e.g. 60 seconds)
51
+ await new Promise((resolve) => setTimeout(resolve, 60000));
52
+ }
53
+ }
54
+
55
+ main().catch((error) => {
56
+ console.error(error);
57
+ process.exit(1);
58
+ });
scripts/setup_database.sql ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- ==========================================
2
+ -- CipherTrust Protocol: Supabase Database Setup
3
+ -- Run this script inside your Supabase SQL Editor
4
+ -- ==========================================
5
+
6
+ -- Enable UUID extension for secure random IDs
7
+ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
8
+
9
+ -- Table: Autonomous Agents / Robots Registry
10
+ CREATE TABLE IF NOT EXISTS agents (
11
+ id SERIAL PRIMARY KEY,
12
+ agent_id INT UNIQUE NOT NULL,
13
+ operator_address VARCHAR(42) NOT NULL,
14
+ registered_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
15
+ active BOOLEAN DEFAULT TRUE,
16
+ trust_variance INT DEFAULT 100,
17
+ public_reputation_badge VARCHAR(42) DEFAULT NULL
18
+ );
19
+
20
+ -- Index for agent query optimizations
21
+ CREATE INDEX IF NOT EXISTS idx_agents_operator ON agents(operator_address);
22
+
23
+ -- Table: Redundant Telemetry Audits
24
+ CREATE TABLE IF NOT EXISTS telemetry_rounds (
25
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
26
+ agent_id INT REFERENCES agents(agent_id) ON DELETE CASCADE,
27
+ round_id INT NOT NULL,
28
+ submitted_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
29
+ sensor_a_reading INT NOT NULL,
30
+ sensor_b_reading INT NOT NULL,
31
+ is_anomaly BOOLEAN DEFAULT FALSE
32
+ );
33
+
34
+ CREATE INDEX IF NOT EXISTS idx_telemetry_agent_round ON telemetry_rounds(agent_id, round_id);
35
+
36
+ -- Table: Location Triangulation Log
37
+ CREATE TABLE IF NOT EXISTS location_proofs (
38
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
39
+ operator_address VARCHAR(42) NOT NULL,
40
+ calculated_x INT NOT NULL,
41
+ calculated_y INT NOT NULL,
42
+ distance_sq_a INT NOT NULL,
43
+ distance_sq_b INT NOT NULL,
44
+ distance_sq_c INT NOT NULL,
45
+ verified BOOLEAN NOT NULL,
46
+ timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
47
+ );
48
+
49
+ -- Table: Multi-Factor Authentication Audits
50
+ CREATE TABLE IF NOT EXISTS auth_audits (
51
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
52
+ user_address VARCHAR(42) NOT NULL,
53
+ auth_type VARCHAR(30) NOT NULL, -- 'biometrics', 'passwordless', 'passport'
54
+ status VARCHAR(15) NOT NULL, -- 'success', 'failed'
55
+ timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
56
+ );
57
+
58
+ CREATE INDEX IF NOT EXISTS idx_auth_user ON auth_audits(user_address);
scripts/simulate_agent.ts ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import hre from "hardhat";
2
+
3
+ async function main() {
4
+ console.log("======================================================================");
5
+ console.log(" CipherTrust: Autonomous Agent Flight & Attack Simulation Script ");
6
+ console.log("======================================================================\n");
7
+
8
+ const [admin, operator, oracle1, oracle2, stranger] = await hre.ethers.getSigners();
9
+ const ctAddress = "0x0000000000000000000000000000000000000000"; // Mock deploy or real depending on hardhat network
10
+
11
+ console.log("[1/6] Deploying CipherTrust Protocol Contract Suite...");
12
+ const ReputationBadge = await hre.ethers.getContractFactory("ReputationBadge");
13
+ const reputationBadge = await ReputationBadge.connect(admin).deploy();
14
+ await reputationBadge.waitForDeployment();
15
+ console.log(` -> ReputationBadge SB-NFT deployed to: ${await reputationBadge.getAddress()}`);
16
+
17
+ const InsurancePool = await hre.ethers.getContractFactory("InsurancePool");
18
+ const insurancePool = await InsurancePool.connect(admin).deploy();
19
+ await insurancePool.waitForDeployment();
20
+ console.log(` -> InsurancePool deployed to: ${await insurancePool.getAddress()}`);
21
+
22
+ const CipherTrust = await hre.ethers.getContractFactory("CipherTrust");
23
+ const cipherTrust = await CipherTrust.connect(admin).deploy();
24
+ await cipherTrust.waitForDeployment();
25
+ console.log(` -> CipherTrust Core deployed to: ${await cipherTrust.getAddress()}`);
26
+
27
+ // Linked contracts
28
+ await (await reputationBadge.connect(admin).setCipherTrust(await cipherTrust.getAddress())).wait();
29
+ await (await insurancePool.connect(admin).setCipherTrust(await cipherTrust.getAddress())).wait();
30
+ await (await cipherTrust.connect(admin).setReputationBadge(await reputationBadge.getAddress())).wait();
31
+ await (await cipherTrust.connect(admin).setInsurancePool(await insurancePool.getAddress())).wait();
32
+
33
+ // Authorize Oracles
34
+ await (await cipherTrust.connect(admin).authorizeOracle(oracle1.address)).wait();
35
+ await (await cipherTrust.connect(admin).authorizeOracle(oracle2.address)).wait();
36
+ await (await cipherTrust.connect(admin).setQuorumThreshold(2)).wait();
37
+ console.log(" -> Oracles authorized. Quorum threshold set to 2.\n");
38
+
39
+ console.log("[2/6] Initializing Underwriting Capital (InsurancePool Staking)...");
40
+ // Stranger stakes 10 ETH into the InsurancePool
41
+ await (await insurancePool.connect(stranger).stake({ value: hre.ethers.parseEther("10") })).wait();
42
+ console.log(` -> Stranger staked 10 ETH. Insurance Pool Assets: ${hre.ethers.formatEther(await insurancePool.totalAssets())} ETH\n`);
43
+
44
+ console.log("[3/6] Registering Autonomous Delivery Drone & Requesting Credit Delegation...");
45
+ // Register drone agent #0
46
+ await (await cipherTrust.connect(admin).registerAgent(operator.address, 0)).wait();
47
+ console.log(" -> Delivery Drone Agent #0 registered.");
48
+
49
+ let agent = await cipherTrust.getAgent(0);
50
+ console.log(` -> Initial Uncertainty Variance (σ²): ${agent.trustScoreVar}`);
51
+ let reqBond = await hre.fhevm.debugger.decryptEuint(5, await cipherTrust.getEncryptedRequiredBond(0));
52
+ console.log(` -> Initial Required Collateral Bond: ${hre.ethers.formatEther(reqBond)} ETH`);
53
+
54
+ // Operator borrows bond from InsurancePool (Credit Delegation)
55
+ await (await cipherTrust.connect(operator).requestCreditDelegation(0, hre.ethers.parseEther("5"))).wait();
56
+ console.log(` -> Borrowed 5 ETH from InsurancePool. Delegated Bond staked: ${hre.ethers.formatEther(await cipherTrust.getDelegatedBond(0))} ETH`);
57
+
58
+ let sufficient = await hre.fhevm.debugger.decryptEbool(await cipherTrust.getEncryptedBondSufficiency(0));
59
+ console.log(` -> Collateral Sufficiency Status under FHE: ${sufficient ? "SUFFICIENT (Ready for Operations)" : "INSUFFICIENT"}\n`);
60
+
61
+ console.log("[4/6] Executing Flight Telemetry Round 1 (Normal Operations)...");
62
+ // Redundant sensor readings: Sensor A = 9, Sensor B = 9, Uptime = 9, Latency = 9, Error = 0
63
+ const scoreVal = 9;
64
+ const errVal = 0;
65
+ const targetAddress = await cipherTrust.getAddress();
66
+
67
+ // Oracle 1 attestation
68
+ const input1 = hre.fhevm.createEncryptedInput(targetAddress, oracle1.address);
69
+ input1.add64(scoreVal); // compA
70
+ input1.add64(scoreVal); // compB
71
+ input1.add64(scoreVal); // uptime
72
+ input1.add64(scoreVal); // latency
73
+ input1.add64(errVal); // error
74
+ const encrypted1 = await input1.encrypt();
75
+ await (
76
+ await cipherTrust.connect(oracle1).submitTelemetry(
77
+ 0,
78
+ encrypted1.handles[0],
79
+ encrypted1.handles[1],
80
+ encrypted1.handles[2],
81
+ encrypted1.handles[3],
82
+ encrypted1.handles[4],
83
+ encrypted1.inputProof
84
+ )
85
+ ).wait();
86
+
87
+ // Oracle 2 attestation
88
+ const input2 = hre.fhevm.createEncryptedInput(targetAddress, oracle2.address);
89
+ input2.add64(scoreVal);
90
+ input2.add64(scoreVal);
91
+ input2.add64(scoreVal);
92
+ input2.add64(scoreVal);
93
+ input2.add64(errVal);
94
+ const encrypted2 = await input2.encrypt();
95
+ await (
96
+ await cipherTrust.connect(oracle2).submitTelemetry(
97
+ 0,
98
+ encrypted2.handles[0],
99
+ encrypted2.handles[1],
100
+ encrypted2.handles[2],
101
+ encrypted2.handles[3],
102
+ encrypted2.handles[4],
103
+ encrypted2.inputProof
104
+ )
105
+ ).wait();
106
+
107
+ // Fast forward block time to simulate operations
108
+ await hre.ethers.provider.send("evm_increaseTime", [172800]); // 2 days
109
+ await hre.ethers.provider.send("evm_mine", []);
110
+
111
+ agent = await cipherTrust.getAgent(0);
112
+ let score = await hre.fhevm.debugger.decryptEuint(5, await cipherTrust.getEncryptedTrustScore(0));
113
+ let bond = await hre.fhevm.debugger.decryptEuint(5, await cipherTrust.getEncryptedRequiredBond(0));
114
+ let interest = await cipherTrust.getInterestAccumulated(0);
115
+
116
+ console.log(` -> Telemetry Round processed. Bayesian Trust Score: ${score}/1000`);
117
+ console.log(` -> Uncertainty Variance (σ²) decayed to: ${agent.trustScoreVar}`);
118
+ console.log(` -> Required Bond reduced to: ${hre.ethers.formatEther(bond)} ETH`);
119
+ console.log(` -> Accumulated Interest accrued to Pool: ${hre.ethers.formatEther(interest)} ETH\n`);
120
+
121
+ console.log("[5/6] Simulating GPS Spoofing Attack (Sensor Outlier Filtration)...");
122
+ // Sensors disagree: Sensor A reports 9 (normal), Sensor B reports 3 (spoofed location drift)
123
+ const inputAttack1 = hre.fhevm.createEncryptedInput(targetAddress, oracle1.address);
124
+ inputAttack1.add64(9); // compA (healthy)
125
+ inputAttack1.add64(3); // compB (spoofed drift > 2)
126
+ inputAttack1.add64(9); // uptime
127
+ inputAttack1.add64(9); // latency
128
+ inputAttack1.add64(0); // error
129
+ const encryptedAttack1 = await inputAttack1.encrypt();
130
+ await (
131
+ await cipherTrust.connect(oracle1).submitTelemetry(
132
+ 0,
133
+ encryptedAttack1.handles[0],
134
+ encryptedAttack1.handles[1],
135
+ encryptedAttack1.handles[2],
136
+ encryptedAttack1.handles[3],
137
+ encryptedAttack1.handles[4],
138
+ encryptedAttack1.inputProof
139
+ )
140
+ ).wait();
141
+
142
+ const inputAttack2 = hre.fhevm.createEncryptedInput(targetAddress, oracle2.address);
143
+ inputAttack2.add64(9);
144
+ inputAttack2.add64(3);
145
+ inputAttack2.add64(9);
146
+ inputAttack2.add64(9);
147
+ inputAttack2.add64(0);
148
+ const encryptedAttack2 = await inputAttack2.encrypt();
149
+ await (
150
+ await cipherTrust.connect(oracle2).submitTelemetry(
151
+ 0,
152
+ encryptedAttack2.handles[0],
153
+ encryptedAttack2.handles[1],
154
+ encryptedAttack2.handles[2],
155
+ encryptedAttack2.handles[3],
156
+ encryptedAttack2.handles[4],
157
+ encryptedAttack2.inputProof
158
+ )
159
+ ).wait();
160
+
161
+ // Await decryption oracle to run FHE checks
162
+ await hre.fhevm.awaitDecryptionOracle();
163
+
164
+ score = await hre.fhevm.debugger.decryptEuint(5, await cipherTrust.getEncryptedTrustScore(0));
165
+ console.log(" -> [SUCCESS] Sensor fusion drift check triggered under FHE.");
166
+ console.log(" -> [SUCCESS] Spoofed Sensor B discarded. Anomaly penalty applied.");
167
+ console.log(` -> Penalized Bayesian Trust Score: ${score}/1000\n`);
168
+
169
+ console.log("[6/6] Simulating Catastrophic Malfunction (FHE Auto-Liquidation)...");
170
+ // Multiple rounds of failure/errors to push trust score below 300
171
+ const inputFail1 = hre.fhevm.createEncryptedInput(targetAddress, oracle1.address);
172
+ inputFail1.add64(1);
173
+ inputFail1.add64(1);
174
+ inputFail1.add64(1);
175
+ inputFail1.add64(1);
176
+ inputFail1.add64(10); // extreme error rate
177
+ const encryptedFail1 = await inputFail1.encrypt();
178
+ await (
179
+ await cipherTrust.connect(oracle1).submitTelemetry(
180
+ 0,
181
+ encryptedFail1.handles[0],
182
+ encryptedFail1.handles[1],
183
+ encryptedFail1.handles[2],
184
+ encryptedFail1.handles[3],
185
+ encryptedFail1.handles[4],
186
+ encryptedFail1.inputProof
187
+ )
188
+ ).wait();
189
+
190
+ const inputFail2 = hre.fhevm.createEncryptedInput(targetAddress, oracle2.address);
191
+ inputFail2.add64(1);
192
+ inputFail2.add64(1);
193
+ inputFail2.add64(1);
194
+ inputFail2.add64(1);
195
+ inputFail2.add64(10);
196
+ const encryptedFail2 = await inputFail2.encrypt();
197
+ await (
198
+ await cipherTrust.connect(oracle2).submitTelemetry(
199
+ 0,
200
+ encryptedFail2.handles[0],
201
+ encryptedFail2.handles[1],
202
+ encryptedFail2.handles[2],
203
+ encryptedFail2.handles[3],
204
+ encryptedFail2.handles[4],
205
+ encryptedFail2.inputProof
206
+ )
207
+ ).wait();
208
+
209
+ // Await decryption oracle to finalize liquidation check
210
+ await hre.fhevm.awaitDecryptionOracle();
211
+
212
+ agent = await cipherTrust.getAgent(0);
213
+ console.log(" -> [SUCCESS] FHE trust score fell below liquidation threshold (300).");
214
+ console.log(` -> Agent Active Status: ${agent.active ? "ACTIVE" : "INACTIVE / DEACTIVATED"}`);
215
+ console.log(` -> Slashed Bond remaining: ${hre.ethers.formatEther(agent.postedBond)} ETH`);
216
+ console.log(` -> Slashed Bond recovered to InsurancePool: ${hre.ethers.formatEther(await insurancePool.totalAssets())} ETH\n`);
217
+
218
+ console.log("======================================================================");
219
+ console.log(" Simulation Completed Successfully! ");
220
+ console.log("======================================================================");
221
+ }
222
+
223
+ main().catch((error) => {
224
+ console.error(error);
225
+ process.exitCode = 1;
226
+ });
tsconfig.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2020",
4
+ "module": "commonjs",
5
+ "moduleResolution": "node",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "outDir": "dist"
11
+ },
12
+ "include": ["./scripts/oracle_service.ts"],
13
+ "exclude": ["node_modules"]
14
+ }