@artblocks/abx-sdk 0.1.0-alpha.12 → 0.1.0-alpha.14

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 (75) hide show
  1. package/dist/abi/generated.d.ts +926 -249
  2. package/dist/abi/generated.d.ts.map +1 -1
  3. package/dist/abi/generated.js +41 -39
  4. package/dist/abi/generated.js.map +1 -1
  5. package/dist/abi/index.d.ts +468 -61
  6. package/dist/abi/index.d.ts.map +1 -1
  7. package/dist/abi/index.js +16 -7
  8. package/dist/abi/index.js.map +1 -1
  9. package/dist/anchors.d.ts +78 -34
  10. package/dist/anchors.d.ts.map +1 -1
  11. package/dist/anchors.js +179 -35
  12. package/dist/anchors.js.map +1 -1
  13. package/dist/create2.d.ts +78 -7
  14. package/dist/create2.d.ts.map +1 -1
  15. package/dist/create2.js +149 -20
  16. package/dist/create2.js.map +1 -1
  17. package/dist/creator-token.d.ts +71 -4
  18. package/dist/creator-token.d.ts.map +1 -1
  19. package/dist/creator-token.js +94 -4
  20. package/dist/creator-token.js.map +1 -1
  21. package/dist/deploy.d.ts +49 -23
  22. package/dist/deploy.d.ts.map +1 -1
  23. package/dist/deploy.js +156 -76
  24. package/dist/deploy.js.map +1 -1
  25. package/dist/deployments.d.ts +4 -0
  26. package/dist/deployments.d.ts.map +1 -1
  27. package/dist/deployments.js +110 -45
  28. package/dist/deployments.js.map +1 -1
  29. package/dist/errors.d.ts +19 -0
  30. package/dist/errors.d.ts.map +1 -1
  31. package/dist/errors.js +24 -0
  32. package/dist/errors.js.map +1 -1
  33. package/dist/generator-document.d.ts +3 -2
  34. package/dist/generator-document.d.ts.map +1 -1
  35. package/dist/generator-document.js +3 -2
  36. package/dist/generator-document.js.map +1 -1
  37. package/dist/generator.d.ts +43 -1
  38. package/dist/generator.d.ts.map +1 -1
  39. package/dist/generator.js +29 -0
  40. package/dist/generator.js.map +1 -1
  41. package/dist/inspect.d.ts +1 -1
  42. package/dist/inspect.js +2 -2
  43. package/dist/inspect.js.map +1 -1
  44. package/dist/onchain-uri.d.ts +15 -1
  45. package/dist/onchain-uri.d.ts.map +1 -1
  46. package/dist/onchain-uri.js +45 -3
  47. package/dist/onchain-uri.js.map +1 -1
  48. package/dist/ops.d.ts +210 -11
  49. package/dist/ops.d.ts.map +1 -1
  50. package/dist/ops.js +308 -34
  51. package/dist/ops.js.map +1 -1
  52. package/dist/reconstruct.d.ts +1 -0
  53. package/dist/reconstruct.d.ts.map +1 -1
  54. package/dist/reconstruct.js +13 -1
  55. package/dist/reconstruct.js.map +1 -1
  56. package/dist/service.d.ts +1 -1
  57. package/dist/service.js +1 -1
  58. package/dist/spine.d.ts +3 -4
  59. package/dist/spine.d.ts.map +1 -1
  60. package/dist/spine.js +0 -0
  61. package/dist/spine.js.map +1 -1
  62. package/dist/staging.d.ts +32 -3
  63. package/dist/staging.d.ts.map +1 -1
  64. package/dist/staging.js +85 -8
  65. package/dist/staging.js.map +1 -1
  66. package/dist/tokendata.d.ts +1 -1
  67. package/dist/tokendata.d.ts.map +1 -1
  68. package/dist/tokendata.js +21 -3
  69. package/dist/tokendata.js.map +1 -1
  70. package/dist/tokens.d.ts +1 -1
  71. package/dist/tokens.js +1 -1
  72. package/dist/tokens.js.map +1 -1
  73. package/dist/types.d.ts +8 -1
  74. package/dist/types.d.ts.map +1 -1
  75. package/package.json +1 -1
package/dist/create2.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { concat, getContractAddress, keccak256, toBytes } from 'viem';
2
- import { abxChunkStoreBytecode, abxFixedPriceMinterBytecode, abxFixedPriceMinter1155Bytecode, abxMetadataRendererBytecode, abxSeedSourceBytecode, editionImageFactoryBytecode, oneOfOneEditionFactoryBytecode, } from './abi/index.js';
2
+ import { abxChunkStoreBytecode, abxCodeLibBytecode, abxEditionLibBytecode, abxMetadataLibBytecode, abxFixedPriceMinterBytecode, abxFixedPriceMinter1155Bytecode, abxMetadataRendererBytecode, abxParamsLibBytecode, abxSeedSourceBytecode, editionCodeFactoryBytecode, editionImageFactoryBytecode, oneOfOneEditionFactoryBytecode, oneOfOneImageFactoryBytecode, seriesCodeFactoryBytecode, seriesImageFactoryBytecode, } from './abi/index.js';
3
3
  /**
4
4
  * Keyless CREATE2 deployment — the TS twin of `contracts/script/AbxSalts.sol`.
5
5
  *
@@ -12,7 +12,9 @@ import { abxChunkStoreBytecode, abxFixedPriceMinterBytecode, abxFixedPriceMinter
12
12
  /** The keyless CREATE2 proxy (Arachnid deterministic-deployment-proxy). Same address on every chain. */
13
13
  export const CREATE2_PROXY = '0x4e59b44847b379578588920cA78FbF26c0B4956C';
