Skip to content

feat: announcement-anchored Dutch auction with fill-size pricing (standalone extension) - #223

Open
deacix wants to merge 6 commits into
masterfrom
cursor/anchored-auction-mvp-2a
Open

feat: announcement-anchored Dutch auction with fill-size pricing (standalone extension)#223
deacix wants to merge 6 commits into
masterfrom
cursor/anchored-auction-mvp-2a

Conversation

@deacix

@deacix deacix commented Aug 7, 2026

Copy link
Copy Markdown
Member

Change Summary

What does this PR change?

Adds the announcement-anchored Dutch auction as a standalone, per-order opt-in extension, plus fill-size-dependent pricing over the order's volume ladder. The first commit is a pure move-only extraction of the existing auction math (_getRateBump/_getAuctionBump and their constants) from SimpleSettlement into an abstract DutchAuctionBase — bodies byte-identical, visibility privateinternal virtual — so the feature itself reads as a small diff on top of code this repo already ships.

Why: a Fusion auction starts at an absolute timestamp baked into the order at build time, so a maker that signs slowly (a multisig collecting signatures) misses its own window and degrades to the floor price. Anchoring starts the schedule from the moment the order was first announced on-chain instead. This executes the team's agreed split of 1inch/limit-order-protocol#430 (the auction mechanics belong in this repo); the anchor is the write-once announcedAt recorded by the registrator in 1inch/limit-order-protocol#435.

Taking amount for a full fill over wall-clock time. Baked at build time the curve reaches the floor at 30 minutes, before a 45-minute multisig can sign, and then sits at the floor indefinitely. Anchored, the order is unfillable until announced at 45 minutes, then runs the same full curve, and its floor tail is ended by the announcement deadline at 80 minutes.

The scenario this exists for: a Safe taking 45 minutes to co-sign. Today the curve decays while owners are still signing and the order is at the floor by the time it can be filled — a free option for resolvers. Anchored, it is unfillable until announced, then runs the same full curve an EOA gets; the optional announcement deadline bounds how long it stays fillable at the floor. The initial bump is exaggerated to 5% for legibility.

Related Issue/Ticket: PT1-724; review thread and reference implementation: 1inch/limit-order-protocol#430.

Testing & Verification

