# Universal Adapter

*This contract provides a single entry-point for atomic swaps, deposits and redemptions.*

### State Variables

#### \_isConfigured

Indicates if the contract was configured.

```solidity
bool internal _isConfigured;
```

#### isPaused

Indicates whether the smart contract is paused or not.

```solidity
bool public isPaused;
```

#### feesCollector

The address of the fees collector.

```solidity
address public feesCollector;
```

#### uniswapRouterAddress

The address of the Uniswap router.

```solidity
address public uniswapRouterAddress;
```

#### vaultReferenceAsset

The reference asset of each whitelisted vault, in the form (vault address => reference asset)

```solidity
mapping(address => address) public vaultReferenceAsset;
```

#### origins

The whitelisted referrers, in the form (origin code => info)

```solidity
mapping(bytes32 => OriginEntry) public origins;
```

#### swapFees

The swap fee of each vault, in the form (vault address => swap fee)

```solidity
mapping(address => uint256) public swapFees;
```

#### whitelistedTokens

The list of whitelisted tokens

```solidity
mapping(address => bool) public whitelistedTokens;
```

#### whitelistedRouters

The list of whitelisted routers for atomic swaps

```solidity
mapping(address => bool) public whitelistedRouters;
```

### Functions

#### constructor

```solidity
constructor();
```

#### ifConfigured

*Throws if the contract was not configured*

```solidity
modifier ifConfigured();
```

#### ifNotConfigured

*Throws if the contract was configured already*

```solidity
modifier ifNotConfigured();
```

#### ifNotPaused

*Throws if the contract is not paused*

```solidity
modifier ifNotPaused();
```

#### ifPaused

*Throws if the contract is paused*

```solidity
modifier ifPaused();
```

#### ifVaultEnabled

*Throws if the vault specified is not enabled*

```solidity
modifier ifVaultEnabled(address vaultAddr);
```

#### configure

Configures the smart contract.

*Throws if the contract was already configured.*

```solidity
function configure(address ownerAddr, address newFeesCollectorAddr) external nonReentrant onlyOwner ifNotConfigured;
```

**Parameters**

| Name                   | Type      | Description                          |
| ---------------------- | --------- | ------------------------------------ |
| `ownerAddr`            | `address` | The new owner of the smart contract. |
| `newFeesCollectorAddr` | `address` | The address of the fees collector.   |

#### setUniswapRouterAddress

Sets the address of the Uniswap router

*Passing the zero address disables the Uniswap router*

```solidity
function setUniswapRouterAddress(address newUniswapRouterAddress)
    external
    nonReentrant
    onlyOwner
    ifConfigured
    ifNotPaused;
```

**Parameters**

| Name                      | Type      | Description                       |
| ------------------------- | --------- | --------------------------------- |
| `newUniswapRouterAddress` | `address` | The address of the Uniswap router |

#### pause

Pauses the smart contract.

```solidity
function pause() external nonReentrant onlyOwner ifConfigured ifNotPaused;
```

#### unPause

Resumes (unpauses) the smart contract.

```solidity
function unPause() external nonReentrant onlyOwner ifConfigured ifPaused;
```

#### discontinue

Discontinues the use of this smart contract.

*The contract is no longer usable after calling this function.*

```solidity
function discontinue() external nonReentrant onlyOwner ifConfigured ifNotPaused;
```

#### enableVaults

Enables the vaults specified.

```solidity
function enableVaults(address[] calldata vaultAddresses, uint256[] calldata newSwapFees)
    external
    nonReentrant
    onlyOwner
    ifConfigured
    ifNotPaused;
```

**Parameters**

| Name             | Type        | Description                            |
| ---------------- | ----------- | -------------------------------------- |
| `vaultAddresses` | `address[]` | The list of vaults to enable.          |
| `newSwapFees`    | `uint256[]` | The swap fee applicable to each vault. |

#### disableVaults

