Skip to content

feat(svm): retire slow fills (ACP-221) - #1550

Merged
Reinis-FRP merged 7 commits into
epic-v5/svmfrom
reinis/acp-221-remove-slow-fills
Sep 30, 2026
Merged

Reinis-FRP merged 7 commits into
epic-v5/svmfrom
reinis/acp-221-remove-slow-fills

Conversation

@Reinis-FRP

Copy link
Copy Markdown
Contributor

Retires Solana slow fills by removing request_slow_fill, execute_slow_relay_leaf, and their client builders. Historical selectors now fail at dispatch; existing requested relays can still be fast-filled with ReplacedSlowFill, with replay and rollback protection preserved.

Preserves serialized account layouts, enum/error slots, historical event decoding, and the two-root admin ABI. Nonzero slow roots remain accepted because HubPool shares the root across destinations; rejecting one could block valid Solana refunds when other chains have slow fills.

Adds raw-selector and upgrade-compatibility tests using a frozen pre-upgrade account, updates the compatibility docs, and quotes the Anchor test glob so fixture subdirectories cannot cause the suite to be skipped.

Based on #1544. CCTP v2/token-rebalance removal remains in #1548; the shared upgrade candidate must also verify its nonzero amount_to_return guard.

Validation completed locally using CI's Anchor 0.31.1 / Solana 2.2.1 toolchain:

  • Verified Docker build of all five SVM programs.
  • anchor test --skip-build: 147 passing.
  • Rust library tests: 15 passing in production configuration; 19 with the test feature.
  • Public artifact and test-IDL generation, TypeScript checks, Rust formatting, Prettier, and Clippy (existing warnings).
  • Gateway path vector: 1 passing.

Resolves ACP-221.

@linear

linear Bot commented Sep 9, 2026

Copy link
Copy Markdown

ACP-221

@droplet-rl droplet-rl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff against reinis/acp-184-step-5-gateway-integration. The removal is clean and the compatibility argument holds up — I re-derived most of the constants rather than taking them on trust, and everything checked out. No code defects found. One deployment-sequencing question I'd like answered before this ships, plus a few nits.

What I independently verified

  • Retired selectors. [39,157,165,187,88,217,207,98] and [26,207,3,168,193,252,59,127] are exactly sha256("global:request_slow_fill")[..8] and sha256("global:execute_slow_relay_leaf")[..8]. The program declares no #[fallback], so both genuinely land on Anchor's default dispatch arm → InstructionFallbackNotFound (101), before any account validation.
  • Frozen account fixture. legacy_requested_slow_fill.json decodes to 45 bytes: discriminator sha256("account:FillStatusAccount")[..8], status = 1, fill_deadline = 4000000000. owner is the declared program ID, and lamports = 1204080 is exactly the rent-exempt minimum for 45 bytes ((128+45) * 3480 * 2). This is a real pre-upgrade account, not a hand-waved stub.
  • Layout assertions. 8 + FillStatusAccount::INIT_SPACE = 45, FilledRelay = 393 bytes with fill_type at offset 392, RequestedSlowFill = 280 bytes — all match a hand-count of the struct fields. Event and account discriminators match the sha256("event:…") / sha256("account:…") derivations.
  • Tests. Ran CI's exact command, cargo test -p svm-spoke --lib: 15/15 pass, and the three new tests::compatibility::* cases are included. With --features test: 19/19. Good call putting mod tests behind plain #[cfg(test)] rather than the test feature — CI (pr.yml:103) doesn't pass --features test, so feature-gating them would have made them dead weight.
  • No dangling references. Nothing in src/, test/, or scripts/ still imports SlowFillLeaf, slowFillHashFn, loadRequestSlowFillParams, or the removed account types. Remaining slowFill hits are either EVM (V3SlowFill in buildSampleTree.ts) or event-name strings in queryEvents*.ts, which stay valid.
  • The doc's close_instruction_params claim. Confirmed — it takes an UncheckedAccount and never deserializes, so stale slow-fill param buffers really can still be closed by their creator without the retired type.
  • AcrossPlus coverage lost with SvmSpoke.SlowFill.AcrossPlus.ts is retained equivalently in SvmSpoke.Fill.AcrossPlus.ts (forwarding, max token distributions, both param modes).

