@aztec/standard-contracts 5.0.0-nightly.20260530

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/artifacts/AuthRegistry.d.json.ts +5 -0
  2. package/artifacts/AuthRegistry.json +7838 -0
  3. package/artifacts/PublicChecks.d.json.ts +5 -0
  4. package/artifacts/PublicChecks.json +4290 -0
  5. package/dest/auth-registry/constants.d.ts +4 -0
  6. package/dest/auth-registry/constants.d.ts.map +1 -0
  7. package/dest/auth-registry/constants.js +7 -0
  8. package/dest/auth-registry/index.d.ts +6 -0
  9. package/dest/auth-registry/index.d.ts.map +1 -0
  10. package/dest/auth-registry/index.js +14 -0
  11. package/dest/auth-registry/lazy.d.ts +7 -0
  12. package/dest/auth-registry/lazy.d.ts.map +1 -0
  13. package/dest/auth-registry/lazy.js +24 -0
  14. package/dest/contract_data.d.ts +63 -0
  15. package/dest/contract_data.d.ts.map +1 -0
  16. package/dest/contract_data.js +96 -0
  17. package/dest/drift.d.ts +54 -0
  18. package/dest/drift.d.ts.map +1 -0
  19. package/dest/drift.js +167 -0
  20. package/dest/index.d.ts +3 -0
  21. package/dest/index.d.ts.map +1 -0
  22. package/dest/index.js +2 -0
  23. package/dest/make_standard_contract.d.ts +9 -0
  24. package/dest/make_standard_contract.d.ts.map +1 -0
  25. package/dest/make_standard_contract.js +40 -0
  26. package/dest/public-checks/constants.d.ts +4 -0
  27. package/dest/public-checks/constants.d.ts.map +1 -0
  28. package/dest/public-checks/constants.js +7 -0
  29. package/dest/public-checks/index.d.ts +6 -0
  30. package/dest/public-checks/index.d.ts.map +1 -0
  31. package/dest/public-checks/index.js +14 -0
  32. package/dest/public-checks/lazy.d.ts +7 -0
  33. package/dest/public-checks/lazy.d.ts.map +1 -0
  34. package/dest/public-checks/lazy.js +24 -0
  35. package/dest/scripts/cleanup_artifacts.js +16 -0
  36. package/dest/scripts/generate_data.js +79 -0
  37. package/dest/standard_contract.d.ts +15 -0
  38. package/dest/standard_contract.d.ts.map +1 -0
  39. package/dest/standard_contract.js +1 -0
  40. package/dest/standard_contract_data.d.ts +19 -0
  41. package/dest/standard_contract_data.d.ts.map +1 -0
  42. package/dest/standard_contract_data.js +45 -0
  43. package/package.json +101 -0
  44. package/src/auth-registry/constants.ts +8 -0
  45. package/src/auth-registry/index.ts +24 -0
  46. package/src/auth-registry/lazy.ts +35 -0
  47. package/src/contract_data.ts +119 -0
  48. package/src/drift.ts +201 -0
  49. package/src/index.ts +2 -0
  50. package/src/make_standard_contract.ts +51 -0
  51. package/src/public-checks/constants.ts +8 -0
  52. package/src/public-checks/index.ts +24 -0
  53. package/src/public-checks/lazy.ts +35 -0
  54. package/src/standard_contract.ts +15 -0
  55. package/src/standard_contract_data.ts +59 -0