Disables the vaults specified.

```solidity
function disableVaults(address[] calldata vaultAddresses) external nonReentrant onlyOwner ifConfigured ifNotPaused;
```

**Parameters**

| Name             | Type        | Description                    |
| ---------------- | ----------- | ------------------------------ |
| `vaultAddresses` | `address[]` | The list of vaults to disable. |

#### setSwapFee

Sets the swap fee of the vault specified.

```solidity
function setSwapFee(address vaultAddr, uint256 fee) external nonReentrant onlyOwner ifConfigured ifNotPaused;
```

**Parameters**

| Name        | Type      | Description                                                    |
| ----------- | --------- | -------------------------------------------------------------- |
| `vaultAddr` | `address` | The address of the ERC-4626 vault.                             |
| `fee`       | `uint256` | The fee applicable to swaps, expressed in bps. It can be zero. |

#### updateFeesCollector

Updates the address of the fees collector.

```solidity
function updateFeesCollector(address newFeesCollectorAddr) external nonReentrant onlyOwner ifConfigured ifNotPaused;
```

**Parameters**

| Name                   | Type      | Description                            |
| ---------------------- | --------- | -------------------------------------- |
| `newFeesCollectorAddr` | `address` | The address of the new fees collector. |

#### enableSwapInputTokens

Allows the tokens specified to be used during an atomic swap.

*This function prevents the fee collector and origin collectors from receiving unauthorized tokens.*

```solidity
function enableSwapInputTokens(address[] calldata tokenAddresses)
    external
    nonReentrant
    onlyOwner
    ifConfigured
    ifNotPaused;
```

**Parameters**

| Name             | Type        | Description                                                           |
| ---------------- | ----------- | --------------------------------------------------------------------- |
| `tokenAddresses` | `address[]` | The list of tokens to enable. These tokens can be used during a swap. |

#### disableSwapInputTokens

Prevents the tokens specified to be used during an atomic swap.

```solidity
function disableSwapInputTokens(address[] calldata tokenAddresses)
    external
    nonReentrant
    onlyOwner
    ifConfigured
    ifNotPaused;
```

**Parameters**

| Name             | Type        | Description                                                               |
| ---------------- | ----------- | ------------------------------------------------------------------------- |
| `tokenAddresses` | `address[]` | The list of tokens to disable. These tokens cannot be used during a swap. |

#### enableRouter

Enables the router address specified.

*Throws if you pass the address of the Uniswap router.*

```solidity
function enableRouter(address routerAddr) external nonReentrant onlyOwner ifConfigured ifNotPaused;
```

**Parameters**

| Name         | Type      | Description                |
| ------------ | --------- | -------------------------- |
| `routerAddr` | `address` | The address of the router. |

#### disableRouter

Disables the router address specified.

*This function allows you to disable a router.*

```solidity
function disableRouter(address routerAddr) external nonReentrant onlyOwner ifConfigured ifNotPaused;
```

**Parameters**

| Name         | Type      | Description            |
| ------------ | --------- | ---------------------- |
| `routerAddr` | `address` | The router to disable. |

#### addOrigin

Enables a new referrer.

*Reverts if the referrer already exists.*

```solidity
function addOrigin(bytes32 originCode, uint256 originFee, address originFeeCollector)
    external
    nonReentrant
    onlyOwner
    ifConfigured
    ifNotPaused;
```

**Parameters**

| Name                 | Type      | Description                                                      |
| -------------------- | --------- | ---------------------------------------------------------------- |
| `originCode`         | `bytes32` | The code of the referrer.                                        |
| `originFee`          | `uint256` | The fee taken by the referrer, expressed in bps. It can be zero. |
| `originFeeCollector` | `address` | The fee collector of the referrer.                               |

#### updateOrigin

Updates the settings of the referrer specified.

*Reverts if the referrer does not exist.*