The Anchor.toml glob quoting fix deserves a specific call-out: test/svm/fixtures/legacySlowFill.ts is the first .ts file under a test/svm/* subdirectory, and since sh expands ** as *, the unquoted pattern would have collapsed to just that fixture file and silently skipped the entire SVM suite. Catching that in the same PR that introduced the trigger is the difference between green CI and green-but-empty CI.

Not verified: I have no Solana validator here, so I could not reproduce the anchor test --skip-build run (147 passing) or the Docker verified build. Taking those on trust from the PR description.

Main item

The account/ABI compatibility story is documented exhaustively, but it's silent on the funding side of in-flight slow fills — see the inline comment on SLOW_FILL_RETIREMENT.md. It's a coordination question about upgrade ordering rather than a defect in this diff, which is why I'm commenting rather than blocking, but I'd like it addressed before deploy.

Remaining comments are nits.

`RootBundle` retains both roots and its refund-claim bitmap. `relay_root_bundle` and its cross-chain admin payload
still accept both `relayer_refund_root` and `slow_relay_root`; the latter is stored and emitted but cannot be executed.
HubPool forwards the same global slow-relay root to every destination. A nonzero root may contain slow fills for
other chains, so rejecting it on Solana would also block delivery of the accompanying refund root.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph explains why a nonzero slow root is still accepted, which I agree with. What it doesn't cover is what happens to the LP funds backing slow-fill leaves that are already in flight when the upgrade lands.

As I understand the bundle flow, the dataworker builds slow-fill leaves from observed RequestedSlowFill events, and the pool rebalance leaf's netSendAmount for the destination chain is sized to cover them. So for any pre-upgrade RequestedSlowFill that hasn't been bundled yet, the sequence after this upgrade is: HubPool sends the funds to the Solana vault → the leaf is in the relayed slow root → and there is no longer an entrypoint that can execute it. The tokens sit in the vault, and the recipient never gets the slow fill.

Self-healing in principle (deposit expires → depositor refunded on the origin chain → excess returns via amount_to_return in a later bundle), but that depends on the dataworker actually handling it, and it isn't free.

Could you confirm the deployment sequencing? Specifically:

  1. Does the dataworker stop emitting SVM slow-fill leaves before or together with this upgrade, so the in-flight window is empty by the time the entrypoint disappears?
  2. If a nonempty window is unavoidable, is stranded vault balance reclaimed through the ordinary amount_to_return path, or does it need a manual step?

Worth a short paragraph here either way — this doc is going to be the reference someone reaches for during the upgrade, and the funding side is the part that moves real money.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the deployment requirements in 5d700387. This is part of the combined Lite-chain upgrade with #1548, which rejects nonzero amount_to_return and removes bridge_tokens_to_hub_pool. The suggested automatic return path therefore will not exist after that upgrade; an origin-chain expiry refund does not recover excess Solana vault funds.

The SDK excludes slow fills to/from Lite chains and requires token equivalence through pool-rebalance routes, so an old request event alone does not imply new funding. However, Lite-chain classification uses the deposit's quote timestamp. Before deployment we still need to verify active dataworker/configuration and reconcile older funded leaves, pending liabilities, and balances. Any residual obligations need settlement before the relevant paths disappear or a separately reviewed recovery procedure. This PR does not establish that the live in-flight window is empty.


Sent from Reinis Martinsons's Codex CLI Agent using gpt-6-astra 🤖

checks. Success transfers the original output amount, writes `Filled`, records the submitting relayer as rent
recipient, and emits `FilledRelay` with `ReplacedSlowFill`. Replay fails with `RelayFilled`. Any transaction failure
rolls back the token transfer and status change. Expired requests remain eligible for ordinary `close_fill_pda`
cleanup to their recorded rent recipient; they cannot be filled after expiry.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things I'd add to this paragraph, both about the pre-upgrade request that isn't fast-filled:

Depositor recourse. The doc says such a request "cannot be filled after expiry" but stops there. Worth stating plainly that the depositor's only remaining recourse is the origin-chain expiry refund — there is no on-Solana fallback at all now. That's the intended outcome of ACP-221, but a reader coming to this doc mid-incident shouldn't have to infer it.

Rent reclamation gap. close_fill_pda remains available to the recorded rent recipient, as you note. But scripts/svm/closeRelayerPdas.ts only enumerates filledRelay events, so it will never surface a stale RequestedSlowFill PDA. Those requesters have ~1.2M lamports each locked up with no tooling that finds it for them; they'd have to go through queryEvents.ts (which does list RequestedSlowFill) and construct the close call by hand. Probably a small follow-up rather than something for this PR, but it's worth a sentence here so the gap is on the record.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documented both in 5d700387: an unfilled expired deposit goes through the dataworker-driven origin-chain refund process, and closing its destination PDA only reclaims rent. The doc also explicitly records that closeRelayerPdas.ts discovers only filled relays; never-filled requests require separate discovery and a close call by the recorded rent recipient. No discovery-tooling change is included here.


Sent from Reinis Martinsons's Codex CLI Agent using gpt-6-astra 🤖

Comment thread test/svm/SvmSpoke.LiteChain.ts Outdated
import { legacyMint, legacyRelay, legacyRequester } from "./fixtures/legacySlowFill";
import { common } from "./SvmSpoke.common";

describe("svm_spoke lite-chain compatibility", () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming nit, but I think it's worth changing before this lands.

"Lite chain" is an established Across term meaning a chain whose liquidity routes through the hub rather than being rebalanced independently — nothing to do with what this suite tests. This file is an upgrade/legacy-compatibility suite: retired selectors, historical event decoding, and fast-filling a frozen pre-upgrade account.

SvmSpoke.Compatibility.ts or SvmSpoke.LegacySlowFill.ts would say what it does. Note that SLOW_FILL_RETIREMENT.md:41 also calls it "the lite-chain suite," so the rename would want to touch both.

One related note: the suite consumes its genesis fixture (fills the account, then closes the PDA), so it is not re-runnable within a single validator session. Fine under anchor test, which starts fresh each time, but since the doc already tells people how to run this against a manually started validator, worth flagging there that it's single-shot.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to SvmSpoke.SlowFillRetirement.ts and documented the fresh-validator requirement in 5d700387. The test body is unchanged.

One terminology correction: Lite chains exclude HubPool LP rebalancing. That is the intended Solana model, with #1548 handling token-rebalancing removal and this PR removing slow fills. The narrower suite name is still more accurate because these tests cover slow-fill retirement compatibility, not the entire combined upgrade.


Sent from Reinis Martinsons's Codex CLI Agent using gpt-6-astra 🤖

Comment thread programs/svm-spoke/src/error.rs Outdated
InvalidFillDeadline,
#[msg("Caller is not the exclusive relayer and exclusivity deadline has not passed!")]
NotExclusiveRelayer,
// Retain retired slow-fill error slots so subsequent error codes do not shift.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment reads as if it introduces a contiguous block of retired slots, but RelayFilled sits between the two retired variants and is very much still live — it's the replay guard in _fill, and the new LiteChain test asserts on it.

Suggest making it variant-scoped, matching the style you used two lines down:

// Historical slow-fill exclusivity error; no longer raised.
#[msg("The Deposit is still within the exclusivity window!")]
NoSlowFillsInExclusivityWindow,

The "so subsequent error codes do not shift" rationale is the important part and is already captured in SLOW_FILL_RETIREMENT.md, so it doesn't need to be restated inline.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to the suggested variant-scoped comment in 5d700387. RelayFilled remains the active replay error; no error values changed.


Sent from Reinis Martinsons's Codex CLI Agent using gpt-6-astra 🤖

@droplet-rl

Copy link
Copy Markdown
Contributor

🔎 View trace

@droplet-rl droplet-rl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 5d700387. All four items addressed, and one of my premises was wrong in a way that matters — thanks for the correction. Approving.

Verification of the follow-up commit

  • Rename. Confirmed a pure rename: git diff -M between 559a391e and 5d700387 shows exactly one content line changed in the file (the describe string). No stale LiteChain references anywhere in .ts/.md/.toml/.yml, and the doc's two references were updated along with the new fresh-validator note.
  • error.rs. Variant-scoped comment applied; no error values or ordering changed. Re-ran CI's cargo test -p svm-spoke --lib at the new HEAD: 15/15, and 19/19 with --features test. v5_errors_use_dedicated_range still passes, so the slot layout is intact.

On the deployment gate — you were right and I was wrong

I checked out sol-cctpv2 to verify the claim rather than take it on trust, and it holds:

  • bundle.rs:116 rejects nonzero amount_to_return with NonZeroAmountToReturn.
  • bridge_tokens_to_hub_pool is gone from programs/svm-spoke/src on that branch entirely, while it still exists on this branch (token_bridge.rs, lib.rs).

So the "self-healing via amount_to_return in a later bundle" fallback I leaned on in my original comment will not exist after the combined upgrade. That makes the residual-funds question strictly more serious than I framed it, not less — there is no automatic recovery path on the far side. Documenting it as a hard pre-deployment gate, with the explicit "the compatibility tests do not establish that the live in-flight window is empty" disclaimer, is the right resolution. That reconciliation is genuinely not something this diff can settle.

I'll also own the terminology error: I glossed Lite chains as routing liquidity through the hub, which is backwards. Your definition — excluded from HubPool LP rebalancing — is what #1548 actually implements. Your point that the narrower suite name is still the better one stands regardless, and the rename is an improvement on both counts.

Summary

The diff itself was clean on first read and remains so. Everything I could check mechanically checks out: the retired selectors are the real sha256("global:…")[..8] values landing on Anchor's default dispatch arm with no #[fallback] in the way, the frozen fixture is a genuine 45-byte pre-upgrade account at the exact rent-exempt minimum, the layout assertions match a hand-count of the struct fields, and the Anchor.toml glob quoting prevents a silent full-suite skip that the new fixtures/ directory would otherwise have triggered.

Still not independently verified, as before: anchor test --skip-build (147 passing) and the Docker verified build — no validator available in my environment.

Approving. Note for anyone reading later: the pre-deployment reconciliation in the new "Lite-chain transition and existing funds" section is a blocking prerequisite for the combined upgrade, not for merging this PR into its stack base.


The token-rebalancing restrictions are a separate upgrade change. In the combined deployment, refund leaves
must have `amount_to_return == 0` and `bridge_tokens_to_hub_pool` is removed. Consequently, ordinary
`amount_to_return` processing cannot recover residual Solana vault funds after that upgrade.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified this against sol-cctpv2 rather than taking it on trust, and it's accurate:

  • programs/svm-spoke/src/instructions/bundle.rs:116 — if relayer_refund_leaf.amount_to_return != 0 { return err!(SvmError::NonZeroAmountToReturn); }
  • bridge_tokens_to_hub_pool returns no hits under programs/svm-spoke/src on that branch, while it's still present on this one.

Recording it here because this paragraph is the load-bearing one for the deployment gate: it's what removes the automatic recovery path a reader might otherwise assume exists (I assumed exactly that in my first review). Anyone evaluating residual vault balances before the combined upgrade should start from this paragraph and treat the reconciliation below as blocking — there is no second chance via amount_to_return afterward.

@droplet-rl

Copy link
Copy Markdown
Contributor

🔎 View trace

@Reinis-FRP
Reinis-FRP marked this pull request as ready for review September 9, 2026 15:31
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-09T15:35:58.707597Z 5d70038 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from 638afe1 to 0c25db4 Compare September 11, 2026 10:48
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch 2 times, most recently from f7f705a to 608c7db Compare September 15, 2026 11:53
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch 2 times, most recently from 5052d26 to e5dd925 Compare September 15, 2026 14:51
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from 608c7db to bc5c128 Compare September 15, 2026 14:51
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from e5dd925 to 3f78703 Compare September 15, 2026 15:20
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from bc5c128 to 0a20d28 Compare September 15, 2026 15:20
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from 3f78703 to e8c4ad5 Compare September 15, 2026 15:27
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from 0a20d28 to d677b2d Compare September 15, 2026 15:27
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from e8c4ad5 to b7cfafe Compare September 15, 2026 15:54
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from 4857e94 to f38ffb8 Compare September 16, 2026 13:13
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch 2 times, most recently from 8dad3f4 to f04c2c3 Compare September 16, 2026 14:00
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from f38ffb8 to 208fe5a Compare September 16, 2026 14:00
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from f04c2c3 to fe3a55d Compare September 18, 2026 07:35
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from 208fe5a to ab766c9 Compare September 18, 2026 07:35
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from fe3a55d to 50fb8e3 Compare September 22, 2026 08:10
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from ab766c9 to efb0124 Compare September 22, 2026 08:10
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from efb0124 to dc0bd72 Compare September 28, 2026 11:04
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from 50fb8e3 to 2215794 Compare September 28, 2026 11:04
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from dc0bd72 to db71398 Compare September 28, 2026 13:09
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from 2215794 to d646de9 Compare September 28, 2026 13:09
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from db71398 to 5c62e14 Compare September 28, 2026 18:42
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-184-step-5-gateway-integration branch from d646de9 to 23277c0 Compare September 28, 2026 18:42
Comment thread test/svm/fixtures/legacySlowFill.ts Outdated
// Deterministic test keys, not production credentials. The matching fill-status account is loaded at genesis.
export const legacyMint = Keypair.fromSeed(Buffer.alloc(32, 221));
export const legacyRequester = Keypair.fromSeed(Buffer.alloc(32, 222)).publicKey;
export const legacyRelay: RelayData = {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we inline these constants into SvmSpoke.SlowFillRetirement.ts and remove this file? There is one consumer, and this small module only defines the deterministic relay and keys matching the frozen account fixture. Keeping them beside the test makes that relationship easier to follow without another import/file boundary.

The frozen JSON account serves a separate purpose and should remain while we test historical-account compatibility: constructing its bytes with the current encoder during the test could hide a layout regression.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in b4f9f57b: inlined the constants beside the test and removed the helper file. The frozen JSON and test body are unchanged, with fixture provenance and the fresh-validator requirement now beside the constants. Carried this through the stack while preserving the later expiry-reclaim test.


Sent from Reinis Martinsons's Codex CLI Agent using gpt-6-astra 🤖

@@ -0,0 +1,71 @@
# SVM slow-fill retirement

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we consolidate this into the existing documentation and remove the standalone retirement document before merging? The useful content has three natural homes:

  • Permanent account-layout, enum-position, and two-root admin ABI constraints: inline comments and the existing adapter spec.
  • Outstanding requests, funded leaves, and residual vault balances: the combined upgrade's deployment runbook. These deployment requirements should be preserved.
  • Fixture provenance and the fresh-validator requirement: beside the test fixture.

That keeps the enduring compatibility rules close to the code and the one-time transition requirements with the deployment, without maintaining another overlapping document. Please update the links to this file as part of the consolidation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidated in b4f9f57b: compatibility rules are in the existing adapter spec, deployment requirements are under its Deployment sequencing section, and fixture notes are beside the test. Removed the standalone doc and updated its links. Restacked through #1565, folding the deployment notes into the existing combined-upgrade section and preserving the V5-only wording after legacy entrypoint retirement.


Sent from Reinis Martinsons's Codex CLI Agent using gpt-6-astra 🤖

there is no destination slow-fill fallback. Closing the fill-status PDA only reclaims rent and does not refund
the deposit. `scripts/svm/closeRelayerPdas.ts` discovers accounts from `FilledRelay` events only, so it does not
find requests that were never filled. Those accounts require separate discovery and a `close_fill_pda` call
by their recorded rent recipient after expiry.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small wording correction to preserve wherever this paragraph ends up: close_fill_pda is permissionless. The account named signer is an UncheckedAccount constrained to the recorded rent recipient; it does not require that recipient's signature. Anyone can submit the close after expiry, but the rent must go to the recorded recipient. Suggest replacing "by their recorded rent recipient after expiry" with "after expiry, returning rent to their recorded rent recipient".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected in b4f9f57b: anyone may submit the close after expiry; rent goes to the recorded recipient. This is now explicit in the adapter spec. My earlier reply here also incorrectly said the recipient had to submit it. No contract behavior changed.


Sent from Reinis Martinsons's Codex CLI Agent using gpt-6-astra 🤖

@grasphoper grasphoper left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, left a few comments

@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from 5c62e14 to dc7d342 Compare September 29, 2026 09:47
Base automatically changed from reinis/acp-184-step-5-gateway-integration to epic-v5/svm September 30, 2026 08:17
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
@Reinis-FRP
Reinis-FRP force-pushed the reinis/acp-221-remove-slow-fills branch from b4f9f57 to 30d8928 Compare September 30, 2026 08:21
@Reinis-FRP
Reinis-FRP merged commit a459f31 into epic-v5/svm Sep 30, 2026
7 checks passed
@Reinis-FRP
Reinis-FRP deleted the reinis/acp-221-remove-slow-fills branch September 30, 2026 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants