From 6e2739d9f2c686d65d35c20322d13de65870468f Mon Sep 17 00:00:00 2001 From: Everest Date: Thu, 30 Jul 2026 04:40:57 +1000 Subject: [PATCH 1/2] spec: make non-upgradeability of the enforcing logic normative Raised by @blockbird on ethereum-magicians.org/t/29098 after an independent recompute of the Sepolia deployment. The linearity guarantee is a property of the deployed code, not of the recorded data. A registry behind an upgrade authority reproduces every published test vector while still admitting a rollback, so "passes the vectors" and "provides the guarantee this ERC claims" are distinct statements. That makes non-upgradeability a precondition of the non-forgeability property rather than a deployment preference, and the spec was therefore weaker than the code implementing it -- the reference deployment already has both EIP-1967 slots empty and no owner, admin, initializer or proxy. - Specification: new "Immutability of the enforcing logic" immediately after the sequence rule it protects, stating MUST NOT deploy behind an upgrade mechanism able to replace the enforcing logic, and MUST expose no upgrade authority over it. Extensions and off-chain tooling MAY still be upgraded. - Security Considerations: the existing Upgradeability note now points at the normative requirement and adds what a verifier should actually check, rather than advising. Restated here per the ERC-8312 precedent, on the view that a requirement stated only in Security Considerations reads as informative. Note for sync: erc/erc-8350.md is a byte-copy of upstream ERCS/erc-8350.md, so this needs the same edit on ethereum/ERCs#1910 before the copies diverge. --- erc/erc-8350.md | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/erc/erc-8350.md b/erc/erc-8350.md index fc22981..6bbf152 100644 --- a/erc/erc-8350.md +++ b/erc/erc-8350.md @@ -160,6 +160,20 @@ accept a transition only if `sequence == currentSequence + 1` and `prevStateRoot == currentStateRoot`. It MUST then atomically store the Transition ID, next state root, and sequence. +### Immutability of the enforcing logic + +The linearity guarantee above is a property of the deployed code, not of the +recorded data. A registry whose implementation can be replaced can be made to +accept a transition violating `sequence == currentSequence + 1`, while still +reproducing every test vector in this document; passing the vectors and providing +the guarantee are therefore distinct claims. + +A conforming registry MUST NOT be deployed behind an upgrade mechanism able to +replace the logic enforcing sequence linearity, state root chaining, or signature +validation, and MUST expose no upgrade authority over that logic. Extensions and +off-chain tooling MAY be upgraded independently, provided they cannot alter the +acceptance rules above. + ### Signing domain All registration, authorization-update, and transition signatures MUST use the @@ -501,10 +515,18 @@ deletion. ### Upgradeability -An upgradeable registry can change hashing or authorization semantics after -users sign transitions. Deployments using proxies are advised to make upgrade -authority explicit, and to freeze or version any change affecting the normative -v1 behavior. +An upgradeable registry can change hashing or authorization semantics after users +sign transitions. Because a replaced implementation can accept a transition that +violates sequence linearity while still reproducing every published test vector, +non-upgradeability of the enforcing logic is a precondition of the non-forgeability +property rather than a deployment preference. It is stated normatively under +"Immutability of the enforcing logic" in the Specification, and repeated here +because a requirement stated only in this section is read as informative. + +Verifiers assessing a deployment SHOULD confirm that no upgrade authority exists +over the registry — for example that the EIP-1967 implementation and admin slots +are empty and that the deployed source exposes no owner, admin, initializer, or +proxy — rather than inferring immutability from vector conformance alone. ## Copyright From ad8d8d4f736bb25373bc5f84ba8e06ec1a54a738 Mon Sep 17 00:00:00 2001 From: Everest Date: Fri, 31 Jul 2026 11:42:13 +1000 Subject: [PATCH 2/2] spec: require a transition reference to carry the registry address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Raised in practice twice within a week on t/29098: JimmyShi22 (ERC-8274) first shipped AgentVerifierUpdated(bytes32 transitionId), then added spaceId; and babyblueviper1's composition example carried registry only after it was pointed out. Both landed on the same gap independently, which is a sign the spec was underspecified rather than that either implementer misread it. The gap: spaceId is deliberately chain-free (one identifier per agent, not per chain), so two chains may hold different histories under the same spaceId and (spaceId, transitionId) does not determine which one is meant. Stated normatively here, and — the part both of us initially got wrong — as a *verification* requirement rather than a resolution convenience. The signing domain sets verifyingContract = registry address, so without the registry the signed digest cannot be reconstructed and the authorizer's signature cannot be checked at all. Describing registry as a "locating annotation" understates it: a reference that omits it is not independently verifiable, and anyone trimming payloads on the annotation reading would break verification without noticing. Also notes chainId MAY be implicit when the reference is emitted on the same chain as the registry, so the common case costs one field, not two. --- erc/erc-8350.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/erc/erc-8350.md b/erc/erc-8350.md index 6bbf152..3c1ac41 100644 --- a/erc/erc-8350.md +++ b/erc/erc-8350.md @@ -196,6 +196,26 @@ The domain prevents a signature from being replayed on another chain or another registry. A `transitionId` remains a chain-independent content identifier; its signature does not. +### Referencing a transition + +A `spaceId` is derived from the controller and salt only, so it is stable across +chains. The same Memory Space identifier can therefore be used for histories on +more than one chain. Two chains MAY hold different histories under the same +`spaceId`, so `(spaceId, transitionId)` alone does not determine which history is +meant. + +A conforming transition reference MUST identify the registry address and the +chain on which that registry is deployed, in addition to `spaceId` and +`transitionId`. The chain context MAY be implicit when the reference is emitted +on the same chain as the registry. + +This is a verification requirement, not only a resolution convenience. The +signing domain sets `verifyingContract` to the registry address, so the signed +digest cannot be reconstructed — and the authorizer's signature therefore cannot +be checked — without knowing which registry accepted the transition. An otherwise +complete reference that omits the registry or chain context is not independently +verifiable. + ### Space registration Registration MUST bind the Space to non-zero `controller` and `authorizer`