```solidity
function updateOrigin(bytes32 originCode, uint256 originFee, address originFeeCollector)
    external
    nonReentrant
    onlyOwner
    ifConfigured
    ifNotPaused;
```

**Parameters**

| Name                 | Type      | Description                                                      |
| -------------------- | --------- | ---------------------------------------------------------------- |
| `originCode`         | `bytes32` | The code of the referrer.                                        |
| `originFee`          | `uint256` | The fee taken by the referrer, expressed in bps. It can be zero. |
| `originFeeCollector` | `address` | The fee collector of the referrer.                               |

#### revokeOrigin

Disables the referrer specified.

```solidity
function revokeOrigin(bytes32 originCode) external nonReentrant onlyOwner ifConfigured ifNotPaused;
```

**Parameters**

| Name         | Type      | Description               |
| ------------ | --------- | ------------------------- |
| `originCode` | `bytes32` | The code of the referrer. |

#### swapAndDeposit

Swaps the tokens specified via Uniswap V3 and deposits the resulting outcome in a given vault.

*This overload runs the swap via Uniswap V3.*

```solidity
function swapAndDeposit(bytes32 originCode, address vaultAddr, address receiverAddr, SingleHopItem[] calldata swaps)
    external
    nonReentrant
    ifConfigured
    ifNotPaused
    returns (uint256 shares, uint256 swapAmountOut);
```

**Parameters**

| Name           | Type              | Description                                                                         |
| -------------- | ----------------- | ----------------------------------------------------------------------------------- |
| `originCode`   | `bytes32`         | The code of the referrer, if any. Pass zero bytes32 if there is no referrer at all. |
| `vaultAddr`    | `address`         | The address of the ERC-4626 vault.                                                  |
| `receiverAddr` | `address`         | The address of the receiver. This address receives the LP tokens.                   |
| `swaps`        | `SingleHopItem[]` | The list of atomic swaps to perform.                                                |

**Returns**

| Name            | Type      | Description                                                                                               |
| --------------- | --------- | --------------------------------------------------------------------------------------------------------- |
| `shares`        | `uint256` | The number of shares acquired.                                                                            |
| `swapAmountOut` | `uint256` | The amount of reference assets swapped via Uniswap V3. Any applicable fees are deducted from this amount. |

#### swapAndDeposit

Swaps the tokens specified through a whitelisted router and deposits the resulting outcome in a given vault.

*This overload runs the swap through an abstract call.*

```solidity
function swapAndDeposit(
    bytes32 originCode,
    address vaultAddr,
    address receiverAddr,
    address tokenApprovalAddr,
    address routerAddr,
    OffchainSwapInfo[] calldata items
) external nonReentrant ifConfigured ifNotPaused returns (uint256 shares, uint256 swapAmountOut);
```

**Parameters**

| Name                | Type                 | Description                                                                         |
| ------------------- | -------------------- | ----------------------------------------------------------------------------------- |
| `originCode`        | `bytes32`            | The code of the referrer, if any. Pass zero bytes32 if there is no referrer at all. |
| `vaultAddr`         | `address`            | The address of the ERC-4626 vault.                                                  |
| `receiverAddr`      | `address`            | The address of the receiver. This address receives the LP tokens.                   |
| `tokenApprovalAddr` | `address`            | The address of the token approver.                                                  |
| `routerAddr`        | `address`            | The address of the router capable of running the atomic swap.                       |
| `items`             | `OffchainSwapInfo[]` | The swaps to perform.                                                               |

**Returns**

| Name            | Type      | Description                                                                                                                     |
| --------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `shares`        | `uint256` | The number of shares acquired.                                                                                                  |
| `swapAmountOut` | `uint256` | The amount of reference assets swapped through the abstract calls specified. Any applicable fees are deducted from this amount. |

#### deposit

Deposits the reference asset in the vault specified.

*Origin fees may apply, depending on the origin. The swap fee is not applicable.*

