# Routing

The Router can aggregate operations across ERC4626 protocol vaults, the Principal Token contract and the associated pools (e.g PT-IBT Curve Pools). This gives users access highly-flexible and personalised transactions.

The Router is inspired from the [Uniswap UniversalRouter](https://docs.uniswap.org/contracts/universal-router/technical-reference).

## How commands work ? <a href="#functions" id="functions"></a>

All transactions to the [`Router`](/technical-reference/contract-functions/router.md)  go through the `execute` functions:

* `execute(bytes calldata commands, bytes[] calldata inputs, uint256 deadline)`
* `execute(bytes calldata commands, bytes[] calldata inputs)`

The first of these functions checks for a deadline parameter. If the `block.timestamp` is after the `deadline` provided the transaction will revert. After that check, the 2 functions otherwise execute identically.

The `execute` functions takes a list of commands , and a list of encoded inputs for each command and execute them in the order specified.

## Available Commands <a href="#command-structure" id="command-structure"></a>

The flexible commands allow users to:

* Add liquidity in the Curve pools
* Remove liquidity from the Curve pools
* Deposit in Principal Tokens
* Deposit in Interest Bearing Tokens
* Wrap vault in ERC-4626 Wrapper
* Redeem from Principal Tokens
* Redeem from Interest Bearing tokens
* Unwrap vault from ERC-4626 Wrapper
* Transfer ERC-20 tokens from Router to any address
* Transfer ERC-20 tokens from `msg.sender` to Router
* Transfer ERC-20 tokens from `msg.sender` to Router with ERC-2612 permit. Compatible with [ERC-4626 IBTs](/glossary.md#ibt), [PTs](/technical-reference/contract-functions/principal-token.md) and [YTs](/technical-reference/contract-functions/yield-token.md).

The list of all the commands along with the accepted parameters can be found in the [Router guide](/technical-reference/contract-functions/router.md#dispatcher).

## Some Useful Routes

### Add liquidity

#### Add liquidity  with assets

This route exclusively uses underlying tokens as input and carries out all necessary deposits and computations to deposit in the PT-IBT pool at the current spot price of the pool, maintaining the same ratios.

**The steps involve:**

1. [**TRANSFER\_FROM**](/technical-reference/contract-functions/router.md#transfer_from-command): Transfer the underlying tokens from the depositor's wallet to the Router.
2. [**DEPOSIT\_ASSET\_IN\_IBT**](/technical-reference/contract-functions/router.md#deposit_asset_in_ibt-command): Deposit all underlying tokens in the specified ERC4626 IBT contract to receive IBT shares.
3. [**CURVE\_SPLIT\_IBT\_LIQUIDITY**](/technical-reference/contract-functions/router.md#curve_split_ibt_liquidity-command): From the pool's balances, divide the liquidity between the IBT to be added to the pool and the IBT to be deposited in the Principal Token contract in exchange for PT and YT shares. Send the minted YT shares to the user.
4. [**CURVE\_ADD\_LIQUIDITY**](/technical-reference/contract-functions/router.md#curve_add_liquidity-command): Add IBT and PT liquidity to the Curve Pool. Send the Curve LP token to the user.

**Example of how to use the router commands to create transactions in Solidity:**

```solidity
import {Commands} from "src/router/Commands.sol";
import {Constants} from "src/router/Constants.sol";

/* 
    ... 
*/

commands = abi.encodePacked(
    bytes1(uint8(Commands.TRANSFER_FROM)),
    bytes1(uint8(Commands.DEPOSIT_ASSET_IN_IBT)),
    bytes1(uint8(Commands.CURVE_SPLIT_IBT_LIQUIDITY)),
    bytes1(uint8(Commands.CURVE_ADD_LIQUIDITY))
);
inputs = new bytes[](4);
inputs[0] = abi.encode(underlying, assets);
inputs[1] = abi.encode(ibt, Constants.CONTRACT_BALANCE, Constants.ADDRESS_THIS);
inputs[2] = abi.encode(
    curvePool,
    Constants.CONTRACT_BALANCE,
    Constants.ADDRESS_THIS,
    receiver
);
inputs[3] = abi.encode(
    curvePool,
    [Constants.CONTRACT_BALANCE, Constants.CONTRACT_BALANCE],
    minMintAmount,
    receiver
);
router.execute(commands, inputs)
```

#### Add liquidity  with IBTs

This route directly takes IBT shares as input and performs all necessary deposits and computations to deposit in the PT-IBT pool at the current spot price of the pool, maintaining the same ratios.

**The steps involve:**

1. [**TRANSFER\_FROM**](/technical-reference/contract-functions/router.md#transfer_from-command): Transfer the IBTs from the depositor's wallet to the Router.
2. [**CURVE\_SPLIT\_IBT\_LIQUIDITY**](/technical-reference/contract-functions/router.md#curve_split_ibt_liquidity-command): From the pool's balances, divide the liquidity between the IBT to add to the pool and the IBT to deposit in the Principal Token contract in exchange for PT and YT shares. Send the minted YT shares to the user.
3. [**CURVE\_ADD\_LIQUIDITY**](/technical-reference/contract-functions/router.md#curve_add_liquidity-command): Add IBT and PT liquidity to the Curve Pool. Send the Curve LP token to the user.

### Remove liquidity

#### Remove liquidity for assets

This route withdraws liquidity from Curve, returning the redeemed underlying assets to the user.

**The steps involve:**

1. [**TRANSFER\_FROM**](/technical-reference/contract-functions/router.md#transfer_from-command): Transfer Curve LP tokens from the user's balance to the Router.
2. [**TRANSFER\_FROM**](/technical-reference/contract-functions/router.md#transfer_from-command): Transfer the required amount of YT tokens to the Router. This step is necessary only before expiry, as after expiry, redeeming shares from the PT contract does not require the user to burn the YT.

{% hint style="info" %}
This step is needed before expiry only as after expiry redeeming shares from the PT contract doesn't require the user to burn the YT.
{% endhint %}

3. [**CURVE\_REMOVE\_LIQUIDITY**](/technical-reference/contract-functions/router.md#curve_remove_liquidity-command): Remove liquidity from Curve to retrieve IBT and PT.
4. [**REDEEM\_PT\_FOR\_ASSET**](/technical-reference/contract-functions/router.md#redeem_pt_for_asset-command): Redeem the PT and YT shares from the PT and send assets to the user.
5. [**REDEEM\_IBT\_FOR\_ASSET**](/technical-reference/contract-functions/router.md#redeem_ibt_for_asset-command): Redeem the IBT shares from the IBT and send assets to the user.
6. [**TRANSFER**](/technical-reference/contract-functions/router.md#transfer-command): Transfer any remaining PTs or YTs if not all PTs and YTs were burnt during the redemption process.

#### Remove liquidity for IBTs

This route withdraws liquidity from Curve, returning the IBTs to the user.

**The steps involve:**

1. [**TRANSFER\_FROM**](/technical-reference/contract-functions/router.md#transfer_from-command): Transfer Curve LP tokens from the user's balance to the Router.
2. [**TRANSFER\_FROM**](/technical-reference/contract-functions/router.md#transfer_from-command): Transfer the required amount of YT tokens to the Router. This step is necessary only before expiry, as after expiry, redeeming shares from the PT contract does not require the user to burn the YT.

{% hint style="info" %}
This step is needed before expiry only as after expiry redeeming shares from the PT contract doesn't require the user to burn the YT.
{% endhint %}

3. [**CURVE\_REMOVE\_LIQUIDITY**](/technical-reference/contract-functions/router.md#curve_remove_liquidity-command): Remove liquidity from Curve to retrieve IBT and PT.
4. [**REDEEM\_PT\_FOR\_IBT**](/technical-reference/contract-functions/router.md#redeem_pt_for_ibt-command): Redeem the PT and YT shares from the PT and send IBTs to the user.
5. [**TRANSFER**](/technical-reference/contract-functions/router.md#transfer-command): Transfer any remaining PTs or YTs if not all PTs and YTs were burnt during the redemption process.

### Exchange your Yield Tokens

#### Exchange IBT for YT

This route is used to exchange IBTs for YTs and involves a flash loan of IBT from the Principal Token contract to borrow IBTs.

**The steps involve:**

1. [**FLASH\_LOAN**](/technical-reference/contract-functions/router.md#flash_loan-command): Perform the flash loan in the PT. The flashloan borrower being the Router that will execute the commands an inputs specified in the flash loan. The flashloan hence involves another nested router execution:
   1. [**DEPOSIT\_IBT\_IN\_PT**](/technical-reference/contract-functions/router.md#deposit_ibt_in_pt-command): Deposit the borrowed IBT in the PT contract
   2. [**CURVE\_SWAP**](/technical-reference/contract-functions/router.md#curve_swap-command): Swap the received PT from the deposit for IBTs

{% hint style="info" %}
Note that the Router's [`onFlashLoan`](/technical-reference/contract-functions/router.md#onflashloan) function is responsible for calling back to execute upon receiving flash loan funds. This function is also tasked with returning the borrowed amount along with the flash loan fees, using a `safeTransferFrom` from the caller's balance.
{% endhint %}

2. [**TRANSFER**](/technical-reference/contract-functions/router.md#transfer-command): Transfer all the YTs to the user

#### Exchange YT for IBT

This route is used to exchange YTs for IBTs and involves a flash loan of IBT from the Principal Token contract to borrow IBTs.

**The steps involve:**

1. [**FLASH\_LOAN**](/technical-reference/contract-functions/router.md#flash_loan-command): Perform the flash loan in the PT. The flashloan borrower being the Router that will execute the commands an inputs specified in the flash loan. The flashloan hence involves another nested router execution:
   1. [**CURVE\_SWAP**](/technical-reference/contract-functions/router.md#curve_swap-command): Swap the IBT  for PTs to get the same amount of PT than YTs to be able to redeem.
   2. [**TRANSFER\_FROM**](/technical-reference/contract-functions/router.md#transfer_from-command): Transfer the YTs fro the users balance to the router
   3. [**REDEEM\_PT\_FOR\_IBT**](/technical-reference/contract-functions/router.md#redeem_pt_for_ibt-command): Redeem PT and YTs for IBTs

{% hint style="info" %}
Note that the Router's `onFlashLoan` function is responsible for calling back to execute upon receiving flash loan funds. This function is also tasked with returning the borrowed amount along with the flash loan fees, using a `safeTransferFrom` from the caller's balance.
{% endhint %}

2. [**TRANSFER**](/technical-reference/contract-functions/router.md#transfer-command): Transfer all the IBTs to the user

## Previewing execution

Router also includes a preview functionnality, where a sequence of commands, along with encoded imputs can be simulated to preview the resulting rate, i.e. the amount of output token obtained at the end of execution for each wei of input token spent at the start of execution (multiplied by 1 ray unit).

* `function previewRate( bytes calldata _commands, bytes[] calldata _inputs ) external view returns (uint256)`
* `function previewSpotRate( bytes calldata _commands, bytes[] calldata _inputs ) external view returns (uint256)`

For ease of use, these functions take similar parameters than the `execute()` function.

{% hint style="warning" %}
Though `previewRate` and `previewSpotRate` mirror input parameters of `execute()`, some commands are not supported for preview. See the [Router guide](/technical-reference/contract-functions/router.md#previewrate) for more details.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.spectra.finance/guides/routing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