package/src/drift.ts ADDED
@@ -0,0 +1,201 @@
1
+ // Build-time-only rendering and drift-detection plumbing shared by the generator
2
+ // (`scripts/generate_data.ts`) and the backup jest test (`standard_contract_data.test.ts`). Lives
3
+ // outside `contract_data.ts` so that `prettier` (a devDependency used only here) does not become a
4
+ // transitive runtime import of the published package.
5
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
6
+
7
+ import { promises as fs } from 'fs';
8
+ import path from 'path';
9
+ import * as prettier from 'prettier';
10
+
11
+ import {
12
+ type ContractData,
13
+ NOIR_STANDARD_ADDRESSES_PATHS,
14
+ STANDARD_CONTRACT_DATA_OUTPUT_PATH,
15
+ STANDARD_CONTRACT_SALT,
16
+ standardContracts,
17
+ } from './contract_data.js';
18
+
19
+ function generateNames(names: string[]) {
20
+ return `
21
+ export const standardContractNames = [
22
+ ${names.map(name => `'${name}'`).join(',\n')}
23
+ ] as const;
24
+
25
+ export type StandardContractName = typeof standardContractNames[number];
26
+ `;
27
+ }
28
+
29
+ function generateSalts(names: string[]) {
30
+ return `
31
+ export const StandardContractSalt: Record<StandardContractName, Fr> = {
32
+ ${names.map(name => `${name}: new Fr(${STANDARD_CONTRACT_SALT.toNumber()})`).join(',\n')}
33
+ };
34
+ `;
35
+ }
36
+
37
+ function generateAddresses(names: string[], contractData: ContractData[]) {
38
+ return `
39
+ export const StandardContractAddress: Record<StandardContractName, AztecAddress> = {
40
+ ${contractData.map((d, i) => `${names[i]}: AztecAddress.fromString('${d.address.toString()}')`).join(',\n')}
41
+ };
42
+ `;
43
+ }
44
+
45
+ function generateClassIdPreimages(names: string[], contractData: ContractData[]) {
46
+ return `
47
+ export const StandardContractClassId: Record<StandardContractName, Fr> = {
48
+ ${contractData.map((d, i) => `${names[i]}: Fr.fromString('${d.classId.toString()}')`).join(',\n')}
49
+ };
50
+
51
+ export const StandardContractClassIdPreimage: Record<StandardContractName, { artifactHash: Fr; privateFunctionsRoot: Fr; publicBytecodeCommitment: Fr }> = {
52
+ ${contractData
53
+ .map(
54
+ (d, i) => `${names[i]}: {
55
+ artifactHash: Fr.fromString('${d.artifactHash.toString()}'),
56
+ privateFunctionsRoot: Fr.fromString('${d.privateFunctionsRoot.toString()}'),
57
+ publicBytecodeCommitment: Fr.fromString('${d.publicBytecodeCommitment.toString()}'),
58
+ }`,
59
+ )
60
+ .join(',\n')}
61
+ };
62
+
63
+ export const StandardContractInitializationHash: Record<StandardContractName, Fr> = {
64
+ ${contractData.map((d, i) => `${names[i]}: Fr.fromString('${d.initializationHash.toString()}')`).join(',\n')}
65
+ };
66
+
67
+ export const StandardContractPrivateFunctions: Record<StandardContractName, { selector: FunctionSelector; vkHash: Fr }[]> = {
68
+ ${contractData
69
+ .map(
70
+ (d, i) =>
71
+ `${names[i]}: [${d.privateFunctions
72
+ .map(
73
+ fn =>
74
+ `{ selector: FunctionSelector.fromField(Fr.fromString('${fn.selector.toField().toString()}')), vkHash: Fr.fromString('${fn.vkHash.toString()}') }`,
75
+ )
76
+ .join(', ')}]`,
77
+ )
78
+ .join(',\n')}
79
+ };
80
+ `;
81
+ }
82
+
83
+ /**
84
+ * Renders the unformatted TypeScript content for `standard_contract_data.ts`. Run {@link formatTs}
85
+ * on the result before comparing against the committed file — the committed file has been
86
+ * prettier-formatted, so unformatted bytes will not byte-match.
87
+ */
88
+ export function renderOutputFile(names: string[], contractData: ContractData[]): string {
89
+ return `
90
+ // GENERATED FILE - DO NOT EDIT. RUN \`yarn generate\` or \`yarn generate:data\`
91
+ import { Fr } from '@aztec/foundation/curves/bn254';
92
+ import { FunctionSelector } from '@aztec/stdlib/abi';
93
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
94
+
95
+ ${generateNames(names)}
96
+
97
+ ${generateSalts(names)}
98
+
99
+ ${generateAddresses(names, contractData)}
100
+
101
+ ${generateClassIdPreimages(names, contractData)}
102
+ `;
103
+ }
104
+
105
+ /**
106
+ * Renders the content for each `standard_addresses.nr` twin. Format-stable — `nargo fmt` will not
107
+ * rewrite the output, so the bytes returned here are byte-equal to what should be on disk.
108
+ */
109
+ export function renderNoirAddresses(rows: { nrConst: string; address: AztecAddress }[]): string {
110
+ // Pre-wrapped to survive `nargo fmt`'s line-width pass without diff churn.
111
+ const globals = rows
112
+ .map(
113
+ r => `pub global ${r.nrConst}: AztecAddress = AztecAddress::from_field(
114
+ ${r.address.toField().toString()},
115
+ );`,
116
+ )
117
+ .join('\n\n');
118
+ return `// GENERATED FILE - DO NOT EDIT. RUN \`yarn workspace @aztec/standard-contracts run generate\`.
119
+ use protocol_types::{address::AztecAddress, traits::FromField};
120
+
121
+ ${globals}
122
+ `;
123
+ }
124
+
125
+ /**
126
+ * Formats TypeScript content with the repo's prettier config so the bytes emitted by the generator
127
+ * (and the expected bytes used by the drift test) match what the eventual `format` step in
128
+ * bootstrap.sh produces. Without this normalization the drift check would false-positive on every
129
+ * run since the raw template-string output differs from the prettier-formatted committed content.
130
+ *
131
+ * The typescript/estree plugins are loaded eagerly and passed explicitly: prettier 3's default
132
+ * lazy-loading via ESM dynamic import is unreliable under jest's `experimental-vm-modules` (the
133
+ * VM context can tear down before the dynamic import resolves), which causes intermittent
134
+ * `Cannot read properties of undefined (reading 'estree')` failures.
135
+ */
136
+ export async function formatTs(filePath: string, content: string): Promise<string> {
137
+ const [typescriptPlugin, estreePlugin] = await Promise.all([
138
+ import('prettier/plugins/typescript.js'),
139
+ import('prettier/plugins/estree.js'),
140
+ ]);
141
+ const config = (await prettier.resolveConfig(path.resolve(filePath))) ?? {};
142
+ return prettier.format(content, {
143
+ ...config,
144
+ filepath: filePath,
145
+ parser: 'typescript',
146
+ plugins: [typescriptPlugin.default ?? typescriptPlugin, estreePlugin.default ?? estreePlugin],
147
+ });
148
+ }
149
+
150
+ /** A rendered target file: the destination path and the exact bytes that should be on disk. */
151
+ export type RenderedTarget = { path: string; content: string };
152
+
153
+ /**
154
+ * Renders every generator output target (the TS data file plus each `standard_addresses.nr` twin)
155
+ * from a list of derived `ContractData`. The TS output is prettier-formatted so the result is
156
+ * byte-comparable against the committed file. Both the generator and the drift test build their
157
+ * comparison against this single function.
158
+ */
159
+ export async function renderAllTargets(names: string[], contractData: ContractData[]): Promise<RenderedTarget[]> {
160
+ const tsContent = await formatTs(STANDARD_CONTRACT_DATA_OUTPUT_PATH, renderOutputFile(names, contractData));
161
+ const noirRows = standardContracts
162
+ .map((c, i) => ({ nrConst: c.nrConst, address: contractData[i].address }))
163
+ .filter((row): row is { nrConst: string; address: AztecAddress } => row.nrConst !== null);
164
+ const noirContent = renderNoirAddresses(noirRows);
165
+ return [
166
+ { path: STANDARD_CONTRACT_DATA_OUTPUT_PATH, content: tsContent },
167
+ ...NOIR_STANDARD_ADDRESSES_PATHS.map(p => ({ path: p, content: noirContent })),
168
+ ];
169
+ }
170
+
171
+ /**
172
+ * Reads a file's current content, or returns `null` if it doesn't exist. Used by the generator to
173
+ * compare against freshly rendered output before deciding to overwrite, and by the drift test to
174
+ * compare the committed file's bytes against the expected bytes.
175
+ */
176
+ export async function readIfExists(filePath: string): Promise<string | null> {
177
+ try {
178
+ return await fs.readFile(filePath, 'utf8');
179
+ } catch (err: any) {
180
+ if (err.code === 'ENOENT') {
181
+ return null;
182
+ }
183
+ throw err;
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Compares `content` against the bytes currently at `filePath`. If they differ (including the file
189
+ * not existing), writes the new content and returns `true`. If they match, leaves the file
190
+ * untouched and returns `false`. Skipping the write when the content is identical avoids mtime
191
+ * churn that would otherwise re-trigger downstream build steps on every generator run.
192
+ */
193
+ export async function writeIfChanged(filePath: string, content: string): Promise<boolean> {
194
+ const existing = await readIfExists(filePath);
195
+ if (existing === content) {
196
+ return false;
197
+ }
198
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
199
+ await fs.writeFile(filePath, content);
200
+ return true;
201
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './auth-registry/index.js';
2
+ export * from './public-checks/index.js';
@@ -0,0 +1,51 @@
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
+ import type { ContractArtifact } from '@aztec/stdlib/abi';
3
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
4
+ import { PublicKeys } from '@aztec/stdlib/keys';
5
+
6
+ import type { StandardContract } from './standard_contract.js';
7
+ import {
8
+ StandardContractAddress,
9
+ StandardContractClassId,
10
+ StandardContractClassIdPreimage,
11
+ StandardContractInitializationHash,
12
+ type StandardContractName,
13
+ StandardContractPrivateFunctions,
14
+ StandardContractSalt,
15
+ } from './standard_contract_data.js';
16
+
17
+ /**
18
+ * Reconstructs a StandardContract from precomputed data without performing any hash computations.
19
+ * Internal to the standard-contracts package — not part of the public API.
20
+ */
21
+ export function makeStandardContract(name: StandardContractName, artifact: ContractArtifact): StandardContract {
22
+ const address = StandardContractAddress[name];
23
+ const salt = StandardContractSalt[name];
24
+ const classId = StandardContractClassId[name];
25
+ const { artifactHash, privateFunctionsRoot, publicBytecodeCommitment } = StandardContractClassIdPreimage[name];
26
+ const initializationHash = StandardContractInitializationHash[name];
27
+
28
+ const contractClass = {
29
+ id: classId,
30
+ version: 1 as const,
31
+ artifactHash,
32
+ privateFunctionsRoot,
33
+ publicBytecodeCommitment,
34
+ packedBytecode: artifact.functions.find(f => f.name === 'public_dispatch')?.bytecode ?? Buffer.alloc(0),
35
+ privateFunctions: StandardContractPrivateFunctions[name],
36
+ };
37
+
38
+ const instance = {
39
+ version: 2 as const,
40
+ currentContractClassId: classId,
41
+ originalContractClassId: classId,
42
+ initializationHash,
43
+ immutablesHash: Fr.ZERO,
44
+ publicKeys: PublicKeys.default(),
45
+ salt,
46
+ deployer: AztecAddress.ZERO,
47
+ address,
48
+ };
49
+
50
+ return { instance, contractClass, artifact, address };
51
+ }
@@ -0,0 +1,8 @@
1
+ // Lightweight metadata leaf export for browser bundles: importing from
2
+ // `@aztec/standard-contracts/public-checks/constants` avoids dragging in the
3
+ // `PublicChecks.json` static import.
4
+ import { StandardContractAddress, StandardContractClassId, StandardContractSalt } from '../standard_contract_data.js';
5
+
6
+ export const STANDARD_PUBLIC_CHECKS_ADDRESS = StandardContractAddress.PublicChecks;
7
+ export const STANDARD_PUBLIC_CHECKS_CLASS_ID = StandardContractClassId.PublicChecks;
8
+ export const STANDARD_PUBLIC_CHECKS_SALT = StandardContractSalt.PublicChecks;
@@ -0,0 +1,24 @@
1
+ import { loadContractArtifact } from '@aztec/stdlib/abi';
2
+ import type { NoirCompiledContract } from '@aztec/stdlib/noir';
3
+
4
+ import PublicChecksJson from '../../artifacts/PublicChecks.json' with { type: 'json' };
5
+ import { makeStandardContract } from '../make_standard_contract.js';
6
+ import type { StandardContract } from '../standard_contract.js';
7
+
8
+ export {
9
+ STANDARD_PUBLIC_CHECKS_ADDRESS,
10
+ STANDARD_PUBLIC_CHECKS_CLASS_ID,
11
+ STANDARD_PUBLIC_CHECKS_SALT,
12
+ } from './constants.js';
13
+
14
+ export const PublicChecksArtifact = loadContractArtifact(PublicChecksJson as NoirCompiledContract);
15
+
16
+ let standardContract: StandardContract;
17
+
18
+ /** Returns the standard deployment of public_checks. */
19
+ export function getStandardPublicChecks(): Promise<StandardContract> {
20
+ if (!standardContract) {
21
+ standardContract = makeStandardContract('PublicChecks', PublicChecksArtifact);
22
+ }
23
+ return Promise.resolve(standardContract);
24
+ }
@@ -0,0 +1,35 @@
1
+ import { type ContractArtifact, loadContractArtifact } from '@aztec/stdlib/abi';
2
+
3
+ import { makeStandardContract } from '../make_standard_contract.js';
4
+ import type { StandardContract } from '../standard_contract.js';
5
+
6
+ export {
7
+ STANDARD_PUBLIC_CHECKS_ADDRESS,
8
+ STANDARD_PUBLIC_CHECKS_CLASS_ID,
9
+ STANDARD_PUBLIC_CHECKS_SALT,
10
+ } from './constants.js';
11
+
12
+ let standardContract: StandardContract;
13
+ let standardContractArtifact: ContractArtifact;
14
+
15
+ export async function getPublicChecksArtifact(): Promise<ContractArtifact> {
16
+ if (!standardContractArtifact) {
17
+ // Cannot assert this import as it's incompatible with bundlers like vite
18
+ // https://github.com/vitejs/vite/issues/19095#issuecomment-2566074352
19
+ // Even if now supported by all major browsers, the MIME type is replaced with
20
+ // "text/javascript"
21
+ // In the meantime, this lazy import is INCOMPATIBLE WITH NODEJS
22
+ const { default: publicChecksJson } = await import('../../artifacts/PublicChecks.json');
23
+ standardContractArtifact = loadContractArtifact(publicChecksJson);
24
+ }
25
+ return standardContractArtifact;
26
+ }
27
+
28
+ /** Returns the standard deployment of public_checks. */
29
+ export async function getStandardPublicChecks(): Promise<StandardContract> {
30
+ if (!standardContract) {
31
+ const artifact = await getPublicChecksArtifact();
32
+ standardContract = makeStandardContract('PublicChecks', artifact);
33
+ }
34
+ return standardContract;
35
+ }
@@ -0,0 +1,15 @@
1
+ import type { ContractArtifact } from '@aztec/stdlib/abi';
2
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
3
+ import type { ContractClassIdPreimage, ContractClassWithId, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
4
+
5
+ /** A non-protocol contract deployed at a canonical artifact-derived address. */
6
+ export interface StandardContract {
7
+ /** Canonical deployed instance. */
8
+ instance: ContractInstanceWithAddress;
9
+ /** Contract class of this contract. */
10
+ contractClass: ContractClassWithId & ContractClassIdPreimage;
11
+ /** Complete contract artifact. */
12
+ artifact: ContractArtifact;
13
+ /** Deployment address for the canonical instance. */
14
+ address: AztecAddress;
15
+ }
@@ -0,0 +1,59 @@
1
+ // GENERATED FILE - DO NOT EDIT. RUN `yarn generate` or `yarn generate:data`
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
+ import { FunctionSelector } from '@aztec/stdlib/abi';
4
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
5
+
6
+ export const standardContractNames = ['AuthRegistry', 'PublicChecks'] as const;
7
+
8
+ export type StandardContractName = (typeof standardContractNames)[number];
9
+
10
+ export const StandardContractSalt: Record<StandardContractName, Fr> = {
11
+ AuthRegistry: new Fr(1),
12
+ PublicChecks: new Fr(1),
13
+ };
14
+
15
+ export const StandardContractAddress: Record<StandardContractName, AztecAddress> = {
16
+ AuthRegistry: AztecAddress.fromString('0x27ced680dd8c176230127b42131054bce7fcd00623650eb695b5588bac81430b'),
17
+ PublicChecks: AztecAddress.fromString('0x05d900a6ed1b4ad3ff52cbe5f98d9b291b0f35c6dd5c41b1642659344d234bfe'),
18
+ };
19
+
20
+ export const StandardContractClassId: Record<StandardContractName, Fr> = {
21
+ AuthRegistry: Fr.fromString('0x2a2197818ebc248f6933c0364e50de7b4dcee6a4e53cfadcebae98d77ec0ca4a'),
22
+ PublicChecks: Fr.fromString('0x022bbd3c085d6a09ec500110852441419c7b1e6dc21a8d459233b72a84d03a1f'),
23
+ };
24
+
25
+ export const StandardContractClassIdPreimage: Record<
26
+ StandardContractName,
27
+ { artifactHash: Fr; privateFunctionsRoot: Fr; publicBytecodeCommitment: Fr }
28
+ > = {
29
+ AuthRegistry: {
30
+ artifactHash: Fr.fromString('0x1bf78e923b58f3e083093a39ccfc37576b9089c439797365cc7fe3b73a000dbc'),
31
+ privateFunctionsRoot: Fr.fromString('0x17b584350f4c3ccafd8f688729afb9feab8976114fb40012e9dee65022c072a4'),
32
+ publicBytecodeCommitment: Fr.fromString('0x2545f39893766508ce37bb5cea5e4dcab04c6f7f79f3089b1c076876e9d268b2'),
33
+ },
34
+ PublicChecks: {
35
+ artifactHash: Fr.fromString('0x030776b58475bf6a0545eaa4f4002f5fe6701bd0d306b68065f4b40ef4fdbe60'),
36
+ privateFunctionsRoot: Fr.fromString('0x202860adb1b8975971eeaf571aaaa88a27f4035290d58532ae7d60b0dfaad54c'),
37
+ publicBytecodeCommitment: Fr.fromString('0x013c4f854a5c87c9daf86c5f9bc07a42c2a061f1d924a5b3564ec7edc8e18cb7'),
38
+ },
39
+ };
40
+
41
+ export const StandardContractInitializationHash: Record<StandardContractName, Fr> = {
42
+ AuthRegistry: Fr.fromString('0x0000000000000000000000000000000000000000000000000000000000000000'),
43
+ PublicChecks: Fr.fromString('0x0000000000000000000000000000000000000000000000000000000000000000'),
44
+ };
45
+
46
+ export const StandardContractPrivateFunctions: Record<
47
+ StandardContractName,
48
+ { selector: FunctionSelector; vkHash: Fr }[]
49
+ > = {
50
+ AuthRegistry: [
51
+ {
52
+ selector: FunctionSelector.fromField(
53
+ Fr.fromString('0x0000000000000000000000000000000000000000000000000000000079a3d418'),
54
+ ),
55
+ vkHash: Fr.fromString('0x06a5c1b3a636c954a90be43cb56a4bdd9dc8aec764151a012e0018753694ff54'),
56
+ },
57
+ ],
58
+ PublicChecks: [],
59
+ };