```solidity
function deposit(bytes32 originCode, uint256 depositAmount, address vaultAddr, address receiverAddr)
    external
    nonReentrant
    ifConfigured
    ifNotPaused
    returns (uint256 shares);
```

**Parameters**

| Name            | Type      | Description                                                                         |
| --------------- | --------- | ----------------------------------------------------------------------------------- |
| `originCode`    | `bytes32` | The code of the referrer, if any. Pass zero bytes32 if there is no referrer at all. |
| `depositAmount` | `uint256` | The deposit amount.                                                                 |
| `vaultAddr`     | `address` | The address of the ERC-4626 vault.                                                  |
| `receiverAddr`  | `address` | The address of the receiver. This address receives the LP tokens.                   |

**Returns**

| Name     | Type      | Description                    |
| -------- | --------- | ------------------------------ |
| `shares` | `uint256` | The number of shares acquired. |

#### requestRedeem

Requests a redemption from the vault specified.

```solidity
function requestRedeem(uint256 shares, address receiverAddr, address holderAddr, address vaultAddr, bytes32 originCode)
    external
    nonReentrant
    ifConfigured
    ifNotPaused
    ifVaultEnabled(vaultAddr)
    returns (uint256 assets, uint256 claimableEpoch);
```

**Parameters**

| Name           | Type      | Description                                                                         |
| -------------- | --------- | ----------------------------------------------------------------------------------- |
| `shares`       | `uint256` | The number of shares to redeem.                                                     |
| `receiverAddr` | `address` | The address of the receiver.                                                        |
| `holderAddr`   | `address` | The address of the tokens holder.                                                   |
| `vaultAddr`    | `address` | The address of the ERC-4626 vault.                                                  |
| `originCode`   | `bytes32` | The code of the referrer, if any. Pass zero bytes32 if there is no referrer at all. |

**Returns**

| Name             | Type      | Description                                                                       |
| ---------------- | --------- | --------------------------------------------------------------------------------- |
| `assets`         | `uint256` | The amount of assets that can be claimed for this specific withdrawal request.    |
| `claimableEpoch` | `uint256` | The date at which the assets become claimable. This is expressed as a Unix epoch. |

#### claim

Allows any public address to process the scheduled withdrawal requests of the receiver specified.

*Throws if the receiving address is not the legitimate address you registered via "requestRedeem()"*

```solidity
function claim(uint256 year, uint256 month, uint256 day, address receiverAddr, address vaultAddr, bytes32 originCode)
    external
    nonReentrant
    ifConfigured
    ifNotPaused
    ifVaultEnabled(vaultAddr)
    returns (uint256 shares, uint256 assets);
```

**Parameters**

| Name           | Type      | Description                                                                         |
| -------------- | --------- | ----------------------------------------------------------------------------------- |
| `year`         | `uint256` | The year component of the claim. It can be a past date.                             |
| `month`        | `uint256` | The month component of the claim. It can be a past date.                            |
| `day`          | `uint256` | The day component of the claim. It can be a past date.                              |
| `receiverAddr` | `address` | The address of the legitimate receiver of the funds.                                |
| `vaultAddr`    | `address` | The address of the ERC-4626 vault.                                                  |
| `originCode`   | `bytes32` | The code of the referrer, if any. Pass zero bytes32 if there is no referrer at all. |

**Returns**

| Name     | Type      | Description                                                                            |
| -------- | --------- | -------------------------------------------------------------------------------------- |
| `shares` | `uint256` | uint256 The effective number of shares (LP tokens) that were burnt from the vault.     |
| `assets` | `uint256` | uint256 The effective amount of reference assets that were transfered to the receiver. |

#### instantRedeem

Redeems the number of shares specified, instantly.

```solidity
function instantRedeem(uint256 shares, address receiverAddr, address vaultAddr, bytes32 originCode)
    external
    nonReentrant
    ifConfigured
    ifNotPaused
    ifVaultEnabled(vaultAddr);
```

