Skip to content

feat(swap-vm): add LimitProgramBuilder for LimitSwapVMRouter - #136

Draft
krboktv wants to merge 1 commit into
masterfrom
cursor/limit-program-builder-1bd9
Draft

krboktv wants to merge 1 commit into
masterfrom
cursor/limit-program-builder-1bd9

Conversation

@krboktv

@krboktv krboktv commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Summary

LimitSwapVMRouter and LimitSwapVMRouterDebug execute programs against the LimitOpcodes table. Its opcode bytes match the full Opcodes table up to staticBalancesXD (0x11) and differ from 0x12 on. The SDK had no table or builder for these routers, so a program built with RegularProgramBuilder runs different instructions there. For example, limitSwap1D is 0x19 in Opcodes but 0x15 in LimitOpcodes, where 0x19 is dutchAuctionBalanceIn1D.

Changes

  • instructions.limitInstructions mirrors LimitOpcodes._opcodes(): 41 slots, bytes 0x00-0x28. LimitOpcodes.sol is identical in the pinned contracts and in v1.0.2.
  • LimitProgramBuilder (exported from programs) has a typed method for every instruction in the table and a static decode(). Its FeeExperimental methods are marked experimental. It has no debug helpers.
  • README: a "Program builders and target routers" section maps each builder to its opcode table and routers.

Testing

  • pnpm nx run-many -t build, pnpm lint, pnpm lint:types and pnpm test pass (swap-vm: 55 files / 690 tests).
  • Unit tests:
    • the table matches the contract order;
    • every method encodes with its expected byte and round-trips through decode();
    • a program using every instruction round-trips;
    • limitSwap1D is 0x15 here and 0x19 in RegularProgramBuilder;
    • a limit order built by both builders has identical args but different opcode bytes;
    • instructions outside the table are rejected.
  • A local forge test against LimitOpcodes (not committed) passes:
    • LimitProgramBuilder programs execute on it: the 0x150101 limit swap returns the expected amount, as does deadline + limitSwap1D + salt;
    • requireMinRate1D (0x17) passes and reverts as expected;
    • the same order built with RegularProgramBuilder (limitSwap1D = 0x19) reverts on the limit table.

Notes

Open in Web Open in Cursor 

LimitSwapVMRouter executes programs against the LimitOpcodes table, whose
opcode bytes differ from the full Opcodes table (e.g. limitSwap1D is 0x15
there and 0x19 in Opcodes). The SDK had no table or builder for it, so
programs built with RegularProgramBuilder executed different instructions
on these routers.

- Add instructions.limitInstructions mirroring LimitOpcodes._opcodes()
  (41 slots, wire bytes 0x00-0x28)
- Add LimitProgramBuilder with typed methods for every instruction of the
  table and a static decode(); FeeExperimental methods are marked
  experimental; no debug helpers
- Document the three program builders and the routers each one targets
  in the README

Co-authored-by: k.kuznetsov <k.kuznetsov@1inch.io>
@sonarqubecloud

sonarqubecloud Bot commented Oct 8, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
37.3% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

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.

2 participants