# On-Chain Integration for Flexible Term Vault (V4)

## Getting Started

To integrate to a loan vault contract, you can start by viewing the contract source code on Etherscan, which will provide you the contract source code, a list of functions and their descriptions, as well as all of the libraries, interfaces, factories, and controllers.&#x20;

{% hint style="info" %}
Flexible Term Vaults implement the [OpenZeppelin ERC-1967 Upgradeable Beacon Proxy ](https://docs.openzeppelin.com/contracts/4.x/api/proxy#UpgradeableBeacon)Pattern.&#x20;
{% endhint %}

## Important Links

[View the Proxy Contract Source Code](https://etherscan.io/address/0x0f8CbdC544dC1D4Bd1bDafE0039Be07B825aF82A#code)

[Read as Proxy, ](https://etherscan.io/address/0x0f8CbdC544dC1D4Bd1bDafE0039Be07B825aF82A#readProxyContract)including all the read functions

[Write as Proxy,](https://etherscan.io/address/0x0f8CbdC544dC1D4Bd1bDafE0039Be07B825aF82A#writeProxyContract) including all the write functions&#x20;

[View the Implementation Contract Source Code](https://etherscan.io/address/0xea8ae2cb0c379d2847a5a8c27a7ce8cbe46fd0d4#code), including the source code, interfaces, factories, controllers, and libraries

[Flexible Term USD Vault Product Documentation](broken://spaces/vTyVj8bFfTwNzXbKANlO/pages/Nv4JjvdJ1EsMjERVbtsl)

#### Using Etherscan to View Documentation

{% embed url="<https://scribehow.com/shared/View_Contract_Documentation_and_Source_Code_on_Etherscan__SYxNTX5vQG2DmB_cOHfNAw>" %}

## Important Functions&#x20;

As a Lender, there are only a handful of functions you will ever need to call.  They are to&#x20;

1. Make Investments
2. Request Withdrawals
3. Read contract data&#x20;

These three are covered in more detail below. There are quite a number more in detailed in the full code, libraries, and interfaces on Etherscan but we present the most important below.&#x20;

{% hint style="info" %}
Flexible Term Vaults implement the [ERC-1967 Beacon Proxy Pattern](https://eips.ethereum.org/EIPS/eip-1967). The only implementation contract you will interact with as a Lender is the PoolFlex contract.&#x20;
{% endhint %}

### Terminology

OpenTrade implements many of the  ERC-4626 and ERC-20 standards. In some cases, the terminology we use in the product is different from those in the code. They are primarily

| Term in Code | Display Name |
| ------------ | ------------ |
| Pool         | Vault        |
| Shares       | Vault Tokens |
| Assets       | USDC, EURC   |

### Key Data Fields and their Decimals / Formatting

<table><thead><tr><th width="230">Field</th><th width="108">Decimals</th><th width="232">Example in Code</th><th>Example in Display</th></tr></thead><tbody><tr><td>assets </td><td>6</td><td>1000000</td><td>1 USDC/EURC</td></tr><tr><td>shares</td><td>6</td><td>1000000</td><td>1 Vault Token</td></tr><tr><td>exchangeRate</td><td>18</td><td>1000261149376738066</td><td>1.000261</td></tr><tr><td>interestRate</td><td>2</td><td>500</td><td>5.00%</td></tr></tbody></table>

## 1. Make Investments

{% hint style="info" %}
The prerequisites for making an investment on mainnet are:

1\) to have been [onboarded](broken://spaces/vTyVj8bFfTwNzXbKANlO/pages/iWbibEbF5McM9bGXq1sw#onboarding-steps) to OpenTrade&#x20;

2\) to have had your [supported digital asset wallet](broken://spaces/vTyVj8bFfTwNzXbKANlO/pages/oJyj5q4GQuE5tahKYx9L) whitelisted and&#x20;

3\) to have have enough ETH in the wallet to pay for gas.&#x20;
{% endhint %}

To make an investment, you must first call the function to create a spending allowance. This is the amount the the caller is authorising the pool contract to spend.&#x20;

```solidity
function approve(address spender, uint256 amount) external returns (bool)
```

...where amount is the number of assets you'd like to approve to be deposited and address is the wallet address of the lender. It will return a boolean, true if the request succesful, false if the request failed.&#x20;

Once the allowance is approved, you will then need to call the function

```solidity
   function deposit(
        uint256 assets,
        address lender
    ) external returns (uint256 shares, uint256 transferInDayTimestamp);
```

where assets is the number of assets you'd like to deposit and lender is the wallet address of the lender making the deposit.&#x20;

To see a demo of this working in action, you can visit our product documentation [here](broken://spaces/vTyVj8bFfTwNzXbKANlO/pages/saAZszpP98Vm1exMZSxU#video-demonstration).

## 2. Request Withdrawals

There is only a single function for creating a withdrawal request. After calling this function successfully, the liquidity asset (USDC, EURC) will be send back to your wallet directly from the vault.&#x20;

To make a withdrawal request, you must call the following function...

```solidity
 function requestRedeem(uint256 shares) external returns (uint256 assets);
```

...where shares is the number of vault tokens you wish to be redeemed. It will return the withdrawal request amount in assets.&#x20;

#### Demo of Making a Withdrawal Request

To view a live example of making a withdrawal request, you can view our product documentation [here](broken://spaces/vTyVj8bFfTwNzXbKANlO/pages/XAc36kjia07WypKmTOqy#video-demonstration-making-an-early-withdrawal-request).

### Previewing Requests

#### Preview Redeem Request

To simulate the result of a withdrawal request at the current block and see how many assets would be withdrawn for a given number of vault tokens (i.e. shares), you can call the following function...

```solidity
 function previewRedeemRequest(
        uint256 shares
    ) external view returns (uint256 assets);
```

It will returns the amount of assets that would be requested if this entire redeem request were to be processed at the current block.  Note: This is equivalent of EIP-4626  *previewRedeem.*&#x20;

#### Preview Withdrawal Request

To simulate the result of a withdrawal request at the current block and see how many vault tokens (i.e. shares)  would be burned if this entire withdrawal request were to be processed at the current block,  you can call the following function...

```solidity
 function previewWithdrawRequest(
        uint256 assets
    ) external view returns (uint256 shares);
```

It will returns the amount of shares that would be burned if this entire withdrawRequest were to be processed at the current block.  Note: This is equivalent of EIP-4626 *previewWithdraw.*&#x20;

### Convert to Assets

To see the get the value of a certain number of vault tokens as converted to liquidity assets (USDC, EURC), you can call the following function for a specified number of assets and it will return the number of shares.

```solidity
    function convertToShares(
        uint256 assets
    ) external view returns (uint256 shares);
```

### Convert to Shares

To see the value of a certain number of assets (USDC, EURC) converted to vault tokens  (i.e. shares), you can call the following function for a specified number of assets and it will return the number of shares.

```solidity
 function convertToAssets(
        uint256 shares
    ) external view returns (uint256 assets);
```

## 3. Reading Contract Data

As a Lender, all of the important information regarding the vault can be called back from the contract.

{% hint style="info" %}
When you call any read function from typescript using popular Ethereum libraries like ethers.js or web3.js, it will return a full list of fields available from the contract ABI.&#x20;
{% endhint %}

### Get Pool Overview State

#### To get the current state of the pool, you can call the function

```solidity
  function getPoolOverview()
        external
        view
        returns (IPoolOverviewStateFlex memory);
```

and it will return the Pool Overview data in the following structure

```solidity
struct IPoolOverviewStateFlex {
    address poolAddr; // the contract address for the pool
    uint256 interestRate; // the current interest rate in bps e.g. 500 = 5.00%
    uint256 dailyInterestRate; // the interest rate earned for a single day
    uint256 totalPrincipalEarningInterest; // the total amount of principal earning interest
    uint256 totalInterestAccrued; // total interest accrued to date
    uint256 totalAssetsDeposited; // total assets deposited to date
    uint256 totalAssetsWithdrawn; // total assets withdrawn to date
    uint256 exchangeRate; // the current share to assets exchange rate
    uint256 totalSupply; // the total number of shares outstanding
    uint256 totalRequestedShares; // the total number of withdrawals outstanding, denominated in shares
    uint256 totalRequestedAssets; // the total number of withdrawals outstanding, denominated in assets
    uint256 totalAssetsTransitioningIn; // the total number of pending deposits, denominate in assets
    uint256 totalSharesTransitioningIn; // the total number of pending deposits, denominated in shares
    uint256 totalAssetsDueForWithdraws; // the total amount of assets due for withdrawal
    uint256 totalFees; // total fees accrued to date
    uint256 feesOutstanding; // total fees remaining unpaid
    uint64[] nonBusinessDays; // a list of non-business days
    uint8 state; // current status of the pool
    uint256 lastDayAccrued; // the last day the accrual occured
```

### Get Pool Configuration

To get the current parameters and configuration of the pool, you can call...

```solidity
function getPoolConfiguration()
        external
        view
        returns (IPoolConfigurationStateFlex memory);
```

and it will return the following data&#x20;

```solidity
struct IPoolConfigurationStateFlex {
    address poolAddr; // the contract address of the pool
    uint256 dailyOriginationFeeRate; // the daily fee rate
    uint256 originationFee; // the annualised fee
    uint256 closeOfDepositTime; // the Advance Cut-Off Time
    uint256 closeOfWithdrawTime; // the Withdrawal Cut-Off Time
    uint256 transferInDays; // the Advance Processing Time
    uint256 transferOutDays; // the Withdrawal Processing Time
    address liquidityAssetAddr;// the contract address of the pool asset (eg. USDC/EURC)
    address poolAdminAddr; // the wallet address of the Pool Admin
    address poolControllerAddr; // the contract address of the pool controll contract
    address withdrawControllerAddr; // the address of the withdraw controller contract
    address borrowerVaultAddr; // the contract address of the borrower vault
    string name; // the name of the pool
    string symbol; // the pool token symbol
    address borrowerManagerAddr; // the wallet address of the borrower manager 
    address borrowerWalletAddr; // the wallet address of the borrower
    uint256 maxCapacity; // the maximum outstanding loan principal for the pool
    uint64[] nonBusinessDays; // a list of non-business days
    address businessDayRegistryAddr; // the contract address of the business day registry
```

### Get Account Overview&#x20;

To get data on a specific wallet address ("account"), you can call the following function...

```solidity
    function getPoolAccountState(
        address accountAddr
    ) external view returns (IPoolAccountStateFlex memory)
```

and it will return the following data

```solidity
struct IPoolAccountStateFlex {
    address poolAddr; // the contract address of the pool
    address accountAddr; // the wallet address for the account
    uint256 tokenBalance; // the current balance of vault tokens held by the wallet
    uint256 maxWithdrawRequest; // the maximum withdrawal request the wallet can make, denominated in assets
    uint256 maxRedeemRequest; //the maximum withdrawal request the wallet can make, denominated in shares
    uint256 requestedSharesOf; // outstanding withdrawal requests for the account, in shares
    uint256 requestedAssetsOf; // outstanding withdrawal requests for the account, in assets
    uint256 principalEarningInterest; // current principal earning interest
    uint256 interestAccrued; // interest accrued by the account to date
    uint256 assetsDeposited; // deposits made by the account to date
    uint256 assetsWithdrawn; // withdrawals repaid to the account to date
    uint256 sharesTransitioningIn; // current pending loans for the account, in shares
    uint256 assetsTransitioningIn; // current pending loans for the account, in assets
    uint256 assetsDueForWithdraws; // withdrawal requests due to be repaid to the account, in assets
    uint256 sharesDueForWithdraws; // withdrawal requests due to be repaid to the account, in shares
```

## Typescript Reference Implementation

Below are typescript examples for making deposits and withdrawals from the vault using ethers.js

```typescript

import * as dotenv from 'dotenv'
import { Contract, JsonRpcProvider, Wallet } from 'ethers';



const VAULT_ADDRESS = '0xa66BA7E8Cf3eD414F07c8a9847CE36Ca4fcE38D7'


export const MAINNET_URL = 'https://eth-mainnet.g.alchemy.com/v2/fcK4AEYquRkIgqn0REy8N0uOsiO3kqKI'

export const SANDBOX_URL = 'https://eth-sepolia.g.alchemy.com/v2/oHCT97GjJyLp6TwUMjZdOGPAqDnr9gu6'
const URL = SANDBOX_URL
const FlexVaultABi =
  require('./PoolFlex.json').abi

function init() {
  dotenv.config()
}

// Note the number of shares are at 6 decimals places so 1e6 is 1 share

async function withdrawSharesFlexVault(shares: BigInt) {
  const provider = new JsonRpcProvider(URL)
  const wallet = new Wallet(process.env.PRIVATE_KEY as string, provider)
  const flexVaultContract = new Contract(VAULT_ADDRESS, FlexVaultABi, wallet)


  const tx = await flexVaultContract.requestRedeem(shares)
  console.log('tx', tx)
  const receipt = await tx.wait()
  console.log('receipt', receipt)

}
// Note the assets (USDC or Eurc) are at 6 decimals places so 1e6 is 1 USDC or Eurc
async function withdrawUSDCFlexVault(assets: BigInt) {
  const provider = new JsonRpcProvider(URL)
  const wallet = new Wallet(process.env.PRIVATE_KEY as string, provider)
  const flexVaultContract = new Contract(VAULT_ADDRESS, FlexVaultABi, wallet)
  const shares = await flexVaultContract.convertToShares(assets)

  const tx = await flexVaultContract.requestRedeem(shares)
  console.log('tx', tx)
  const receipt = await tx.wait()
  console.log('receipt', receipt)

}

// Note the assets (USDC or Eurc) are at 6 decimals places so 1e6 is 1 USDC or Eurc
async function depositFlexVault(assets: BigInt) {
  const provider = new JsonRpcProvider(URL)
  const wallet = new Wallet(process.env.PRIVATE_KEY as string, provider)

  const flexVaultContract = new Contract(VAULT_ADDRESS, FlexVaultABi, wallet)


  const tx = await flexVaultContract.deposit(assets, wallet.address)
  console.log('tx', tx)
  const receipt = await tx.wait()
  console.log('receipt', receipt)

}

init()
withdrawUSDCFlexVault(1000000n)
  .then()
  .catch((err: Error) => {
    console.error('err', err)
  })
```


---

# 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://sandboxdocs.opentrade.io/opentrade-sandbox/version-4-integrations/on-chain-integration-for-flexible-term-vault-v4.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.
