# VaultRouter

### High-Level Overview

The `VaultRouter` contract serves as an intermediary for interacting with the `WrappedDollarVault`. It facilitates deposits, withdrawals, and other operations by abstracting the complexities of approvals and token swaps. The router ensures that arbitrary tokens can be used as input, while the vault operates exclusively with USD-denominated ERC4626 tokens.

The router is tightly integrated with the `WrappedDollarVault` and requires registration via the `setRouter()` function in the vault. Only registered routers can interact with the vault, ensuring controlled access and preventing unauthorized operations.

The router implementation used by the investment vault aims to swap bUSD0 to yield bearing token when depositing into the vault and swap back to bUSD0 when withdrawing from the vault.

### Contract Summary

\
The contract provides the following main functions:

* **deposit**: Swaps arbitrary tokens for the vault's underlying asset and deposits them into the vault.
* **withdraw**: Withdraws assets from the vault and swaps them for arbitrary tokens.
* **depositWithPermit**: Allows gasless approval of tokens and deposits them into the vault.
* **withdrawWithPermit**: Allows gasless approval of tokens and withdraw them from the vault.

Inherited Contracts

* **ReentrancyGuard**: Prevents reentrancy attacks in critical functions.
* **Pausable**: Enables emergency halt of contract operations.

### Functionality Breakdown

#### 1. Access Control and Security

* **Router Registration**: The router must be registered with the vault via the `setRouter()` function. This ensures only authorized routers can interact with the vault.
* **Reentrancy Protection**: All critical functions are protected against reentrancy attacks using the `nonReentrant` modifier.

#### 2. Token Swapping

* **Arbitrary Token Support**: The router integrates with external decentralized exchanges (DEXs) to swap arbitrary tokens for the vault's underlying asset. However in the current implementation we use paraswap.
* **Permit Support**: Enables gasless approvals for tokens using the `permit` function, reducing friction for users.

#### 3. Deposit and Withdrawal

* **Deposit**: Users can deposit bUSD0 or SUSDS tokens into the vault by swapping them for the vault underlying asset. The router handles the swap and deposit process seamlessly.
* **Withdraw**: Users can withdraw assets from the vault and swap them for bUSD0 tokens. The router ensures the correct amount of tokens is returned after fees.

#### 4. Upgradability and Maintenance

* **Modular Design**: The router is designed to work with any `WrappedDollarVault` vault, allowing flexibility for future upgrades.
* **VaultRouter**: The contract can be paused and a new router can be setup in the Vault. this allow for easy upgrade.

### Security Analysis

**Method: Deposit**

Swaps bUSD0 or USDS tokens for the vault's underlying asset and deposits them into the vault. This function ensures that users can interact with the vault using arbitrary tokens, abstracting the complexity of token swaps.

{% code lineNumbers="true" %}

```solidity
function deposit(
        IParaSwapAugustus augustus,
        IERC20 tokenIn,
        uint256 amountIn,
        uint256 minTokensToReceive,
        uint256 minSharesToReceive,
        address receiver,
        bytes calldata swapData
    )
        public
        payable
        whenNotPaused
        nonReentrant
        returns (uint256 sharesReceived)
    {
        if (tokenIn != USD0PP && tokenIn != SUSDS) {
            revert InvalidInputToken(address(tokenIn));
        }
        if (receiver == address(0)) {
            revert NullAddress();
        }
        uint256 tokensAmount = _convertToTokens(
            augustus, tokenIn, amountIn, minTokensToReceive, swapData
        );

        sharesReceived = VAULT.deposit(tokensAmount, receiver);
        if (sharesReceived < minSharesToReceive) {
            revert InsufficientSharesReceived();
        }
        emit Deposit(receiver, address(tokenIn), amountIn, sharesReceived);
        return sharesReceived;
    }
```

{% endcode %}

**Description**

The `deposit` function allows users to deposit an ERC20 token into the vault by first swapping it for the vault's underlying asset using ParaSwap. The swapped assets are then deposited into the vault, and the user receives vault shares in return. This function ensures that users can interact with the vault using arbitrary tokens, abstracting the complexity of token swaps. The function is protected by a `nonReentrant` modifier to prevent reentrancy attacks during the swap and deposit process. It returns the number of vault shares minted and sent to the `receiver`.

**16-21 Input Validation**:

* Ensures `augustus`, `tokenIn`, and `receiver` are valid addresses.
* Ensures `amountIn` is greater than zero to prevent invalid deposits.

**22-23 Swap Execution**:

