@agenticprimitives/contracts 1.0.0-alpha.21 → 1.0.0-alpha.23

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.
package/README.md CHANGED
@@ -78,3 +78,12 @@ Trust infrastructure should be the most transparent code you depend on, so the a
78
78
  Testnet/pilot-ready. Production launch is gated on the public checklist in the root README — including third-party contract audit and governance key rotation. Track every security finding live in [`docs/audits/findings.yaml`](../../docs/audits/findings.yaml).
79
79
 
80
80
  **Production deployment is deliberately deferred:** the testnet uses a publicly disclosed deployer EOA on purpose (it keeps the demo reproducible). The production rotation runbook is [`AUDIT.md` § 4.1](./AUDIT.md#41-the-production-gate-open-audit-item-n1).
81
+
82
+ ## Incremental ontology scripts
83
+
84
+ | Script | Adds | Notes |
85
+ | --- | --- | --- |
86
+ | `script/AddAgentTypeRoots.s.sol` | typed roots + `atl:AgentTypeEnum` members (spec 346) | one `PermissionlessSubregistry` per root |
87
+ | `script/AddVerticalRoots.s.sol` | app-registered vertical roots + `atl:agentSubtype` (spec 346 §2.4) | vocabulary is the app's |
88
+ | `script/AddDistributionPredicate.s.sol` | `atl:distribution` (string JSON per `AgentDistributionV1`, spec 347 §8.5) | idempotent; run 2026-08-30 on faithchain (34348) + Base Sepolia |
89
+ | `script/AddCardPredicates.s.sol` | `atl:cardDigest` (bytes32) + `atl:cardUri` (string) (spec 347 §8.3); `UPDATE_SHAPE=true` refreshes `atl:AgentName` to shape v2 (14 props) | idempotent; run 2026-08-30 on faithchain (34348) + Base Sepolia |
@@ -35,5 +35,16 @@
35
35
  "agentRegistryBase": "0xB18534CA9c679968132ca2a43E454f5fA341030D",
36
36
  "agenticGovernance": "0x27c1F21ffA275e61Fe152Edd4f2676fD6a816dDa",
37
37
  "timelockController": "0xeB66E0B92287E53BB5A80bD2a01002150249DC94",
38
- "governanceGuardian": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44"
38
+ "governanceGuardian": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44",
39
+ "permissionlessSubregistries": {
40
+ "me": "0xDEABb2Ed8382775a01752f171bC4c625AcD15A71",
41
+ "org": "0x13D2cabD890C93eF24937cc19dcDdc2a4d914418",
42
+ "team": "0xC80e6B102721F6D0b158124E0095D3B12d941126",
43
+ "svc": "0xcf6d51c105E83621FcFA58D89a3846B8090352b4",
44
+ "workspace": "0x9f8b948a9a18C68dBF862cE61444112A93d9A491",
45
+ "treasury": "0xDFA05aa99B1C5dA606a438eaF7eD3b52a231E385",
46
+ "registry": "0x32d3a37f44614959049b9f19D610554e8D4aBD6C",
47
+ "church": "0x97402E5A152670f356Eab9fD4270e1c8888ffc87",
48
+ "circle": "0xE194187c64c45803eda55BC399A4e7d39C1449A6"
49
+ }
39
50
  }
@@ -0,0 +1,49 @@
1
+ {
2
+ "agentAccountFactory": "0x464eEe7518c3c97DA570592481329E0627E9a3B8",
3
+ "agentAccountImplementation": "0x8691bFE5Cd0bf532050e27d4fF0Cd1F82d1aE9a7",
4
+ "agentNameRegistry": "0x60E949D52660A9D4143ecB0fdA56c0457f20aED9",
5
+ "agentNameResolver": "0xa5855906C0De3813E74BEe201973071e0c844115",
6
+ "agentNameUniversalResolver": "0xF343054e046A4145ccae499ECB28197394eE0798",
7
+ "agentProfileResolver": "0xB03F7C06ad3274F584AB72794406D639c02A45e1",
8
+ "agentRelationship": "0x5015bD7d422e003511246f848cDd798cb00BB968",
9
+ "agreementRegistry": "0x5b580E741DBb4f57F6D885dF2c12F4e0B53B6f50",
10
+ "allowedMethodsEnforcer": "0xdBb2E47793393C499efB0f3fcbf6Ca8669791a41",
11
+ "allowedTargetsEnforcer": "0x2156311097A936de1916a878bF53Bfd43c7b5715",
12
+ "approvedHashRegistry": "0xC6a4983bC6649f7C46c9E7d83f1Cd7e9078AFc7b",
13
+ "attestationRegistry": "0x4c94A0355380b8F5023eDd5f8A8131B020de19FA",
14
+ "callDataHashEnforcer": "0x142e97F9012e587330Cfe6222E01338D1A200378",
15
+ "chainId": 34348,
16
+ "custodyPolicy": "0xfb3662Ddc308FAc977A1F663948A447055722d3B",
17
+ "delegationManager": "0x710cb1bF08C234Df397e0910331e0A29710EF4F7",
18
+ "deployer": "0x1fcd93189311bedE20a02592cC83f31199A303bF",
19
+ "entryPoint": "0xf7855250B3363AB7649B10957d8908A9AFcdD4B5",
20
+ "geoFeatureRegistry": "0x4D0B90F17148ED671CfeEc1a6DAC4ee297f521B0",
21
+ "mockUsdc": "0xdaE09066A2cc32f6203605619137dcF01A9B49Ae",
22
+ "ontologyTermRegistry": "0xA8Eaa2415EBF4250B041abD1561A3756CeEa0A6C",
23
+ "paymentEnforcer": "0x07fA0aE59FdE4B7ce8962d6fE7a1d648ec3DD5CE",
24
+ "paymentReceiptRegistry": "0x5FfDd6186C1bBc4628187B1c4C1fDaA39F870d43",
25
+ "permissionlessSubregistry": "0x9E803ac48b0F32BCE10BFC183b30f6d756DB11CC",
26
+ "permissionlessSubregistryDemoAgent": "0xEeB709C92C9287dBc3151d90c2ef18b07E9f303a",
27
+ "quorumEnforcer": "0x9bF556A36F3dF3972E355dE4215476Dc268bD0C7",
28
+ "relationshipTypeRegistry": "0x0222388C3F9612058fb1bB2A9760c470DbD2121b",
29
+ "shapeRegistry": "0xBd19d53981677357052EF9768B70929217a6F1F0",
30
+ "skillDefinitionRegistry": "0xd692952978Aa3Bbc5F167060fAAd8eEFA48ADF93",
31
+ "smartAgentPaymaster": "0xbd93fEC6910ffD74F14709188b5a9B6C6965b2a7",
32
+ "timestampEnforcer": "0x73A7B878168b7DE48677617179A8bE894f0Dfe96",
33
+ "universalSignatureValidator": "0xeDd56f500325D4701B9985A34e5Fa6EED6716137",
34
+ "valueEnforcer": "0x8759c1a6cEBF1D5069e9434EF46327Bf2ef69975",
35
+ "permissionlessSubregistries": {
36
+ "me": "0x7fd5e2A3a49c321a4CEd39bE403eCde2Fc1CB823",
37
+ "org": "0x5eA2Bd3986f1924764d145515C3680fAbaaBbE6a",
38
+ "team": "0x57Db73fA77C19601f5dCdeB79de40aAE9C505892",
39
+ "svc": "0xeBe1247403fB8e82f0cBb70D158AE38f627174A2",
40
+ "workspace": "0x823D33D20F7a8F0dBe315aC67633804eEd21d56A",
41
+ "treasury": "0xf1df2D9b779C62a8BF5707C799d8E6842382892B",
42
+ "registry": "0x01a1008bF5b9690415BA9c2d108197B48339b393",
43
+ "church": "0x65bBf8Fe17c62E711d903Dd5318F2F3Ef8f19866",
44
+ "circle": "0x23ffbDADCC0255699d1CBF19244a98594777bDe5",
45
+ "household": "0x9c3373E8F28739Df3aA478C18209fD7eeD769F5b"
46
+ },
47
+ "agentRegistryBase": "0x0Be172F1b5cfD1d084CEc2cF2Af0A0cE9023Deb1",
48
+ "digestBindingEnforcer": "0xA3bb9BCC9b2F6F2419E1aBe5ED6Fd5399b9E68e1"
49
+ }
@@ -0,0 +1 @@
1
+ {"deposit":1000000000000000,"smartAgentPaymaster":"0x7C8BaafA542c57fF9B2B90612bf8aB9E86e22C09","stake":500000000000000}
@@ -338,6 +338,39 @@
338
338
  "outputs": [],
