ethereum-optimism / ethereum-optimism/actions

Optimize getQuote to skip calldata encoding when wallet is not needed

Open
#331 1 comment 0 reactions 0 assignees View on GitHub
good first issue help wanted
Dominant language
TypeScript
Stars
32
Forks
25
Avg merge
10h 20m
Merged PRs (30d)
16

Description

## Problem

`getQuote()` currently builds both pricing data and swap calldata (via `_getQuote` in each provider). When called from the `ActionsSwapNamespace` (read-only, no wallet), the calldata is wasted — no one can execute it without a wallet.

This is especially costly with price routing (`settings.routing: 'price'`), where `getQuote()` fetches quotes from all eligible providers in parallel. Each quote encodes calldata that will never be used except for the winning quote — and even that won't be used if the caller only needs display data.

The same pattern now exists in borrow: read-only preview flows can call `actions.borrow.getQuote(...)`, but the current implementation still builds the full executable quote, including the pre-built transaction bundle, even when the caller only needs `positionAfter`, fees, and the safe-ceiling LTV.

## Proposed Solution

Add an internal `includeCalldata` / `includeExecution` flag to read-only quoting flows:

1. **`ActionsSwapNamespace.getQuote()`** — calls provider with `includeCalldata: false`. Returns a `SwapQuote` with `execution` omitted or set to a sentinel. Faster because it skips `encodeSwap()` / `encodeCLSwap()` / `encodeUniversalRouterSwap()`.

2. **`WalletSwapNamespace.getQuote()`** — calls provider with `includeCalldata: true` (default). Returns a full `SwapQuote` ready for `execute()`.

3. **Provider `_getQuote()`** — accepts the flag and conditionally skips the encoding step. The quoting step (RPC calls to get amounts) still runs in both cases.

4. **Borrow parity** — apply the same pattern to borrow quote building so read-only borrow preview paths can skip execution-bundle construction while wallet-bound borrow quotes still return full executable data.

The quote types could make execution optional, or we could have two internal return paths with a shared base.

## Why This Matters

- With 2+ providers and price routing, every swap `getQuote()` call currently does N encoding operations. Only 1 is ever used.
- The `ActionsSwapNamespace` is explicitly read-only — encoding calldata for it is pure waste.
- The encoding involves `encodeFunctionData`, `encodeAbiParameters`, `encodePacked` — non-trivial compute per call.
- Borrow has the same avoidable overhead for preview-only callers that do not need executable transactions.

## Scope

- Add `includeCalldata?: boolean` to `SwapQuoteParams` or as an internal-only param
- Update `_getQuote` in `VelodromeSwapProvider` and `UniswapSwapProvider` to skip encoding when false
- Override `getQuote` in `ActionsSwapNamespace` to pass `includeCalldata: false`
- Ensure `WalletSwapNamespace` defaults to `includeCalldata: true`
- Extend the same approach to borrow quote building, likely with an internal `includeExecution` flag or a parallel quote builder path
- Update tests to cover both paths

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.