# Overview

The Internet Corporate Bond

Copra enables protocol partner to issue **fixed-yield protocol debt** in order to

* Grow TVL
* Leverage own yield

Protocol debt is a novel primitive aiming to be the **future standard of DeFi lending**

> Inspired by the corporate bond asset class, which is how lending commonly happen in TradFi, and is a missing financial primitive in DeFi

It addresses two crucial barriers currently holding back what should have been a much larger DeFi yield-farming space

* Uncertain yields
* Complex risks

Protocol debt offers both **fixed-yield** and **principal-protection** by encapsulating virtually any yield-bearing liquidity pool in DeFi


# How It Works

<figure><img src="https://3251301222-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7IUb6hmEj08b42Hg3Nry%2Fuploads%2FRv3DeT3fUelPWPjbLXrU%2FScreenshot%202024-07-22%20at%2022.32.07.png?alt=media&amp;token=40269778-3a75-4390-bc79-b338b66a8695" alt=""><figcaption></figcaption></figure>

1. Copra **opens a vault** with certain parameters for protocol partners, **integrating with one or more of their liquidity pools**
2. The vault will be **loaded with buffer funds from insurers** where the first insurer will be the protocol partner itself (that’s how they leverage their own yield)
3. This setup allows **lenders to get fixed-yield and some principal-protection** through vault accounting
4. The vault runs through virtual **30-days tenor** to allow for term updates and **perpetually rolls-over**
5. **Liquidation mechanism** further protects lenders by **securing the deployed funds back to the vault** when certain thresholds are breached


# For Protocols

Issue Fixed-Yield Protocol Debt to Support Growth and Revenue

## Use Cases

### Grow TVL

Protocols often have volatile yields and complex strategies hence hard to attract TVL, having to resort to token emission that attracts mercenary capitals.

With Copra, depositors can instead get fixed-yield and principal-protection, helping protocols accumulate TVL effectively.

### Leverage Own Yield Strategies

Many protocols are confident in their own yield strategies (as they understand them best) and deploy their treasury capital to generate income.

Copra helps protocols do that in a scalable way by earning the spread between fixed-cost debt and the yield generated.

### Alleviate Liquidity Bottlenecks

Some protocols intrinsically have pools lacking in liquidity which can act as bottlenecks to overall protocol growth. Liquidity raised through protocol debt could be used to relieve these specific bottlenecks.

### Reduce Reliance on Token Emission

Compared to token-based liquidity mining which mainly attracts mercenary capitals that will exploit the token reward and leave immediately once it's exhausted, raising liquidity via fixed-yield Copra vault is an efficient and sustainable alternative to promote protocol growth.


# For Lenders

Get Fixed-Yield and Principal-Protection via Protocol Debt

## Value Propositions

### Fixed-Yield

Enjoy the certainty of fixed-yield via Copra vault, instead of the uncertainty of floating-performance-based yield when depositing directly into underlying pools.

### Principal-protected

Lending via Copra vault is principal-protected via insurance buffer that is posted upfront by insurers. This insurance buffer covers against risks such as drawdown risks and liquidity risks. This reduces the need of having to heavily assess and manage the risk of underlying pools, providing comfort and convenience to lenders.

### Fully Secured On-Chain

Unlike un(der)collateralized lending where lender funds is moved off-chain, funds lent to Copra vaults is fully secured on-chain. Copra vault contracts are only integrated with the whitelisted underlying pools, hence can only deploy funds to those pool contracts.

### Liquidation Monitoring

Certain thresholds related to NAV (net asset value) are monitored in real-time. Breach on any of those thresholds will trigger liquidation mechanism, which is withdrawal of funds from all underlying whitelisted pools back to the vault contract in order to protect lenders from any loss.


# Technical

Technical Specifications

## Overview

<figure><img src="https://3251301222-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7IUb6hmEj08b42Hg3Nry%2Fuploads%2FDufVhGnTvuIOCZLQc7xW%2FScreenshot%202024-03-18%20at%203.14.37%E2%80%AFPM.png?alt=media&amp;token=73beaf63-127a-4f7a-b331-c4f58de98a52" alt=""><figcaption></figcaption></figure>