**Parameters**

| Name           | Type      | Description                                                                         |
| -------------- | --------- | ----------------------------------------------------------------------------------- |
| `shares`       | `uint256` | The number of shares to redeem.                                                     |
| `receiverAddr` | `address` | The address of the receiver.                                                        |
| `vaultAddr`    | `address` | The address of the ERC-4626 vault.                                                  |
| `originCode`   | `bytes32` | The code of the referrer, if any. Pass zero bytes32 if there is no referrer at all. |

#### getOrigin

Gets the details of the referrer specified.

```solidity
function getOrigin(bytes32 originCode) external view returns (uint256 originFee, address originFeeCollector);
```

**Parameters**

| Name         | Type      | Description               |
| ------------ | --------- | ------------------------- |
| `originCode` | `bytes32` | The code of the referrer. |

**Returns**

| Name                 | Type      | Description                                      |
| -------------------- | --------- | ------------------------------------------------ |
| `originFee`          | `uint256` | The fee taken by the referrer, expressed in bps. |
| `originFeeCollector` | `address` | The fee collector of the referrer.               |

#### \_deposit

*Applies origin fees and deposits the reference asset in the vault*

```solidity
function _deposit(
    bytes32 originCode,
    uint256 depositAmount,
    address vaultAddr,
    address underlyingAssetAddr,
    address receiverAddr
) private returns (uint256 shares);
```

#### \_applyOriginFees

*Applies origin fees. The fee is applied if -and only if- the origin code is valid.*

```solidity
function _applyOriginFees(uint256 consumableAmount, bytes32 originCode, address vaultAddr, address underlyingAssetAddr)
    private
    returns (uint256 newBalance);
```

#### \_applySwapFees

*Applies the respective swap fee*

```solidity
function _applySwapFees(uint256 consumableAmount, address underlyingAssetAddr, address vaultAddr)
    private
    returns (uint256 newBalance);
```

#### \_swapViaUniswapV3

*Runs a swap via Uniswap V3*

```solidity
function _swapViaUniswapV3(SingleHopItem[] calldata items, address underlyingAssetAddr) private;
```

#### \_swapViaOffchainCall

*Runs a swap based on the off-chain quote specified*

```solidity
function _swapViaOffchainCall(
    address underlyingAssetAddr,
    address tokenApprovalAddr,
    address routerAddr,
    OffchainSwapInfo[] calldata items
) private;
```

### Events

#### ContractPaused

```solidity
event ContractPaused();
```

#### ContractResumed

```solidity
event ContractResumed();
```

#### ContractDiscontinued

```solidity
event ContractDiscontinued();
```

#### ContractConfigured

```solidity
event ContractConfigured();
```

#### TokenEnabled

```solidity
event TokenEnabled(address indexed tokenAddr);
```

#### TokenDisabled

```solidity
event TokenDisabled(address indexed tokenAddr);
```

#### VaultEnabled

```solidity
event VaultEnabled(address indexed vaultAddr, uint256 newSwapFee);
```

#### VaultDisabled

```solidity
event VaultDisabled(address indexed vaultAddr);
```

#### FeesCollectorUpdated

```solidity
event FeesCollectorUpdated(address newFeesCollectorAddr);
```

#### SwapFeeUpdated

```solidity
event SwapFeeUpdated(address indexed vaultAddr, uint256 fee);
```

#### SwapFeeApplied

```solidity
event SwapFeeApplied(
    address indexed vaultAddr, address indexed referenceAssetAddr, uint256 consumableAmount, uint256 feeAmount
);
```

#### Deposit

```solidity
event Deposit(
    address indexed vaultAddr,
    address referenceAssetAddr,
    uint256 effectiveDepositAmount,
    uint256 shares,
    bytes32 originCode
);
```

#### OriginFeeApplied