How was this tested?

  • Unit tests

  • Integration tests

  • Manual testing (describe steps)

  • Verified on staging

  • Baseline suite: 115 passing. After the extraction commit the untouched existing suite still passes exactly 115 — the refactor is behaviorally identical by test evidence, not just by eyeball.

  • 16 new tests for the anchored extension: pricing parity with the settlement's own auction, anchored-start cases (stale built start ignored, later built start wins, same-block announce-and-fill), unannounced anchored order reverting, exclusivity windows (anchored window held open, staggered resolvers, empty whitelist, non-whitelisted takers waiting out every window), the announcement deadline exact at its boundary, deadline-without-anchor failing closed, and chaining behind SimpleSettlement.

  • 15 new tests for the ladder: matrix rows hit exactly on a fresh order, interpolation between and past rows, successive fills repriced on the remainder, zero-premium completion, lazy monotonicity rejection, a seeded superadditivity sweep (random partitions never undercut a single sweep, priced through the contract's own views), and the gas-bump interaction. Total: 146 passing.

  • New contracts at 100% line coverage; yarn lint fully green — this branch carries a one-commit fix for the two pre-existing scripts/ lint errors (space-before-function-paren in mint-kyc.js and transfer-ownership.js) that had master's lint job red.

Risk Assessment

Risk Level:

  • Low - Minor changes, no operational impact
  • Medium - Moderate changes, limited impact, standard rollback available
  • High - Significant changes, potential operational impact, complex rollback

Risks & Impact

  • No deployed-contract changes and no redeploys. SimpleSettlement's source is refactored (inheritance only; its untouched test suite pins identical behavior), and deployed settlement instances are unaffected. The extension is a new, separately deployed contract that orders opt into through their extension bytes.
  • Deploy sequencing: the extension's constructor takes the registrator address, so the updated OrderRegistrator from feat: record first announcement time in OrderRegistrator limit-order-protocol#435 deploys first per chain; config/constants carries the placeholder where those addresses land.
  • Tests announce through a minimal write-once mock (OrderRegistratorMock) because the pinned @1inch/limit-order-protocol-contract 4.3.2 predates the announcedAt view; the production interface is declared locally as one view function.

What's inside

Every feature is opt-in per order via a flags byte; with no flags set, pricing matches the settlement's existing auction exactly.

  • Anchored start (auction flag 0x01): auction start = max(announcedAt, builtStartTime). An anchored order that was never announced reverts OrderNotAnnounced; a re-announcement can never move the anchor (write-once at the registrator).
  • Announcement-anchored resolver exclusivity + deadline (post-interaction blob): whitelist windows measured from the announcement instead of absolute time, and an optional fill-by deadline — fillable at exactly announcedAt + delay, reverting AuctionExpired strictly after. The deadline flag without the anchored flag reverts InvalidFlagCombination. It lives in the post-interaction because a post-interaction is not skippable by getter mis-assembly.
  • Volume-ladder fill pricing (auction flag 0x02): a fill pays a premium by its share of the remaining amount (1e4 base) over a piecewise-linear curve — a tenth of what is left prices at the 1/10 row whether it is the first fill or the fifth — and whoever completes the order pays no premium at all. The curve is enforced non-increasing lazily during the walk (NonMonotonicFillCurve), so splitting always costs takers more than sweeping. In the making-amount direction the share is estimated at the worst rate bump and repriced, so the estimate never exceeds the exact solution.

Visualizations

The fill curve over the volume ladder: the quote matrix hit exactly at each row and interpolated in between, next to the single-row schedule with no interior points — both falling to zero for a fill that takes the whole remainder

One encoding for every schedule, drawn over the share of the remainder a fill takes: the matrix hits each quote row exactly at its rung and interpolates in between; a curve with no interior points (dashed) is the one-parameter schedule. Both end at zero, so completion is never penalized.

Bar chart comparing the total premium paid for one sweep, two halves, four quarters, ten tenths and a 30/30/40 split, under the quote matrix and a single-row curve

Splitting always costs the takers more than one sweep, and the fill that completes the order pays no premium at all — superadditivity, pinned in this PR by the seeded random-partition test priced through the contract's own views.

Two panels for a low-liquidity pair. Left: the value a resolver keeps as a share of the fill, against fill size — 2.66 percent for a tenth-sized fill under flat pricing, zero at every size under the volume ladder. Right: extra proceeds for the maker by fill pattern, up to plus 2.74 percent against a resolver that cherry-picks ten percent and stops

Where the ladder earns its keep: on a thin book where a full sweep costs 4% in price impact, a resolver filling a tenth today keeps 2.66% of that fill purely because the slice was small; the ladder prices the slice at its own size and the value stays with the maker. Sweeping is unaffected. The impact model and its assumptions are documented in 1inch/limit-order-protocol#430; the matrix there is set to the full modelled edge, so production rows should sit below it to leave partial fills some margin.

Measured costs, from the reference implementation

Two panels of measured gas. Left: cost of one fill — against the live mainnet Settlement, 92,089 gas today versus 107,410 with the anchored auction chained behind it, plus 15,321. Right: new per-order costs — announcing an order costs 31,132 gas.

Every number is receipt.gasUsed from real fills of the reference implementation (1inch/limit-order-protocol#430 — identical pricing logic and the same chained-call structure as this PR), measured against both the live mainnet Settlement on a fork and a local mirror: chaining the anchored auction behind the deployed settlement costs about 15.0–15.3k gas per fill, the fill ladder adds 1,365 gas to a partial fill and 558 to a completing one, and the per-order announcement costs 31,132 gas for a lean order. The right panel's DelegatedMaker bar belongs to a separate, currently parked proposal — not this PR. Reproduction harnesses live on the reference branch: scripts/gas-comparison.js, scripts/gas-comparison-fork.js, scripts/price-impact.js, scripts/fill-curve-data.js.

Notes for reviewers

cursoragent and others added 4 commits August 7, 2026 13:03
Move-only change: _getRateBump and _getAuctionBump leave SimpleSettlement
for an abstract base with internal virtual visibility, so a standalone
extension can reuse the time-curve math. No behavior change.

Co-authored-by: Sergej Kunz <info@deacix.de>
FusionAnchoredAuction is a standalone amount getter and post-interaction,
referenced per order and chainable behind the deployed settlement, so no
settlement redeployment is needed. Opt-in per order via flags: an anchored
auction starts at max(announcedAt, built start), resolver exclusivity
windows measure from the announcement, and an announcement deadline stops
fills strictly after announcedAt plus the delay. announcedAt is read from
the limit-order-protocol#435 registrator through a one-function local
interface.

Co-authored-by: Sergej Kunz <info@deacix.de>
Volume-ladder fill pricing behind auction flags bit 0x02: a fill pays a
premium read from a piecewise curve over its share of the remaining
making amount, interpolated between points with an implied final point
of zero premium at the full remainder, so whoever completes the order
pays no premium. The walk enforces monotonicity lazily and reverts a
rising stretch as NonMonotonicFillCurve. The making-amount direction
estimates the share at the worst rate bump and reprices from it, which
can only overstate the bump.

Co-authored-by: Sergej Kunz <info@deacix.de>
…r-2b

feat: price each fill by its share of the remainder
@cursor cursor Bot changed the title Cursor/anchored auction mvp 2a feat: announcement-anchored Dutch auction with fill-size pricing (standalone extension) Aug 7, 2026
cursoragent and others added 2 commits August 7, 2026 15:27
@deacix

deacix commented Aug 8, 2026

Copy link
Copy Markdown
Member Author

@SteMak — your review of 1inch/limit-order-protocol#430 drove the restructure that produced this PR; here is how each of your points that applies to this repo is addressed, so the review can continue here.

"Fusion extends Limit Order Protocol. Limit Order Protocol is not a correct place to implement Fusion functionality." Agreed and done — the auction mechanics now live here. The only limit-order-protocol change left is the registrator's write-once announcedAt (1inch/limit-order-protocol#435), which this extension reads through a locally declared one-view interface; no dependency bump, no circular reference.

"Has a lot of duplications from existing code. Has to be reorganized to demonstrate real code changes." The first commit (06fe413) is a pure move: _getRateBump/_getAuctionBump leave SimpleSettlement for the abstract DutchAuctionBase with bodies byte-identical and only private becoming internal virtual — the untouched existing test suite (115 passing before and after) pins that nothing changed behaviorally. The extension then inherits the base, so the diff reads commit-by-commit: extraction, the anchored feature (0068ea0), the fill ladder (13918b3).

"Tons of AI'sh comments are a headache." NatSpec here is deliberately terse — one line per member where possible, with multi-line blocks only where a packed byte layout has to be documented.

Deployment shape, since it is the flip side of the layering point: this ships as a separately deployed, per-order opt-in extension rather than a settlement change, because avoiding a redeploy of the deployed settlement is a hard requirement. Folding the logic into a future settlement version stays available whenever one ships anyway, and would recover the chained-call overhead measured in 1inch/limit-order-protocol#430.

For completeness: your registrator comments (signature removal, EIP-1271 compatibility, the firstRegistration return) are resolved in 1inch/limit-order-protocol#435, which restores master's signed permissionless registerOrder unchanged and only adds the write-once timestamp. Your DelegatedMaker comments are parked together with the contract itself, pending the team's decision on whether and where it ships.

@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@cursor Hey, can you justify the contract structure changes?
It feel that the logic could be implemented just in contracts/SimpleSettlement.sol in 30-100 LoC without populating codebase with additional base and extension contracts

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

All claims are verified against the code. No changes are needed — this is a justification question, so here is the answer.


Fair question — and worth being upfront that you're partly right: nothing in this logic is technically impossible to write inside SimpleSettlement.sol, and the anchored start alone would be ~10–15 lines there. The structure isn't about possibility; it's forced by one constraint and one of your own review points.

1. Editing SimpleSettlement.sol ships nothing. SimpleSettlement/Settlement are live at fixed create3 addresses on 18 chains (the README table — 0x2Ad5004c... almost everywhere). A change to the settlement's source only exists after a settlement redeploy, which was a hard requirement to avoid: new address, resolver/SDK/backend migration, dual-running during cutover, and on mainnet the DAO-flavored Settlement variant. It would also couple the settlement's constructor (and therefore its deployability on every chain) to the limit-order-protocol#435 registrator rolling out first, and change the live auctionDetails wire format that deployed instances and every order builder already parse (the flags byte and embedded fill curve don't fit the current layout without a versioning branch inside the settlement). A separately deployed contract referenced per order is the only shape that makes the feature usable against the settlements that already exist — and only orders that opt in ever touch the new parsing; a plain Fusion order's code path is unchanged.

The chaining this relies on is not new machinery — it's the LOP's designed composition point, already in the deployed settlement bytecode. The deployed getter delegates its tail to the next getter by address:

    ) internal view virtual returns (uint256) {
        if (extraData.length >= 20) {
            return IAmountGetter(address(bytes20(extraData))).getMakingAmount(
                order, extension, orderHash, taker, takingAmount, remainingMakingAmount, extraData[20:]
            );
        } else {
            return order.makingAmount.mulDiv(takingAmount, order.takingAmount);
        }
    }

and FeeTaker._postInteraction does the same for post-interactions (line 159). The composition test (test/FusionAnchoredAuction.js, "composition with SimpleSettlement") exercises exactly this: settlement in front, extension priced and enforced behind it.

2. DutchAuctionBase is the anti-duplication move, not an abstraction for its own sake. Once the feature is a standalone contract, it needs the settlement's _getAuctionBump walk and the two constants. The options were copy-paste — which your #430 review rightly objected to ("has a lot of duplications from existing code") — or a shared base. The base is a pure move: 86 lines, bodies byte-identical, privateinternal virtual, nothing else in SimpleSettlement touched (commit 06fe413, net +89/−78), and the untouched 115-test settlement suite pins that behavior is unchanged. Inheriting SimpleSettlement instead would drag FeeTaker/Ownable/fee logic into the extension and run fee code twice when chained, so the auction math is the minimal correct unit. It's also the same layering the LOP repo itself uses (AmountGetterBaseAmountGetterWithFeeFeeTaker).

3. On the LoC estimate. In a world where a redeploy were acceptable, the honest in-settlement diff for the full agreed scope — anchor, announcement-relative exclusivity, deadline, and the fill ladder with its worst-case estimate/reprice in the making direction — is ~120–150 lines of logic, not 30–100; folding in would save only the ~30 lines of whitelist-walk and gas-bump scaffolding the standalone version has to carry itself. The extension file reads as 300 lines because half is NatSpec pinning the packed byte layouts. So the structure costs roughly one screen of scaffolding and one 86-line moved file, and buys shipping without a settlement release.

4. It doesn't foreclose your version. When a settlement v-next ships anyway, absorbing this into it is deliberately cheap — the math already sits in the base, so it's the ~15 lines of anchor/deadline plus the ladder functions moving one file over — and doing so recovers the ~15k gas chained-call overhead measured in #430. That's the sequencing being proposed: extension now so slow-signing makers stop bleeding to the floor, fold-in whenever a settlement redeploy happens for its own reasons.

Open in Web Open in Cursor 

@1inch 1inch deleted a comment from cursor Bot Aug 8, 2026
@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@cursor compress the answer to one paragraph, it either should start with "yes, it would be better to fold changes to SimpleSettlement" or "here is the list of objections behind the design, each consistent with solidity development best practices"

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Here is the compressed one-paragraph version of the answer.


Here is the list of objections behind the design, each consistent with solidity development best practices: (1) deployed code is immutable — SimpleSettlement/Settlement are live at fixed create3 addresses on 18 chains, so logic added to SimpleSettlement.sol ships only via a settlement redeploy (address change, resolver/SDK migration, and a constructor newly coupled to the per-chain registrator rollout), which was a hard requirement to avoid; (2) composition over modification — the deployed bytecode already delegates amount-getter and post-interaction tails to a next address (AmountGetterBase, FeeTaker), so a standalone opt-in extension is the LOP's designed extension point, keeps the new parsing out of every plain Fusion order's path, and avoids changing the live auctionDetails wire format, which the flags byte and embedded fill curve would otherwise break; (3) DRY without inheritance bloat — the extension needs the settlement's auction math, and DutchAuctionBase is a byte-identical 86-line move (pinned by the untouched 115-test suite) rather than the copy-paste your #430 review objected to, while inheriting all of SimpleSettlement would drag fee/owner logic in and run it twice when chained; (4) the full agreed scope (anchor, announcement-relative exclusivity, deadline, fill ladder with the making-direction estimate) is ~120–150 lines of logic wherever it lives, so folding in saves only ~30 lines of scaffolding today — and remains available at the next settlement release anyway, where absorbing the extension is a small diff that also recovers the ~15k gas chaining overhead.

Open in Web Open in Cursor 

@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@cursor make the list a list, any referred links either should work or be removed

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Both cross-repo references resolve (verified through the GitHub CLI), so they stay as links; everything else is plain text. Here is the answer as a list.


Here is the list of objections behind the design, each consistent with solidity development best practices:

  1. Deployed code is immutable. SimpleSettlement/Settlement are live at fixed create3 addresses on 18 chains (the README deployment table), so logic added to SimpleSettlement.sol ships only via a settlement redeploy — a new address, resolver/SDK migration, and a constructor newly coupled to the per-chain rollout of the registrator from 1inch/limit-order-protocol#435. Avoiding that redeploy was a hard requirement.
  2. Composition over modification. The deployed settlement bytecode already delegates amount-getter and post-interaction tails to a next address (AmountGetterBase, FeeTaker), so a standalone opt-in extension is the protocol's designed extension point. It keeps the new parsing out of every plain Fusion order's path and avoids changing the live auctionDetails wire format, which the flags byte and embedded fill curve would otherwise break.
  3. DRY without inheritance bloat. The extension needs the settlement's auction math. DutchAuctionBase is a byte-identical 86-line move (commit 06fe413, pinned by the untouched 115-test suite) rather than the copy-paste your review of 1inch/limit-order-protocol#430 objected to; inheriting all of SimpleSettlement instead would drag fee/owner logic into the extension and run it twice when chained.
  4. The LoC saving is small and nothing is foreclosed. The full agreed scope (anchor, announcement-relative exclusivity, deadline, fill ladder with the making-direction estimate) is ~120–150 lines of logic wherever it lives; folding in saves only ~30 lines of scaffolding today. It remains available at the next settlement release anyway, where absorbing the extension is a small diff that also recovers the ~15k gas chaining overhead.
Open in Web Open in Cursor 

@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@cursor

  1. That's not a justification. Anyway, this PR changes SimpleSettlement, so if it was an objection to not modify it, it is filled
  2. That mess of words does not make any sense to me, be consistent in your claims
  3. The PR proposes 2 more files introducing more inheritance, inheritance bloat rather increases than solved
  4. That's not a justification of changes

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

His four objections share one root — my previous framing was imprecise — so this reply restates the single constraint exactly and answers each point from it. No code changes are requested yet, so I'm answering only.


The imprecision is mine, so let me state the one claim everything rests on, exactly: the feature must be fillable through the settlement contracts already deployed at fixed addresses on 18 chains, and their bytecode cannot change. All four answers follow from that sentence.

  1. Agreed, the objection was never "don't touch SimpleSettlement.sol" — this PR touches it, and that's fine. The objection is "don't make the feature depend on a settlement redeploy". The edit here is a behavior-neutral move of two private functions (existing 115 tests pass unchanged), and the feature works whether or not the refactored settlement is ever deployed. Feature logic written inside SimpleSettlement.sol is different in kind: it exists on-chain only after new settlements deploy on every chain and resolvers/SDK/orders migrate to the new address.

  2. Stated as mechanics, once: an order's extension bytes name an amount-getter address plus data; the deployed settlement, after parsing its own auction details, delegates the remaining bytes to the next address in that data (AmountGetterBase._getMakingAmount in the pinned package, same tail-delegation for post-interactions in FeeTaker — this is in the live bytecode today). So new pricing logic at a new address is reachable by any order signed now, chained behind the live settlement — verified against the mainnet settlement on a fork, which is where the PR's gas numbers come from. New pricing logic inside SimpleSettlement.sol is reachable by no order until a redeploy. That is the whole of point 2.

  3. The two files are the cost of that constraint plus the cost of not duplicating. FusionAnchoredAuction.sol must exist because the logic must live at its own address (point 2). DutchAuctionBase.sol exists only because that contract and SimpleSettlement need the same 86 lines of auction math, and copying them is the duplication your review of 1inch/limit-order-protocol#430 objected to. Solidity offers exactly two ways to share internal functions across two deployed contracts — a common abstract base or an internal-function library — and both cost one file; the hierarchy cost is one flat parent holding previously-inline code, not a deeper chain. I picked the base because it keeps the extraction byte-identical with SimpleSettlement's call sites untouched and matches the AmountGetterBase/AmountGetterWithFee/FeeTaker layering the codebase already builds on. If you'd rather see a DutchAuctionLib library, the conversion is mechanical — say the word and I'll push it.

  4. Correct — LoC was never offered as the justification; it was a rebuttal of the 30–100 LoC estimate. The justification is point 2's constraint: an in-settlement implementation of any size ships nothing until a redeploy. The real fork here is a deployment decision, not a style one — if the team decides the feature may wait for the next settlement release, folding it in is the better end state, and this structure makes that fold a small diff. This PR implements the decision as it was given to me: usable against the live settlements, no redeploy.

Open in Web Open in Cursor 

@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@cursor Was it a reply containing justification of what I have asked? If so, I completely missed those in the text bloat

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Yes — it was points 1–2 of the previous reply. Here is the entire justification, minus everything else:

The new auction logic must be usable by orders that settle through the already-deployed settlement contracts (immutable bytecode, 18 chains). Code added to SimpleSettlement.sol does not run on-chain until a settlement redeploy, so an in-settlement implementation cannot meet that requirement at any line count. Therefore the logic lives in one new contract at its own address — FusionAnchoredAuction.sol — which the deployed settlements already delegate to through order extension data. DutchAuctionBase.sol exists only so that contract and SimpleSettlement share the auction math instead of duplicating it.

Open in Web Open in Cursor 

@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@cursor
Fine. Let's dive into the objection. Does it mean that new call stack looks as limit order protocol -> fusion settlement -> new extension? How many funds transfers does the new design cause?

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Both questions verified directly against the pinned LOP 4.3.2 sources and the extension. No code changes needed — here is the answer.


Call stack: yes, with one correction — the extension is in two legs of the fill, and the middle hop is optional.

  • Pricing (view): LOP → settlement getter → extension getter. One staticcall chain per fill (a second calculateTakingAmount call happens only when a taking-amount fill gets capped to the remainder, OrderMixin line 317–320).
  • Enforcement: LOP → settlement.postInteraction (fee split) → extension.postInteraction (time/whitelist checks).
  • An order that doesn't need the settlement's fees can reference the extension directly: LOP → extension, no middle hop. Both shapes are in the test suite.

Funds transfers: the extension adds zero. Its getters are view; its postInteraction reads announcedAt plus timestamps and either reverts or returns — it never holds or moves tokens, and has no transfer code at all. So the count is exactly today's Fusion count:

  1. maker asset: maker → taker (LOP core);
  2. taker asset: taker → settlement, which is the order receiver (LOP core);
  3. settlement pays out of itself (FeeTaker._postInteraction): remainder → maker, plus integrator-fee and protocol-fee transfers when nonzero — 1 to 3 transfers.

Total 3–5 ERC20 transfers with the settlement in front, same as now; 2 in the direct LOP → extension shape. The chained hop's entire cost is call overhead, fork-measured at ~15.0–15.3k gas per fill against the live mainnet settlement — none of it is token movement.

Open in Web Open in Cursor 

@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@cursor reduce answer bloat. no fee orders are not in scope

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

Yes — LOP → settlement → extension, in both legs of a fill: the pricing staticcall and postInteraction.

Funds transfers: unchanged, the extension performs none (view getters; its postInteraction only checks and reverts). As today: maker asset maker → taker, taker asset taker → settlement, settlement pays receiver plus fee recipients — 3–5 ERC20 transfers total, the same with or without the extension.

Open in Web Open in Cursor 

@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@cursor Justify no redeploy of settlement requirement
Do users interact with settlement directly? Do users give allowances to settlement? What is the cost (not in money but user flow changes) of redeploying settlement?

@cursor

cursor Bot commented Aug 8, 2026

Copy link
Copy Markdown

All three claims verified in the test suite and contracts. Answering directly, including where his implied point is right.


Do users interact with settlement directly? No. Makers only sign an off-chain order; resolvers fill through lopv4.fillOrderArgs (via their own resolver contracts). The settlement is reached only by the LOP inside the fill — getter, postInteraction (guarded onlyLimitOrderProtocol), and as the order's receiver for the fee split.

Do users give allowances to settlement? No. Every approval in the flow targets the LOP or permit2 (maker and taker side alike). The settlement holds the taker asset only transiently, inside the fill transaction.

Cost of a redeploy, in flow terms: for makers, zero — no allowance migration, no flow change. The cost is operational coordination: the settlement address is embedded in each order's signed extension bytes, so the order-building backend, SDK releases, and every resolver's config and address vetting must switch per chain; in-flight orders keep filling through the old address (a short dual-run — Fusion orders live minutes); deploy-and-verify on 18 chains; and, with this feature folded in, each chain's new settlement additionally gates on the 1inch/limit-order-protocol#435 registrator being live there first, since it becomes a constructor dependency.

So, candidly: the no-redeploy requirement is not forced by user-facing friction — your questions establish that correctly. It is an operational and release-cadence constraint, and it came to this PR as an input (the team's split decision on 1inch/limit-order-protocol#430; PT1-724), not as my derivation. If the team is willing to pay the coordination cost and ship this inside the next settlement version, folding it in is the better end state — the extraction commit deliberately keeps that fold small. That call is the Fusion team's to make; the PR as written implements the constraint as given.

Open in Web Open in Cursor 

@SteMak

SteMak commented Aug 8, 2026

Copy link
Copy Markdown

@deacix I see, you put "no redeploy of SimpleSettlement" as a hard requirement for this PR, however, neither I nor cursor see objections for such a hard requirement as it is no cost for makers and takers migration to a redeployed settlement
Removing the requirement would fold PR into meaningful size, keep existing architecture, avoid additional cross-contract calls

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