1. Borrowers and lenders can deposit and withdraw into the `LiquidityWarehouse` contract by calling the relevant functions.
   1. Borrowers can call `depositBorrower` to deposit assets and `withdrawBorrower` to withdraw assets
   2. Lenders can call `depositLender` to deposit assets and `withdrawLender` to withdraw assets.
2. An automated Chainlink Automation contract named `DebtCovenant` monitors the net asset values of both the borrower and lender deposits. This contract can call `deactivate` to deactivate the `LiquidityWarehouse` if the liquidation threshold has been breached as well as `activate` to reactivate the `LiquidityWarehouse` if the liquidation threshold is fulfilled. A full description on how the liquidation threshold is calculated is outlined [here](https://www.notion.so/Tech-Docs-75c06bc77ee54b0389ef6f51b102c995?pvs=21).
3. Assets in the `LiquidityWarehouse` are periodically deployed to the borrower’s smart contracts. These assets are withdrawn to the `LiquidityWarehouse` in two cases namely
   1. When a lender calls `withdrawLender` and there is insufficient liquidity in the `LiquidityWarehouse`
   2. When `deactivate` is called to automatically withdraw all deployed assets from the borrower’s smart contracts.

## Terms

The exact terms of the `LiquidityWarehouse` are stored in the `Terms` struct.

```jsx
 struct Terms {
      /// @notice The asset the loans in the liquidity
      /// warehouse is denominated in
      IERC20 asset;
      /// @notice The address that will receive fees
      address feeRecipient;
      /// @notice The liquidation threshold of the liquidity warehouse
      uint64 liquidationThreshold;
      /// @notice The capacity threshold of the liquidity warehouse
      uint64 capacityThreshold;
      /// @notice The interest rate of the liquidity warehouse
      uint64 interestRate;
      /// @notice The fee taken from compounded interest of the liquidity warehouse
      uint64 interestFee;
      /// @notice The fee taken from withdrawals
      uint64 withdrawalFee;
  }
```

These parameters can be updated by the `DEFAULT_ADMIN` function by calling the [relevant functions](#roles).

## Net Asset Value

The total NAV (Net Asset Value) of a `LiquidityWarehouse` comprises of the NAV of reserve liquidity on the Liquidity Warehouse as well as NAV from funds deployed to Whitelisted Target pools.

$$
totalNAV = reserveNAV + deployedNAV
$$

For accounting purpose, total NAV can also be expressed as summation of lenders NAV and borrowers NAV.

$$
totalNAV = lenderNAV + borrower NAV
$$

To ensure that lenders have seniority over borrower for the fixed interest, lender’s NAV is whichever is larger between total NAV and lenders balance, where lenders balance is the amount *theoretically owed* to the lenders compounded by fixed interest.

$$
lenderNAV = min(totalNAV, lenderBalance)
$$

This also means, to be consistent with the above formula, borrowers NAV is the leftover of total NAV subtracted by the lenders balance with 0 as the floor.

$$
borrowerNAV = max(totalNAV - lenderBalance, 0)
$$

Both lenders NAV and borrowers NAV have corresponding LP tokens representing their share of the NAV. These LP tokens are minted and burned as depositors deposit/withdraw from the `LiquidityWarehouse`. The value of each of these LP tokens is given by dividing their respective total NAV values and the total LP token supply.

$$
lenderLPTokenValue = \frac{lenderNAV}{lenderLPTokenTotalSupply}
$$

$$
borrowerLPTokenValue = \frac{borrowerNAV}{borrowerLPTokenTotalSupply}
$$

#### Calculating Deployed NAV

The deployed net asset value is calculated by iterating through the list of `s_withdrawTargets` and determining the NAV for that target. The logic to calculate the NAV for each target is implemented in the `_getDeployedAssetValue` function of the borrower specific `LiquidityWarehouse` implementation.

```jsx
uint256 deployedNAV;
/// We acknowledge that this may be gas intensive but we do not foresee there 
/// being a high number of withdraw targets
for (uint256 i; i < withdrawTargets.length; ++i) {
    deployedNAV += _getDeployedAssetValue(withdrawTargets[i]);
}
```

The mechanism for updating the list of `s_withdrawTargets` is outlined in the Access Control section below.

## Thresholds

There are two thresholds that relates to the ratio between borrowers NAV and total NAV:

* *Capacity threshold*: prevents deposits by lender and withdrawal by borrower if the resulting ratio between borrowers NAV and total NAV would be below the threshold

$$
\frac{borrowerNAV}{totalNAV} < capacityThreshold
$$

* *Liquidation threshold*: allows for liquidation if the ratio between borrowers NAV and total NAV is below the threshold

$$
\frac{borrowerNAV}{totalNAV} < liquidationThreshold
$$

LiquidationThreshold is enforced to always be lower then capacityThreshold

$$
liquidationThreshold < capacityThreshold
$$

These thresholds can be configured by the contract admin by calling `setLiquidationThreshold` and `setCapacityThreshold`

## Liquidation

A `LiquidityWarehouse` can be deactivated anytime the `liquidationThreshold` is breached by calling `deactivate` and reactivated by calling `activate`. Both of these functions are not access controlled, which means that any address is allowed to call it whenever the correct conditions are met.

The `liquidationThreshold` is considered to be breached whenever the following formula is true

$$
\frac{borrowerNAV}{totalNAV}\<liquidationThreshold
$$

What CAN be done when the `LiquidationWarehouse` is ACTIVE

* Borrowers can deposit and withdraw by calling `depositBorrower` and `withdrawBorrower`
* Lenders can deposit and withdraw by calling `depositLender` and `withdrawLender`
* Interest owed to the lenders continues to compound

What CANNOT be done when the `LiquidationWarehouse` is ACTIVE

* Borrowers cannot withdraw an amount that will breach the `capacityThreshold`
* Addresses cannot call `liquidate` to withdraw all deployed assets from whitelisted targets

What CAN be done when the `LiquidationWarehouse` is ACTIVE

* The contract admin can continue to call `execute` to perform operational tasks

What CANNOT be done when the `LiquidationWarehouse` is INACTIVE

* Borrowers CANNOT deposit by calling `depositBorrower`
* Interest stops accruing
* Permissioned actors CANNOT execute actions by calling `execute`

#### Withdrawing Liquidity

Liquidity deployed to the whitelisted targets can be withdrawn by either

1. Passing in an array of whitelisted targets in the `deactivate` function to deactivate and withdraw in the same transaction.
2. Passing in an array of whitelisted targets in the `liquidate` function. This function exists in case the call to `deactivate` could not withdraw the full deployed amount from all the whitelisted targets.

Internally both of these functions will loop through the list of whitelisted targets and try to withdraw as much liquidity as it can from each of the addresses passed in. The exact mechanism to withdraw funds will be implemented by the borrower specific implementation of the `LiquidityWarehouse` in the `_withdrawFromTarget` function.

#### `DebtCovenant`

In addition to the `LiquidationWarehouse`, Copra will also implement a `DebtCovenant` contract using Chainlink Automation to monitor the `LiquidationWarehouse`'s liquidation ratio and automatically call `activate` or `deactivate` when the liquidation threshold is breached.

Chainlink Automation compatible contracts require that the implementation contract implements a `checkUpkeep` function to check whether or not an action needs to be performed and a `performUpkeep` function to execute the required transactions.

The `checkUpkeep` function will check to see if the liquidation threshold has been breached and determine whether or not a `LiquidityWarehouse` needs to be activated/deactivated. In addition to this it will also determine a list of whitelisted target addresses that the `LiquidityWarehouse` needs to withdraw liquidity from when deactivating.

The `performUpkeep` function will take in the data returned from `checkUpkeep` and call the relevant functions on the `LiquidityWarehouse`.

## Deposits

Lenders and borrowers can both deposit into the `LiquidityWarehouse` to earn a fixed yield on their assets. In order to start the `LiquidityWarehouse` borrowers must first deposit an amount by calling `depositBorrower` to deposit some assets into the `LiquidityWarehouse`. Lenders can then call `depositLender` to deposit assets as long as the ratio between the borrower’s NAV and lender’s NAV is not greater than the `capacityThreshold`.

#### **Example**

* `LiquidityWarehouse` has a `capacityThreshold` of 10%
* Borrower has deposited 10 USDC
* Lender’s can deposit up to a maximum of 90 USDC

<figure><img src="https://3251301222-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7IUb6hmEj08b42Hg3Nry%2Fuploads%2FLBnPO9CcMjBE0TRiQmjM%2FScreenshot%202024-03-18%20at%205.51.45%E2%80%AFPM.png?alt=media&amp;token=f6eba8b7-a850-4d93-80fe-ef92d8f1c4de" alt="" width="375"><figcaption></figcaption></figure>

In return for depositing assets into the `LiquidityWarehouse`, lenders and borrowers are both minted LP tokens that represent their share of their respective balances. These LP tokens both exist within the `LiquidityWarehouse` contract, which implements ERC1155 in order to support multiple tokens. The lender’s LP token is reserved at ID 0 and the borrower’s LP token is reserved at ID 1. The amount of LP tokens minted for both lenders and borrowers are shown below.

$$
mintedLenderLPTokenAmount = \frac{lenderDepositAmount}{lenderLPTokenValue}
$$

$$
mintedBorrowerLPTokenAmount = \frac{borrowerDepositAmount}{borrowerLPTokenValue}
$$

## Withdrawals

Depositors can withdraw from the `LiquidityWarehouse` by either calling `withdrawLender` or `withdrawBorrower` depending on whether they had deposited into the lender or borrower pools. Both of these functions takes in an `amount` parameter, which represents the amount of shares that the depositor wishes to burn in exchange for receiving withdrawn assets. The amount of withdrawable assets are given below.

$$
lenderWithdrawalAmount= amountLenderLPToken \*lenderLPTokenValue
$$

$$
borrowerWithdrawalAmount= amountBorrowerLPToken \*borrowerLPTokenValue
$$

In addition to taking in an `amount` parameter, the withdrawer may also specify a list of `whitelistedTargets` to withdraw assets from whitelisted targets from if the amount of assets in the `LiquidityWarehouse` is not enough to cover the withdrawable amount. The exact mechanism to facilitate withdrawals is left to the borrower specific implementation contract to implement in the `_withdrawFromTarget` function. This function

## Access Control and Operations

The `LiquidityWarehouse` contract can be externally controlled to call functions on another contract particularly for the purpose of deployments (and withdrawals) of funds from the `LiquidityWarehouse` to whitelisted targets.

#### Whitelisting Callers

Callers can be whitelisted to perform certain function calls on specific target addresses by calling the `toggleWhitelist` function, which takes in an array of `LiquidityWarehouseAccessControl.Action` structs.

```jsx
struct Action {
      /// @notice The caller of the action
      address caller;
      /// @notice The target of the action
      address target;
      /// @notice The function that the action
      /// will call
      bytes4 fnSelector;
      /// @notice True if the action is whitelisted
      bool isWhitelisted;
      /// @notice True if this is the withdraw function
      bool isWithdraw;
  }
```

The whitelisted function calls, targets and callers are hashed together using `keccak256` to generate an action ID, which are then mapped to a `boolean` value to represent whether or not the call is whitelisted.

```jsx
 bytes32 actionId = keccak256(abi.encode(target, caller, fnSelector));
 s_whitelistedActions[actionId] = action.isWhitelisted;
```

#### Withdraw Targets

The `LiquidtyWarehouse` needs to keep track of the list of whitelisted target addresses to calculate NAV and to withdraw liquidity from when the liquidity warehouse is deactivated. This list is stored as an `EnumerablAddressSet` in the `s_withdrawTargets` storage variable. Addresses can be added to this set by passing in an `Action` struct with `isWithdraw` and `isWhitelisted` set to true. Conversely the address can be removed from `s_withdrawTargets` by setting `isWithdraw` to true and `isWhitelisted` to false.

#### Execution

Whitelisted callers and the contract’s `DEFAULT_ADMIN` can call `execute` to perform any operational transactions as the `LiquidityWarehouse`. Example operational transactions include

* Calling `approve` on an ERC20 token contract to approve an address to spend the assets in the `LiquidityWarehouse`
* Calling functions on the borrower’s protocol to deploy assets from the `LiquidityWarehouse`

The `execute` function takes in an array of `ExecuteAction` structs

```jsx
struct ExecuteAction {
      /// @notice The target address the action will call
      address target;
      /// @notice The action's calldata
      bytes data;
      /// @notice The amount of wei to send when executing
      /// the action
      uint256 value;
  }
```

For each `ExecuteAction`, the `execute` function will first regenerate an `actionId` using `msg.sender`, `[executeAction.target](<http://executeAction.target>)` and the function signature being called derived from `bytes4(executeAction.data)`. The generated `actionId` will then be compared with the `boolean` entry in `s_whitelistedActions` to determine whether or not the caller has been whitelisted to perform the given action. This step is skipped if the caller is the `DEFAULT_ADMIN`.

## Fees

There are two protocol fees

* *Interest fees*: a percentage of interest amount added to lenders balance, practically implemented by minting appropriate amount of lender LP token to protocol treasury address

$$
interestFees=interestFees%\*(lenderBalanceAfterInterest - lenderBalanceBeforeInterest)
$$

$$
lenderLPTokenMintToTreasury=lenderLPTokenTotalSupply\*interestFees/(lenderBalanceAfterInterest-interestFees)
$$

* *Withdrawal fees*: a percentage of amount withdrawn by lender or borrower, practically implemented by transferring appropriate amount of lender or borrower LP token to protocol treasury address and subtracting withdrawal fees from total withdrawal amount

$$
LPTokenTransferToTreasury = withdrawalFees%\*LPTokenRedeemed
$$

$$
withdrawalAmountAfterFees = withdrawalAmount\*(1-withdrawalFees%)
$$

## Roles

There are two privileged roles

1. `PAUSER_ROLE`: this will be owned by a 2 out of 3 multisig contract, and has the ability to pause (and unpause) the Liquidity Warehouse contract
   1. when the Liquidity Warehouse is paused, both lender and borrower deposit functions i.e `depositLender` and `depositBorrower` cannot be called
2. `DEFAULT_ADMIN_ROLE`: The `DEFAULT_ADMIN` will be able to update the terms of the `LiquidityWarehouse` and interact with the underlying borrower protocol to deploy and withdraw assets. This introduces a degree of centralization risk as a malicious `DEFAULT_ADMIN` will be able to steal user funds. In order to mitigate this risk, all `LiquidityWarehouses` will be owned by a Timelock contract so that there is a delay period before sensitive transactions are executed. A Gnosis Multisig requiring 2 out of 3 signer addresses will be granted the `PROPOSER`, `EXECUTOR` and `CANCELLER` roles on the Timelock contract so that the the multisig can propose, execute or cancel operations

List of functions callable by the `DEFAULT_ADMIN`

| Action                                                                                                                                                                                                                                                                                                                                                                   | Function Name             |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------- |
| Updating the fixed interest rate                                                                                                                                                                                                                                                                                                                                         | `setInterestRate`         |
| Updating the liquidation threshold                                                                                                                                                                                                                                                                                                                                       | `setLiquidationThreshold` |
| Updating the capacity threshold                                                                                                                                                                                                                                                                                                                                          | `setCapacityThreshold`    |
| Updating the interest fee                                                                                                                                                                                                                                                                                                                                                | `setInterestFee`          |
| Updating the withdrawal fee                                                                                                                                                                                                                                                                                                                                              | `setWithdrawalFee`        |
| Updating the fee recipient address                                                                                                                                                                                                                                                                                                                                       | `setFeeRecipient`         |
| Updating the list of whitelisted functions                                                                                                                                                                                                                                                                                                                               | `toggleWhitelist`         |
| Call functions on behalf of the LiquidityWarehouse. Examples of this include deploying assets to borrower protocols and withdrawing. This action is centralized to the `DEFAULT_ADMIN` but is mitigated by the fact that the Liquidity Warehouses will be owned by a Timelock contract so that lenders and borrowers have sufficient time to react to malicious activity | `execute`                 |


# Security Audits

## 1. Sherlock

Security audit report by Sherlock dated 21 March 2024 is attached below.

{% embed url="<https://github.com/sherlock-protocol/sherlock-reports/blob/main/audits/2024.03.21%20-%20Final%20-%20Copra%20Finance%20Audit%20Report.pdf>" %}

## 2. Zokyo

Security audit report by Zokyo dated 23 July 2024 is attached below.

{% file src="/files/fKa4OahlEEHWGzaiAC9j" %}

## 3. Fuzzland

Security audit report by Fuzzland dated 19 September 2024 is attached below

{% embed url="<https://docs.fuzz.land/Copra-Audit-Report-103112096c218034879ff6e24a06b105>" %}

## 4. Hash

Security audit report by Hash dated 1 June 2024 is attached below

{% file src="/files/hf8lvF2k9H8lZLc4GnUm" %}


# Contract Addresses

| Vault                   | Chain    | Contract Address                                                                                                     |
| ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------------- |
| Teahouse USDC           | Arbitrum | [0xbC89bAc7b3697120019D30154102403e846c665b](https://arbiscan.io/address/0xbc89bac7b3697120019d30154102403e846c665b) |
| Teahouse WETH (Retired) | Arbitrum | [0x60059A0fC1AaB2b21561C8845E74Acab740A347F](https://arbiscan.io/address/0x60059a0fc1aab2b21561c8845e74acab740a347f) |
| Teahouse WETH 2         | Arbitrum | [0xa2EA80D2c66CABC50De584a4368F00b4fD487F77](https://arbiscan.io/address/0xa2ea80d2c66cabc50de584a4368f00b4fd487f77) |
| KTX USDC                | Arbitrum | [0xB9c726bC4d9F00da48f3FD77cE30100CfB83648D](https://arbiscan.io/address/0xb9c726bc4d9f00da48f3fd77ce30100cfb83648d) |
| KTX WETH                | Arbitrum | [0x1C047Ff881f9bbCf72C947e6f91eA70c95cd58b0](https://arbiscan.io/address/0x1c047ff881f9bbcf72c947e6f91ea70c95cd58b0) |
| KTX WBTC                | Arbitrum | [0x10179BA515f2a38B72f4fd14De993AFA0c4DC16e](https://arbiscan.io/address/0x10179ba515f2a38b72f4fd14de993afa0c4dc16e) |
| Steadefi WETH (Retired) | Arbitrum | [0xE3a80A636161b6E105180A9b9CB6aD6209eC917e](https://arbiscan.io/address/0xe3a80a636161b6e105180a9b9cb6ad6209ec917e) |
| Steadefi USDC (Retired) | Arbitrum | [0x14c1FC0E04C2ffB82c5A90486e3115801A238d51](https://arbiscan.io/address/0x14c1fc0e04c2ffb82c5a90486e3115801a238d51) |
| Steadefi WBTC (Retired) | Arbitrum | [0x94303996E6ae470a2fe4b03A04f1bCc69C6D6895](https://arbiscan.io/address/0x94303996e6ae470a2fe4b03a04f1bcc69c6d6895) |
| Reserve USDC            | Arbitrum | [0x6A2E561Abd768392E2F5C32C2dfB79bF75840b57](https://arbiscan.io/address/0x6a2e561abd768392e2f5c32c2dfb79bf75840b57) |
| Reserve WETH (Retired)  | Arbitrum | [0xA6c486f9D87Eccc91bac8d597Ad09B5B4344fEAb](https://arbiscan.io/address/0xa6c486f9d87eccc91bac8d597ad09b5b4344feab) |
| Reserve USDC 2          | Arbitrum | [0x9400d0E43EAcfbDb11197cA92D32e7aeE03c1508](https://arbiscan.io/address/0x9400d0e43eacfbdb11197ca92d32e7aee03c1508) |
| Reserve WETH 2          | Arbitrum | [0xAFFAd400997EA9F412Ec793cAb0Ee1adA18776a0](https://arbiscan.io/address/0xaffad400997ea9f412ec793cab0ee1ada18776a0) |
| GammaSwap USDC          | Arbitrum | [0xa2EA80D2c66CABC50De584a4368F00b4fD487F77](https://arbiscan.io/address/0xa2ea80d2c66cabc50de584a4368f00b4fd487f77) |
| GammaSwap WETH          | Arbitrum | [0x9b21818bdeDeeC833ec0CE94600F385337Fa822f](https://arbiscan.io/address/0x9b21818bdedeec833ec0ce94600f385337fa822f) |


# Whitepaper

Whitepaper

{% file src="/files/kaQoH1A7kL76iD1fE83J" %}

Overview Deck

{% embed url="<https://docsend.com/view/ay7ruw69ywb4jr2q>" %}