339
339
  "stateMutability": "nonpayable"
340
340
  },
341
+ {
342
+ "type": "function",
343
+ "name": "updateEntry",
344
+ "inputs": [
345
+ {
346
+ "name": "registryId",
347
+ "type": "bytes32",
348
+ "internalType": "bytes32"
349
+ },
350
+ {
351
+ "name": "entryId",
352
+ "type": "bytes32",
353
+ "internalType": "bytes32"
354
+ },
355
+ {
356
+ "name": "cardHash",
357
+ "type": "bytes32",
358
+ "internalType": "bytes32"
359
+ },
360
+ {
361
+ "name": "bindingProofHash",
362
+ "type": "bytes32",
363
+ "internalType": "bytes32"
364
+ },
365
+ {
366
+ "name": "claimHashes",
367
+ "type": "bytes32[]",
368
+ "internalType": "bytes32[]"
369
+ }
370
+ ],
371
+ "outputs": [],
372
+ "stateMutability": "nonpayable"
373
+ },
341
374
  {
342
375
  "type": "event",
343
376
  "name": "RegistryClaimUpdated",
@@ -506,6 +539,37 @@
506
539
  ],
507
540
  "anonymous": false
508
541
  },
542
+ {
543
+ "type": "event",
544
+ "name": "RegistryEntryUpdated",
545
+ "inputs": [
546
+ {
547
+ "name": "registryId",
548
+ "type": "bytes32",
549
+ "indexed": true,
550
+ "internalType": "bytes32"
551
+ },
552
+ {
553
+ "name": "entryId",
554
+ "type": "bytes32",
555
+ "indexed": true,
556
+ "internalType": "bytes32"
557
+ },
558
+ {
559
+ "name": "cardHash",
560
+ "type": "bytes32",
561
+ "indexed": false,
562
+ "internalType": "bytes32"
563
+ },
564
+ {
565
+ "name": "bindingProofHash",
566
+ "type": "bytes32",
567
+ "indexed": false,
568
+ "internalType": "bytes32"
569
+ }
570
+ ],
571
+ "anonymous": false
572
+ },
509
573
  {
510
574
  "type": "event",
511
575
  "name": "RegistryPolicyUpdated",
@@ -0,0 +1,129 @@
1
+ [
2
+ {
3
+ "type": "function",
4
+ "name": "afterHook",
5
+ "inputs": [
6
+ {
7
+ "name": "",
8
+ "type": "bytes",
9
+ "internalType": "bytes"
10
+ },
11
+ {
12
+ "name": "",
13
+ "type": "bytes",
14
+ "internalType": "bytes"
15
+ },
16
+ {
17
+ "name": "",
18
+ "type": "bytes32",
19
+ "internalType": "bytes32"
20
+ },
21
+ {
22
+ "name": "",
23
+ "type": "address",
24
+ "internalType": "address"
25
+ },
26
+ {
27
+ "name": "",
28
+ "type": "address",
29
+ "internalType": "address"
30
+ },
31
+ {
32
+ "name": "",
33
+ "type": "address",
34
+ "internalType": "address"
35
+ },
36
+ {
37
+ "name": "",
38
+ "type": "uint256",
39
+ "internalType": "uint256"
40
+ },
41
+ {
42
+ "name": "",
43
+ "type": "bytes",
44
+ "internalType": "bytes"
45
+ }
46
+ ],
47
+ "outputs": [],
48
+ "stateMutability": "pure"
49
+ },
50
+ {
51
+ "type": "function",
52
+ "name": "beforeHook",
53
+ "inputs": [
54
+ {
55
+ "name": "terms",
56
+ "type": "bytes",
57
+ "internalType": "bytes"
58
+ },
59
+ {
60
+ "name": "args",
61
+ "type": "bytes",
62
+ "internalType": "bytes"
63
+ },
64
+ {
65
+ "name": "",
66
+ "type": "bytes32",
67
+ "internalType": "bytes32"
68
+ },
69
+ {
70
+ "name": "",
71
+ "type": "address",
72
+ "internalType": "address"
73
+ },
74
+ {
75
+ "name": "",
76
+ "type": "address",
77
+ "internalType": "address"
78
+ },
79
+ {
80
+ "name": "",
81
+ "type": "address",
82
+ "internalType": "address"
83
+ },
84
+ {
85
+ "name": "",
86
+ "type": "uint256",
87
+ "internalType": "uint256"
88
+ },
89
+ {
90
+ "name": "",
91
+ "type": "bytes",
92
+ "internalType": "bytes"
93
+ }
94
+ ],
95
+ "outputs": [],
96
+ "stateMutability": "pure"
97
+ },
98
+ {
99
+ "type": "error",
100
+ "name": "BadArgsLength",
101
+ "inputs": []
102
+ },
103
+ {
104
+ "type": "error",
105
+ "name": "BadTermsLength",
106
+ "inputs": []
107
+ },
108
+ {
109
+ "type": "error",
110
+ "name": "DigestMismatch",
111
+ "inputs": [
112
+ {
113
+ "name": "kind",
114
+ "type": "bytes32",
115
+ "internalType": "bytes32"
116
+ },
117
+ {
118
+ "name": "bound",
119
+ "type": "bytes32",
120
+ "internalType": "bytes32"
121
+ },
122
+ {
123
+ "name": "presented",
124
+ "type": "bytes32",
125
+ "internalType": "bytes32"
126
+ }
127
+ ]
128
+ }
129
+ ]
@@ -23,6 +23,7 @@ export declare const CallDataHashEnforcer: Abi;
23
23
  export declare const CaveatEnforcerBase: Abi;
24
24
  export declare const CustodyPolicy: Abi;
25
25
  export declare const DelegationManager: Abi;
26
+ export declare const DigestBindingEnforcer: Abi;
26
27
  export declare const GeoFeatureRegistry: Abi;
27
28
  export declare const GovernanceManaged: Abi;
28
29
  export declare const IAgentAccount: Abi;
package/dist/abi/index.js CHANGED
@@ -23,6 +23,7 @@ export { default as CallDataHashEnforcer } from './CallDataHashEnforcer.json' wi
23
23
  export { default as CaveatEnforcerBase } from './CaveatEnforcerBase.json' with { type: 'json' };
24
24
  export { default as CustodyPolicy } from './CustodyPolicy.json' with { type: 'json' };
25
25
  export { default as DelegationManager } from './DelegationManager.json' with { type: 'json' };
26
+ export { default as DigestBindingEnforcer } from './DigestBindingEnforcer.json' with { type: 'json' };
26
27
  export { default as GeoFeatureRegistry } from './GeoFeatureRegistry.json' with { type: 'json' };
27
28
  export { default as GovernanceManaged } from './GovernanceManaged.json' with { type: 'json' };
28
29
  export { default as IAgentAccount } from './IAgentAccount.json' with { type: 'json' };
@@ -39,6 +39,7 @@ export interface Deployments {
39
39
  readonly "timelockController": Address;
40
40
  readonly "governanceGuardian": Address;
41
41
  readonly "chainId": number;
42
+ readonly "permissionlessSubregistries": string;
42
43
  readonly "deploymentEpoch": string;
43
44
  }
44
45
  export declare const CONTRACTS: Deployments;
@@ -38,6 +38,17 @@ export const CONTRACTS = {
38
38
  "agenticGovernance": "0x27c1F21ffA275e61Fe152Edd4f2676fD6a816dDa",
39
39
  "timelockController": "0xeB66E0B92287E53BB5A80bD2a01002150249DC94",
40
40
  "governanceGuardian": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44",
41
+ "permissionlessSubregistries": {
42
+ "me": "0xDEABb2Ed8382775a01752f171bC4c625AcD15A71",
43
+ "org": "0x13D2cabD890C93eF24937cc19dcDdc2a4d914418",
44
+ "team": "0xC80e6B102721F6D0b158124E0095D3B12d941126",
45
+ "svc": "0xcf6d51c105E83621FcFA58D89a3846B8090352b4",
46
+ "workspace": "0x9f8b948a9a18C68dBF862cE61444112A93d9A491",
47
+ "treasury": "0xDFA05aa99B1C5dA606a438eaF7eD3b52a231E385",
48
+ "registry": "0x32d3a37f44614959049b9f19D610554e8D4aBD6C",
49
+ "church": "0x97402E5A152670f356Eab9fD4270e1c8888ffc87",
50
+ "circle": "0xE194187c64c45803eda55BC399A4e7d39C1449A6"
51
+ },
41
52
  "deploymentEpoch": "ep_015f71625117a4d1"
42
53
  };
43
54
  export default CONTRACTS;
@@ -0,0 +1,44 @@
1
+ // Generated by scripts/build-deployments.mjs — do not edit by hand.
2
+ // Source: deployments-faithchain.json
3
+ import type { Address } from 'viem';
4
+ export interface Deployments {
5
+ readonly "agentAccountFactory": Address;
6
+ readonly "agentAccountImplementation": Address;
7
+ readonly "agentNameRegistry": Address;
8
+ readonly "agentNameResolver": Address;
9
+ readonly "agentNameUniversalResolver": Address;
10
+ readonly "agentProfileResolver": Address;
11
+ readonly "agentRelationship": Address;
12
+ readonly "agreementRegistry": Address;
13
+ readonly "allowedMethodsEnforcer": Address;
14
+ readonly "allowedTargetsEnforcer": Address;
15
+ readonly "approvedHashRegistry": Address;
16
+ readonly "attestationRegistry": Address;
17
+ readonly "callDataHashEnforcer": Address;
18
+ readonly "custodyPolicy": Address;
19
+ readonly "delegationManager": Address;
20
+ readonly "deployer": Address;
21
+ readonly "entryPoint": Address;
22
+ readonly "geoFeatureRegistry": Address;
23
+ readonly "mockUsdc": Address;
24
+ readonly "ontologyTermRegistry": Address;
25
+ readonly "paymentEnforcer": Address;
26
+ readonly "paymentReceiptRegistry": Address;
27
+ readonly "permissionlessSubregistry": Address;
28
+ readonly "permissionlessSubregistryDemoAgent": Address;
29
+ readonly "quorumEnforcer": Address;
30
+ readonly "relationshipTypeRegistry": Address;
31
+ readonly "shapeRegistry": Address;
32
+ readonly "skillDefinitionRegistry": Address;
33
+ readonly "smartAgentPaymaster": Address;
34
+ readonly "timestampEnforcer": Address;
35
+ readonly "universalSignatureValidator": Address;
36
+ readonly "valueEnforcer": Address;
37
+ readonly "agentRegistryBase": Address;
38
+ readonly "digestBindingEnforcer": Address;
39
+ readonly "chainId": number;
40
+ readonly "permissionlessSubregistries": string;
41
+ readonly "deploymentEpoch": string;
42
+ }
43
+ export declare const CONTRACTS: Deployments;
44
+ export default CONTRACTS;
@@ -0,0 +1,53 @@
1
+ // Generated by scripts/build-deployments.mjs — do not edit by hand.
2
+ // Source: deployments-faithchain.json
3
+ export const CONTRACTS = {
4
+ "agentAccountFactory": "0x464eEe7518c3c97DA570592481329E0627E9a3B8",
5
+ "agentAccountImplementation": "0x8691bFE5Cd0bf532050e27d4fF0Cd1F82d1aE9a7",
6
+ "agentNameRegistry": "0x60E949D52660A9D4143ecB0fdA56c0457f20aED9",
7
+ "agentNameResolver": "0xa5855906C0De3813E74BEe201973071e0c844115",
8
+ "agentNameUniversalResolver": "0xF343054e046A4145ccae499ECB28197394eE0798",
9
+ "agentProfileResolver": "0xB03F7C06ad3274F584AB72794406D639c02A45e1",
10
+ "agentRelationship": "0x5015bD7d422e003511246f848cDd798cb00BB968",
11
+ "agreementRegistry": "0x5b580E741DBb4f57F6D885dF2c12F4e0B53B6f50",
12
+ "allowedMethodsEnforcer": "0xdBb2E47793393C499efB0f3fcbf6Ca8669791a41",
13
+ "allowedTargetsEnforcer": "0x2156311097A936de1916a878bF53Bfd43c7b5715",
14
+ "approvedHashRegistry": "0xC6a4983bC6649f7C46c9E7d83f1Cd7e9078AFc7b",
15
+ "attestationRegistry": "0x4c94A0355380b8F5023eDd5f8A8131B020de19FA",
16
+ "callDataHashEnforcer": "0x142e97F9012e587330Cfe6222E01338D1A200378",
17
+ "chainId": 34348,
18
+ "custodyPolicy": "0xfb3662Ddc308FAc977A1F663948A447055722d3B",
19
+ "delegationManager": "0x710cb1bF08C234Df397e0910331e0A29710EF4F7",
20
+ "deployer": "0x1fcd93189311bedE20a02592cC83f31199A303bF",
21
+ "entryPoint": "0xf7855250B3363AB7649B10957d8908A9AFcdD4B5",
22
+ "geoFeatureRegistry": "0x4D0B90F17148ED671CfeEc1a6DAC4ee297f521B0",
23
+ "mockUsdc": "0xdaE09066A2cc32f6203605619137dcF01A9B49Ae",
24
+ "ontologyTermRegistry": "0xA8Eaa2415EBF4250B041abD1561A3756CeEa0A6C",
25
+ "paymentEnforcer": "0x07fA0aE59FdE4B7ce8962d6fE7a1d648ec3DD5CE",
26
+ "paymentReceiptRegistry": "0x5FfDd6186C1bBc4628187B1c4C1fDaA39F870d43",
27
+ "permissionlessSubregistry": "0x9E803ac48b0F32BCE10BFC183b30f6d756DB11CC",
28
+ "permissionlessSubregistryDemoAgent": "0xEeB709C92C9287dBc3151d90c2ef18b07E9f303a",
29
+ "quorumEnforcer": "0x9bF556A36F3dF3972E355dE4215476Dc268bD0C7",
30
+ "relationshipTypeRegistry": "0x0222388C3F9612058fb1bB2A9760c470DbD2121b",
31
+ "shapeRegistry": "0xBd19d53981677357052EF9768B70929217a6F1F0",
32
+ "skillDefinitionRegistry": "0xd692952978Aa3Bbc5F167060fAAd8eEFA48ADF93",
33
+ "smartAgentPaymaster": "0xbd93fEC6910ffD74F14709188b5a9B6C6965b2a7",
34
+ "timestampEnforcer": "0x73A7B878168b7DE48677617179A8bE894f0Dfe96",
35
+ "universalSignatureValidator": "0xeDd56f500325D4701B9985A34e5Fa6EED6716137",
36
+ "valueEnforcer": "0x8759c1a6cEBF1D5069e9434EF46327Bf2ef69975",
37
+ "permissionlessSubregistries": {
38
+ "me": "0x7fd5e2A3a49c321a4CEd39bE403eCde2Fc1CB823",
39
+ "org": "0x5eA2Bd3986f1924764d145515C3680fAbaaBbE6a",
40
+ "team": "0x57Db73fA77C19601f5dCdeB79de40aAE9C505892",
41
+ "svc": "0xeBe1247403fB8e82f0cBb70D158AE38f627174A2",
42
+ "workspace": "0x823D33D20F7a8F0dBe315aC67633804eEd21d56A",
43
+ "treasury": "0xf1df2D9b779C62a8BF5707C799d8E6842382892B",
44
+ "registry": "0x01a1008bF5b9690415BA9c2d108197B48339b393",
45
+ "church": "0x65bBf8Fe17c62E711d903Dd5318F2F3Ef8f19866",
46
+ "circle": "0x23ffbDADCC0255699d1CBF19244a98594777bDe5",
47
+ "household": "0x9c3373E8F28739Df3aA478C18209fD7eeD769F5b"
48
+ },
49
+ "agentRegistryBase": "0x0Be172F1b5cfD1d084CEc2cF2Af0A0cE9023Deb1",
50
+ "digestBindingEnforcer": "0xA3bb9BCC9b2F6F2419E1aBe5ED6Fd5399b9E68e1",
51
+ "deploymentEpoch": "ep_80afd31afaeacbf9"
52
+ };
53
+ export default CONTRACTS;
@@ -1,9 +1,11 @@
1
1
  // Generated by scripts/build-deployments.mjs — do not edit by hand.
2
2
  import type { Address } from 'viem';
3
- import type { Deployments } from './base-sepolia';
3
+ import type { Deployments } from './base-sepolia.js';
4
4
  export type { Deployments };
5
5
  export declare const BASE_SEPOLIA: Deployments;
6
+ export declare const FAITHCHAIN: Deployments;
7
+ export declare const PAYMASTER_ANVIL: Deployments;
6
8
  export declare const REGISTRIES_BASE_SEPOLIA: Deployments;
7
9
 
8
- export type Network = 'base-sepolia' | 'registries-base-sepolia';
10
+ export type Network = 'base-sepolia' | 'faithchain' | 'paymaster-anvil' | 'registries-base-sepolia';
9
11
  export declare function getDeployments(network: Network): Deployments;
@@ -1,11 +1,17 @@
1
1
  // Generated by scripts/build-deployments.mjs — do not edit by hand.
2
2
  import { CONTRACTS as BASE_SEPOLIA } from './base-sepolia.js';
3
3
  export { BASE_SEPOLIA };
4
+ import { CONTRACTS as FAITHCHAIN } from './faithchain.js';
5
+ export { FAITHCHAIN };
6
+ import { CONTRACTS as PAYMASTER_ANVIL } from './paymaster-anvil.js';
7
+ export { PAYMASTER_ANVIL };
4
8
  import { CONTRACTS as REGISTRIES_BASE_SEPOLIA } from './registries-base-sepolia.js';
5
9
  export { REGISTRIES_BASE_SEPOLIA };
6
10
 
7
11
  const TABLE = {
8
12
  "base-sepolia": BASE_SEPOLIA,
13
+ "faithchain": FAITHCHAIN,
14
+ "paymaster-anvil": PAYMASTER_ANVIL,
9
15
  "registries-base-sepolia": REGISTRIES_BASE_SEPOLIA,
10
16
  };
11
17
 
@@ -0,0 +1,11 @@
1
+ // Generated by scripts/build-deployments.mjs — do not edit by hand.
2
+ // Source: deployments-paymaster-anvil.json
3
+ import type { Address } from 'viem';
4
+ export interface Deployments {
5
+ readonly "smartAgentPaymaster": Address;
6
+ readonly "deposit": number;
7
+ readonly "stake": number;
8
+ readonly "deploymentEpoch": string;
9
+ }
10
+ export declare const CONTRACTS: Deployments;
11
+ export default CONTRACTS;
@@ -0,0 +1,9 @@
1
+ // Generated by scripts/build-deployments.mjs — do not edit by hand.
2
+ // Source: deployments-paymaster-anvil.json
3
+ export const CONTRACTS = {
4
+ "deposit": 1000000000000000,
5
+ "smartAgentPaymaster": "0x7C8BaafA542c57fF9B2B90612bf8aB9E86e22C09",
6
+ "stake": 500000000000000,
7
+ "deploymentEpoch": "ep_45ca31c3315a5978"
8
+ };
9
+ export default CONTRACTS;
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@agenticprimitives/contracts",
3
- "version": "1.0.0-alpha.21",
3
+ "version": "1.0.0-alpha.23",
4
+ "type": "module",
4
5
  "description": "Solidity contracts + ABIs + flattened sources + per-network deployment addresses for the agenticprimitives stack.",
5
6
  "license": "MIT",
6
7
  "repository": {
@@ -38,11 +39,15 @@
38
39
  "deployments-*.json"
39
40
  ],
40
41
  "devDependencies": {
41
- "solhint": "^5.0.5"
42
+ "solhint": "^5.0.5",
43
+ "viem": "^2.52.2"
42
44
  },
43
45
  "publishConfig": {
44
46
  "access": "public"
45
47
  },
48
+ "peerDependencies": {
49
+ "viem": "^2.52.2"
50
+ },
46
51
  "scripts": {
47
52
  "setup": "bash setup.sh",
48
53
  "build": "forge build && pnpm run build:abi && pnpm run build:deployments",
@@ -64,6 +69,11 @@
64
69
  "deploy:payment-escrow:base-sepolia": "DEPLOY_NETWORK=base-sepolia forge script script/DeployPaymentEscrow.s.sol --rpc-url $BASE_SEPOLIA_RPC --broadcast --private-key $PRIVATE_KEY --sig 'run()'",
65
70
  "deploy:registries:merge": "node scripts/merge-registry-deploy.mjs",
66
71
  "verify:base-sepolia": "bash scripts/verify-base-sepolia.sh",
67
- "clean": "rm -rf out cache broadcast dist"
72
+ "clean": "rm -rf out cache broadcast dist",
73
+ "deploy:faithchain": "DEPLOY_NETWORK=faithchain forge script script/Deploy.s.sol --rpc-url $FAITHCHAIN_RPC --broadcast --private-key $PRIVATE_KEY",
74
+ "deploy:paymaster:faithchain": "DEPLOY_NETWORK=faithchain forge script script/DeployPaymaster.s.sol --rpc-url $FAITHCHAIN_RPC --broadcast --private-key $PRIVATE_KEY --sig 'run()'",
75
+ "deploy:registries:faithchain": "DEPLOY_NETWORK=faithchain forge script script/DeployRegistries.s.sol --rpc-url $FAITHCHAIN_RPC --broadcast --private-key $PRIVATE_KEY --sig 'run()'",
76
+ "deploy:payments:faithchain": "DEPLOY_NETWORK=faithchain forge script script/DeployPayments.s.sol --rpc-url $FAITHCHAIN_RPC --broadcast --private-key $PRIVATE_KEY --sig 'run()'",
77
+ "deploy:payment-escrow:faithchain": "DEPLOY_NETWORK=faithchain forge script script/DeployPaymentEscrow.s.sol --rpc-url $FAITHCHAIN_RPC --broadcast --private-key $PRIVATE_KEY --sig 'run()'"
68
78
  }
69
79
  }
