Skip to content

feat(ur-sdk): add SwapRouter.encodeSwaps() with safety envelope#517

Draft
marktoda wants to merge 14 commits intomainfrom
encode-swaps
Draft

feat(ur-sdk): add SwapRouter.encodeSwaps() with safety envelope#517
marktoda wants to merge 14 commits intomainfrom
encode-swaps

Conversation

@marktoda
Copy link
Collaborator

@marktoda marktoda commented Feb 23, 2026

PR Scope

Please title your PR according to the following types and scopes following conventional commits:

  • fix(SDK name): will trigger a patch version
  • chore(<type>): will not trigger any release and should be used for internal repo changes
  • <type>(public): will trigger a patch version for non-code changes (e.g. README changes)
  • feat(SDK name): will trigger a minor version
  • feat(breaking): will trigger a major version for a breaking change

Description

[Summary of the change, motivation, and context]

How Has This Been Tested?

[e.g. Manually, E2E tests, unit tests, Storybook]

Are there any breaking changes?

[e.g. Type definitions, API definitions]

If there are breaking changes, please ensure you bump the major version Bump the major version (by using the title feat(breaking): ...), post a notice in #eng-sdks, and explicitly notify all Uniswap Labs consumers of the SDK.

(Optional) Feedback Focus

[Specific parts of this PR you'd like feedback on, or that reviewers should pay closer attention to]

(Optional) Follow Ups

[Things that weren't addressed in this PR, ways you plan to build on this work, or other ways this work could be extended]


✨ Claude-Generated Content

Description

Adds a new SwapRouter.encodeSwaps(spec, swapSteps) entry point that separates safety-critical logic (SDK-owned) from swap encoding (routing-owned). This allows routing services to describe swaps as structured SwapStep data while the SDK handles the safety envelope: Permit2 approval, token transfer into router, slippage protection via SWEEP/UNWRAP_WETH, and excess refund for EXACT_OUTPUT trades.

Changes

New API

  • Added SwapRouter.encodeSwaps(spec, swapSteps) method in src/swapRouter.ts
  • Added SwapSpecification type for SDK-owned safety metadata (tokens, amounts, slippage, permit, deadline, UR version)
  • Added SwapStep discriminated union for routing-owned swap commands (V2/V3/V4 swaps, WRAP_ETH, UNWRAP_WETH)

Type Definitions (src/types/encodeSwaps.ts)

  • SwapSpecification: tradeType, inputToken, outputToken, amount, quote, slippageTolerance, optional recipient/permit/deadline/urVersion
  • SwapStep: V2SwapExactIn, V2SwapExactOut, V3SwapExactIn, V3SwapExactOut, V4Swap, WrapEth, UnwrapWeth
  • V4 action types: V4SwapExactIn, V4SwapExactInSingle, V4SwapExactOut, V4SwapExactOutSingle, V4Settle, V4SettleAll, V4SettlePair, V4Take, V4TakeAll, V4TakePortion, V4TakePair, V4CloseCurrency, V4Sweep, V4Unwrap
  • Re-exports PoolKey and PathKey from @uniswap/v4-sdk

Utilities

  • encodeSwapStep() in src/utils/encodeSwapStep.ts - data-driven encoder using COMMAND_DEFINITION for param extraction
  • v4ActionToParams() in src/utils/encodeV4Action.ts - maps V4Action to V4Planner params with UR version support

Exports

  • All new types exported from src/index.ts

How Has This Been Tested?

Unit tests in test/unit/encodeSwaps.test.ts covering:

  • v4ActionToParams for SETTLE, TAKE, SWAP_EXACT_IN (V2.0 and V2.1 with maxHopSlippage)
  • encodeSwapStep for V2, V3, V4 swaps and WRAP_ETH
  • SwapRouter.encodeSwaps integration tests:
    • EXACT_INPUT: ERC20 → ERC20, Native ETH → ERC20, ERC20 → Native ETH
    • EXACT_OUTPUT: ERC20 → ERC20, Native ETH → ERC20 (with refund)
    • Permit2 permit prepending
    • Deadline encoding

Are there any breaking changes?

No - this is a new API that coexists with the existing swapCallParameters() method. Consumers can migrate at their own pace.

Developer and others added 10 commits February 21, 2026 02:27
Design for new SwapRouter.encodeSwaps() that separates safety-critical
encoding (permits, token transfers, slippage sweeps) from routing's
swap commands. Enables routing to innovate on path shapes without SDK
changes while the SDK owns the safety envelope.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the new encodeSwaps() method that separates safety-critical
encoding (permit, token pull, slippage sweep) from routing's swap
commands. Supports EXACT_INPUT and EXACT_OUTPUT with ERC20 and native
ETH on both sides.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix minAmountOut to use amount/(1+s) instead of amount*(1-s) to match
  SDK-standard slippage calculation
- Add invariant for empty swapSteps
- Add missing "with Permit2 permit" test case
- Import ROUTER_AS_RECIPIENT from constants in tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Import PoolKey and PathKey from @uniswap/v4-sdk instead of
  redefining them locally (PathKey.fee narrowed from BigNumberish
  to number to match v4-sdk)
- Derive ACTION_NAME_TO_ENUM programmatically from Actions enum
  instead of manual mapping, so it stays in sync automatically

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace manual switch statement with automatic param extraction using
COMMAND_DEFINITION param names (which match SwapStep field names by
convention). Derive CommandType from step.type string automatically.
V4_SWAP retains special handling for V4Planner pre-encoding.

Adding new swap step types now only requires the type definition —
no switch case to maintain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add undefined guard on COMMAND_DEFINITION param extraction to fail
  fast if a SwapStep field name diverges from the expected param name
- Restrict STEP_TYPE_TO_COMMAND to swap-relevant commands only instead
  of mapping all CommandTypes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot changed the title Encode swaps feat(ur-sdk): add SwapRouter.encodeSwaps() with safety envelope Feb 23, 2026
@semgrep-code-uniswap
Copy link

Semgrep found 1 ssc-cee3e6d5-d7c8-4c35-9815-076aa1ebfd49 finding:

Risk: Affected versions of rollup are vulnerable to Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').

Manual Review Advice: A vulnerability from this advisory is reachable if you use Rollup to bundle JavaScript with import.meta.url and the output format is set to cjs, umd, or iife formats, while allowing users to inject scriptless HTML elements with unsanitized name attributes

Fix: Upgrade this library to at least version 2.79.2 at sdks/package-lock.json:27661.

Reference(s): GHSA-gcx4-mw62-g8wm, CVE-2024-47068

Semgrep found 2 ssc-17eda294-146f-4ed3-91f7-5ef1b349d687 findings:

Risk: Affected versions of @babel/traverse and babel-traverse are vulnerable to Incomplete List of Disallowed Inputs / Incorrect Comparison. Compiling untrusted code with Babel using plugins that invoke the internal path.evaluate() or path.evaluateTruthy() methods (for example @babel/plugin-transform-runtime, @babel/preset-env with useBuiltIns, or any polyfill‐provider plugin) allows a maliciously crafted AST to execute arbitrary code on the build machine during compilation.

Manual Review Advice: A vulnerability from this advisory is reachable if you use Babel to compile untrusted JavaScript

Fix: There are no safe versions of this library available for upgrade. Library included at sdks/package-lock.json:26929.

Reference(s): GHSA-67hx-6x53-jw92, CVE-2023-45133

Semgrep found 1 ssc-592ab7c9-5593-400a-b545-dc108b1c006b finding:

Risk: @openzeppelin/contracts versions >= 3.3.0 before 3.4.2, >= 4.0.0 before 4.3.1 are vulnerable to Improper Privilege Management. A vulnerability found in TimelockController exposes a security loophole wherein an individual possessing the executor role can exploit the flaw to promptly seize control of the timelock. This is achieved by resetting the delay to zero, which subsequently leads to a privilege escalation, ultimately granting the attacker unrestrained access to the assets held within the contract.

Manual Review Advice: A vulnerability from this advisory is reachable if you have users configured with the executor role or have configured the executor role as open, which effectively permits any user to utilize the role

Fix: Upgrade this library to at least version 3.4.2 at sdks/package-lock.json:7439.

Reference(s): GHSA-fg47-3c2x-m2wr, CVE-2021-39167

@hensha256
Copy link
Contributor

you pushed a package-lock.json

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