```solidity
event OriginFeeApplied(
    address indexed vaultAddr,
    address indexed referenceAssetAddr,
    uint256 consumableAmount,
    uint256 feeAmount,
    bytes32 indexed originCode
);
```

#### RedemptionRequested

```solidity
event RedemptionRequested(
    uint256 shares,
    address receiverAddr,
    address holderAddr,
    address indexed vaultAddr,
    bytes32 indexed originCode,
    uint256 assets,
    uint256 claimableEpoch
);
```

#### RedemptionClaimed

```solidity
event RedemptionClaimed(
    uint256 year,
    uint256 month,
    uint256 day,
    address receiverAddr,
    address indexed vaultAddr,
    bytes32 indexed originCode,
    uint256 shares,
    uint256 assets
);
```

#### InstantRedeption

```solidity
event InstantRedeption(uint256 shares, address receiverAddr, address indexed vaultAddr, bytes32 indexed originCode);
```

#### OriginAdded

```solidity
event OriginAdded(bytes32 indexed originCode, uint256 originFee, address originFeeCollector);
```

#### OriginUpdated

```solidity
event OriginUpdated(bytes32 indexed originCode, uint256 originFee, address originFeeCollector);
```

#### OriginRevoked

```solidity
event OriginRevoked(bytes32 indexed originCode);
```

### Errors

#### InvalidOrigin

```solidity
error InvalidOrigin();
```

#### OriginAlreadyExists

```solidity
error OriginAlreadyExists();
```

#### RouterNotSet

```solidity
error RouterNotSet();
```

#### InvalidRouter

```solidity
error InvalidRouter();
```

#### InvalidTokenApprovalAddress

```solidity
error InvalidTokenApprovalAddress();
```

#### InvalidVault

```solidity
error InvalidVault();
```

#### UnsupportedVault

```solidity
error UnsupportedVault();
```

#### InvalidFeeCollector

```solidity
error InvalidFeeCollector();
```

#### FeeCollectorNotSet

```solidity
error FeeCollectorNotSet();
```

#### VaultTokenNotAllowed

```solidity
error VaultTokenNotAllowed();
```

#### InvalidFee

```solidity
error InvalidFee();
```

#### InvalidToken

```solidity
error InvalidToken();
```

#### LengthMismatch

```solidity
error LengthMismatch();
```

#### AddressRequired

```solidity
error AddressRequired();
```

#### ContractIsPaused

```solidity
error ContractIsPaused();
```

#### ContractNotPaused

```solidity
error ContractNotPaused();
```

#### InvalidReceiver

```solidity
error InvalidReceiver();
```

#### SwapFailed

```solidity
error SwapFailed(bytes returnData);
```

#### SwapFailedNoReason

```solidity
error SwapFailedNoReason();
```

#### TokenNotWhitelisted

```solidity
error TokenNotWhitelisted();
```

#### SlippageCheckFailed

```solidity
error SlippageCheckFailed();
```

#### OriginFeeTooHigh

```solidity
error OriginFeeTooHigh();
```

#### SwapFeeTooHigh

```solidity
error SwapFeeTooHigh();
```

#### NotConfigured

```solidity
error NotConfigured();
```

#### AlreadyConfigured

```solidity
error AlreadyConfigured();
```

#### AmountTooLow

```solidity
error AmountTooLow();
```

### Structs

#### OriginEntry

```solidity
struct OriginEntry {
    uint256 originFee;
    address originFeeCollector;
}
```

#### SingleHopItem

```solidity
struct SingleHopItem {
    uint256 amountIn;
    uint256 minAmountOut;
    address tokenIn;
    uint24 fee;
    uint160 sqrtPriceLimitX96;
}
```

#### OffchainSwapInfo

```solidity
struct OffchainSwapInfo {
    uint256 amountIn;
    uint256 minAmountOut;
    address tokenIn;
    bytes payload;
}
```


---

# 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://docs.upshift.finance/developer-docs/universal-adapter.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.
