@artblocks/abx-sdk 0.1.0-alpha.30 → 0.1.0-alpha.32
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/CHANGELOG.md +91 -0
- package/dist/chunks.d.ts +94 -4
- package/dist/chunks.d.ts.map +1 -1
- package/dist/chunks.js +97 -5
- package/dist/chunks.js.map +1 -1
- package/dist/deployments.d.ts +15 -0
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +20 -0
- package/dist/deployments.js.map +1 -1
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +22 -0
- package/dist/errors.js.map +1 -1
- package/dist/node.d.ts +59 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +68 -0
- package/dist/node.js.map +1 -1
- package/dist/reconstruct.d.ts +27 -1
- package/dist/reconstruct.d.ts.map +1 -1
- package/dist/reconstruct.js +37 -3
- package/dist/reconstruct.js.map +1 -1
- package/dist/resume.d.ts +70 -19
- package/dist/resume.d.ts.map +1 -1
- package/dist/resume.js +54 -3
- package/dist/resume.js.map +1 -1
- package/dist/script-chunks.d.ts +81 -0
- package/dist/script-chunks.d.ts.map +1 -1
- package/dist/script-chunks.js +95 -0
- package/dist/script-chunks.js.map +1 -1
- package/dist/token.d.ts +10 -0
- package/dist/token.d.ts.map +1 -1
- package/dist/token.js +31 -0
- package/dist/token.js.map +1 -1
- package/package.json +1 -1
package/dist/resume.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
/** Diff the
|
|
2
|
-
|
|
1
|
+
/** Diff the four id-agnostic leg groups against what the contract already holds. Shared by
|
|
2
|
+
* {@link planResume} and {@link planEditionResume} — the mint leg is appended by each caller,
|
|
3
|
+
* since its shape differs (see the class doc). */
|
|
4
|
+
async function planCoreLegs(read, legs) {
|
|
3
5
|
const calls = [];
|
|
4
6
|
const done = [];
|
|
5
7
|
const todo = [];
|
|
6
|
-
const sending = { chunkIndices: [], chunkBytes: [], schemaKeys: [], deps: false, uri: false
|
|
8
|
+
const sending = { chunkIndices: [], chunkBytes: [], schemaKeys: [], deps: false, uri: false };
|
|
7
9
|
// ── script chunks ───────────────────────────────────────────────────────────
|
|
8
10
|
// Compared by CONTENT, not by count. A count check would call a chunk "present" when a hand-repair
|
|
9
11
|
// wrote different bytes at that index, and re-sending is the cheap, correct answer to any doubt.
|
|
@@ -75,6 +77,15 @@ export async function planResume(read, legs) {
|
|
|
75
77
|
todo.push('on-chain URI: wire the metadata renderers + the animation field');
|
|
76
78
|
}
|
|
77
79
|
}
|
|
80
|
+
return { calls, done, todo, sending };
|
|
81
|
+
}
|
|
82
|
+
/** Diff the intended 721 setup against what the contract already holds. */
|
|
83
|
+
export async function planResume(read, legs) {
|
|
84
|
+
const core = await planCoreLegs(read, legs);
|
|
85
|
+
const calls = core.calls;
|
|
86
|
+
const done = core.done;
|
|
87
|
+
const todo = core.todo;
|
|
88
|
+
const sending = { ...core.sending, mints: 0 };
|
|
78
89
|
// ── reserve mints ───────────────────────────────────────────────────────────
|
|
79
90
|
// A SHORTFALL, never a re-send: mint is the one non-idempotent leg, and a token cannot be un-minted.
|
|
80
91
|
if (legs.mints.intendedTotal > 0) {
|
|
@@ -92,4 +103,44 @@ export async function planResume(read, legs) {
|
|
|
92
103
|
}
|
|
93
104
|
return { calls, done, todo, sending };
|
|
94
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Diff the intended EditionCode setup against what the contract already holds. The non-mint legs are
|
|
108
|
+
* IDENTICAL diffing to {@link planResume} ({@link planCoreLegs}); the mint leg is a per-id shortfall
|
|
109
|
+
* against `totalSupply(id)` instead of a single shortfall against a whole-contract total, and each
|
|
110
|
+
* shortfall rides as ONE `mint(to, id, amount)` call (the amount argument does the work a 721 resume
|
|
111
|
+
* needs N repeated calls for).
|
|
112
|
+
*/
|
|
113
|
+
export async function planEditionResume(read, legs) {
|
|
114
|
+
const core = await planCoreLegs(read, legs);
|
|
115
|
+
const calls = core.calls;
|
|
116
|
+
const done = core.done;
|
|
117
|
+
const todo = core.todo;
|
|
118
|
+
const sending = { ...core.sending, mints: 0 };
|
|
119
|
+
// ── reserve mints, per id ────────────────────────────────────────────────────
|
|
120
|
+
// Same shortfall principle as the 721 leg, one id finer: minting again would mint MORE copies of
|
|
121
|
+
// that id, and a copy cannot be un-minted. Every id is read and reported independently so a
|
|
122
|
+
// creator sees exactly which ids are short, not just an aggregate count.
|
|
123
|
+
if (legs.mints.length) {
|
|
124
|
+
const perIdTodo = [];
|
|
125
|
+
let short = 0;
|
|
126
|
+
let complete = 0;
|
|
127
|
+
for (const m of legs.mints) {
|
|
128
|
+
const supply = BigInt(await read.totalSupplyForId(m.id));
|
|
129
|
+
const shortfall = m.intendedAmount > supply ? m.intendedAmount - supply : 0n;
|
|
130
|
+
if (shortfall === 0n) {
|
|
131
|
+
complete++;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
calls.push(m.dataForAmount(shortfall));
|
|
135
|
+
short++;
|
|
136
|
+
perIdTodo.push(`id ${m.id}: mint ${shortfall} more (${supply} of ${m.intendedAmount} exist)`);
|
|
137
|
+
}
|
|
138
|
+
sending.mints = short;
|
|
139
|
+
if (short === 0)
|
|
140
|
+
done.push(`mints: all ${legs.mints.length} premint id(s) already fully minted`);
|
|
141
|
+
else
|
|
142
|
+
todo.push(`mints: ${perIdTodo.join('; ')}`);
|
|
143
|
+
}
|
|
144
|
+
return { calls, done, todo, sending };
|
|
145
|
+
}
|
|
95
146
|
//# sourceMappingURL=resume.js.map
|
package/dist/resume.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../src/resume.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../src/resume.ts"],"names":[],"mappings":"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"}
|
package/dist/script-chunks.d.ts
CHANGED
|
@@ -7,7 +7,17 @@
|
|
|
7
7
|
* never parses the reassembled program. Splitting AT an existing newline (and dropping it, because
|
|
8
8
|
* the join puts it back) makes `chunks.join('\n') === source`. A 22 kB+ span with no newline is
|
|
9
9
|
* refused: there is no honest split that matches the on-chain join.
|
|
10
|
+
*
|
|
11
|
+
* This module also carries the write-side counterpart to that split (`prepareSetScriptChunk` /
|
|
12
|
+
* `prepareRemoveLastScriptChunk`, wrapping `OnChainScript.sol`'s `setScriptChunk`/
|
|
13
|
+
* `removeLastScriptChunk` — contracts/src/extensions/onchain-script/OnChainScript.sol) and the
|
|
14
|
+
* SAFE-REPLACEMENT planning + verification pair (`planScriptReplace` / `verifyScriptReplace`) that
|
|
15
|
+
* `abx replace-script` is built on (packages/cli/src/ownerops.ts). Both take a small reader
|
|
16
|
+
* interface rather than a viem client — the same shape `resume.ts` uses — so the diff and the
|
|
17
|
+
* post-write verification are testable with a fake chain, no RPC, no signer.
|
|
10
18
|
*/
|
|
19
|
+
import { type Address, type Hex } from 'viem';
|
|
20
|
+
import type { PreparedTx } from './ops.js';
|
|
11
21
|
/** SSTORE2 data-contract code limit is 24576 bytes (EIP-170) minus STOP; stay conservative. */
|
|
12
22
|
export declare const DEFAULT_SCRIPT_CHUNK_SIZE = 22000;
|
|
13
23
|
/** The byte the on-chain generator inserts between script chunks. Must stay in lockstep with
|
|
@@ -21,4 +31,75 @@ export declare const SCRIPT_CHUNK_JOIN = "\n";
|
|
|
21
31
|
export declare function splitScriptChunks(source: string, chunkSize?: number): Uint8Array[];
|
|
22
32
|
/** Inverse of {@link splitScriptChunks}: the join the generator performs on chain. */
|
|
23
33
|
export declare function joinScriptChunks(chunks: readonly Uint8Array[]): string;
|
|
34
|
+
/** Owner writes/replaces the on-chain program chunk at `index` (`index === count` appends) —
|
|
35
|
+
* `OnChainScript.setScriptChunk`. Content should come from {@link splitScriptChunks} so the
|
|
36
|
+
* generator's newline-join reassembles the exact source. Signer must be the owner. */
|
|
37
|
+
export declare function prepareSetScriptChunk(args: {
|
|
38
|
+
contract: Address;
|
|
39
|
+
index: bigint | number;
|
|
40
|
+
chunk: Hex;
|
|
41
|
+
chainId: number;
|
|
42
|
+
}): PreparedTx;
|
|
43
|
+
/** Remove the LAST on-chain program chunk (the list stays dense; order is load-bearing) —
|
|
44
|
+
* `OnChainScript.removeLastScriptChunk`. There is no "remove N": shrinking by more than one chunk
|
|
45
|
+
* is this call, repeated. Signer must be the owner. */
|
|
46
|
+
export declare function prepareRemoveLastScriptChunk(args: {
|
|
47
|
+
contract: Address;
|
|
48
|
+
chainId: number;
|
|
49
|
+
}): PreparedTx;
|
|
50
|
+
/** The two on-chain reads a replace-script diff/verify needs. An interface, not a client, so both
|
|
51
|
+
* are testable without a chain — see the module doc. */
|
|
52
|
+
export interface ScriptChunkReader {
|
|
53
|
+
scriptChunkCount(): Promise<number>;
|
|
54
|
+
/** Stored bytes at `index`, or `null` when unset/unreadable (index ≥ count, or a transient miss). */
|
|
55
|
+
scriptChunk(index: number): Promise<Hex | null>;
|
|
56
|
+
}
|
|
57
|
+
export interface ScriptReplacePlan {
|
|
58
|
+
/** `{index, hex}` for every index whose ON-CHAIN content differs from the target (or is missing
|
|
59
|
+
* entirely) — these need `setScriptChunk`. Compared by CONTENT, not by count, for the identical
|
|
60
|
+
* reason `resume.ts`'s chunk leg is: a hand-repaired index that already matches the target must
|
|
61
|
+
* not be re-sent (SSTORE2 deposit is 200 gas/byte — the most expensive way to be "safe"). */
|
|
62
|
+
toWrite: Array<{
|
|
63
|
+
index: number;
|
|
64
|
+
hex: Hex;
|
|
65
|
+
}>;
|
|
66
|
+
/** How many trailing chunks to pop via `removeLastScriptChunk` — non-zero only when the
|
|
67
|
+
* replacement uses FEWER chunks than what's on-chain now. There is no "remove N" call, so this
|
|
68
|
+
* many single `removeLastScriptChunk` calls are queued (see {@link prepareRemoveLastScriptChunk}). */
|
|
69
|
+
toRemove: number;
|
|
70
|
+
/** `scriptChunkCount()` before this plan runs. */
|
|
71
|
+
currentCount: number;
|
|
72
|
+
/** `next.length` — the chunk count this plan drives the contract toward. */
|
|
73
|
+
targetCount: number;
|
|
74
|
+
/** Nothing differs at all — the replacement already matches on-chain byte for byte. The command
|
|
75
|
+
* must send NOTHING in this case, not an empty-but-"successful" transaction. */
|
|
76
|
+
noop: boolean;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Diff a replacement program's chunks against what a contract holds NOW, so `replace-script` sends
|
|
80
|
+
* only what actually changed. Mirrors `resume.ts`'s script-chunk leg (`planCoreLegs`) exactly —
|
|
81
|
+
* content, not count, decides "present" — the difference being that a resume leg is checked
|
|
82
|
+
* present/absent as a GROUP (the setup multicall is atomic, so partial-content-mismatch never
|
|
83
|
+
* legitimately happens), while a replacement is expected to change SOME indices and not others, so
|
|
84
|
+
* each index is diffed and reported independently.
|
|
85
|
+
*/
|
|
86
|
+
export declare function planScriptReplace(read: ScriptChunkReader, next: readonly Hex[]): Promise<ScriptReplacePlan>;
|
|
87
|
+
export interface ScriptVerifyResult {
|
|
88
|
+
/** Whether the on-chain script, read back and reassembled, is byte-identical to what was asked for. */
|
|
89
|
+
ok: boolean;
|
|
90
|
+
/** The reassembled program, for a diagnostic when `ok` is false. */
|
|
91
|
+
reassembled: string;
|
|
92
|
+
/** `scriptChunkCount()` at verification time. */
|
|
93
|
+
chunkCount: number;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Read the completed script back from chain and confirm it reassembles EXACTLY to `expectedSource`
|
|
97
|
+
* — the safety property that justifies `replace-script` existing at all. A transaction not
|
|
98
|
+
* reverting is proof the EVM accepted each call; it is NOT proof the final program is what was
|
|
99
|
+
* intended (a stale RPC view, a concurrent write racing the same contract, or a bug in the ordering
|
|
100
|
+
* of writes-vs-removes could all leave a script that "sent fine" and reassembles to garbage). This
|
|
101
|
+
* is the check that turns "the multicall didn't revert" into "the program is provably correct" —
|
|
102
|
+
* run it BEFORE reporting success, never after.
|
|
103
|
+
*/
|
|
104
|
+
export declare function verifyScriptReplace(read: ScriptChunkReader, expectedSource: string): Promise<ScriptVerifyResult>;
|
|
24
105
|
//# sourceMappingURL=script-chunks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-chunks.d.ts","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"script-chunks.d.ts","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAiC,KAAK,OAAO,EAAE,KAAK,GAAG,EAAC,MAAM,MAAM,CAAC;AAE5E,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,UAAU,CAAC;AAIzC,+FAA+F;AAC/F,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD;sEACsE;AACtE,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAItC;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAkC,GAC5C,UAAU,EAAE,CAmCd;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAGtE;AAQD;;uFAEuF;AACvF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,UAAU,CAmBb;AAED;;wDAEwD;AACxD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GAAG,UAAU,CAUnG;AAOD;yDACyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,qGAAqG;IACrG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,iBAAiB;IAChC;;;kGAG8F;IAC9F,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,GAAG,CAAA;KAAC,CAAC,CAAC;IAC1C;;2GAEuG;IACvG,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB;qFACiF;IACjF,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,SAAS,GAAG,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAUjH;AAED,MAAM,WAAW,kBAAkB;IACjC,uGAAuG;IACvG,EAAE,EAAE,OAAO,CAAC;IACZ,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAYtH"}
|
package/dist/script-chunks.js
CHANGED
|
@@ -7,7 +7,18 @@
|
|
|
7
7
|
* never parses the reassembled program. Splitting AT an existing newline (and dropping it, because
|
|
8
8
|
* the join puts it back) makes `chunks.join('\n') === source`. A 22 kB+ span with no newline is
|
|
9
9
|
* refused: there is no honest split that matches the on-chain join.
|
|
10
|
+
*
|
|
11
|
+
* This module also carries the write-side counterpart to that split (`prepareSetScriptChunk` /
|
|
12
|
+
* `prepareRemoveLastScriptChunk`, wrapping `OnChainScript.sol`'s `setScriptChunk`/
|
|
13
|
+
* `removeLastScriptChunk` — contracts/src/extensions/onchain-script/OnChainScript.sol) and the
|
|
14
|
+
* SAFE-REPLACEMENT planning + verification pair (`planScriptReplace` / `verifyScriptReplace`) that
|
|
15
|
+
* `abx replace-script` is built on (packages/cli/src/ownerops.ts). Both take a small reader
|
|
16
|
+
* interface rather than a viem client — the same shape `resume.ts` uses — so the diff and the
|
|
17
|
+
* post-write verification are testable with a fake chain, no RPC, no signer.
|
|
10
18
|
*/
|
|
19
|
+
import { encodeFunctionData, hexToBytes } from 'viem';
|
|
20
|
+
import { seriesCodeAbi } from './abi/index.js';
|
|
21
|
+
const ZERO_VALUE = '0x0';
|
|
11
22
|
/** SSTORE2 data-contract code limit is 24576 bytes (EIP-170) minus STOP; stay conservative. */
|
|
12
23
|
export const DEFAULT_SCRIPT_CHUNK_SIZE = 22_000;
|
|
13
24
|
/** The byte the on-chain generator inserts between script chunks. Must stay in lockstep with
|
|
@@ -60,4 +71,88 @@ export function joinScriptChunks(chunks) {
|
|
|
60
71
|
const dec = new TextDecoder();
|
|
61
72
|
return chunks.map((c) => dec.decode(c)).join(SCRIPT_CHUNK_JOIN);
|
|
62
73
|
}
|
|
74
|
+
// ── writes: OnChainScript.sol's setScriptChunk / removeLastScriptChunk ────────
|
|
75
|
+
// No `prepare*` wrapper existed for either before this — every caller (deploy-code's setup
|
|
76
|
+
// multicall, its --resume leg) hand-encoded `encodeFunctionData` inline. These mirror
|
|
77
|
+
// `prepareSetDependency`/`prepareRemoveLastDependency` (ops.ts) exactly: same `PreparedTx` shape,
|
|
78
|
+
// same "one index-addressed setter + one pop-the-tail remover" split.
|
|
79
|
+
/** Owner writes/replaces the on-chain program chunk at `index` (`index === count` appends) —
|
|
80
|
+
* `OnChainScript.setScriptChunk`. Content should come from {@link splitScriptChunks} so the
|
|
81
|
+
* generator's newline-join reassembles the exact source. Signer must be the owner. */
|
|
82
|
+
export function prepareSetScriptChunk(args) {
|
|
83
|
+
const index = BigInt(args.index);
|
|
84
|
+
const bytes = (args.chunk.length - 2) / 2;
|
|
85
|
+
// EVM code deposit is 200 gas/byte — the same physics-backed floor the code-setup multicall
|
|
86
|
+
// computes for its script-chunk legs (ops.ts). Restated per-chunk here so a caller that assembles
|
|
87
|
+
// its own multicall (`replace-script`) can sum an honest `gasFloor` instead of trusting
|
|
88
|
+
// `eth_estimateGas` against a target too fresh for the estimator to see (see PreparedTx.gasFloor's
|
|
89
|
+
// own doc for why a wrong estimate must be DETECTED, not silently replaced).
|
|
90
|
+
const gasFloor = bytes > 0 ? `0x${(bytes * 200).toString(16)}` : undefined;
|
|
91
|
+
return {
|
|
92
|
+
op: 'set-script-chunk',
|
|
93
|
+
to: args.contract,
|
|
94
|
+
data: encodeFunctionData({ abi: seriesCodeAbi, functionName: 'setScriptChunk', args: [index, args.chunk] }),
|
|
95
|
+
value: ZERO_VALUE,
|
|
96
|
+
chainId: args.chainId,
|
|
97
|
+
summary: `Set script chunk [${index}] (${bytes} byte${bytes === 1 ? '' : 's'})`,
|
|
98
|
+
fields: { contract: args.contract, index: index.toString(), bytes: String(bytes) },
|
|
99
|
+
...(gasFloor === undefined ? {} : { gasFloor }),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Remove the LAST on-chain program chunk (the list stays dense; order is load-bearing) —
|
|
103
|
+
* `OnChainScript.removeLastScriptChunk`. There is no "remove N": shrinking by more than one chunk
|
|
104
|
+
* is this call, repeated. Signer must be the owner. */
|
|
105
|
+
export function prepareRemoveLastScriptChunk(args) {
|
|
106
|
+
return {
|
|
107
|
+
op: 'remove-last-script-chunk',
|
|
108
|
+
to: args.contract,
|
|
109
|
+
data: encodeFunctionData({ abi: seriesCodeAbi, functionName: 'removeLastScriptChunk', args: [] }),
|
|
110
|
+
value: ZERO_VALUE,
|
|
111
|
+
chainId: args.chainId,
|
|
112
|
+
summary: 'Remove the last script chunk (the list stays dense)',
|
|
113
|
+
fields: { contract: args.contract },
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Diff a replacement program's chunks against what a contract holds NOW, so `replace-script` sends
|
|
118
|
+
* only what actually changed. Mirrors `resume.ts`'s script-chunk leg (`planCoreLegs`) exactly —
|
|
119
|
+
* content, not count, decides "present" — the difference being that a resume leg is checked
|
|
120
|
+
* present/absent as a GROUP (the setup multicall is atomic, so partial-content-mismatch never
|
|
121
|
+
* legitimately happens), while a replacement is expected to change SOME indices and not others, so
|
|
122
|
+
* each index is diffed and reported independently.
|
|
123
|
+
*/
|
|
124
|
+
export async function planScriptReplace(read, next) {
|
|
125
|
+
const currentCount = await read.scriptChunkCount();
|
|
126
|
+
const toWrite = [];
|
|
127
|
+
for (let i = 0; i < next.length; i++) {
|
|
128
|
+
const stored = i < currentCount ? await read.scriptChunk(i) : null;
|
|
129
|
+
if (stored !== null && stored.toLowerCase() === next[i].toLowerCase())
|
|
130
|
+
continue;
|
|
131
|
+
toWrite.push({ index: i, hex: next[i] });
|
|
132
|
+
}
|
|
133
|
+
const toRemove = Math.max(0, currentCount - next.length);
|
|
134
|
+
return { toWrite, toRemove, currentCount, targetCount: next.length, noop: toWrite.length === 0 && toRemove === 0 };
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Read the completed script back from chain and confirm it reassembles EXACTLY to `expectedSource`
|
|
138
|
+
* — the safety property that justifies `replace-script` existing at all. A transaction not
|
|
139
|
+
* reverting is proof the EVM accepted each call; it is NOT proof the final program is what was
|
|
140
|
+
* intended (a stale RPC view, a concurrent write racing the same contract, or a bug in the ordering
|
|
141
|
+
* of writes-vs-removes could all leave a script that "sent fine" and reassembles to garbage). This
|
|
142
|
+
* is the check that turns "the multicall didn't revert" into "the program is provably correct" —
|
|
143
|
+
* run it BEFORE reporting success, never after.
|
|
144
|
+
*/
|
|
145
|
+
export async function verifyScriptReplace(read, expectedSource) {
|
|
146
|
+
const chunkCount = await read.scriptChunkCount();
|
|
147
|
+
const chunks = [];
|
|
148
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
149
|
+
const hex = await read.scriptChunk(i);
|
|
150
|
+
// `scriptChunkCount()` and `scriptChunk(i)` are two separate reads against (hopefully) the same
|
|
151
|
+
// block; a `null` here means they disagree, which is itself the failure this function exists to
|
|
152
|
+
// catch — report it as a verification miss rather than silently reassembling a gap.
|
|
153
|
+
chunks.push(hex === null ? new Uint8Array(0) : hexToBytes(hex));
|
|
154
|
+
}
|
|
155
|
+
const reassembled = joinScriptChunks(chunks);
|
|
156
|
+
return { ok: reassembled === expectedSource, reassembled, chunkCount };
|
|
157
|
+
}
|
|
63
158
|
//# sourceMappingURL=script-chunks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-chunks.js","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"script-chunks.js","sourceRoot":"","sources":["../src/script-chunks.ts"],"names":[],"mappings":"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"}
|
package/dist/token.d.ts
CHANGED
|
@@ -15,6 +15,16 @@ export declare function verifyAgainstHash(bytes: Uint8Array | string, field: Met
|
|
|
15
15
|
* Decode a `reader` field value → `(reader, pointer)` addresses. Content is then
|
|
16
16
|
* obtained on-chain by `IAbxOnChainReader(reader).read(pointer)` (an `eth_call`). The
|
|
17
17
|
* reader encapsulates storage + on-chain decoding; this just unpacks the two addresses.
|
|
18
|
+
*
|
|
19
|
+
* Requires the CANONICAL `abi.encode(address reader, address pointer)` shape: exactly two
|
|
20
|
+
* 32-byte words, each zero-padded in its leading 12 bytes. `decodeAbiParameters` alone is
|
|
21
|
+
* too permissive to use as the only gate here — it happily reads an `address` out of a word
|
|
22
|
+
* with non-zero padding, and it ignores any bytes beyond the words a type list needs, so a
|
|
23
|
+
* truncated-then-repadded, trailing-garbage, or double-encoded (e.g. `abi.encode(bytes)`
|
|
24
|
+
* wrapping a reader pair) value can decode into a plausible but wrong address pair instead
|
|
25
|
+
* of failing. Because the decoded `reader` address is then `eth_call`'d directly (see
|
|
26
|
+
* `resolveFieldBytes` in token-api), a silent mis-decode here is a wrong-contract call, not
|
|
27
|
+
* a cosmetic bug — so this checks shape and padding itself before trusting the ABI decode.
|
|
18
28
|
*/
|
|
19
29
|
export declare function decodeReader(value: Hex): {
|
|
20
30
|
reader: Address;
|
package/dist/token.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,OAAO,EACZ,KAAK,GAAG,EACT,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAC,aAAa,EAAE,YAAY,EAAE,UAAU,EAAC,MAAM,YAAY,CAAC;AAExE,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,IAAI,CAG1F;AAED,mGAAmG;AACnG,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAExF;AAED,wBAAgB,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAEzD;AAID,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAMvD;AAED,mDAAmD;AACnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,CAE5D;AAED,8GAA8G;AAC9G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,GAAG,IAAI,CAKlG;AAED
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,OAAO,EACZ,KAAK,GAAG,EACT,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAC,aAAa,EAAE,YAAY,EAAE,UAAU,EAAC,MAAM,YAAY,CAAC;AAExE,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,IAAI,CAG1F;AAED,mGAAmG;AACnG,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAExF;AAED,wBAAgB,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAEzD;AAID,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAMvD;AAED,mDAAmD;AACnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,CAE5D;AAED,8GAA8G;AAC9G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,GAAG,IAAI,CAKlG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,GAAG,GAAG;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CA4B5E;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,GAAG,CAInE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,OAAO,GAAG,GAAG,CAE/D;AAED,+FAA+F;AAC/F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAGvD"}
|
package/dist/token.js
CHANGED
|
@@ -39,8 +39,39 @@ export function verifyAgainstHash(bytes, field) {
|
|
|
39
39
|
* Decode a `reader` field value → `(reader, pointer)` addresses. Content is then
|
|
40
40
|
* obtained on-chain by `IAbxOnChainReader(reader).read(pointer)` (an `eth_call`). The
|
|
41
41
|
* reader encapsulates storage + on-chain decoding; this just unpacks the two addresses.
|
|
42
|
+
*
|
|
43
|
+
* Requires the CANONICAL `abi.encode(address reader, address pointer)` shape: exactly two
|
|
44
|
+
* 32-byte words, each zero-padded in its leading 12 bytes. `decodeAbiParameters` alone is
|
|
45
|
+
* too permissive to use as the only gate here — it happily reads an `address` out of a word
|
|
46
|
+
* with non-zero padding, and it ignores any bytes beyond the words a type list needs, so a
|
|
47
|
+
* truncated-then-repadded, trailing-garbage, or double-encoded (e.g. `abi.encode(bytes)`
|
|
48
|
+
* wrapping a reader pair) value can decode into a plausible but wrong address pair instead
|
|
49
|
+
* of failing. Because the decoded `reader` address is then `eth_call`'d directly (see
|
|
50
|
+
* `resolveFieldBytes` in token-api), a silent mis-decode here is a wrong-contract call, not
|
|
51
|
+
* a cosmetic bug — so this checks shape and padding itself before trusting the ABI decode.
|
|
42
52
|
*/
|
|
43
53
|
export function decodeReader(value) {
|
|
54
|
+
const hex = value.slice(2);
|
|
55
|
+
const WORD_HEX_LEN = 64; // one 32-byte ABI word, as hex chars
|
|
56
|
+
const EXPECTED_HEX_LEN = WORD_HEX_LEN * 2; // exactly two words: (address reader, address pointer)
|
|
57
|
+
if (hex.length !== EXPECTED_HEX_LEN) {
|
|
58
|
+
throw new Error(`decodeReader: expected exactly two 32-byte ABI words (abi.encode(address reader, address ` +
|
|
59
|
+
`pointer) — ${EXPECTED_HEX_LEN / 2} bytes), received ${hex.length / 2} bytes (${value}). This ` +
|
|
60
|
+
`looks like a truncated, trailing-byte, or double-encoded value; only output from ` +
|
|
61
|
+
`encodeReader() is accepted.`);
|
|
62
|
+
}
|
|
63
|
+
const ZERO_PAD = '0'.repeat(24); // the 12 zero bytes a canonical address word pads with
|
|
64
|
+
const words = [
|
|
65
|
+
['reader', hex.slice(0, WORD_HEX_LEN)],
|
|
66
|
+
['pointer', hex.slice(WORD_HEX_LEN, WORD_HEX_LEN * 2)],
|
|
67
|
+
];
|
|
68
|
+
for (const [name, word] of words) {
|
|
69
|
+
if (!word.startsWith(ZERO_PAD)) {
|
|
70
|
+
throw new Error(`decodeReader: ${name} word is not canonically zero-padded — expected its leading 12 bytes ` +
|
|
71
|
+
`to be zero, received 0x${word}. A non-zero-padded address word is not produced by ` +
|
|
72
|
+
`encodeReader() and is rejected as a non-canonical encoding.`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
44
75
|
const [reader, pointer] = decodeAbiParameters([{ type: 'address' }, { type: 'address' }], value);
|
|
45
76
|
return { reader, pointer };
|
|
46
77
|
}
|
package/dist/token.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,MAAM,EACN,WAAW,EACX,UAAU,EACV,mBAAmB,GAGpB,MAAM,MAAM,CAAC;AACd,OAAO,EAAC,uBAAuB,IAAI,CAAC,EAAC,MAAM,YAAY,CAAC;AAGxD,qDAAqD;AACrD,MAAM,UAAU,SAAS,CAAC,KAAmB,EAAE,OAAwB;IACrE,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;AAC5D,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,OAAO,CAAC,MAAuB,EAAE,SAAiB;IAChE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,IAAI,IAAI,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,cAAsB;IAC9C,OAAO,cAAc,KAAK,CAAC,CAAC,MAAM,IAAI,cAAc,KAAK,CAAC,CAAC,MAAM,CAAC;AACpE,CAAC;AAED,gFAAgF;AAEhF,oDAAoD;AACpD,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC7C,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,WAAW,CAAC,KAAoB;IAC9C,OAAO,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,8GAA8G;AAC9G,MAAM,UAAU,iBAAiB,CAAC,KAA0B,EAAE,KAAoB;IAChF,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAClF,IAAI,KAAK,CAAC,cAAc,KAAK,CAAC,CAAC,SAAS;QAAE,OAAO,SAAS,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC;IAClF,IAAI,KAAK,CAAC,cAAc,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC;IAC5E,OAAO,IAAI,CAAC;AACd,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED