@integraledger/lcp-binding-evm-escrow 0.14.0 → 0.15.1

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 CHANGED
@@ -1,5 +1,39 @@
1
1
  # @integraledger/lcp-binding-evm-escrow
2
2
 
3
+ ## 0.15.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 78a8748: `saltFromAtrHash` welded whatever `BigInt` would parse. It was a bare `BigInt(atrHash)`, and the call site
8
+ said a malformed value would be "surfaced by BigInt() (fail-fast)" — but `BigInt` accepts any parseable
9
+ numeral, so it surfaced almost nothing. Counted across the EVM rails, this was the only one with no
10
+ atrHash validation anywhere in it: `binding-evm-x402` 2 call sites, `binding-evm-mpp` 6,
11
+ `binding-tempo-mpp` 3, escrow 0.
12
+
13
+ The harm is a silent round trip rather than a crash. Measured: `0x` + `ab`×31 welded as a salt and came
14
+ back out of `atrHashFromSalt` as `0x00abab…` — a DIFFERENT hash, so a verifier reports a mismatch against
15
+ a settlement that welded exactly what it was handed. `"12345"` welded as `0x…3039`. A 33-byte value came
16
+ back as 68 characters, which is not a bytes32 at all. `"0b1010"`, `"0o777"`, `""` and a whitespace-padded
17
+ hash all welded too.
18
+
19
+ `saltFromAtrHash` now goes through `canonicalAtrHash`, which throws — its stated contract for an emit
20
+ path, and what the original comment intended. Uppercase hex DIGITS are still accepted and lowercased: the
21
+ ATR canon is case-insensitive on the digits, and a counterparty spelling its own hash that way is
22
+ conformant. `atrHashFromSalt` asserts the salt fits a uint256 for the mirror reason — `padStart` pads and
23
+ never truncates, so an out-of-range salt returned a string longer than a bytes32 that then compared
24
+ unequal to every real atrHash instead of being refused.
25
+ - Updated dependencies [1da6c07]
26
+ - Updated dependencies [431b8ec]
27
+ - @integraledger/lcp-binding-evm-common@0.15.1
28
+ - @integraledger/lcp-binding-core@0.15.1
29
+
30
+ ## 0.15.0
31
+
32
+ ### Patch Changes
33
+
34
+ - @integraledger/lcp-binding-core@0.15.0
35
+ - @integraledger/lcp-binding-evm-common@0.15.0
36
+
3
37
  ## 0.14.0
4
38
 
5
39
  ### Patch Changes
package/README.md CHANGED
@@ -13,7 +13,6 @@ npm install @integraledger/lcp-binding-evm-escrow
13
13
  | **Carrier** | `PaymentInfo.salt` |