14
14
  /** Canonical salt strings — MUST stay byte-identical to `contracts/script/AbxSalts.sol`, since the
15
- * deterministic address is `keccak256(0xff ++ proxy ++ keccak256(salt) ++ keccak256(initcode))`. */
15
+ * deterministic address is `keccak256(0xff ++ proxy ++ keccak256(salt) ++ keccak256(initcode))`.
16
+ * `test/create2-salts.test.ts` diffs this table against that file, both ways, so drift can't be
17
+ * quiet: the two halves have to be one fact. */
16
18
  export const ABX_SALT = {
17
19
  oneOfOneFactory: 'abx.factory.one-of-one.v1',
18
20
  seriesFactory: 'abx.factory.series.v1',
@@ -22,14 +24,17 @@ export const ABX_SALT = {
22
24
  fixedPriceMinter: 'abx.minter.fixed-price.v1',
23
25
  seedSource: 'abx.seed-source.v1',
24
26
  generator: 'abx.generator.v1',
25
- // ERC-1155 editions (twins of the above; naming follows the parity plan verbatim). Listed here
26
- // for parity with `AbxSalts.sol` even though `editionCodeFactory`'s salt (like
27
- // `seriesCodeFactory`'s above) is never fed to `predictCreate2Address` — see the class-level
28
- // dev note below on why the lib-linked factory has no SDK-side prediction.
27
+ // ERC-1155 editions (twins of the above; naming follows the parity plan verbatim).
29
28
  oneOfOneEditionFactory: 'abx.one-of-one-edition-factory.v1',
30
29
  editionFactory: 'abx.edition-factory.v1',
31
30
  editionCodeFactory: 'abx.edition-code-factory.v1',
32
31
  fixedPriceMinter1155: 'abx.fixed-price-minter-1155.v1',
32
+ // Delegatecalled write-path libraries — CREATE2 like everything else here (see the
33
+ // "delegatecalled write-path libraries" note below, and `DeployLibraries.s.sol`).
34
+ paramsLib: 'abx.lib.params.v1',
35
+ codeLib: 'abx.lib.code.v1',
36
+ editionLib: 'abx.lib.edition.v1',
37
+ metadataLib: 'abx.lib.metadata.v1',
33
38
  };
34
39
  /** The 32-byte salt a CREATE2 deploy uses (`keccak256` of the canonical string). */
35
40
  export const saltHash = (salt) => keccak256(toBytes(salt));
@@ -55,21 +60,145 @@ export const predictSeedSource = () => predictCreate2Address(ABX_SALT.seedSource
55
60
  // ── ERC-1155 editions ──────────────────────────────────────────────────────────
56
61
  //
57
62
  // `DeployOneOfOneEdition.s.sol` / `DeployEdition.s.sol` / `DeployMinter1155.s.sol` each deploy
58
- // their contract with a fixed `AbxSalts` salt and NO constructor args, so — exactly like the
59
- // renderer/chunk-store/1155-minter-free singletons above — the SDK's own bytecode (from
60
- // `generated.ts`) is sufficient to predict the address before any deploy. `EditionCodeFactory` is
61
- // the one exception: its implementation `delegatecall`s three externally-linked libraries
62
- // (`AbxParamsLib`/`AbxCodeLib`/`AbxEditionLib`), so its FINAL initcode embeds those libraries'
63
- // deployed addresses — which are nonce-dependent, not fixed by source alone — and is therefore
64
- // not something the SDK can predict ahead of a deploy. Mirrors exactly why `SeriesCodeFactory` has
65
- // no `predict*` here either (see `deploySeriesCodeFactory`'s own doc comment in `deploy.ts`).
66
- /** The canonical (cross-chain-identical) `OneOfOneEditionFactory` address for the current
67
- * bytecode — the 1/1-edition trust anchor. */
68
- export const predictOneOfOneEditionFactory = () => predictCreate2Address(ABX_SALT.oneOfOneEditionFactory, oneOfOneEditionFactoryBytecode);
69
- /** The canonical (cross-chain-identical) `EditionImageFactory` address for the current
70
- * bytecode — the multi-artwork edition trust anchor. */
71
- export const predictEditionFactory = () => predictCreate2Address(ABX_SALT.editionFactory, editionImageFactoryBytecode);
63
+ // their contract with a fixed `AbxSalts` salt and NO constructor args, so the salt + this build's
64
+ // bytecode fix the address before any deploy. `AbxFixedPriceMinter1155` is a plain singleton and is
65
+ // predicted right below; the two edition IMAGE factories are not — `OneOfOneEdition`/`EditionImage`
66
+ // both delegate bodies into `AbxEditionLib`, so their factories carry a link placeholder and their
67
+ // predictions live with the library-linked factories in the write-path-library section below
68
+ // (`predictOneOfOneEditionFactory`/`predictEditionFactory`), next to the two code factories.
69
+ /** The canonical (cross-chain-identical) `OneOfOneImageFactory` address for the current bytecode —
70
+ * the 721 1/1 trust anchor. */
71
+ export const predictFactory = () => predictCreate2Address(ABX_SALT.oneOfOneFactory, linkFactory());
72
+ /** The canonical (cross-chain-identical) `SeriesImageFactory` address for the current bytecode —
73
+ * the 721 multi-token trust anchor. */
74
+ export const predictSeriesFactory = () => predictCreate2Address(ABX_SALT.seriesFactory, linkSeriesFactory());
72
75
  /** The canonical (cross-chain-identical) `AbxFixedPriceMinter1155` address for the current
73
76
  * bytecode — the shared, ownerless edition sale singleton. */
74
77
  export const predictFixedPriceMinter1155 = () => predictCreate2Address(ABX_SALT.fixedPriceMinter1155, abxFixedPriceMinter1155Bytecode);
78
+ // ── delegatecalled write-path libraries ────────────────────────────────────────
79
+ //
80
+ // A `public` library function is compiled as a `delegatecall` to a SEPARATELY deployed copy of the
81
+ // library, and solc leaves a `__$<id>$__` placeholder in the caller's bytecode where that copy's
82
+ // address goes. Linking is the substitution of an address into that placeholder.
83
+ //
84
+ // **Linking does not cost determinism.** These libraries are deployed through the same keyless
85
+ // CREATE2 proxy at the canonical salts above (`DeployLibraries.s.sol` is the forge twin), so a
86
+ // library's address is `f(proxy, salt, creation bytecode)` and nothing else — the deployer's nonce
87
+ // is not an input to a CREATE2 address (it is an input to plain `CREATE`, which is where the
88
+ // confusion came from). Predict the libraries, substitute them, and the linked factory's initcode
89
+ // is fixed too — hence the FOUR `predict*Factory` helpers at the bottom of this section.
90
+ //
91
+ // Worth stating plainly, because the opposite belief was load-bearing: two ERC-1155 token types
92
+ // (`OneOfOneEdition`/`EditionImage`) were held library-free and an EIP-170 size floor was relaxed to
93
+ // avoid "losing" a factory's deterministic address. What was actually true was narrower and
94
+ // self-inflicted — the SDK deployed its libraries with a plain EOA `CREATE` (`to: null`) by its own
95
+ // choice, so *it* could not predict them, and that local limitation was written up as a property of
96
+ // libraries in general. It isn't one. The broadcast artifacts always said so: every recorded library
97
+ // deploy went through the keyless proxy, and `AbxParamsLib` landed at ONE address on Sepolia and
98
+ // Base Sepolia from deployer nonces 215 apart. Both of those token types now delegate into
99
+ // `AbxEditionLib` exactly as `EditionCode` does, so FOUR factories here are library-linked, not two.
100
+ //
101
+ // **Losing track of that is a bug class, not a footnote.** Three separate times a contract became
102
+ // library-linked and this file went on hashing its UNLINKED bytecode, and the failure is silent:
103
+ // viem does not reject a `__$…$__` placeholder, it UTF-8-encodes it — so the prediction is a
104
+ // real-looking address that is the hash of ASCII garbage, for the addresses platforms allowlist, and
105
+ // the same bytes would go out as initcode. `link.test.ts`'s "nothing deployable carries a
106
+ // placeholder" guard derives its subject set from the exported bytecodes rather than a list of
107
+ // names, precisely so the next contract to become library-linked cannot escape the same way.
108
+ //
109
+ // **The real trap is compile-time linking, not linking.** Substituting into the placeholder happens
110
+ // AFTER compilation, so it cannot change the library's own creation bytecode. Handing solc the
111
+ // addresses at build time instead (`forge build/script --libraries src/…:Lib:0x…`) writes the
112
+ // library map into `settings.libraries` in every artifact's metadata, and the metadata hash is
113
+ // appended to the creation bytecode — so the library's own address moves, and so does the linked
114
+ // factory's. Optimizer settings do the same (the code tokens compile at `optimizer_runs = 200`,
115
+ // everything else at 1,000,000). One canonical bytecode per library, therefore: the one
116
+ // `sync-abis` reads from a plain `forge build`, which is what these predictions use.
117
+ /** Fully-qualified library names (solc's link keys — path-sensitive, so they must match how the
118
+ * contracts are compiled: `src/libraries/…` as `foundry.toml` sees them). */
119
+ export const LIB_FQN = {
120
+ paramsLib: 'src/libraries/AbxParamsLib.sol:AbxParamsLib',
121
+ codeLib: 'src/libraries/AbxCodeLib.sol:AbxCodeLib',
122
+ editionLib: 'src/libraries/AbxEditionLib.sol:AbxEditionLib',
123
+ metadataLib: 'src/libraries/AbxMetadataLib.sol:AbxMetadataLib',
124
+ };
125
+ /** The solc link placeholder for a fully-qualified library name: `__$<keccak(fqn)[0:34]>$__`. */
126
+ export const libPlaceholder = (fullyQualified) => `__$${keccak256(toBytes(fullyQualified)).slice(2, 36)}$__`;
127
+ /**
128
+ * Link `bytecode` against deployed libraries — the post-compile placeholder substitution `forge`
129
+ * does at build time, done here so a sandbox / fresh chain needs no forge. Throws if any
130
+ * placeholder is left over, since an unlinked `__$…$__` is not valid hex and the RPC would reject
131
+ * the transaction with an opaque `Invalid byte sequence`.
132
+ */
133
+ export function linkLibraries(bytecode, links) {
134
+ let out = bytecode;
135
+ for (const [fqn, address] of links)
136
+ out = out.split(libPlaceholder(fqn)).join(address.slice(2).toLowerCase());
137
+ if (out.includes('__$'))
138
+ throw new Error(`unlinked library placeholder remains: ${/__\$[0-9a-f]{34}\$__/.exec(out)?.[0]}`);
139
+ return out;
140
+ }
141
+ /** The canonical (cross-chain-identical) `AbxParamsLib` address — the params write path both code
142
+ * token types delegatecall. */
143
+ export const predictParamsLib = () => predictCreate2Address(ABX_SALT.paramsLib, abxParamsLibBytecode);
144
+ /** The canonical (cross-chain-identical) `AbxCodeLib` address — the script/code write path. */
145
+ export const predictCodeLib = () => predictCreate2Address(ABX_SALT.codeLib, abxCodeLibBytecode);
146
+ /** The canonical (cross-chain-identical) `AbxEditionLib` address — the 1155 uri / creator-token /
147
+ * edition-supply write path that **all three** edition token types (`OneOfOneEdition`,
148
+ * `EditionImage`, `EditionCode`) delegatecall.
149
+ * `AbxEditionLib` itself delegatecalls `AbxParamsLib`, so it is linked before it is deployed: the
150
+ * one library here whose own initcode depends on another library's address. */
151
+ export const predictEditionLib = () => predictCreate2Address(ABX_SALT.editionLib, linkEditionLib());
152
+ /** The canonical `AbxMetadataLib` address. Linked by ALL SIX token types — the metadata field store
153
+ * was inlined into every one of them until the 2026-08-14 audit asked for EIP-170 headroom before
154
+ * further remediation, so externalizing it is what made even the plainest 721 factory
155
+ * library-linked. It links nothing itself, so it is deployed first. */
156
+ export const predictMetadataLib = () => predictCreate2Address(ABX_SALT.metadataLib, abxMetadataLibBytecode);
157
+ /** `AbxEditionLib`'s canonical initcode: its shipped bytecode linked against `AbxParamsLib`. */
158
+ export const linkEditionLib = () => linkLibraries(abxEditionLibBytecode, [[LIB_FQN.paramsLib, predictParamsLib()]]);
159
+ /** `OneOfOneEditionFactory`'s canonical initcode: linked against `AbxEditionLib` (the only library
160
+ * its embedded `OneOfOneEdition` implementation delegates into). `AbxEditionLib`'s own address
161
+ * already accounts for its `AbxParamsLib` link — see {@link predictEditionLib}. */
162
+ export const linkOneOfOneEditionFactory = () => linkLibraries(oneOfOneEditionFactoryBytecode, [
163
+ [LIB_FQN.editionLib, predictEditionLib()],
164
+ [LIB_FQN.metadataLib, predictMetadataLib()],
165
+ ]);
166
+ /** `EditionImageFactory`'s canonical initcode: linked against `AbxEditionLib`, the sibling of
167
+ * {@link linkOneOfOneEditionFactory}. */
168
+ export const linkEditionFactory = () => linkLibraries(editionImageFactoryBytecode, [
169
+ [LIB_FQN.editionLib, predictEditionLib()],
170
+ [LIB_FQN.metadataLib, predictMetadataLib()],
171
+ ]);
172
+ /** `SeriesCodeFactory`'s canonical initcode: linked against the two write-path libraries. */
173
+ export const linkSeriesCodeFactory = () => linkLibraries(seriesCodeFactoryBytecode, [
174
+ [LIB_FQN.paramsLib, predictParamsLib()],
175
+ [LIB_FQN.codeLib, predictCodeLib()],
176
+ [LIB_FQN.metadataLib, predictMetadataLib()],
177
+ ]);
178
+ /** `EditionCodeFactory`'s canonical initcode: linked against all three write-path libraries. */
179
+ export const linkEditionCodeFactory = () => linkLibraries(editionCodeFactoryBytecode, [
180
+ [LIB_FQN.paramsLib, predictParamsLib()],
181
+ [LIB_FQN.codeLib, predictCodeLib()],
182
+ [LIB_FQN.editionLib, predictEditionLib()],
183
+ [LIB_FQN.metadataLib, predictMetadataLib()],
184
+ ]);
185
+ /** The two ERC-721 image factories' canonical initcode. They linked NOTHING until the metadata
186
+ * field store was externalized; now every token type is library-linked. */
187
+ export const linkFactory = () => linkLibraries(oneOfOneImageFactoryBytecode, [[LIB_FQN.metadataLib, predictMetadataLib()]]);
188
+ export const linkSeriesFactory = () => linkLibraries(seriesImageFactoryBytecode, [[LIB_FQN.metadataLib, predictMetadataLib()]]);
189
+ /** The canonical (cross-chain-identical) `SeriesCodeFactory` address — the code-project trust
190
+ * anchor. Predictable because its libraries are (see the section note above). */
191
+ export const predictSeriesCodeFactory = () => predictCreate2Address(ABX_SALT.seriesCodeFactory, linkSeriesCodeFactory());
192
+ /** The canonical (cross-chain-identical) `EditionCodeFactory` address — the code-project EDITION
193
+ * trust anchor. */
194
+ export const predictEditionCodeFactory = () => predictCreate2Address(ABX_SALT.editionCodeFactory, linkEditionCodeFactory());
195
+ /** The canonical (cross-chain-identical) `OneOfOneEditionFactory` address — the 1/1-edition trust
196
+ * anchor. Predicted from LINKED initcode: `OneOfOneEdition` delegates its uri / creator-token /
197
+ * edition-supply bodies into `AbxEditionLib`, so the shipped factory bytecode carries a link
198
+ * placeholder (hashing it unlinked yields a plausible-looking address for a trust anchor that
199
+ * nothing can ever be deployed to — see the section note). */
200
+ export const predictOneOfOneEditionFactory = () => predictCreate2Address(ABX_SALT.oneOfOneEditionFactory, linkOneOfOneEditionFactory());
201
+ /** The canonical (cross-chain-identical) `EditionImageFactory` address — the multi-work edition
202
+ * trust anchor, the sibling of {@link predictOneOfOneEditionFactory} (same single library link). */
203
+ export const predictEditionFactory = () => predictCreate2Address(ABX_SALT.editionFactory, linkEditionFactory());
75
204
  //# sourceMappingURL=create2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create2.js","sourceRoot":"","sources":["../src/create2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create2.js","sourceRoot":"","sources":["../src/create2.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,15 @@
8
8
  * zero — never un-enrolls. Every transfer that isn't a mint/burn (or the validator's own)
9
9
  * staticcalls `validateTransfer(caller, from, to, tokenId)` on the validator; a policy
10
10
  * violation reverts and bubbles.
11
+ *
12
+ * **`setTransferValidator` is owner-only only while the collection has an owner.** Once
13
+ * `owner() == address(0)` the contract opens one asymmetric door: **anyone** may suspend
14
+ * enforcement by passing `zeroAddress`, and nobody — including that caller — may ever arm a
15
+ * validator again. That is the dead-man release for the worst reachable state (a validator that
16
+ * reverts every transfer on a collection with nobody left to re-point it, which would otherwise
17
+ * strand every collector's token forever). An integrator building for collectors should expose
18
+ * that suspension path on a renounced collection rather than gating it behind an owner check that
19
+ * can no longer be satisfied — see {@link prepareSetTransferValidator}.
11
20
  */
12
21
  import { type Address, type PublicClient } from 'viem';
13
22
  import type { PreparedTx } from './ops.js';
@@ -50,12 +59,70 @@ export interface CreatorTokenStatus {
50
59
  * must read as `{enrolled: false, validator: zeroAddress}`, not as an error.
51
60
  */
52
61
  export declare function readCreatorTokenStatus(client: PublicClient, contract: Address): Promise<CreatorTokenStatus>;
62
+ /** What {@link probeTransferValidator} found. Only `ok` may be written to a live collection.
63
+ *
64
+ * - `ok` — the address has code and refuses a selector no validator implements,
65
+ * which is what every live validator does (see the probe's doc).
66
+ * - `no-code` — nothing deployed at this address on this chain. Enforcement would read
67
+ * as ON everywhere and check nothing.
68
+ * - `permissive-fallback` — it has code, but it answers an unknown selector *successfully*. A
69
+ * Safe, an uninitialised proxy, or a 7702-delegated EOA does this, and
70
+ * because `validateTransfer` returns nothing there is no ABI decode to
71
+ * fail — so every transfer would silently pass validation.
72
+ * - `unreachable` — the RPC didn't answer. Says nothing about the address; retry.
73
+ */
74
+ export type TransferValidatorVerdict = 'ok' | 'no-code' | 'permissive-fallback' | 'unreachable';
75
+ /** The result of {@link probeTransferValidator} — verdict plus what was observed, for a message. */
76
+ export interface TransferValidatorProbe {
77
+ verdict: TransferValidatorVerdict;
78
+ address: Address;
79
+ /** First line of the revert/transport error, when there was one. */
80
+ error?: string;
81
+ }
82
+ /**
83
+ * Ask a candidate transfer validator a question no validator can answer, and require it to FAIL.
84
+ *
85
+ * **`code.length > 0` is not enough**, which is why this exists and why the on-chain guard was
86
+ * rewritten to match. Two shapes enforce nothing while every read surface — ERC-165,
87
+ * `getTransferValidator()`, the extension beacon — reports enforcement as on: no code at all, and a
88
+ * *permissive fallback* that succeeds for any selector. `validateTransfer` returns nothing, so
89
+ * there is no ABI decode to fail; a Safe (its `FallbackManager.fallback()` returns empty when no
90
+ * handler is set), an uninitialised proxy, and an EIP-7702-delegated EOA all pass a has-code check
91
+ * and then wave every transfer through. A creator pasting their own Safe is the likely real case.
92
+ *
93
+ * So the probe inverts the question: a real validator **reverts** here (verified against OpenSea's
94
+ * SATSR and three Limit Break deployments on mainnet and Sepolia), and a permissive one returns
95
+ * empty success. This mirrors the contract exactly — the same selector, the same "must fail" rule —
96
+ * so an address that passes here is an address the token will accept, and the CLI stops reporting
97
+ * "no code on this chain" for an address that plainly has code.
98
+ *
99
+ * An ERC-165 gate was measured and rejected: none of those four live validators advertises
100
+ * `ITransferValidator`/`ITransferValidator1155`, so requiring an id would refuse the entire
101
+ * ecosystem, including the validator ABX itself recommends.
102
+ *
103
+ * **A misconfiguration guard, not a security boundary** — a contract can always be written to pass
104
+ * this and enforce nothing. It catches the honest mistake. Never throws for an on-chain reason:
105
+ * every failure is a verdict (mirrors `probeSeedSource`).
106
+ */
107
+ export declare function probeTransferValidator(client: PublicClient, validator: Address,
108
+ /** The enrolling/enrolled token, when known — the probe is made as the token, because that is
109
+ * the `msg.sender` the contract's own staticcall presents. */
110
+ opts?: {
111
+ as?: Address;
112
+ }): Promise<TransferValidatorProbe>;
53
113
  /**
54
114
  * Re-point an enrolled token's transfer validator, or suspend enforcement with
55
- * `zeroAddress` (the token stays enrolled). Signer must be the owner. Reverts
56
- * `NotCreatorToken()` on a token that didn't enroll at deploy — enrollment can never be
57
- * added later — and `InvalidTransferValidator()` on a non-zero validator with no code;
58
- * callers should read {@link readCreatorTokenStatus} first and refuse those before gas.
115
+ * `zeroAddress` (the token stays enrolled). Reverts `NotCreatorToken()` on a token that didn't
116
+ * enroll at deploy — enrollment can never be added later — and `InvalidTransferValidator()` on a
117
+ * validator the chain's own probe refuses (no code on this chain, **or** a permissive fallback that
118
+ * would enforce nothing); call {@link probeTransferValidator} first and refuse those before gas.
119
+ *
120
+ * **Who may sign:** the owner, while there is one. On a collection whose `owner()` is
121
+ * `address(0)`, **any** signer may send this with `validator = zeroAddress` to suspend enforcement
122
+ * permanently — the dead-man release described in this module's header. Arming a validator is still
123
+ * owner-only, so an ownerless collection can only move toward transferability, never back. A UX for
124
+ * collectors should offer that suspension when it sees a renounced, enforcing collection; gating it
125
+ * on `owner()` would hide the one recovery a stranded holder has.
59
126
  */
60
127
  export declare function prepareSetTransferValidator(args: {
61
128
  contract: Address;
@@ -1 +1 @@
1
- {"version":3,"file":"creator-token.d.ts","sourceRoot":"","sources":["../src/creator-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAkC,KAAK,OAAO,EAAE,KAAK,YAAY,EAAC,MAAM,MAAM,CAAC;AAEtF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,UAAU,CAAC;AAEzC,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,EAAG,YAAqB,CAAC;AAChE,qFAAqF;AACrF,eAAO,MAAM,iCAAiC,EAAG,YAAqB,CAAC;AACvE,iGAAiG;AACjG,eAAO,MAAM,0BAA0B,EACrC,oEAA6E,CAAC;AAEhF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAKlE,CAAC;AAEF,4FAA4F;AAC5F,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAExF;AAED,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,QAAQ,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,UAAU,CAiBb"}
1
+ {"version":3,"file":"creator-token.d.ts","sourceRoot":"","sources":["../src/creator-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAkC,KAAK,OAAO,EAAY,KAAK,YAAY,EAAC,MAAM,MAAM,CAAC;AAEhG,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,UAAU,CAAC;AAEzC,0FAA0F;AAC1F,eAAO,MAAM,0BAA0B,EAAG,YAAqB,CAAC;AAChE,qFAAqF;AACrF,eAAO,MAAM,iCAAiC,EAAG,YAAqB,CAAC;AACvE,iGAAiG;AACjG,eAAO,MAAM,0BAA0B,EACrC,oEAA6E,CAAC;AAEhF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAKlE,CAAC;AAEF,4FAA4F;AAC5F,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAExF;AAED,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,QAAQ,EAAE,OAAO,CAAC;IAClB,uFAAuF;IACvF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,OAAO,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAe7B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,wBAAwB,GAAG,IAAI,GAAG,SAAS,GAAG,qBAAqB,GAAG,aAAa,CAAC;AAEhG,oGAAoG;AACpG,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,wBAAwB,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,OAAO;AAClB;+DAC+D;AAC/D,IAAI,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GACxB,OAAO,CAAC,sBAAsB,CAAC,CAsBjC;AAoBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,UAAU,CAiBb"}
@@ -8,6 +8,15 @@
8
8
  * zero — never un-enrolls. Every transfer that isn't a mint/burn (or the validator's own)
9
9
  * staticcalls `validateTransfer(caller, from, to, tokenId)` on the validator; a policy
10
10
  * violation reverts and bubbles.
11
+ *
12
+ * **`setTransferValidator` is owner-only only while the collection has an owner.** Once
13
+ * `owner() == address(0)` the contract opens one asymmetric door: **anyone** may suspend
14
+ * enforcement by passing `zeroAddress`, and nobody — including that caller — may ever arm a
15
+ * validator again. That is the dead-man release for the worst reachable state (a validator that
16
+ * reverts every transfer on a collection with nobody left to re-point it, which would otherwise
17
+ * strand every collector's token forever). An integrator building for collectors should expose
18
+ * that suspension path on a renounced collection rather than gating it behind an owner check that
19
+ * can no longer be satisfied — see {@link prepareSetTransferValidator}.
11
20
  */
12
21
  import { encodeFunctionData, zeroAddress } from 'viem';
13
22
  import { oneOfOneImageAbi } from './abi/index.js';
@@ -65,12 +74,93 @@ export async function readCreatorTokenStatus(client, contract) {
65
74
  ]);
66
75
  return { enrolled, validator };
67
76
  }
77
+ /**
78
+ * A selector no transfer validator implements — the probe question. Same constant the contract's
79
+ * own `_requireHasCode` uses, so the SDK and the chain agree about which addresses are refused.
80
+ */
81
+ const NOT_A_VALIDATOR_SELECTOR = '0xa9b1c2d3';
82
+ /**
83
+ * Ask a candidate transfer validator a question no validator can answer, and require it to FAIL.
84
+ *
85
+ * **`code.length > 0` is not enough**, which is why this exists and why the on-chain guard was
86
+ * rewritten to match. Two shapes enforce nothing while every read surface — ERC-165,
87
+ * `getTransferValidator()`, the extension beacon — reports enforcement as on: no code at all, and a
88
+ * *permissive fallback* that succeeds for any selector. `validateTransfer` returns nothing, so
89
+ * there is no ABI decode to fail; a Safe (its `FallbackManager.fallback()` returns empty when no
90
+ * handler is set), an uninitialised proxy, and an EIP-7702-delegated EOA all pass a has-code check
91
+ * and then wave every transfer through. A creator pasting their own Safe is the likely real case.
92
+ *
93
+ * So the probe inverts the question: a real validator **reverts** here (verified against OpenSea's
94
+ * SATSR and three Limit Break deployments on mainnet and Sepolia), and a permissive one returns
95
+ * empty success. This mirrors the contract exactly — the same selector, the same "must fail" rule —
96
+ * so an address that passes here is an address the token will accept, and the CLI stops reporting
97
+ * "no code on this chain" for an address that plainly has code.
98
+ *
99
+ * An ERC-165 gate was measured and rejected: none of those four live validators advertises
100
+ * `ITransferValidator`/`ITransferValidator1155`, so requiring an id would refuse the entire
101
+ * ecosystem, including the validator ABX itself recommends.
102
+ *
103
+ * **A misconfiguration guard, not a security boundary** — a contract can always be written to pass
104
+ * this and enforce nothing. It catches the honest mistake. Never throws for an on-chain reason:
105
+ * every failure is a verdict (mirrors `probeSeedSource`).
106
+ */
107
+ export async function probeTransferValidator(client, validator,
108
+ /** The enrolling/enrolled token, when known — the probe is made as the token, because that is
109
+ * the `msg.sender` the contract's own staticcall presents. */
110
+ opts = {}) {
111
+ let code;
112
+ try {
113
+ code = await client.getCode({ address: validator });
114
+ }
115
+ catch (err) {
116
+ return { verdict: 'unreachable', address: validator, error: firstLine(err) };
117
+ }
118
+ if (!code || code === '0x')
119
+ return { verdict: 'no-code', address: validator };
120
+ try {
121
+ await client.call({
122
+ to: validator,
123
+ data: NOT_A_VALIDATOR_SELECTOR,
124
+ ...(opts.as ? { account: opts.as } : {}),
125
+ });
126
+ }
127
+ catch (err) {
128
+ // A revert is the PASS: this is what a real validator does with an unknown selector. A
129
+ // transport failure lands here too, so classify it rather than calling a broken RPC "ok".
130
+ return isTransportFailure(err)
131
+ ? { verdict: 'unreachable', address: validator, error: firstLine(err) }
132
+ : { verdict: 'ok', address: validator };
133
+ }
134
+ return { verdict: 'permissive-fallback', address: validator };
135
+ }
136
+ /** First line of an error message — a revert reason is readable; viem's full dump is not. */
137
+ function firstLine(err) {
138
+ return String(err?.message ?? err).split('\n')[0].trim();
139
+ }
140
+ /** Distinguish "the node said this call reverted" (a verdict) from "the node didn't answer" (retry).
141
+ * viem reports a revert as an execution error carrying revert data or the word itself; anything
142
+ * that never reached execution (timeout, socket, HTTP status, rate limit) must not read as a pass. */
143
+ function isTransportFailure(err) {
144
+ const name = err?.name ?? '';
145
+ const msg = String(err?.message ?? err);
146
+ if (/execution reverted|reverted with|revert reason|InvalidTransferValidator/i.test(msg))
147
+ return false;
148
+ return (/Timeout|Socket|Network|HttpRequest|Connection|RateLimit|InternalRpc|LimitExceeded/i.test(name) ||
149
+ /timed? out|timeout|socket hang up|ECONN|fetch failed|status code|too many requests|rate limit/i.test(msg));
150
+ }
68
151
  /**
69
152
  * Re-point an enrolled token's transfer validator, or suspend enforcement with
70
- * `zeroAddress` (the token stays enrolled). Signer must be the owner. Reverts
71
- * `NotCreatorToken()` on a token that didn't enroll at deploy — enrollment can never be
72
- * added later — and `InvalidTransferValidator()` on a non-zero validator with no code;
73
- * callers should read {@link readCreatorTokenStatus} first and refuse those before gas.
153
+ * `zeroAddress` (the token stays enrolled). Reverts `NotCreatorToken()` on a token that didn't
154
+ * enroll at deploy — enrollment can never be added later — and `InvalidTransferValidator()` on a
155
+ * validator the chain's own probe refuses (no code on this chain, **or** a permissive fallback that
156
+ * would enforce nothing); call {@link probeTransferValidator} first and refuse those before gas.
157
+ *
158
+ * **Who may sign:** the owner, while there is one. On a collection whose `owner()` is
159
+ * `address(0)`, **any** signer may send this with `validator = zeroAddress` to suspend enforcement
160
+ * permanently — the dead-man release described in this module's header. Arming a validator is still
161
+ * owner-only, so an ownerless collection can only move toward transferability, never back. A UX for
162
+ * collectors should offer that suspension when it sees a renounced, enforcing collection; gating it
163
+ * on `owner()` would hide the one recovery a stranded holder has.
74
164
  */
75
165
  export function prepareSetTransferValidator(args) {
76
166
  const suspending = args.validator === zeroAddress;
@@ -1 +1 @@
1
- {"version":3,"file":"creator-token.js","sourceRoot":"","sources":["../src/creator-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAC,kBAAkB,EAAE,WAAW,EAAkC,MAAM,MAAM,CAAC;AACtF,OAAO,EAAC,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;AAGhD,0FAA0F;AAC1F,MAAM,CAAC,MAAM,0BAA0B,GAAG,YAAqB,CAAC;AAChE,qFAAqF;AACrF,MAAM,CAAC,MAAM,iCAAiC,GAAG,YAAqB,CAAC;AACvE,iGAAiG;AACjG,MAAM,CAAC,MAAM,0BAA0B,GACrC,oEAA6E,CAAC;AAEhF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAA4B;IACrE,oBAAoB;IACpB,QAAQ,EAAE,4CAA4C;IACtD,yBAAyB;IACzB,KAAK,EAAE,4CAA4C;CACpD,CAAC;AAEF,4FAA4F;AAC5F,MAAM,UAAU,mCAAmC,CAAC,OAAe;IACjE,OAAO,8BAA8B,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC;AAUD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAoB,EACpB,QAAiB;IAEjB,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9C,MAAM;aACH,YAAY,CAAC;YACZ,OAAO,EAAE,QAAQ;YACjB,GAAG,EAAE,gBAAgB;YACrB,YAAY,EAAE,mBAAmB;YACjC,IAAI,EAAE,CAAC,0BAA0B,CAAC;SACnC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAqB;QACzC,MAAM;aACH,YAAY,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,gBAAgB,EAAE,YAAY,EAAE,sBAAsB,EAAC,CAAC;aAC9F,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,CAAqB;KAChD,CAAC,CAAC;IACH,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAC,CAAC;AAC/B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAI3C;IACC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,KAAK,WAAW,CAAC;IAClD,OAAO;QACL,EAAE,EAAE,wBAAwB;QAC5B,EAAE,EAAE,IAAI,CAAC,QAAQ;QACjB,IAAI,EAAE,kBAAkB,CAAC;YACvB,GAAG,EAAE,gBAAgB;YACrB,YAAY,EAAE,sBAAsB;YACpC,IAAI,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;SACvB,CAAC;QACF,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,OAAO,EAAE,UAAU;YACjB,CAAC,CAAC,mFAAmF;YACrF,CAAC,CAAC,qCAAqC,IAAI,CAAC,SAAS,EAAE;QACzD,MAAM,EAAE,EAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAC;KAC7D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"creator-token.js","sourceRoot":"","sources":["../src/creator-token.ts"],"names":[],"mappings":"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"}
package/dist/deploy.d.ts CHANGED
@@ -86,7 +86,7 @@ export interface SeriesCodeInitParams extends SeriesInitParams {
86
86
  * of {@link SeriesTokenFieldInput} (identical shape; ABX's `OnChainMetadata.TokenFieldInput` has
87
87
  * no standard-specific fields). Reused directly rather than duplicated. */
88
88
  export type EditionTokenFieldInput = SeriesTokenFieldInput;
89
- /** Mirrors `OneOfOneEdition.InitParams` — copies of a single artwork, id space fixed to `{0}`. */
89
+ /** Mirrors `OneOfOneEdition.InitParams` — copies of a single work, id space fixed to `{0}`. */
90
90
  export interface OneOfOneEditionInitParams {
91
91
  owner: Address;
92
92
  /** Recipient of the deploy-time mint (`0x0` or `mintAmount: 0` ⇒ defer all minting). */
@@ -120,7 +120,7 @@ export interface OneOfOneEditionInitParams {
120
120
  tokenFields: OnChainFieldInput[];
121
121
  contractFields: OnChainFieldInput[];
122
122
  }
123
- /** Mirrors `EditionImage.InitParams` — copies of many distinct artworks (N ids × copies each). */
123
+ /** Mirrors `EditionImage.InitParams` — copies of many distinct works (N ids × copies each). */
124
124
  export interface EditionImageInitParams {
125
125
  owner: Address;
126
126
  name: string;
@@ -132,7 +132,7 @@ export interface EditionImageInitParams {
132
132
  royaltyReceiver: Address;
133
133
  royaltyBps: number;
134
134
  transferValidator: Address;
135
- /** The id-space cap N (> 0): the number of distinct artworks this project may ever have.
135
+ /** The id-space cap N (> 0): the number of distinct works this project may ever have.
136
136
  * Monotonically non-increasing (floor = the id high-water mark, NOT `totalSupply()` — ids are
137
137
  * caller-named, not sequential). */
138
138
  maxInvocations: bigint | number;
@@ -143,7 +143,7 @@ export interface EditionImageInitParams {
143
143
  paused: boolean;
144
144
  /** Recipient for the deploy-time mint (`0x0` ⇒ defer all minting). */
145
145
  mintTo: Address;
146
- /** Distinct artworks to mint at deploy, ids `[0, mintCount)`; `<= maxInvocations`. */
146
+ /** Distinct works to mint at deploy, ids `[0, mintCount)`; `<= maxInvocations`. */
147
147
  mintCount: bigint | number;
148
148
  /** Copies of EACH deploy-minted id (must be `> 0` if `mintCount > 0`). */
149
149
  mintAmount: bigint | number;
@@ -189,6 +189,7 @@ export declare function saltGuard(salt: Hex): Address;
189
189
  export declare function deployFactory(send: SendTx, publicClient: PublicClient): Promise<DeployResult<'factory'> & {
190
190
  factory: Address;
191
191
  implementation: Address;
192
+ metadataLib: Address;
192
193
  }>;
193
194
  /**
194
195
  * Deploy the canonical Series clone factory — the trust anchor for multi-token drops.
@@ -198,20 +199,27 @@ export declare function deployFactory(send: SendTx, publicClient: PublicClient):
198
199
  export declare function deploySeriesFactory(send: SendTx, publicClient: PublicClient): Promise<DeployResult<'seriesFactory'> & {
199
200
  factory: Address;
200
201
  implementation: Address;
202
+ metadataLib: Address;
201
203
  }>;
202
204
  /**
203
- * Deploy the code-project trust root on a chain with no canonical set: the two
204
- * delegatecalled write-path libraries first ({AbxParamsLib}, {AbxCodeLib}), the factory
205
- * bytecode LINKED against them (solc placeholders replaced — what forge does at build
206
- * time, done here so a sandbox/fresh chain needs no forge), then the factory (whose
207
- * constructor deploys the {SeriesCode} implementation). Each of the three deploys is a
208
- * plain contract creation (no canonical/CREATE2 address — the libraries' addresses are
209
- * nonce-dependent, so there is nothing to predict), sent through `send` in order since the
210
- * factory's bytecode can only be linked once the two library addresses are known.
205
+ * Deploy the code-project trust root on a chain with no canonical set: the two delegatecalled
206
+ * write-path libraries first ({AbxParamsLib}, {AbxCodeLib}), the factory bytecode LINKED against
207
+ * them (solc placeholders replaced — what forge does at build time, done here so a sandbox/fresh
208
+ * chain needs no forge), then the factory (whose constructor deploys the {SeriesCode}
209
+ * implementation).
210
+ *
211
+ * All three go through the keyless CREATE2 proxy at canonical `AbxSalts` salts, so all three land at
212
+ * addresses that are the same on every chain and computable before the first transaction — the
213
+ * factory's included: linking substitutes an address into already-compiled bytecode, so once the
214
+ * libraries are predictable the linked initcode is fixed too (`predictSeriesCodeFactory()`). The
215
+ * ordering below is still sequential, but now for a plain data-dependency reason rather than a
216
+ * nonce one. See `create2.ts`'s write-path-library note for why the old "libraries are
217
+ * nonce-dependent" story was wrong, and for the compile-time-linking trap that IS real.
211
218
  */
212
219
  export declare function deploySeriesCodeFactory(send: SendTx, publicClient: PublicClient): Promise<{
213
220
  factory: Address;
214
221
  implementation: Address;
222
+ metadataLib: Address;
215
223
  paramsLib: Address;
216
224
  codeLib: Address;
217
225
  txHash: Hex;
@@ -286,18 +294,30 @@ export declare function deploySeries(send: SendTx, publicClient: PublicClient, a
286
294
  * keyless CREATE2 proxy with the canonical `AbxSalts.ONE_OF_ONE_EDITION_FACTORY` salt — matching
287
295
  * how `contracts/script/DeployOneOfOneEdition.s.sol` actually deploys it — so its address is the
288
296
  * SAME on every chain and predictable before the deploy tx (`predictOneOfOneEditionFactory()`).
297
+ *
298
+ * Library-linked, like the two code factories: `OneOfOneEdition` delegates its uri /
299
+ * creator-token / edition-supply bodies into `AbxEditionLib`, so this deploys `AbxParamsLib` +
300
+ * `AbxEditionLib` first ({@link ensureEditionLibraries}) and sends the factory's initcode LINKED
301
+ * against the settled library address. Linking costs nothing in determinism — see `create2.ts`'s
302
+ * write-path-library note.
289
303
  */
290
304
  export declare function deployOneOfOneEditionFactory(send: SendTx, publicClient: PublicClient): Promise<DeployResult<'factory'> & {
291
305
  factory: Address;
292
306
  implementation: Address;
307
+ metadataLib: Address;
308
+ paramsLib: Address;
309
+ editionLib: Address;
293
310
  }>;
294
- /** Deploy the canonical `EditionImageFactory` — the multi-artwork edition trust anchor. CREATE2
311
+ /** Deploy the canonical `EditionImageFactory` — the multi-work edition trust anchor. CREATE2
295
312
  * via the keyless proxy + the canonical `AbxSalts.EDITION_FACTORY` salt (see {@link
296
313
  * deployOneOfOneEditionFactory}'s doc note on why this differs from the 721 series factory's
297
- * plain-creation bootstrap). */
314
+ * plain-creation bootstrap, and why `AbxEditionLib` has to land first). */
298
315
  export declare function deployEditionFactory(send: SendTx, publicClient: PublicClient): Promise<DeployResult<'factory'> & {
299
316
  factory: Address;
300
317
  implementation: Address;
318
+ metadataLib: Address;
319
+ paramsLib: Address;
320
+ editionLib: Address;
301
321
  }>;
302
322
  /** Deploy `AbxFixedPriceMinter1155` — the canonical, ownerless, multi-tenant edition sale
303
323
  * singleton (the Minter spine's edition lane). Sibling of `deployFixedPriceMinter`, one id
@@ -319,7 +339,7 @@ export declare function deployOneOfOneEdition(send: SendTx, publicClient: Public
319
339
  clone: Address;
320
340
  }>;
321
341
  /**
322
- * Deploy an EditionImage (multi-artwork edition) NFT as an immutable EIP-1167 clone, at a
342
+ * Deploy an EditionImage (multi-work edition) NFT as an immutable EIP-1167 clone, at a
323
343
  * deterministic address. The edition twin of `deploySeries`.
324
344
  */
325
345
  export declare function deployEditionImage(send: SendTx, publicClient: PublicClient, args: {
@@ -332,18 +352,24 @@ export declare function deployEditionImage(send: SendTx, publicClient: PublicCli
332
352
  /**
333
353
  * Deploy the code-project edition trust root on a chain with no canonical set: the THREE
334
354
  * delegatecalled write-path libraries first ({AbxParamsLib}, {AbxCodeLib}, {AbxEditionLib} — the
335
- * edition twin of `deploySeriesCodeFactory`'s two-lib dance, extended by the one library
336
- * `EditionCode` alone needs — see `AbxEditionLib`'s class-level dev note), the factory bytecode
337
- * LINKED against all three (solc placeholders replaced — what forge does at build time, done here
338
- * so a sandbox/fresh chain needs no forge), then the factory (whose constructor deploys the
339
- * {EditionCode} implementation). Each deploy is a plain contract creation (no canonical/CREATE2
340
- * address — the libraries' addresses are nonce-dependent, so there is nothing to predict; see
341
- * `create2.ts`'s class-level dev note on the ERC-1155-editions section), sent through `send` in
342
- * order since the factory's bytecode can only be linked once all three library addresses are known.
355
+ * edition twin of `deploySeriesCodeFactory`'s two-lib dance, plus the 1155 write path {@link
356
+ * deployOneOfOneEditionFactory} and {@link deployEditionFactory} link too), the factory bytecode
357
+ * LINKED against all three, then the factory (whose constructor deploys the {EditionCode}
358
+ * implementation). CREATE2 at canonical `AbxSalts` salts throughout, exactly like
359
+ * {@link deploySeriesCodeFactory}, so the whole set is cross-chain-identical and predictable
360
+ * (`predictEditionCodeFactory()`). This is the only factory linking all three libraries; it is NOT
361
+ * the only one linking {AbxEditionLib} — all three 1155 token types delegate into it.
362
+ *
363
+ * One wrinkle the 721 twin doesn't have: {AbxEditionLib} delegatecalls {AbxParamsLib}, so its OWN
364
+ * shipped bytecode carries an unlinked placeholder and has to be linked before it can be deployed
365
+ * ({@link ensureEditionLib} does this via `linkEditionLib()`). Deploying it raw is what made this
366
+ * function fail with an opaque `Invalid byte sequence` — `__$…$__` is not hex, and the old
367
+ * unlinked-placeholder guard only checked the factory's bytecode, never the library's.
343
368
  */
344
369
  export declare function deployEditionCodeFactory(send: SendTx, publicClient: PublicClient): Promise<{
345
370
  factory: Address;
346
371
  implementation: Address;
372
+ metadataLib: Address;
347
373
  paramsLib: Address;
348
374
  codeLib: Address;
349
375
  editionLib: Address;