@integraledger/lcp-binding-evm-x402 0.10.1 → 0.12.0
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 +60 -0
- package/dist/asset-transfer-method-filter.d.ts +1 -1
- package/dist/asset-transfer-method-filter.js +1 -1
- package/dist/constants.d.ts +13 -8
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/manifest.js +1 -1
- package/dist/manifest.js.map +1 -1
- package/package.json +4 -4
- package/src/asset-transfer-method-filter.ts +1 -1
- package/src/constants.ts +13 -8
- package/src/manifest.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# @integraledger/lcp-binding-evm-x402
|
|
2
2
|
|
|
3
|
+
## 0.12.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @integraledger/lcp-kernel@0.12.0
|
|
9
|
+
- @integraledger/lcp-binding-core@0.12.0
|
|
10
|
+
- @integraledger/lcp-binding-evm-common@0.12.0
|
|
11
|
+
|
|
12
|
+
## 0.10.2
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- b2ffecc: Report the class a record actually supports, place a terms URL on UCP, and stop refusing a conformant UCP
|
|
17
|
+
profile — the remediation of the 2026-08-19 conformance re-audit.
|
|
18
|
+
|
|
19
|
+
**`verify` now computes `supportedClass` instead of echoing the claim.** It was `anyFailed ? "TC-0" :
|
|
20
|
+
claimedClass`, so a record proving nothing — no settlement, no acceptance, no authority chain — reported
|
|
21
|
+
whatever class the caller named, while the field's own published docblock promised "what the record
|
|
22
|
+
honestly supports, not what the caller asked for". It is now the highest class every one of whose required
|
|
23
|
+
steps is `proved`, `TC-0` on any failure, computed from the steps alone: neither capped by the claim (rungs
|
|
24
|
+
that reach TC-3 read TC-3 where the caller claimed TC-2) nor lifted by it. White paper #4 §5 defines the
|
|
25
|
+
class of a transaction as "the highest class whose criteria it fully meets", and this is that.
|
|
26
|
+
|
|
27
|
+
The claim is not discarded — the report gains **`claimedClass`**, a required member, because `verified`
|
|
28
|
+
answers "did the record reach the class it claimed?" and cannot be read without it. The two fields are the
|
|
29
|
+
report's two halves: an input echoed, and a finding computed. Where they differ, the record did not reach
|
|
30
|
+
its own shape. An out-of-taxonomy claim now lands only in the echo and can no longer masquerade as a
|
|
31
|
+
finding.
|
|
32
|
+
|
|
33
|
+
**UCP can advertise a terms URL.** Its policy object declares `url` — "Optional link to the full policy
|
|
34
|
+
document", `format: uri` — on the very entry this placement writes, and §C.3's illustration carries `url`
|
|
35
|
+
and `atrHash` side by side there. The manifest previously said the protocol had no slot, citing `links[]`,
|
|
36
|
+
which §C.3 separates as "a standing page, not a per-transaction record". The obstacle was mechanical:
|
|
37
|
+
`termsUrlFields` addresses document paths, and a tagged-array entry's index is chosen at write time. The
|
|
38
|
+
`tagged-array` container therefore gains `termsUrlField`, written onto the same entry in the same write, and
|
|
39
|
+
read back through the same first-match rule. UCP was the last shipped protocol that refused an
|
|
40
|
+
advertisement carrying its own locator (integra-protocol#8).
|
|
41
|
+
|
|
42
|
+
**`readUcpProfile` no longer refuses a conformant business profile.** `requireHttps` mapped an ABSENT `spec`
|
|
43
|
+
to the same branch as a malformed one, and the live host requires `spec` only of a platform declaration —
|
|
44
|
+
as this repository's own README already said. It is now `requireHttpsIfDeclared`: absence is absence, and a
|
|
45
|
+
declared value is still held to the host's https MUST.
|
|
46
|
+
|
|
47
|
+
Also: `requireWritten` replaces an unchecked cast in the x402 override, so a broken postcondition throws
|
|
48
|
+
instead of returning a success carrying no document; six x402 citations move to the revision that actually
|
|
49
|
+
touches the file they name, and a new gate refuses any `owner/repo@sha` in source that `spec-pins.json` does
|
|
50
|
+
not record; four spec citations move from line anchors to section anchors; the escrow binding states why it
|
|
51
|
+
declares no §8.3.1 off-canonical variant, and asserts it; and §C.3's `policies[]` illustration is recorded as
|
|
52
|
+
invalid against the live UCP schema, which shows `description` as a bare string where the host requires an
|
|
53
|
+
object — owed upstream, not a defect here.
|
|
54
|
+
|
|
55
|
+
Corpus 844 → 847, root `ec4ad1b02a81538b…`.
|
|
56
|
+
|
|
57
|
+
- Updated dependencies [b2ffecc]
|
|
58
|
+
- Updated dependencies [822190a]
|
|
59
|
+
- @integraledger/lcp-binding-core@0.11.0
|
|
60
|
+
- @integraledger/lcp-binding-evm-common@0.10.2
|
|
61
|
+
- @integraledger/lcp-kernel@0.11.0
|
|
62
|
+
|
|
3
63
|
## 0.10.1
|
|
4
64
|
|
|
5
65
|
**0.10.0 was staged and withdrawn before approval; this is that release, re-cut.** The conformance corpus
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 1. **Asset-transfer-method filter.** The atrHash-as-nonce weld rides ONLY on EIP-3009
|
|
5
5
|
* `transferWithAuthorization`, whose `nonce` is a payer-controlled 32-byte field committed on-chain in
|
|
6
6
|
* `AuthorizationUsed`. x402's `exact` scheme on EVM defines **three** methods, verified at
|
|
7
|
-
* `x402-foundation/x402@
|
|
7
|
+
* `x402-foundation/x402@db5da2e65952`, `specs/schemes/exact/scheme_exact_evm.md` (read 2026-08-11):
|
|
8
8
|
*
|
|
9
9
|
* 1. `eip3009` — tokens with native `transferWithAuthorization` (the default when `extra` omits it)
|
|
10
10
|
* 2. `permit2` — tokens without it, via a proxy and the canonical Permit2 contract
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 1. **Asset-transfer-method filter.** The atrHash-as-nonce weld rides ONLY on EIP-3009
|
|
5
5
|
* `transferWithAuthorization`, whose `nonce` is a payer-controlled 32-byte field committed on-chain in
|
|
6
6
|
* `AuthorizationUsed`. x402's `exact` scheme on EVM defines **three** methods, verified at
|
|
7
|
-
* `x402-foundation/x402@
|
|
7
|
+
* `x402-foundation/x402@db5da2e65952`, `specs/schemes/exact/scheme_exact_evm.md` (read 2026-08-11):
|
|
8
8
|
*
|
|
9
9
|
* 1. `eip3009` — tokens with native `transferWithAuthorization` (the default when `extra` omits it)
|
|
10
10
|
* 2. `permit2` — tokens without it, via a proxy and the canonical Permit2 contract
|
package/dist/constants.d.ts
CHANGED
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
* cast call <asset> "version()(string)" --rpc-url <rpc>
|
|
18
18
|
* cast call <asset> "DOMAIN_SEPARATOR()(bytes32)" --rpc-url <rpc>
|
|
19
19
|
*
|
|
20
|
-
* **AN UPSTREAM MISMATCH,
|
|
21
|
-
* implementation
|
|
22
|
-
* `x402-foundation/x402@
|
|
20
|
+
* **AN UPSTREAM MISMATCH, SINCE FIXED — recorded because it is the kind that fails silently.** x402's own
|
|
21
|
+
* Go implementation disagreed with the chain about Monad. Verified 2026-08-08 at
|
|
22
|
+
* `x402-foundation/x402@db9dabd0c674` — the last commit touching `go/mechanisms/evm/constants.go`, which is
|
|
23
|
+
* pinned as `x402-go` in `spec-pins.json` and is NOT the specification pin: the SDK and the specification
|
|
24
|
+
* are separate path sets that move on separate schedules. At that revision the `"eip155:143"` entry names
|
|
23
25
|
* the SAME asset address as the `monad` entry below — `0x754704Bc059F8C67012fEd69BC8A327a5aafb603` — and
|
|
24
26
|
* gives it EIP-712 domain `Name: "USD Coin"`. The deployed contract's `name()` returns `"USDC"`, which is
|
|
25
27
|
* what the entry below carries and what the pinned `DOMAIN_SEPARATOR()` assertion in this repository holds
|
|
@@ -29,11 +31,14 @@
|
|
|
29
31
|
* "USD Coin" against a contract reporting "USDC" produces an authorization that simply does not recover to
|
|
30
32
|
* the payer. That is the silent failure this whole file exists to prevent, and here it is upstream.
|
|
31
33
|
*
|
|
32
|
-
* **REPORTED UPSTREAM 2026-08-08:** x402-foundation/x402#3102, with the `cast call`
|
|
33
|
-
* observation that USDC deployments are not uniform on this — Base Sepolia and Monad
|
|
34
|
-
* Base mainnet and Avalanche report "USD Coin", so a value copied between chains yields
|
|
35
|
-
* separator rather than an obvious error.
|
|
36
|
-
*
|
|
34
|
+
* **REPORTED UPSTREAM 2026-08-08 and FIXED 2026-08-10:** x402-foundation/x402#3102, with the `cast call`
|
|
35
|
+
* reproduction and the observation that USDC deployments are not uniform on this — Base Sepolia and Monad
|
|
36
|
+
* report "USDC" while Base mainnet and Avalanche report "USD Coin", so a value copied between chains yields
|
|
37
|
+
* a wrong domain separator rather than an obvious error. `76bda78ef420` (PR #3105) changed the Go entry to
|
|
38
|
+
* `"USDC"`, matching the chain and matching the row below. The account is kept because the failure mode is
|
|
39
|
+
* the reason this file exists at all, and because the pin above is what a reader would otherwise re-derive.
|
|
40
|
+
* Our entry never depended on the outcome: the token contract computes the separator, so the chain was and
|
|
41
|
+
* remains the authority.
|
|
37
42
|
*
|
|
38
43
|
* **What this file is not.** It is not an endorsement of a rail, an allowlist, or a supported-chain list.
|
|
39
44
|
* `createX402Adapter` takes any `X402AdapterConfig`, and a deployment absent here is not thereby refused —
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAC1B,MAAM,GACN,cAAc,GACd,WAAW,GACX,OAAO,CAAC;AAoCZ;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAajE;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,IAAI,kBAAkB,EAAE,CAE1D"}
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AA8DA;;;;GAIG;AACH,MAAM,WAAW,GAAkD;IACjE,IAAI,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,4CAA4C;QACnD,SAAS,EAAE,UAAU;QACrB,YAAY,EAAE,GAAG;KAClB;IACD,qGAAqG;IACrG,qGAAqG;IACrG,cAAc,EAAE;QACd,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,4CAA4C;QACnD,SAAS,EAAE,MAAM;QACjB,YAAY,EAAE,GAAG;KAClB;IACD,SAAS,EAAE;QACT,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,4CAA4C;QACnD,SAAS,EAAE,UAAU;QACrB,YAAY,EAAE,GAAG;KAClB;IACD,KAAK,EAAE;QACL,OAAO,EAAE,GAAG;QACZ,KAAK,EAAE,4CAA4C;QACnD,SAAS,EAAE,MAAM;QACjB,YAAY,EAAE,GAAG;KAClB;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,oGAAoG;IACpG,iFAAiF;IACjF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC;QAC7C,CAAC,CAAC,WAAW,CAAC,IAA0B,CAAC;QACzC,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,MAAM,KAAK,SAAS;QACtB,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,cAAc,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YACnF,oGAAoG;YACpG,8FAA8F,CACjG,CAAC;IACJ,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,mBAAmB;IACjC,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAyB,CAAC;AAC1D,CAAC"}
|
package/dist/manifest.js
CHANGED
|
@@ -23,7 +23,7 @@ export const X402_MANIFEST = {
|
|
|
23
23
|
indexing: "nonce-topic:AuthorizationUsed",
|
|
24
24
|
finality: {
|
|
25
25
|
reversible: false,
|
|
26
|
-
note: "instant, final settlement (EIP-3009) — no on-rail reversal; recourse is the record's elected forum, and finality is never represented as dispute resolution (PAY-3/RCS-5) The atrHash welded as the EIP-3009 nonce MUST be per-transaction: an EIP-3009 nonce is one-time use, so one payer paying twice under the same ATR reproduces the same authorization and the token rejects the second with no LCP-level diagnostic. LCP §6.1 wants a per-transaction ATR anyway.",
|
|
26
|
+
note: "instant, final settlement (EIP-3009) — no on-rail reversal; recourse is the record's elected forum, and finality is never represented as dispute resolution (PAY-3/RCS-5). The atrHash welded as the EIP-3009 nonce MUST be per-transaction: an EIP-3009 nonce is one-time use, so one payer paying twice under the same ATR reproduces the same authorization and the token rejects the second with no LCP-level diagnostic. LCP §6.1 wants a per-transaction ATR anyway.",
|
|
27
27
|
},
|
|
28
28
|
// The payer's EIP-3009 signature commits to the nonce (= atrHash): signature-grade weld.
|
|
29
29
|
weldGrades: { ERC3009: "signature" },
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAoB;IAC5C,IAAI,EAAE,UAAU;IAChB,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,cAAc;IACvB,WAAW,EAAE,eAAe;IAC5B,QAAQ,EAAE;QACR,OAAO,EAAE,IAAI;QACb,oBAAoB,EAAE,IAAI;QAC1B,gBAAgB,EAAE,IAAI;KACvB;IACD,YAAY,EAAE,UAAU,EAAE,2FAA2F;IACrH,WAAW,EAAE,YAAY,EAAE,gFAAgF;IAC3G,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE;QACR,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAoB;IAC5C,IAAI,EAAE,UAAU;IAChB,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,cAAc;IACvB,WAAW,EAAE,eAAe;IAC5B,QAAQ,EAAE;QACR,OAAO,EAAE,IAAI;QACb,oBAAoB,EAAE,IAAI;QAC1B,gBAAgB,EAAE,IAAI;KACvB;IACD,YAAY,EAAE,UAAU,EAAE,2FAA2F;IACrH,WAAW,EAAE,YAAY,EAAE,gFAAgF;IAC3G,QAAQ,EAAE,+BAA+B;IACzC,QAAQ,EAAE;QACR,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,4cAA4c;KACnd;IACD,yFAAyF;IACzF,UAAU,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE;IACpC,YAAY,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,EAAE,gBAAgB;IACpE,wGAAwG;IACxG,qGAAqG;IACrG,kGAAkG;IAClG,eAAe,EAAE,CAAC,UAAU,EAAE,gBAAgB,CAAC;CAChD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@integraledger/lcp-binding-evm-x402",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Welds an ATR hash into an x402 instant settlement on any EVM chain.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lcp",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"homepage": "https://github.com/IntegraLedger/integra-protocol/tree/main/packages/binding-evm-x402#readme",
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"viem": "2.55.11",
|
|
48
|
-
"@integraledger/lcp-binding-core": "0.
|
|
49
|
-
"@integraledger/lcp-
|
|
50
|
-
"@integraledger/lcp-
|
|
48
|
+
"@integraledger/lcp-binding-core": "0.12.0",
|
|
49
|
+
"@integraledger/lcp-binding-evm-common": "0.12.0",
|
|
50
|
+
"@integraledger/lcp-kernel": "0.12.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/node": "24.13.3",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 1. **Asset-transfer-method filter.** The atrHash-as-nonce weld rides ONLY on EIP-3009
|
|
5
5
|
* `transferWithAuthorization`, whose `nonce` is a payer-controlled 32-byte field committed on-chain in
|
|
6
6
|
* `AuthorizationUsed`. x402's `exact` scheme on EVM defines **three** methods, verified at
|
|
7
|
-
* `x402-foundation/x402@
|
|
7
|
+
* `x402-foundation/x402@db5da2e65952`, `specs/schemes/exact/scheme_exact_evm.md` (read 2026-08-11):
|
|
8
8
|
*
|
|
9
9
|
* 1. `eip3009` — tokens with native `transferWithAuthorization` (the default when `extra` omits it)
|
|
10
10
|
* 2. `permit2` — tokens without it, via a proxy and the canonical Permit2 contract
|
package/src/constants.ts
CHANGED
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
* cast call <asset> "version()(string)" --rpc-url <rpc>
|
|
18
18
|
* cast call <asset> "DOMAIN_SEPARATOR()(bytes32)" --rpc-url <rpc>
|
|
19
19
|
*
|
|
20
|
-
* **AN UPSTREAM MISMATCH,
|
|
21
|
-
* implementation
|
|
22
|
-
* `x402-foundation/x402@
|
|
20
|
+
* **AN UPSTREAM MISMATCH, SINCE FIXED — recorded because it is the kind that fails silently.** x402's own
|
|
21
|
+
* Go implementation disagreed with the chain about Monad. Verified 2026-08-08 at
|
|
22
|
+
* `x402-foundation/x402@db9dabd0c674` — the last commit touching `go/mechanisms/evm/constants.go`, which is
|
|
23
|
+
* pinned as `x402-go` in `spec-pins.json` and is NOT the specification pin: the SDK and the specification
|
|
24
|
+
* are separate path sets that move on separate schedules. At that revision the `"eip155:143"` entry names
|
|
23
25
|
* the SAME asset address as the `monad` entry below — `0x754704Bc059F8C67012fEd69BC8A327a5aafb603` — and
|
|
24
26
|
* gives it EIP-712 domain `Name: "USD Coin"`. The deployed contract's `name()` returns `"USDC"`, which is
|
|
25
27
|
* what the entry below carries and what the pinned `DOMAIN_SEPARATOR()` assertion in this repository holds
|
|
@@ -29,11 +31,14 @@
|
|
|
29
31
|
* "USD Coin" against a contract reporting "USDC" produces an authorization that simply does not recover to
|
|
30
32
|
* the payer. That is the silent failure this whole file exists to prevent, and here it is upstream.
|
|
31
33
|
*
|
|
32
|
-
* **REPORTED UPSTREAM 2026-08-08:** x402-foundation/x402#3102, with the `cast call`
|
|
33
|
-
* observation that USDC deployments are not uniform on this — Base Sepolia and Monad
|
|
34
|
-
* Base mainnet and Avalanche report "USD Coin", so a value copied between chains yields
|
|
35
|
-
* separator rather than an obvious error.
|
|
36
|
-
*
|
|
34
|
+
* **REPORTED UPSTREAM 2026-08-08 and FIXED 2026-08-10:** x402-foundation/x402#3102, with the `cast call`
|
|
35
|
+
* reproduction and the observation that USDC deployments are not uniform on this — Base Sepolia and Monad
|
|
36
|
+
* report "USDC" while Base mainnet and Avalanche report "USD Coin", so a value copied between chains yields
|
|
37
|
+
* a wrong domain separator rather than an obvious error. `76bda78ef420` (PR #3105) changed the Go entry to
|
|
38
|
+
* `"USDC"`, matching the chain and matching the row below. The account is kept because the failure mode is
|
|
39
|
+
* the reason this file exists at all, and because the pin above is what a reader would otherwise re-derive.
|
|
40
|
+
* Our entry never depended on the outcome: the token contract computes the separator, so the chain was and
|
|
41
|
+
* remains the authority.
|
|
37
42
|
*
|
|
38
43
|
* **What this file is not.** It is not an endorsement of a rail, an allowlist, or a supported-chain list.
|
|
39
44
|
* `createX402Adapter` takes any `X402AdapterConfig`, and a deployment absent here is not thereby refused —
|
package/src/manifest.ts
CHANGED
|
@@ -25,7 +25,7 @@ export const X402_MANIFEST: BindingManifest = {
|
|
|
25
25
|
indexing: "nonce-topic:AuthorizationUsed",
|
|
26
26
|
finality: {
|
|
27
27
|
reversible: false,
|
|
28
|
-
note: "instant, final settlement (EIP-3009) — no on-rail reversal; recourse is the record's elected forum, and finality is never represented as dispute resolution (PAY-3/RCS-5) The atrHash welded as the EIP-3009 nonce MUST be per-transaction: an EIP-3009 nonce is one-time use, so one payer paying twice under the same ATR reproduces the same authorization and the token rejects the second with no LCP-level diagnostic. LCP §6.1 wants a per-transaction ATR anyway.",
|
|
28
|
+
note: "instant, final settlement (EIP-3009) — no on-rail reversal; recourse is the record's elected forum, and finality is never represented as dispute resolution (PAY-3/RCS-5). The atrHash welded as the EIP-3009 nonce MUST be per-transaction: an EIP-3009 nonce is one-time use, so one payer paying twice under the same ATR reproduces the same authorization and the token rejects the second with no LCP-level diagnostic. LCP §6.1 wants a per-transaction ATR anyway.",
|
|
29
29
|
},
|
|
30
30
|
// The payer's EIP-3009 signature commits to the nonce (= atrHash): signature-grade weld.
|
|
31
31
|
weldGrades: { ERC3009: "signature" },
|