14
14
  | **Surface** | `createEscrowAdapter` returning [`@integraledger/lcp-binding-core`](../binding-core#readme)'s `WeldAdapter` over a `ChainReader` |
15
15
 
16
-
17
16
  Built on [`@integraledger/lcp-binding-core`](../binding-core#readme)'s `WeldAdapter` and
18
17
  [`@integraledger/lcp-binding-evm-common`](../binding-evm-common#readme). Installing this package installs
19
18
  **viem**.
package/dist/adapter.d.ts CHANGED
@@ -25,9 +25,33 @@ export interface PaymentInfo {
25
25
  feeReceiver: `0x${string}`;
26
26
  salt: bigint;
27
27
  }
28
- /** `salt = uint256(atrHash)` — the 32-byte atrHash reinterpreted as a uint256. */
28
+ /**
29
+ * `salt = uint256(atrHash)` — the 32-byte atrHash reinterpreted as a uint256.
30
+ *
31
+ * ⛔ **VALIDATED, because `BigInt` is not a validation.** This was a bare `BigInt(atrHash)` on the
32
+ * strength of a comment saying a malformed value would be "surfaced by BigInt() (fail-fast)". `BigInt`
33
+ * accepts any parseable numeral — a decimal string, a binary or octal literal, a whitespace-padded value,
34
+ * a hash of the wrong length — so it fails fast on almost nothing, and this was the only EVM rail with no
35
+ * atrHash check anywhere in it.
36
+ *
37
+ * The harm is a SILENT ROUND TRIP rather than a crash. A 31-byte value welds and comes back out of
38
+ * {@link atrHashFromSalt} zero-extended — a DIFFERENT hash — so a verifier reports a mismatch against a
39
+ * settlement that welded exactly what it was handed. `"12345"` welds as `0x…3039`.
40
+ *
41
+ * THROWS rather than refusing, which is {@link canonicalAtrHash}'s contract for an emit path and what the
42
+ * original comment meant to arrange: writing a canonical form of a non-hash puts a fabricated reference
43
+ * on a wire. Uppercase hex DIGITS are accepted and lowercased — the ATR canon is case-insensitive on the
44
+ * digits, so a counterparty spelling its own hash that way is conformant.
45
+ */
29
46
  export declare function saltFromAtrHash(atrHash: `0x${string}`): bigint;
30
- /** Recover the atrHash from a `PaymentInfo.salt` — the reverse (lowercase 0x, 32 bytes). */
47
+ /**
48
+ * Recover the atrHash from a `PaymentInfo.salt` — the reverse (lowercase 0x, 32 bytes).
49
+ *
50
+ * ⛔ The range is asserted for the same reason the forward direction validates: `padStart` pads and never
51
+ * truncates, so a salt outside `[0, 2^256)` returns a string LONGER than a bytes32, which then compares
52
+ * unequal to every real atrHash instead of being refused. Unreachable through the adapter — viem decodes
53
+ * `salt` as a uint256 — and reachable by any caller of this export.
54
+ */
31
55
  export declare function atrHashFromSalt(salt: bigint): `0x${string}`;
32
56
  /** The per-payment proposal inputs (everything but `salt`, which the adapter fills from the atrHash). */
33
57
  export type EscrowProposalContext = Omit<PaymentInfo, "salt">;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAKV,WAAW,EACZ,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,KAAK,GAAG,EAAkB,KAAK,GAAG,EAAY,MAAM,MAAM,CAAC;AAEpE,OAAO,EAAE,KAAK,eAAe,EAAkB,MAAM,gBAAgB,CAAC;AAMtE;0EAC0E;AAC1E,eAAO,MAAM,iBAAiB,EAAE,GAO9B,CAAC;AAEH,iGAAiG;AACjG,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,OAAO,EAAE,KAAK,MAAM,EAAE,GAAG,MAAM,CAE9D;AACD,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAE3D;AAED,yGAAyG;AACzG,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAC9D;;+EAE+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;qFAEqF;AACrF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACvB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;IACtB;;;;;;;;;;;;;OAaG;IACH,eAAe,EAAE,KAAK,MAAM,EAAE,CAAC;IAC/B,2GAA2G;IAC3G,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,KAAK,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACtB,sEAAsE;IACtE,KAAK,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACtB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,SAAS,GAAG,EAAE,EACpB,MAAM,EAAE,MAAM,GACb,gBAAgB,EAAE,CA0CpB;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,WAAW,CAqG5E"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAKV,WAAW,EACZ,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,KAAK,GAAG,EAAkB,KAAK,GAAG,EAAY,MAAM,MAAM,CAAC;AAEpE,OAAO,EAAE,KAAK,eAAe,EAAkB,MAAM,gBAAgB,CAAC;AAMtE;0EAC0E;AAC1E,eAAO,MAAM,iBAAiB,EAAE,GAO9B,CAAC;AAEH,iGAAiG;AACjG,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,KAAK,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,KAAK,MAAM,EAAE,GAAG,MAAM,CAE9D;AACD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAM3D;AAED,yGAAyG;AACzG,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAC9D;;+EAE+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;qFAEqF;AACrF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACvB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;IACtB;;;;;;;;;;;;;OAaG;IACH,eAAe,EAAE,KAAK,MAAM,EAAE,CAAC;IAC/B,2GAA2G;IAC3G,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,KAAK,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACtB,sEAAsE;IACtE,KAAK,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACtB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,SAAS,GAAG,EAAE,EACpB,MAAM,EAAE,MAAM,GACb,gBAAgB,EAAE,CA0CpB;AAED,sDAAsD;AACtD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,WAAW,CAsG5E"}
package/dist/adapter.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { refOf } from "@integraledger/lcp-binding-evm-common";
2
+ import { canonicalAtrHash } from "@integraledger/lcp-kernel";
2
3
  import { decodeEventLog, parseAbi } from "viem";
3
4
  import { AUTH_CAPTURE_ESCROW } from "./collectors.js";
4
5
  import { EVENT_TO_STATE } from "./lifecycle.js";
@@ -14,12 +15,38 @@ export const ESCROW_EVENTS_ABI = parseAbi([
14
15
  "event PaymentReclaimed(bytes32 indexed paymentInfoHash, uint256 amount)",
15
16
  "event PaymentRefunded(bytes32 indexed paymentInfoHash, uint256 amount, address tokenCollector)",
16
17
  ]);
17
- /** `salt = uint256(atrHash)` — the 32-byte atrHash reinterpreted as a uint256. */
18
+ /**
19
+ * `salt = uint256(atrHash)` — the 32-byte atrHash reinterpreted as a uint256.
20
+ *
21
+ * ⛔ **VALIDATED, because `BigInt` is not a validation.** This was a bare `BigInt(atrHash)` on the
22
+ * strength of a comment saying a malformed value would be "surfaced by BigInt() (fail-fast)". `BigInt`
23
+ * accepts any parseable numeral — a decimal string, a binary or octal literal, a whitespace-padded value,
24
+ * a hash of the wrong length — so it fails fast on almost nothing, and this was the only EVM rail with no
25
+ * atrHash check anywhere in it.
26
+ *
27
+ * The harm is a SILENT ROUND TRIP rather than a crash. A 31-byte value welds and comes back out of
28
+ * {@link atrHashFromSalt} zero-extended — a DIFFERENT hash — so a verifier reports a mismatch against a
29
+ * settlement that welded exactly what it was handed. `"12345"` welds as `0x…3039`.
30
+ *
31
+ * THROWS rather than refusing, which is {@link canonicalAtrHash}'s contract for an emit path and what the
32
+ * original comment meant to arrange: writing a canonical form of a non-hash puts a fabricated reference
33
+ * on a wire. Uppercase hex DIGITS are accepted and lowercased — the ATR canon is case-insensitive on the
34
+ * digits, so a counterparty spelling its own hash that way is conformant.
35
+ */
18
36
  export function saltFromAtrHash(atrHash) {
19
- return BigInt(atrHash);
37
+ return BigInt(canonicalAtrHash(atrHash, "saltFromAtrHash"));
20
38
  }
21
- /** Recover the atrHash from a `PaymentInfo.salt` — the reverse (lowercase 0x, 32 bytes). */
39
+ /**
40
+ * Recover the atrHash from a `PaymentInfo.salt` — the reverse (lowercase 0x, 32 bytes).
41
+ *
42
+ * ⛔ The range is asserted for the same reason the forward direction validates: `padStart` pads and never
43
+ * truncates, so a salt outside `[0, 2^256)` returns a string LONGER than a bytes32, which then compares
44
+ * unequal to every real atrHash instead of being refused. Unreachable through the adapter — viem decodes
45
+ * `salt` as a uint256 — and reachable by any caller of this export.
46
+ */
22
47
  export function atrHashFromSalt(salt) {
48
+ if (salt < 0n || salt >= 1n << 256n)
49
+ throw new Error(`atrHashFromSalt: salt must fit a uint256, got ${salt.toString()}`);
23
50
  return `0x${salt.toString(16).padStart(64, "0")}`;
24
51
  }
25
52
  /**
@@ -71,8 +98,9 @@ export function createEscrowAdapter(config) {
71
98
  manifest: ESCROW_MANIFEST,
72
99
  async propose(atrHash, ctx) {
73
100
  const c = ctx;
74
- // The salt is filled from the atrHash — never re-derived. No value-level Refusal
75
- // on this path; a malformed atrHash is a programming error surfaced by BigInt() (fail-fast).
101
+ // The salt is filled from the atrHash — never re-derived. No value-level Refusal on this path; a
102
+ // malformed atrHash is a programming error and `saltFromAtrHash` throws on one. It used to say
103
+ // "surfaced by BigInt()", which surfaced almost nothing — see that function.
76
104
  const paymentInfo = { ...c, salt: saltFromAtrHash(atrHash) };
77
105
  return { ok: true, value: { paymentInfo } };
78
106
  },
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,EAAE,MAAM,uCAAuC,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAY,cAAc,EAAY,QAAQ,EAAE,MAAM,MAAM,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAwB,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,QAAQ,GACZ,yOAAyO,CAAC;AAE5O;0EAC0E;AAC1E,MAAM,CAAC,MAAM,iBAAiB,GAAQ,QAAQ,CAAC;IAC7C,4DAA4D,QAAQ,uDAAuD;IAC3H,yDAAyD,QAAQ,2FAA2F;IAC5J,4GAA4G;IAC5G,sEAAsE;IACtE,yEAAyE;IACzE,gGAAgG;CACjG,CAAC,CAAC;AAkBH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe,CAAC,OAAsB;IACpD,OAAO,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAC9D,CAAC;AACD;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,IAAI,GAAG,EAAE,IAAI,IAAI,IAAI,EAAE,IAAI,IAAI;QACjC,MAAM,IAAI,KAAK,CACb,iDAAiD,IAAI,CAAC,QAAQ,EAAE,EAAE,CACnE,CAAC;IACJ,OAAO,KAAK,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC;AACpD,CAAC;AA4DD;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAoB,EACpB,MAAc;IAEd,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,GAAG,GAAuB,EAAE,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,IAAI;YAAE,SAAS;QACjD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,cAAc,CAAC;gBAC7B,GAAG,EAAE,iBAAiB;gBACtB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,GAAG,CAAC,MAAM;aACnB,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,OAAO,CAAC,IAUpB,CAAC;YACF,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,OAAO,CAAC,SAAuC;gBACrD,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,GAAG,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS;oBAChC,CAAC,CAAC;wBACE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI;wBAC3B,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK;wBAC7B,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK;wBAC7B,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ;qBACpC;oBACH,CAAC,CAAC,EAAE,CAAC;gBACP,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,MAAM,EAAE,GAAG,CAAC,eAAe;aAC5B,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,mBAAmB,CAAC,MAA2B;IAC7D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,mBAAmB,CAAC;IACpD,OAAO;QACL,QAAQ,EAAE,eAAe;QAEzB,KAAK,CAAC,OAAO,CACX,OAAsB,EACtB,GAAY;YAEZ,MAAM,CAAC,GAAG,GAA4B,CAAC;YACvC,iGAAiG;YACjG,+FAA+F;YAC/F,6EAA6E;YAC7E,MAAM,WAAW,GAAgB,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC;QAC9C,CAAC;QAED,KAAK,CAAC,OAAO,CACX,GAAkB,EAClB,KAAoB;YAEpB,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAU,CAAC;YAClE,4FAA4F;YAC5F,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAClD,CAAC,CAAC,EAAoC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAC9D,CAAC;YACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBACrB,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,SAAS,EAAE,sBAAsB;oBACjC,IAAI,EAAE,6BAA6B;oBACnC,MAAM,EAAE,qFAAqF;iBAC9F,CAAC;YACJ,qGAAqG;YACrG,kGAAkG;YAClG,wDAAwD;YACxD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC9D,IAAI,KAAK,KAAK,SAAS;oBACrB,OAAO;wBACL,OAAO,EAAE,IAAI;wBACb,SAAS,EAAE,sBAAsB;wBACjC,IAAI,EAAE,4BAA4B;wBAClC,MAAM,EAAE,4CAA4C,GAAG,CAAC,QAAQ,kBAAkB,GAAG,CAAC,MAAM,EAAE;qBAC/F,CAAC;gBACJ,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1D,CAAC;YACD,kGAAkG;YAClG,uGAAuG;YACvG,qGAAqG;YACrG,mFAAmF;YACnF,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACpD,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,SAAS,EAAE,sBAAsB;oBACjC,IAAI,EAAE,6BAA6B;oBACnC,MAAM,EAAE,cAAc,GAAG,CAAC,MAAM,YAAY,QAAQ,CAAC,IAAI,gGAAgG;iBAC1J,CAAC;YACJ,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE,eAAe,CAAE,MAAM,CAAC,CAAC,CAA6B,CAAC,IAAI,CAAC;aACpE,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,OAAO,CACX,GAAkB,EAClB,KAAoB;YAEpB,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAU,CAAC;YAClE,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YACxD,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC5C,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACxB,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;oBAC7B,EAAE;oBACF,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC;iBAChD,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,SAAS,CACb,OAAsB,EACtB,KAAoB;YAEpB,mGAAmG;YACnG,mGAAmG;YACnG,gGAAgG;YAChG,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;gBACtC,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,oCAAoC;gBAC1F,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,UAAU;gBACzC,OAAO,EAAE,QAAQ;aAClB,CAAC,CAAU,CAAC;YACb,OAAO,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC;iBAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC;iBAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1E,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integraledger/lcp-binding-evm-escrow",
3
- "version": "0.14.0",
3
+ "version": "0.15.1",
4
4
  "description": "Welds an ATR hash into an authorize-and-capture escrow settlement on EVM chains.",
5
5
  "keywords": [
6
6
  "lcp",
@@ -42,14 +42,14 @@
42
42
  },
43
43
  "homepage": "https://github.com/IntegraLedger/integra-protocol/tree/main/packages/binding-evm-escrow#readme",
44
44
  "dependencies": {
45
- "viem": "2.55.19",
46
- "@integraledger/lcp-binding-evm-common": "0.14.0",
47
- "@integraledger/lcp-binding-core": "0.14.0"
45
+ "@integraledger/lcp-binding-core": "0.15.1",
46
+ "@integraledger/lcp-binding-evm-common": "0.15.1",
47
+ "viem": "2.55.19"
48
48
  },
49
49
  "devDependencies": {
50
+ "@integraledger/lcp-kernel": "0.15.1",
50
51
  "@types/node": "24.13.3",
51
- "vitest": "4.1.11",
52
- "@integraledger/lcp-kernel": "0.14.0"
52
+ "vitest": "4.1.11"
53
53
  },
54
54
  "license": "Apache-2.0",
55
55
  "engines": {
package/src/adapter.ts CHANGED
@@ -12,6 +12,7 @@ import type {
12
12
  WeldAdapter,
13
13
  } from "@integraledger/lcp-binding-core";
14
14
  import { refOf } from "@integraledger/lcp-binding-evm-common";
15
+ import { canonicalAtrHash } from "@integraledger/lcp-kernel";
15
16
  import { type Abi, decodeEventLog, type Log, parseAbi } from "viem";
16
17
  import { AUTH_CAPTURE_ESCROW } from "./collectors.js";
17
18
  import { type EscrowEventName, EVENT_TO_STATE } from "./lifecycle.js";
@@ -47,12 +48,40 @@ export interface PaymentInfo {
47
48
  salt: bigint;
48
49
  }
49
50
 
50
- /** `salt = uint256(atrHash)` — the 32-byte atrHash reinterpreted as a uint256. */
51
+ /**
52
+ * `salt = uint256(atrHash)` — the 32-byte atrHash reinterpreted as a uint256.
53
+ *
54
+ * ⛔ **VALIDATED, because `BigInt` is not a validation.** This was a bare `BigInt(atrHash)` on the
55
+ * strength of a comment saying a malformed value would be "surfaced by BigInt() (fail-fast)". `BigInt`
56
+ * accepts any parseable numeral — a decimal string, a binary or octal literal, a whitespace-padded value,
57
+ * a hash of the wrong length — so it fails fast on almost nothing, and this was the only EVM rail with no
58
+ * atrHash check anywhere in it.
59
+ *
60
+ * The harm is a SILENT ROUND TRIP rather than a crash. A 31-byte value welds and comes back out of
61
+ * {@link atrHashFromSalt} zero-extended — a DIFFERENT hash — so a verifier reports a mismatch against a
62
+ * settlement that welded exactly what it was handed. `"12345"` welds as `0x…3039`.
63
+ *
64
+ * THROWS rather than refusing, which is {@link canonicalAtrHash}'s contract for an emit path and what the
65
+ * original comment meant to arrange: writing a canonical form of a non-hash puts a fabricated reference
66
+ * on a wire. Uppercase hex DIGITS are accepted and lowercased — the ATR canon is case-insensitive on the
67
+ * digits, so a counterparty spelling its own hash that way is conformant.
68
+ */
51
69
  export function saltFromAtrHash(atrHash: `0x${string}`): bigint {
52
- return BigInt(atrHash);
70
+ return BigInt(canonicalAtrHash(atrHash, "saltFromAtrHash"));
53
71
  }
54
- /** Recover the atrHash from a `PaymentInfo.salt` — the reverse (lowercase 0x, 32 bytes). */
72
+ /**
73
+ * Recover the atrHash from a `PaymentInfo.salt` — the reverse (lowercase 0x, 32 bytes).
74
+ *
75
+ * ⛔ The range is asserted for the same reason the forward direction validates: `padStart` pads and never
76
+ * truncates, so a salt outside `[0, 2^256)` returns a string LONGER than a bytes32, which then compares
77
+ * unequal to every real atrHash instead of being refused. Unreachable through the adapter — viem decodes
78
+ * `salt` as a uint256 — and reachable by any caller of this export.
79
+ */
55
80
  export function atrHashFromSalt(salt: bigint): `0x${string}` {
81
+ if (salt < 0n || salt >= 1n << 256n)
82
+ throw new Error(
83
+ `atrHashFromSalt: salt must fit a uint256, got ${salt.toString()}`,
84
+ );
56
85
  return `0x${salt.toString(16).padStart(64, "0")}`;
57
86
  }
58
87
 
@@ -179,8 +208,9 @@ export function createEscrowAdapter(config: EscrowAdapterConfig): WeldAdapter {
179
208
  ctx: unknown,
180
209
  ): Promise<Outcome<EscrowProposal>> {
181
210
  const c = ctx as EscrowProposalContext;
182
- // The salt is filled from the atrHash — never re-derived. No value-level Refusal
183
- // on this path; a malformed atrHash is a programming error surfaced by BigInt() (fail-fast).
211
+ // The salt is filled from the atrHash — never re-derived. No value-level Refusal on this path; a
212
+ // malformed atrHash is a programming error and `saltFromAtrHash` throws on one. It used to say
213
+ // "surfaced by BigInt()", which surfaced almost nothing — see that function.
184
214
  const paymentInfo: PaymentInfo = { ...c, salt: saltFromAtrHash(atrHash) };
185
215
  return { ok: true, value: { paymentInfo } };
186
216
  },