@@ -1112,6 +1112,17 @@ contract AgentAccount is
1112
1112
  /// EntryPoint / self / DelegationManager; the guard hardens
1113
1113
  /// against a malicious target re-entering through one of those
1114
1114
  /// callers.
1115
+ ///
1116
+ /// Slither reports `reentrancy-eth` here because `_delegationExecCtx`
1117
+ /// is written after the external calls. The write is `= false`, and the
1118
+ /// flag is RESTRICTIVE while set: `_rejectDelegatedGovernance` reverts a
1119
+ /// delegation-originated governance self-call only when it is true. A
1120
+ /// reentrant frame therefore observes the *more* restricted state, never
1121
+ /// a bypass — and the only readers of the flag are `execute` (guarded by
1122
+ /// `nonReentrant` on this very function) and `executeBatch`, whose own
1123
+ /// exemption is justified at its declaration. The flag is transient
1124
+ /// (EIP-1153), so it cannot survive the transaction either.
1125
+ // slither-disable-next-line reentrancy-eth
1115
1126
  function execute(address target, uint256 value, bytes calldata data) external override nonReentrant whenNotPaused {
1116
1127
  _requireForExecute();
1117
1128
 
@@ -1174,6 +1185,15 @@ contract AgentAccount is
1174
1185
  /// OUTER `execute` already holds the guard, so external re-entry
1175
1186
  /// is blocked; `_requireForExecute` restricts entry to
1176
1187
  /// EntryPoint / self / DM (DM has its own `nonReentrant`).
1188
+ ///
1189
+ /// Slither reports `reentrancy-eth` here for the same reason as
1190
+ /// `execute`, and it is a false positive for the same reason: the
1191
+ /// post-call write clears `_delegationExecCtx`, a transient flag that
1192
+ /// only ever *adds* a restriction while set. Note this function is
1193
+ /// deliberately un-guarded (see above), so the suppression is scoped to
1194
+ /// this detector on this declaration only — any other high-severity
1195
+ /// finding here still fails the build.
1196
+ // slither-disable-next-line reentrancy-eth
1177
1197
  function executeBatch(Call[] calldata calls) external override whenNotPaused {
1178
1198
  _requireForExecute();
1179
1199
 
@@ -357,8 +357,18 @@ contract AgentAccountFactory is GovernanceManaged {
357
357
  if (thresholds[5] > sodCap) thresholds[5] = sodCap;
358
358
  }
359
359
 
360
+ // DEV/TEST-CHAIN CARVE-OUT (local demo only): on a local development chain the T4 floor is lifted
361
+ // so a demo can drive an admin custody action's schedule→apply back-to-back without a real-time
362
+ // wait, and a zero override yields a ZERO T4 safety delay instead of the 1-hour production default.
363
+ // Gated strictly by `block.chainid` — anvil (31337/1337) and the local faithchain (34348). Every
364
+ // PRODUCTION and public TESTNET chain id (Base Sepolia 84532, mainnet, …) keeps the audited
365
+ // EXT-TL-FLOOR-1 invariant. T5 (24h) and T6 (recovery, 48h) are NOT relaxed even on dev — the
366
+ // CustodyPolicy requires a non-zero timelock for those tiers, and the demo only exercises T4.
367
+ bool devChain = block.chainid == 31337 || block.chainid == 1337 || block.chainid == 34348;
368
+ uint32 floor4 = devChain ? 0 : uint32(1 hours);
369
+
360
370
  uint32[7] memory timelocks;
361
- timelocks[4] = timelockOverrides[4] == 0 ? uint32(1 hours) : timelockOverrides[4];
371
+ timelocks[4] = timelockOverrides[4] == 0 ? floor4 : timelockOverrides[4];
362
372
  timelocks[5] = timelockOverrides[5] == 0 ? uint32(24 hours) : timelockOverrides[5];
363
373
  timelocks[6] = timelockOverrides[6] == 0 ? uint32(48 hours) : timelockOverrides[6];
364
374
 
@@ -366,8 +376,9 @@ contract AgentAccountFactory is GovernanceManaged {
366
376
  // below the product floor. A zero override inherits the floor default above; a non-zero override below
367
377
  // the floor reverts, so a mode>0 (custody-governed) account can never deploy with sub-floor T4/T5/T6
368
378
  // (recovery = T6) delays. The "T5=24h / recovery=48h" guarantee becomes a protocol invariant, not a UI
369
- // convention (spec 300 — raise-only). Demo/testnet fast-timelock deploys use zero overrides (defaults).
370
- if (timelocks[4] < 1 hours) revert TimelockBelowFloor(4, timelocks[4], uint32(1 hours));
379
+ // convention (spec 300 — raise-only). The T4 floor is `floor4` (production value on real chains, 0 on
380
+ // the dev-chain carve-out); T5/T6 keep their audited floors on every chain.
381
+ if (timelocks[4] < floor4) revert TimelockBelowFloor(4, timelocks[4], floor4);
371
382
  if (timelocks[5] < 24 hours) revert TimelockBelowFloor(5, timelocks[5], uint32(24 hours));
372
383
  if (timelocks[6] < 48 hours) revert TimelockBelowFloor(6, timelocks[6], uint32(48 hours));
373
384
 
@@ -0,0 +1,72 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.28;
3
+
4
+ import "../agency/ICaveatEnforcer.sol";
5
+
6
+ /**
7
+ * @title DigestBindingEnforcer
8
+ * @notice Binds a delegation to a 32-byte digest of an OFF-CHAIN artifact — an intent, a disclosure
9
+ * projection, an accepted offer — so that the delegation is a MANDATE (spec 336 §8.3, spec 350
10
+ * §2): authority *for a reason*, not authority for any purpose until revoked.
11
+ *
12
+ * @dev terms = abi.encode(bytes32 kind, bytes32 digest)
13
+ * args = abi.encode(bytes32 presented) — supplied by the redeemer at redemption
14
+ *
15
+ * `kind` names WHICH artifact the digest is of, so an off-chain reader can tell an intent binding
16
+ * from a projection binding without guessing:
17
+ * keccak256("ap:intent") — the canonical intent (RFC 8785 JCS bytes)
18
+ * keccak256("ap:projection") — what was disclosed to the grantee (spec 336 §4)
19
+ * keccak256("ap:offer") — the accepted offer (spec 336 §5)
20
+ * One enforcer serves all three: the mechanics are identical and the kind belongs in the terms,
21
+ * where it is signed, rather than in which contract address was chosen.
22
+ *
23
+ * WHAT THIS ENFORCES, HONESTLY. The chain cannot know what an intent *means*; it can only hold
24
+ * the redeemer to a commitment. `beforeHook` requires the redeemer to PRESENT the digest it is
25
+ * acting under, and reverts if that is not the bound one. Two things follow:
26
+ * 1. the binding is part of the SIGNED delegation — immutable, inspectable, and what the
27
+ * off-chain per-step verifier (`delegation.verifyMandateForStep`) compares a step's
28
+ * intent digest against. That verifier is where "does this step belong to this intent" is
29
+ * actually decided; this contract makes the answer un-forgeable rather than deciding it;
30
+ * 2. the presented digest lands in the transaction, so the receipt's `intentDigest` and the
31
+ * chain's record of what the redeemer claimed to be doing are the same bytes — evidence a
32
+ * third party can check without trusting either side.
33
+ * A redeemer that copies `terms` into `args` satisfies the check; that is the point — it has
34
+ * now committed, on chain, to that intent, and a step whose real intent differs is caught by the
35
+ * verifier that computed the digest from the step rather than from the caveat.
36
+ *
37
+ * R6.7 — Stateless validator: hooks are `pure`, zero storage; the DM-side pause check gates all
38
+ * reachable enforcer dispatch.
39
+ */
40
+ contract DigestBindingEnforcer is ICaveatEnforcer {
41
+ error BadTermsLength();
42
+ error BadArgsLength();
43
+ error DigestMismatch(bytes32 kind, bytes32 bound, bytes32 presented);
44
+
45
+ function beforeHook(
46
+ bytes calldata terms,
47
+ bytes calldata args,
48
+ bytes32,
49
+ address,
50
+ address,
51
+ address,
52
+ uint256,
53
+ bytes calldata
54
+ ) external pure override {
55
+ if (terms.length != 64) revert BadTermsLength();
56
+ if (args.length != 32) revert BadArgsLength();
57
+ (bytes32 kind, bytes32 bound) = abi.decode(terms, (bytes32, bytes32));
58
+ bytes32 presented = abi.decode(args, (bytes32));
59
+ if (presented != bound) revert DigestMismatch(kind, bound, presented);
60
+ }
61
+
62
+ function afterHook(
63
+ bytes calldata,
64
+ bytes calldata,
65
+ bytes32,
66
+ address,
67
+ address,
68
+ address,
69
+ uint256,
70
+ bytes calldata
71
+ ) external pure override {}
72
+ }
@@ -28,9 +28,22 @@ library AgentProfilePredicates {
28
28
  // ─── Identity-only ──────────────────────────────────────────────
29
29
 
30
30
  bytes32 internal constant ATL_DESCRIPTION = keccak256("atl:description");
31
- /// spec 282 — publicly-asserted skill labels (string; the indexer projects to approf:skills, the
32
- /// discovery matcher ranks on it). The agent's full private skill claims live in agent-skills VCs.
31
+ /// @dev LEGACY READ ONLY (ADR-0051). Publicly-asserted labels, written before the vocabulary settled
32
+ /// on "capability" for what an agent can do. New writes go to `ATL_CAPABILITIES`; readers consult
33
+ /// this only when that is empty, which is the documented migration state — not a second mechanism
34
+ /// (ADR-0013). Kept because agents named under it are still on chain.
33
35
  bytes32 internal constant ATL_SKILLS = keccak256("atl:skills");
36
+ /// ADR-0051 — the ids of what this agent CAN DO, comma-joined, same rail as the legacy labels above.
37
+ /// The SAME ids appear in `profile.capabilities[].id`, in ARD `capabilities[]`, and in the A2A card's
38
+ /// `skills[]` (the wire's name for them). Ids only: names, descriptions and examples live in the
39
+ /// profile record, because the chain is the place to prove WHICH capabilities are claimed, not to
40
+ /// store their prose. The indexer projects to approf:capabilities.
41
+ bytes32 internal constant ATL_CAPABILITIES = keccak256("atl:capabilities");
42
+ /// spec 347 §8.5 — how to OBTAIN AND RUN this agent's software: a JSON string per
43
+ /// `AgentDistributionV1` (agent-profile; JCS-canonical; mirrors the ACP registry agent.schema.json
44
+ /// `distribution` + `acp`/`version`). SA-keyed identity property, string datatype; the indexer
45
+ /// projects it to approf:distribution and registry files (ACP registry.json / ARD) are projections.
46
+ bytes32 internal constant ATL_DISTRIBUTION = keccak256("atl:distribution");
34
47
  bytes32 internal constant ATL_HOMEPAGE = keccak256("atl:homepage");
35
48
  bytes32 internal constant ATL_AVATAR = keccak256("atl:avatar");
36
49
  bytes32 internal constant ATL_PROFILE_SCHEMA_URI = keccak256("atl:profileSchemaURI");
@@ -66,6 +66,60 @@ library AgentNamePredicates {
66
66
  /// name→credential index (ADR-0040 amendment). Never set automatically.
67
67
  bytes32 internal constant ATL_CONNECTION_ADDRESS = keccak256("atl:connectionAddress");
68
68
 
69
+ // ─── Derived type (spec 346 §2.3 / ADR-0061) ────────────────────
70
+ //
71
+ // SA-KEYED records on the AgentProfileResolver subject (NOT name-node records): the
72
+ // suffix of a typed name (.me .org .team .svc .workspace .treasury) is a CLAIM
73
+ // validated against these. `atl:agentKind` stays the 3-valued ROOT; `atl:agentType`
74
+ // is the closed DERIVED layer under it (team ⊂ org; service / workspace /
75
+ // treasury ⊂ service). Roles other than workspace are an open-set string.
76
+
77
+ /// `atl:agentType` — the derived agent type. `bytes32` (hashed enum). Bound to AGENT_TYPE_ENUM.
78
+ bytes32 internal constant ATL_AGENT_TYPE = keccak256("atl:agentType");
79
+
80
+ /// `atl:serviceRole` — open-set service role (`workspace` REQUIRED for that type). `string`.
81
+ bytes32 internal constant ATL_SERVICE_ROLE = keccak256("atl:serviceRole");
82
+
83
+ /// `atl:agentSubtype` — a VERTICAL subtype of the generic derived type (spec 346 §2.4), e.g. an app-registered
84
+ /// kind of organization. The vocabulary is the app's; the chain stores the slug. `string`.
85
+ bytes32 internal constant ATL_AGENT_SUBTYPE = keccak256("atl:agentSubtype");
86
+
87
+ /// `atl:cardDigest` — sha256 (as bytes32) of the RELEASED A2A Agent Card this name currently publishes
88
+ /// (spec 347 §8.3). Content-addresses the card; the card itself is served at the a2aEndpoint host's
89
+ /// `/.well-known/agent-card.json`. Never authority — a verifier compares the fetched bytes to this digest.
90
+ bytes32 internal constant ATL_CARD_DIGEST = keccak256("atl:cardDigest");
91
+
92
+ /// `atl:cardUri` — explicit URI of the released A2A Agent Card when it is not at the default well-known
93
+ /// path of the a2aEndpoint host (spec 347 §8.3). `string`.
94
+ bytes32 internal constant ATL_CARD_URI = keccak256("atl:cardUri");
95
+
96
+ /// Enum set bound to `atl:agentType`. Ten members; mirrors `types.DerivedAgentType`.
97
+ bytes32 internal constant AGENT_TYPE_ENUM = keccak256("atl:AgentTypeEnum");
98
+
99
+ bytes32 internal constant AGENT_TYPE_PERSON = keccak256("person");
100
+ bytes32 internal constant AGENT_TYPE_ORG = keccak256("org");
101
+ bytes32 internal constant AGENT_TYPE_TEAM = keccak256("team");
102
+ bytes32 internal constant AGENT_TYPE_SERVICE = keccak256("service");
103
+ bytes32 internal constant AGENT_TYPE_WORKSPACE = keccak256("workspace");
104
+ bytes32 internal constant AGENT_TYPE_TREASURY = keccak256("treasury");
105
+ bytes32 internal constant AGENT_TYPE_REGISTRY = keccak256("registry"); // the Service Agent that OPERATES a registry
106
+ bytes32 internal constant AGENT_TYPE_CHURCH = keccak256("church"); // organization-class (ADR-0061 amendment 2026-08-30)
107
+ bytes32 internal constant AGENT_TYPE_CIRCLE = keccak256("circle"); // organization-class
108
+ bytes32 internal constant AGENT_TYPE_HOUSEHOLD = keccak256("household"); // organization-class (spec 368, 2026-09-07)
109
+
110
+ // Per-root `rootKind` tags for the ten typed roots (AgentNameRegistry.initializeRoot). Mirrors
111
+ // agent-naming `rootKindForTld`. The legacy roots (.agent / .impact) carry KIND_AGENT.
112
+ bytes32 internal constant ROOT_KIND_PERSON = keccak256("namespace:Person");
113
+ bytes32 internal constant ROOT_KIND_ORGANIZATION = keccak256("namespace:Organization");
114
+ bytes32 internal constant ROOT_KIND_TEAM = keccak256("namespace:Team");
115
+ bytes32 internal constant ROOT_KIND_SERVICE = keccak256("namespace:Service");
116
+ bytes32 internal constant ROOT_KIND_WORKSPACE = keccak256("namespace:Workspace");
117
+ bytes32 internal constant ROOT_KIND_TREASURY = keccak256("namespace:Treasury");
118
+ bytes32 internal constant ROOT_KIND_REGISTRY = keccak256("namespace:Registry");
119
+ bytes32 internal constant ROOT_KIND_CHURCH = keccak256("namespace:Church");
120
+ bytes32 internal constant ROOT_KIND_CIRCLE = keccak256("namespace:Circle");
121
+ bytes32 internal constant ROOT_KIND_HOUSEHOLD = keccak256("namespace:Household");
122
+
69
123
  // ─── Shape + enum-set ids ───────────────────────────────────────
70
124
 
71
125
  /// `atl:AgentName` — the class id for ShapeRegistry validation.
@@ -108,6 +108,12 @@ contract AgentRegistryBase {
108
108
  bytes32 cardHash,
109
109
  bytes32 bindingProofHash
110
110
  );
111
+ event RegistryEntryUpdated(
112
+ bytes32 indexed registryId,
113
+ bytes32 indexed entryId,
114
+ bytes32 cardHash,
115
+ bytes32 bindingProofHash
116
+ );
111
117
  event RegistryEntryRenewed(bytes32 indexed registryId, bytes32 indexed entryId, uint64 expiresAt);
112
118
  event RegistryEntrySuspended(bytes32 indexed registryId, bytes32 indexed entryId, bytes32 reasonHash);
113
119
  event RegistryEntryRevoked(bytes32 indexed registryId, bytes32 indexed entryId, bytes32 reasonHash);
@@ -196,6 +202,32 @@ contract AgentRegistryBase {
196
202
  emit RegistryEntryRenewed(registryId, entryId, expiresAt);
197
203
  }
198
204
 
205
+ /// @notice Re-point an ACTIVE entry at a newer card. RB-01: the subject and only the subject.
206
+ /// @dev Cards are versioned and republished; without this an entry is pinned forever to whatever card it
207
+ /// was registered with, so a directory could never reflect a new release (found live 2026-08-30: the only
208
+ /// paths were `registerEntry`, which reverts `EntryExists`, and `renewEntry`, which moves only the expiry).
209
+ /// The subject re-signs: `bindingProofHash` covers the new card, so an update proves the same thing a
210
+ /// registration does. Membership is NOT re-checked — admission decided this agent belongs; which card it
211
+ /// publishes is not an admission question (a registry that disagrees can suspend the entry).
212
+ function updateEntry(
213
+ bytes32 registryId,
214
+ bytes32 entryId,
215
+ bytes32 cardHash,
216
+ bytes32 bindingProofHash,
217
+ bytes32[] calldata claimHashes
218
+ ) external {
219
+ Entry storage e = _entries[_entryKey(registryId, entryId)];
220
+ if (e.status == EntryStatus.None) revert EntryNotFound();
221
+ if (msg.sender != e.subjectAgent) revert SubjectMismatch(); // RB-01
222
+ if (e.status != EntryStatus.Active) revert NotActive(); // RB-04 (Suspended/Revoked)
223
+
224
+ e.cardHash = cardHash;
225
+ e.bindingProofHash = bindingProofHash;
226
+ e.claimsRoot = keccak256(abi.encode(claimHashes));
227
+
228
+ emit RegistryEntryUpdated(registryId, entryId, cardHash, bindingProofHash);
229
+ }
230
+
199
231
  /// @notice Suspend an active entry. RB-03: admin action (controller or policy-authorized) — NOT subject.
200
232
  function suspendEntry(bytes32 registryId, bytes32 entryId, bytes32 reasonHash) external {
201
233
  Entry storage e = _entries[_entryKey(registryId, entryId)];