Odosswap token approvals: direct vs Permit2 in Odos Router V2

Odos Router V2 defines two authorization paths for ERC-20 inputs: an allowance granted directly to the router or a Permit2 signature backed by a separate token allowance to Permit2. The chosen swap function determines which permission applies.

Updated

Odos's hosted trading and API services have shut down. Its July 23, 2026 wind-down announcement set July 27 for the app's read-only switch and July 30 for all company-operated services to end.

Direct allowances and Permit2

Odos Router V2 authorization paths
Authorization detail Direct allowance Permit2 SignatureTransfer
Spender approved at the token contract The Router V2 deployment on the selected network The selected Permit2 contract
Permission needed for the input Sufficient token allowance to the router Sufficient token allowance to Permit2 plus a valid signed permit authorizing the router
V2 entry points swap , swapMulti and their compact variants swapPermit2 and swapMultiPermit2
Input transfer The router uses SafeERC20.safeTransferFrom to call the token's transferFrom The router calls Permit2's permitTransferFrom

An allowance belongs to one owner, token contract and spender on a particular network. Approving that spender records permission for a later transfer; approval alone doesn't move the tokens or complete a swap. A sufficient remaining allowance can cover another transfer without a new token approval.


What the Permit2 signature covers

Router V2 uses Permit2's SignatureTransfer interface. Both Permit2 entry points pass the router caller, msg.sender , as the token owner. For swapPermit2 , the signed token and permitted amount must match inputToken and inputAmount : V2 constructs both the token permission and requested transfer from those fields. The multi-swap entry point constructs a batch permission for its ERC-20 inputs.

The permit includes a nonce, deadline and signature. Its nonce must be unused and its deadline must not have passed; a successful transaction consumes the nonce. This one-use authorization is separate from Permit2's standing AllowanceTransfer permissions. Using or expiring the signature doesn't erase the underlying ERC-20 allowance to Permit2.

Worked example: Two spender allowances

Hypothetical inputs: requested swap input = 482 token units; allowance to the relevant Router V2 deployment = 312 token units; allowance to the selected Permit2 contract = 697 token units. All amounts concern the same wallet, token and network. Assume a standard ERC-20 with sufficient wallet balance and no unrelated transfer restrictions.

The direct swap path has an allowance shortfall of 482 - 312 = 170 token units, so its input transfer can't proceed with that allowance. The separate 697-unit Permit2 allowance doesn't reduce this shortfall because it authorizes a different spender.

For swapPermit2 , 697 units covers the requested 482-unit transfer. That path also needs a valid signature authorizing the relevant Router V2 spender for this token and the exact 482-unit amount, with an unused nonce and an unexpired deadline. Meeting those authorization conditions doesn't guarantee the swap completes: route execution and output checks must also pass. Increasing the router allowance changes the direct-path shortfall; changing the Permit2 allowance doesn't.


Input amounts and transfer destinations

The allowance limit and swap input amount are separate values. V2's direct ERC-20 approval helpers interpret a zero input amount as the caller's full balance of that token. swapMultiPermit2 also resolves zero ERC-20 input amounts to their full balances before constructing the batch permit. The single-token swapPermit2 passes inputAmount unchanged, so zero isn't a universal full-balance instruction across V2 entry points. The selected spender still needs permission for the resolved transfer amount.

For ERC-20 inputs, the input receiver is the transfer destination and can differ from the approved spender: V2 uses the supplied inputReceiver for a single swap or each input's receiver for a multi-swap. In compact calls, a zero input receiver resolves to the executor. Output recipients are separate; a zero output receiver in those compact calls resolves to the caller.

Native-coin inputs use msg.value and don't require an ERC-20 allowance. The payable swapMultiPermit2 path handles native value separately from its ERC-20 batch permit.

Illustration: Input amounts and transfer destinations (Odosswap token approvals)

View image file


Reducing permissions after the shutdown

Token allowances are on-chain state, so closing a hosted service doesn't automatically revoke them. For a standard ERC-20, approve(spender, 0) clears the selected spender's allowance at that token contract on that network. It doesn't move a balance or reverse a completed swap.

Removing the allowance granted to Router V2 leaves the separate allowance granted to Permit2 unchanged. Clearing the token allowance to Permit2 also affects other integrations using that Permit2 instance for the same owner and token on that network. The owner can invalidate selected Permit2 signature nonces without changing the token allowance.