design: settle the four remaining UNDECIDED cases - #36
Merged
Conversation
Closes #32. Nothing in behaviour.md is marked UNDECIDED any more. 1. Double approval - no-op, not an error. A duplicate is overwhelmingly a retry after an uncertain outcome, and with Met terminal there is no state to protect. Erroring would not catch the mistake people fear either: approving the wrong milestone is a different call that succeeds regardless. Authorization is still checked first, and no second event is emitted so the indexer's fold never sees one approval twice. 2. Cancel after end - permitted. behaviour.md's own framing of this case was wrong: it called such a cancel harmless because nothing is unstreamed, which holds only when every milestone is resolved. With a milestone unmet the tranche has streamed in full but is entirely held, and rule 4 returns it to the sender - 12,000,000,000 on the worked example, not zero. Permitting the call is what makes a never-approved milestone recoverable; rejecting it would strand the tranche permanently. Lifecycle diagram gains the missing Completed -> Canceled arrow. 3. Non-standard tokens - store the measured balance delta. True by construction for any asset, one extra balance read at creation. Fixes fee-on-transfer; rebasing stays unsupported because no creation-time measurement binds a balance that moves later. 4. Archived entry - the contract never runs. Called directly the transaction fails at the host level on the footprint; there is no contract branch to write and none could exist. An SDK obligation. Also corrects the stale asymmetry note, which cited a missing diagram arrow as evidence. It was worth nothing on its own - the same missing arrow produced opposite answers for the two cases that leaned on it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K4KmSPBuq484Zt65qsK177
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #32. Second of Track A (#34). Nothing in
behaviour.mdis markedUNDECIDEDany more — 34 scenarios, up from 31.The interesting one is case 2, because the issue's premise was wrong
behaviour.md described cancel-after-end as probably harmless: "functionally a no-op cancel (refund = 0, since nothing is unstreamed) would be harmless if allowed."
That holds only when every milestone is resolved. With a milestone still unmet, the tranche has streamed in full but is entirely
held, and the unapproved-milestone rule returns the whole thing to the sender:So it's a real transfer, and the decision matters more than the entry suggested. Permitted, because it is the only in-protocol way to resolve a milestone nobody ever approved — rejecting it would strand the tranche permanently, which is threat-model T3 arriving by a second route. The lifecycle diagram gains the
Completed --> Canceledarrow it was missing.Knock-on: this is a strong argument for creating grant streams cancelable, now stated in
concepts.md.The other three
Metterminal (#17) there's no state to protect. Erroring wouldn't catch the mistake people actually fear — approving the wrong milestone is a different call that succeeds regardless. Auth still checked first; no second event, so the indexer's fold never sees one approval twice.One correction to merged work
The asymmetry note added in #26 justified treating two cases differently on the grounds that the lifecycle diagram drew no arrow for either. That evidence turned out to be worth nothing on its own — the same missing arrow has now produced opposite answers for the two cases that leaned on it. The diagram was incomplete, not eloquent. Note rewritten to say so.
Changes
docs/specs/behaviour.md— 3 new scenarios, 2UNDECIDEDplaceholders replaced with real ones,Undecided cases→Resolved caseswith the reasoning keptdocs/architecture.md— lifecycle arrow; SEP-41 TODO resolveddocs/concepts.md— cancel-after-end rule stateddocs/research/threat-model.md— T4 status → MitigatedNext in Track A: #33.