* Interacts with ParaSwap to swap `tokenIn` for the vault's underlying asset using the provided `swapData`.
* Ensures the received tokens meet or exceed `minTokensToReceive`, reverting if the condition is not met to protect users from unfavorable swaps.

**26-29 Deposit Execution**:

* Deposits the swapped assets into the vault on behalf of the `receiver`.
* Ensures the resulting vault shares meet or exceed `minSharesToReceive`, reverting if the condition is not met to protect users from unfavorable deposits.

**30 Event Emission**:

* Emits a `Deposit` event with details of the operation, including the `receiver`, `tokenIn`, `amountIn`, and `sharesReceived`.

***

**Method: depositWithPermit**

Executes a permit before depositing it into the vault.

{% code lineNumbers="true" %}

```solidity
     function depositWithPermit(
        IParaSwapAugustus augustus,
        IERC20 tokenIn,
        uint256 amountIn,
        uint256 minTokensToReceive,
        uint256 minSharesToReceive,
        address receiver,
        bytes calldata swapData,
        PermitParams calldata permitParams
    )
        public
        whenNotPaused
        returns (uint256 sharesReceived)
    {
        try ERC20Permit(address(tokenIn)).permit(
            _msgSender(),
            address(this),
            permitParams.value,
            permitParams.deadline,
            permitParams.v,
            permitParams.r,
            permitParams.s
        ) { } catch { } // solhint-disable-line no-empty-blocks

        return deposit(
            augustus,
            tokenIn,
            amountIn,
            minTokensToReceive,
            minSharesToReceive,
            receiver,
            swapData
        );
    }

```

{% endcode %}

**15-23 Permit Execution**:

* Uses the provided `permitParams` to approve the router for spending `tokenIn` without requiring a separate transaction.

**25-32 Deposit Execution**:

* Deposits the swapped assets into the vault.
* Ensures the resulting shares meet or exceed `minSharesToReceive`.

***

#### Method: withdraw

Withdraws assets from the vault and converts them to bUSD0.

{% code lineNumbers="true" %}

```solidity
  function withdraw(
        IParaSwapAugustus augustus,
        uint256 assets,
        uint256 minUSD0ppToReceive,
        address receiver,
        bytes calldata swapData
    )
        public
        whenNotPaused
        nonReentrant
        returns (uint256 amountUSD0pp)
    {
        if (receiver == address(0)) {
            revert NullAddress();
        }

        VAULT.withdraw(assets, address(this), _msgSender());

        amountUSD0pp = _convertTokensToUSD0pp(
            augustus, assets, minUSD0ppToReceive, swapData
        );

        USD0PP.safeTransfer(receiver, amountUSD0pp);
        emit Withdraw(receiver, assets, amountUSD0pp);
        return amountUSD0pp;
    }
```

{% endcode %}

**Description**

The `withdraw` function allows users to withdraw assets from the vault and convert them to bUSD0  using ParaSwap. The withdrawn assets are swapped for bUSD0 and the resulting amount are sent to the specified receiver. It returns the amount of USD0PP received by the `receiver`.

**13-15 Input Validation**:

* Ensures `receiver` is a valid addresses.

**17 Withdrawal Execution**:

* Withdraws the specified `assets` from the vault.

**19-20 Swap Execution**:

* Interacts with ParaSwap to swap the withdrawn assets for bUSD0.
* Ensures the received bUSD0 meets or exceeds `minUSD0ppToReceive`.

**24 Event Emission**:

* Emits a `Withdraw` event with details of the operation.

***

#### Method: withdrawWithPermit

Executes a permit and withdraws assets from the vault, converting them to bUSD0.

{% code lineNumbers="true" %}

```solidity
function withdrawWithPermit(
    IParaSwapAugustus augustus,
    uint256 assets,
    uint256 minUSD0ppToReceive,
    address receiver,
    bytes calldata swapData,
    PermitParams calldata permitParams
) external returns (uint256 amountUSD0pp){
     try ERC20Permit(address(VAULT)).permit(
            _msgSender(),
            address(this),
            permitParams.value,
            permitParams.deadline,
            permitParams.v,
            permitParams.r,
            permitParams.s
        ) { } catch { } // solhint-disable-line no-empty-blocks

        return
            withdraw(augustus, assets, minUSD0ppToReceive, receiver, swapData);
    } 
```

{% endcode %}

**9-17 Permit Execution**:

* Uses the provided `permitParams` to approve the router for spending vault shares without requiring a separate transaction.

**19-20 Withdraw Execution**

* Call the vault's withdraw function


---

# 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://tech.usual.money/smart-contracts/token-contracts/usual-usd0++-investment-vault/vaultrouter.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.
