# Illuminate - DeFi: Fixed

An introduction to the Illuminate ecosystem.

**TL;DR**

***Illuminate provides institutions and applications optimized routing across all DeFi liquidity in order to capture a maximal fixed APY.***\
\
Most simply described, Illuminate aggregates and wraps principal tokens with similar maturities and underlying assets into one single (meta) principal token (iPTs).

The meta principal token (iPT) is traded on a secondary market YieldSpace AMM to provide access to Illuminate’s optimized yields and enable the scalability all expirable applications – from lend/borrow, aggregation and “Banking” (Maker, Liquity, etc.,) to options + futures.<br>

![](https://lh5.googleusercontent.com/REt9i11H3X_FXG6JKvoUeW25Y8xAHGKmVLI89YVjLO5MuC8uHelLHDGlTA3K7b6puhXlJ2GqwCDKmOhHasi9bAamcn2m66OFCCsSF1h4fbuj856t_jS9jpclJPWQY3zwD3ipuy3E9o94sBNbRUxo1Q)

<img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2Fm1gOhJ3bUHs0RmKHuRZj%2Ffile.excalidraw.svg?alt=media&amp;token=35a595c0-5d52-427b-899c-064f20d45985" alt="" class="gitbook-drawing">

## Fixed-Yields

The fixed-yield space first saw traction in 2020 with Dan Robinson & Allan Niemerg's paper on "[YieldSpace -- An Automated Liquidity Provider for Fixed Yield Tokens](https://yield.is/YieldSpace.pdf)", their YieldSpace concept having since been extended by \~10 protocols.

![](https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FkIzuiqt0e1ZdHx2MmHKV%2Fimage.png?alt=media\&token=53c73b8d-2074-4d72-b5d8-e14848d286b5)

This early research led to significant experimentation with regard to optimizations of the YieldSpace model and enabled a number of different yield origination models so long as they utilize a tradable principal token (PT).

Protocols such as **Swivel** take interest-bearing deposits from across the entirety of the Ethereum (and Layer-2) ecosystem and enable the decomposition of these deposits into their future yield - leaving behind the deposits redemption in the form of a PT.

Protocols such as **Porter & Maple** allow DAOs and institutions to issue collateralized debt through PTs and borrow directly from lenders at a fixed-rate.

And protocols such as **Yield** allow *anyone* to deposit their collateral and mint PTs that they can sell and effectively borrow against at a fixed-rate.

These protocols have seen consistent growth with an overall market that has oscillated between 500m-2b, however even with consistent growth significant issues remain in the current market structure that prevents scalability and the participation of most major cohorts.

<img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2Fm1gOhJ3bUHs0RmKHuRZj%2Ffile.excalidraw.svg?alt=media&amp;token=35a595c0-5d52-427b-899c-064f20d45985" alt="" class="gitbook-drawing">

## Current Issues

Without scalable liquidity or optimized yields, user-facing applications (Yearn, Maker, InstaDapp, etc.), integrators (Contango, FiatDAO, etc.), rate-traders, and large depositors are all unable to participate in the fixed-rate space.

***Inefficient structural design across numerous facets (instrument standardization, IMM dates, liquidity fragmentation, etc.) prevents the deployment of liquidity to any significant degree.***

Specifically, integrators and applications are unable to scale, while DeFi's institutions are faced with the same concerns as recently failed banks (SVB, Credit Suisse) with regard to the exit liquidity available should they themselves experience their own liquidity event.

## Structural Flaws

### Prohibitive Integration

Integrators are currently unable to confidently integrate fixes rates in any form.&#x20;

Whether looking to deposit capital as an aggregator or a new project looking to build around fixed-rate infrastructure, liquidity and market structure remain core issues.

#### **User-Facing Integrations (Defi's "Banks")**

Many protocols (Maker, Yearn, Indexcoop, etc.) effectively act as deposit aggregators with a mandate to optimize yield for their users or organizations.&#x20;

Similar to traditional banks (e.g. SVB & Credit Suisse), this mandate extends to fixed-term instruments (PTs), and in a similar vein, PTs are the most illiquid part of their balance sheets.

***That said, should a user-facing application face their own liquidity crunch, significant market liquidity for PTs is necessary to ensure the effective exit of large positions.***

#### Protocol Integrations

Other protocols (Contango, FiatDAO, Napier, etc.) build around fixed-rates utilizing PTs as part of their core infrastructure.&#x20;

***These applications are currently limited to integration with sole fragmented liquidity sources meaning their own scalability is entirely dependent on unreliable liquidity and suboptimal yields.***

Further, should an application attempt to source their own liquidity across multiple PTs, developer teams are then faced with integrating multiple currencies and tenors for each protocol, a maintenance debt that scales exponentially as liquidity is sourced.

## Native Market Inefficiencies

Without consistent maturity dates, arbitrageurs are unable to interact cross-protocol, and market-makers are unable to remain delta neutral.

Without a system to bridge similar maturity dates, each protocol's liquidity exists in a silo, and unlike new spot DEX/AMMs that can easily attract arbitrageur liquidity, each protocol suffers from the need to bootstrap individually.&#x20;

This fragmentation results in inefficient market pricing, and exacerbates the already insufficient depth for larger market participants.&#x20;

## Poor User Experiences

Retail users are currently faced with the need to compare offerings across a staggering number of protocols, which themselves source yields from a variety of of lending markets.&#x20;

In context of recent market events (Anchor), retail users are faced with the need to conduct due diligence to identify the risks of reach protocol, as well as their integrated/partner lending markets.

These asks are unreasonable of even advanced market participants.

<img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2Fm1gOhJ3bUHs0RmKHuRZj%2Ffile.excalidraw.svg?alt=media&amp;token=35a595c0-5d52-427b-899c-064f20d45985" alt="" class="gitbook-drawing">

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2Frrkqdq1QFxyrQUoUakIV%2Fimage.png?alt=media&amp;token=67b75724-b169-40a7-aedf-7bce1c55de05" alt=""><figcaption></figcaption></figure>

***Illuminate remediates all of the above issues through the creation of an aggregated meta principal token (iPT).***&#x20;

Through this single interface for fixed-yields, we guarantee lenders the best rate in DeFi, developers the best integration and optimized yields, and traders the depth necessary for active participation.

**Lenders:** Lend confidently with access to previously inaccessible liquidity and knowledge that source of their yield is optimal.

**Protocols:**\
&#x20;        **- Aggregators & DAOs:** Deploy scalable capital to fixed-rates without risks surrounding withdrawals and concerns of poor exit liquidity.\
&#x20;        **- DeFi Integrators:** Build scalable integrations utilizing fixed-rate infrastructure with access to both scalable liquidity and an optimized source of yield.

**Traders:** Trade actively across fixed-rate protocols, arbitraging rates and no longer concerned with risks surrounding asynchronous maturities.

<img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2Fm1gOhJ3bUHs0RmKHuRZj%2Ffile.excalidraw.svg?alt=media&amp;token=35a595c0-5d52-427b-899c-064f20d45985" alt="" class="gitbook-drawing">

## Illuminate -- An Ecosystem

Described further in [Integrations](https://docs.illuminate.finance/illuminate-defi-fixed/integrations), the existence of deep fixed rate liquidity enables an ecosystem of products built upon "maturity atomicity", starting with *Illuminated Options*.

### **Maturity Atomicity**

In traditional contexts, instrument composability is relatively restricted by settlement delays and large ticket sizes.&#x20;

However in the context of Defi / atomic transactions, settlement delays are irrelevant and instruments can be created with tight maturity tolerances (preferably atomic), enabling an increasingly rehypothecated and higher yielding financial stack.

Rephrased, developers can create instruments that mature simultaneously and in doing so construct products with a structural composability (and high yield) that is impossible to compete with traditionally.


# iPTs: Meta Principal Tokens

A description of our core mechanism -- iPTs.

The core mechanism behind the Illuminate Protocol is the wrapping of external principal tokens into "meta" principal tokens, Illuminate PTs (iPTs).

![](https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FRPZWKkzScoiYalPXQsLf%2Fimage.png?alt=media\&token=eff6e0f3-1baf-44a5-b535-c7728b70c8e4)

### Minting iPTs (Wrapping PTs)

At any point before maturity approved principal tokens can be wrapped at a 1:1 ratio by Illuminate, returning **iPTs.**

iPTs trade freely on secondary YieldSpace markets and are only minted when external PTs provide arbitrage opportunities.

#### Collateralization

As discussed in [Maturity & Redemption](/illuminate-defi-fixed/maturity-and-redemption), iPTs can only be redeemed once all external principal tokens have themselves matured and been redeemed.

Because all external principal tokens are redeemed by Illuminate before an iPT's maturity date, iPTs  are always collateralized 1:1 by underlying deposits in time for redemption.

### EIP-5095

iPTs are [EIP-5095](https://ethereum-magicians.org/t/eip-5095-principal-token-standard/9259) compliant principal tokens.

This means that they are redeemable at a 1:1 ratio for underlying tokens upon maturity, and follow a standard interface allowing the easy integration of Illuminate into any dApp or wallet.


# Lending

A description of the lending process and involved risks / security considerations.

Due to the pricing dynamics discussed in [Pricing & Arbitrage](/illuminate-defi-fixed/pricing-and-arbitrage), lenders can be confident that iPTs provide the largest discount and therefore best rate on the market.

### Lending (Purchasing iPTs)

In order to "lend", applications purchase iPTs from secondary markets to capture their discount. Once purchased, lenders hold iPTs and wait until maturity for redemption.

Once maturity is reached, lenders can either redeem manually or optionally utilize an automatic redemption process enabled by our implementation of [EIP-5095](https://ethereum-magicians.org/t/eip-5095-principal-token-standard/9259).

This makes lending as simple as purchasing an iPT and... thats it!

### Optimized Routing

While iPTs should in nearly all cases provide the largest discount, off-chain applications can optimize further and utilize the Illuminate API (IlluminAPI).

The IlluminAPI provides a granular response as to the optimal rate and if purchasing iPTs directly is suboptimal, Illuminate provides convenience lending methods for the purchase and wrapping of external PTs.

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FBVKgupX2phutYx2LtlOO%2FIlluminate%20Slide%209.jpeg?alt=media&amp;token=6760e6a7-ae74-4c3d-bc5e-d6807b4b9f68" alt=""><figcaption></figcaption></figure>

<img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2Fm1gOhJ3bUHs0RmKHuRZj%2Ffile.excalidraw.svg?alt=media&amp;token=35a595c0-5d52-427b-899c-064f20d45985" alt="" class="gitbook-drawing">

## Risks

Like most, Illuminate shares some core risks that come with our integrated DeFi protocols.

These include:\
&#x20;     \- Smart Contract Bugs + Reviewer Oversight\
&#x20;     \- Oracle Liveliness\
&#x20;     \- Liquidator Liveliness

Should any of our external integrations face a shortfall event, iPTs may then become partially collateralized.

This may either reduce yields or lead to negative yields in the case of significant external protocol losses.

### Audits

We work to reduce these risks through diligent audits alongside Code4rena and Sherlock (TBD).

For a report of our first audit with code4rena, check out the official report, and our blog post review:\
Code4rena Audit: [Link](https://code4rena.com/contests/2022-06-illuminate-contest)\
Code4rena Review:&#x20;

Sherlock Audit 1: [Link](https://app.sherlock.xyz/audits/contests/12)\
Sherlock Audit 2: [Link](https://app.sherlock.xyz/audits/contests/35)

As a disclaimer, audits should not be considered an advertisement of safety, and are only a single indicator of the safety of a protocol.

### Insurance

We also provide insurance through our safety module (Information TBD) and a baseline coverage of up to $10,000,000 through our partnership with Sherlock (TBD).

### Bug Bounty

Through our partner Immunefi, we offer up to a $500,000 bug bounty for the report of severe vulnerabilities.&#x20;

A record of previously public payouts:

<https://swivel.substack.com/p/swivilian-report-initial-audit-finding>


# Maturity & Redemption

A description of the redemption and coordination process for external principal tokens.

## Redeeming External Principal Tokens

As external principal tokens (e.g. Swivel, Element, Yield, etc.,) mature, Illuminate redeems each owned external principal token, ensuring a 1:1 collateralization of all iPTs.

This redemption is an asynchronous process performed by keepers, and as each external principal token matures, underlying tokens are returned to Illuminate for users to later redeem.

![External PT -> USDC -> Illuminate Vault | Pre-iPT maturity](https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FM4Mv1lAL3DezcF824Cxv%2Fredemption-2-01.png?alt=media\&token=43f73f0a-dac9-4237-9fd2-abd38cbfc038)

With this process we ensure the fungibility of iPTs and accommodate external principal tokens regardless of their maturity choice.

## Maturity Choice

With external principal tokens redeemed and iPTs fully collateralized, the iPT redemption process can begin.&#x20;

In order to ensure maximal liquidity, Illuminate attempts to integrate all PTs within a reasonable (2-3 week) range, and iPT maturities are aligned with the last maturing external PT.

*E.g. In the example above, Element's PT matures last, on Sep 30th. Therefore, Illuminate's iPT matures on Sep 30th as well.*

## Redeeming iPTs

Given our integration of [EIP-5095](https://github.com/ethereum/EIPs/pull/5095) for our iPTs there are multiple routes for redemption.

#### Direct Illuminate Redemption

Once maturity has hit, users can redeem their iPTs through our Redeemer. This is the most gas efficient method, iPTs are burnt, and lenders are returned 1:1 amounts of underlying.

#### EIP-5095 Redemption

Developers / Integrators may find it easier to redeem through the methods available on the iPT itself.&#x20;

This alternate method of redemption allows lenders to redeem their iPTs through solely the iPT interface.

This ensures secondary markets do not need to interact with the core Illuminate codebase, and redemption to third party wallets or other applications can be seamless.

#### Automated Redemption

With our custom EIP-5095 implementation, users can approve third-party redemption of their iPTs.

Through this functionality, users can enable automatic redemptions handled by third-party keepers through Illuminate's Redeemer.


# Integrations

An integration demonstration alongside our initial integration partners

***Any integrations pictured are to be taken as examples. We cannot confirm / deny any ongoing partnerships and/or integrations.***

### Expirable Futures

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FU6JQKpjArtUZps4o6RLH%2Fimage.png?alt=media&amp;token=a1e7219d-945a-4790-9dbf-c2f9ee00237a" alt=""><figcaption><p>Utilizing iPTs as core lending within a futures contract</p></figcaption></figure>


# YieldSpace AMM

A description of the liquidity provision mechanisms behind Illuminate

### Secondary Markets

In order to provide easy on-chain access to what integrators can be confident is the *best rate,* an on-chain secondary market for iPTs is necessary.

In order to provide liquid secondary markets for Illuminate's iPTs, we've partnered with [Yield Protocol](https://yieldprotocol.com/) to utilize their upcoming variant of the YieldSpace AMM design.

### Pricing Theta

The YieldSpace design is a variant of the traditional $$x\*y=k$$ AMM, with an additional a modifier applied in between trades that ensures the price of a PT increases as time passes.

This constantly increasing price ensures that even in the absence of trades, the PTs themselves can trade at a consistent rate. Though the price of the PT may change, the rate itself remains consistent.

![](https://lh4.googleusercontent.com/Ld-ZTD_69tnCFoazeKWgMbIBFKqxqWUy2vMVnM4ZW5Qm3weXMwUoXtvkmlsszeF_oU6J4ekIXO7svkfsd5vwyTe25EPLThrRJOrZJUozOcQ6ZuEsy21UcfFkVRL5T0WlCGtYLtDr185NW8V9ASKw)

## Choosing A YieldSpace Variant

After significant due diligence, we concluded that the Yield Protocol YieldSpace implementation was both the most gas efficient and simple integration offered on the market.&#x20;

Element Protocol's YieldSpace implementation is then largely a direct implementation of YieldSpace, but in the Balancer ecosystem.

While Sense Protocol has innovated on YieldSpace with the SenseSpace AMM that accrues interest to the underlying asset while providing liquidity.

That said, YieldSpace is able to emulate the benefits of SenseSpace with minimal external or internal improvements that are likely to be implemented by Yield Protocol themselves.

With this context, the unique benefits of each are largely:

**YieldSpace:** Gas Efficient, Simple Integration

**SenseSpace:** Balancer Ecosystem Access

**Element's YieldSpace:** None? (Feel free to correct us!)


# Pricing & Arbitrage

A description of the optimized pricing and iPT pegging mechanism

## Enforcing Pricing through Arbitrage

In the example below, Swivel has recently received a large sell order for PTs, which has pushed the Swivel PT price down to 0.93.

Because iPTs are trading at 0.95, an arbitrageur can purchase Swivel's PT, wrap them into iPTs, and immediately sell them on a secondary market for an easy profit.

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FqNFopkU960jCSWTzPXcX%2FScreen%20Shot%202022-09-06%20at%2012.22.08%20PM.png?alt=media&amp;token=9a5b746f-ecfc-4779-9d75-a9ca0150ab11" alt=""><figcaption><p>Arbitrageur purchasing Swivel PTs -> Wrapping iPTs -> Selling iPT for profit</p></figcaption></figure>

This arbitrage has multiple impacts on both the market structure of Illuminate, as well as the market structure of our integrated external PTs.

#### Optimized On-Chain Lending

First and foremost, this natural arbitrage ensures iPTs trade at or below par with the lowest priced external PT on the market.

In the context of lending this ensures the largest discount for iPT purchasers and therefore the best rate and lending experience.

#### Increased External PT Depth & Volume

With the addition of iPT markets, each external PT has access to increased depth through the additional liquidity provided by the iPT arbitrage process.

Further, in the process of arbitraging an external PT with iPTs, each external protocols garner increased volume alongside any price divergence.&#x20;


# Smart Contracts


# Lender

### User Flow

The Lender contract can be used by calling the `lend` method on any principal. The contract overloads the `lend` operation for all principals, and principals that have matching signatures can use the `p` (principal) parameter to distinguish which principal they would like to execute the loan on.

To execute a `lend` operation, the Lender will transfer an user's underlying asset to the Lender contract alongside a specified maturity (`m`), amount (`a`) and any additional data that the principal requires to execute the loan (e.g. pool information)

Within each `lend` operation, the Lender contract will extract a fee and lend the rest of the capital on the appropriate principal. The Lender contract will maintain custody of the principal token. To track the user's outstanding position, an ERC-5095 token for that market will be minted and sent to the user.

### Motivation

The primary purpose of the Lender contract is to facilitate lending at the best rates aggregated among the available interest rate swap protocols in DeFi. At a high level, users should be able to bring an asset and lend it out over some period of time and get the best fixed rate on their lent capital.

This is made possible by the `markets` mapping, which brings together multiple maturities for different lending markets. For example, USDC may be lent on Pendle, Swivel and Tempus, and have slightly different maturities (e.g. June 28, June 29, and June 30 respectively). Illuminate combines these three lending markets into one, and allows users to gain access to the best possible rate. In addition, by combining these markets into a single market represented by a unique ERC-5095 token, Illuminate enables arbitrage between these rates, ensuring that the best rate is given to users.

### Data Organization

This section describes several key pieces of data that Lender needs.

* `markets`: This mapping maps tuples of `(uint256, address)` (which represent a unique market) to a list of `address[9]` (which represent principal tokens). These addresses are token contracts for the principal tokens in each of the interest rate swap protocols supported by Illuminate.
* `Principals`: This enum contains the supported interest rate swap protocols by Illuminate. The order matters -- it indicates which position in the `markets` mapping value is being referred to by the user. For example, a user can refer to the Illuminate principal token by using the value `0` because it is the first value in the enum. Note that the Principals enum is defined in the MarketPlace.sol contract.
* `swivelAddr`, `pendleAddr` and `tempusAddr`: These `address` attributes are necessary to conduct `lend` operations on their respective protocols. This means that in addition to the principal token address, these addresses are used to facilitate the swap of the underlying for the principal token of that particular protocol.&#x20;

Note that the `Principals` enum is defined below:

```
    enum Principals {
        Illuminate,
        Swivel,
        Yield,
        Element,
        Pendle,
        Tempus,
        Sense,
        Apwine,
        Notional
    }
```


# Lender.sol

This document describes the functions, attributes and modifiers in Lender.sol

## Lender

[Git Source](https://github.com/Swivel-Finance/illuminate/blob/7162e4822e4bbebd99b67c43e703ecedf92a2138/src/Lender.sol)

**Author:** Sourabh Marathe, Julian Traversa, Rob Robbins

The lender contract executes loans on behalf of users

The contract holds the principal tokens and mints an ERC-5095 tokens to users to represent their loans

### State Variables

#### HOLD

minimum wait before the admin may withdraw funds or change the fee rate

```solidity
uint256 public constant HOLD = 3 days;
```

#### admin

address that is allowed to set and withdraw fees, disable principals, etc. It is commonly used in the authorized modifier.

```solidity
address public admin;
```

#### marketPlace

address of the MarketPlace contract, used to access the markets mapping

```solidity
address public marketPlace;
```

#### paused

mapping that determines if a principal has been paused by the admin

```solidity
mapping(uint8 => bool) public paused;
```

#### halted

flag that allows admin to stop all lending and minting across the entire protocol

```solidity
bool public halted;
```

#### swivelAddr

contract used to execute swaps on Swivel's exchange

```solidity
address public immutable swivelAddr;
```

#### pendleAddr

a SushiSwap router used by Pendle to execute swaps

```solidity
address public immutable pendleAddr;
```

#### apwineAddr

a pool router used by APWine to execute swaps

```solidity
address public immutable apwineAddr;
```

#### premiums

a mapping that tracks the amount of unswapped premium by market. This underlying is later transferred to the Redeemer during Swivel's redeem call

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

#### feenominator

this value determines the amount of fees paid on loans

```solidity
uint256 public feenominator;
```

#### feeChange

represents a point in time where the feenominator may change

```solidity
uint256 public feeChange;
```

#### MIN\_FEENOMINATOR

represents a minimum that the feenominator must exceed

```solidity
uint256 public constant MIN_FEENOMINATOR = 500;
```

#### fees

maps underlying tokens to the amount of fees accumulated for that token

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

#### withdrawals

maps a token address to a point in time, a hold, after which a withdrawal can be made

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

#### \_NOT\_ENTERED

```solidity
uint256 private constant _NOT_ENTERED = 1;
```

#### \_ENTERED

```solidity
uint256 private constant _ENTERED = 2;
```

#### \_status

```solidity
uint256 private _status = _NOT_ENTERED;
```

#### MAX\_VALUE

maximum amount of value that can flow through a protocol in a day (in USD)

```solidity
uint256 public constant MAX_VALUE = 2_000_000e27;
```

#### protocolFlow

maps protocols to how much value, in USD, has flowed through each protocol

```solidity
mapping(uint8 => uint256) public protocolFlow;
```

#### periodStart

timestamp from which values flowing through protocol has begun

```solidity
mapping(uint8 => uint256) public periodStart;
```

#### etherPrice

estimated price of ether, set by the admin

```solidity
uint256 public etherPrice = 2_500;
```

### Functions

#### authorized

ensures that only a certain address can call the function

```solidity
modifier authorized(address a);
```

**Parameters**

| Name | Type      | Description                                      |
| ---- | --------- | ------------------------------------------------ |
| `a`  | `address` | address that msg.sender must be to be authorized |

#### unpaused

reverts on all markets where the paused mapping returns true

```solidity
modifier unpaused(address u, uint256 m, uint8 p);
```

**Parameters**

| Name | Type      | Description                                                    |
| ---- | --------- | -------------------------------------------------------------- |
| `u`  | `address` | address of an underlying asset                                 |
| `m`  | `uint256` | maturity (timestamp) of the market                             |
| `p`  | `uint8`   | principal value according to the MarketPlace's Principals Enum |

#### matured

reverts if called after maturity

```solidity
modifier matured(uint256 m);
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `m`  | `uint256` | maturity (timestamp) of the market |

#### nonReentrant

prevents users from re-entering contract

```solidity
modifier nonReentrant();
```

#### constructor

initializes the Lender contract

```solidity
constructor(address s, address p, address a);
```

**Parameters**

| Name | Type      | Description         |
| ---- | --------- | ------------------- |
| `s`  | `address` | the Swivel contract |
| `p`  | `address` | the Pendle contract |
| `a`  | `address` | the APWine contract |

#### approve

approves the redeemer contract to spend the principal tokens held by the lender contract.

```solidity
function approve(address u, uint256 m, address r) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                                                    |
| ---- | --------- | -------------------------------------------------------------- |
| `u`  | `address` | address of an underlying asset                                 |
| `m`  | `uint256` | maturity (timestamp) of the market                             |
| `r`  | `address` | the address being approved, in this case the redeemer contract |

**Returns**

| Name     | Type   | Description                              |
| -------- | ------ | ---------------------------------------- |
| `<none>` | `bool` | bool true if the approval was successful |

#### approve

bulk approves the usage of addresses at the given ERC20 addresses.

*the lengths of the inputs must match because the arrays are paired by index*

```solidity
function approve(address[] calldata u, address[] calldata a) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type        | Description                                             |
| ---- | ----------- | ------------------------------------------------------- |
| `u`  | `address[]` | array of ERC20 token addresses that will be approved on |
| `a`  | `address[]` | array of addresses that will be approved                |

**Returns**

| Name     | Type   | Description        |
| -------- | ------ | ------------------ |
| `<none>` | `bool` | true if successful |

#### approve

approves market contracts that require lender approval

```solidity
function approve(address u, address a, address e, address n, address p) external authorized(marketPlace);
```

**Parameters**

| Name | Type      | Description                    |
| ---- | --------- | ------------------------------ |
| `u`  | `address` | address of an underlying asset |
| `a`  | `address` | APWine's router contract       |
| `e`  | `address` | Element's vault contract       |
| `n`  | `address` | Notional's token contract      |
| `p`  | `address` | Sense's periphery contract     |

#### setAdmin

sets the admin address

```solidity
function setAdmin(address a) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description            |
| ---- | --------- | ---------------------- |
| `a`  | `address` | address of a new admin |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### setFee

sets the feenominator to the given value

```solidity
function setFee(uint256 f) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                                                                          |
| ---- | --------- | ------------------------------------------------------------------------------------ |
| `f`  | `uint256` | the new value of the feenominator, fees are not collected when the feenominator is 0 |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### setMarketPlace

sets the address of the marketplace contract which contains the addresses of all the fixed rate markets

```solidity
function setMarketPlace(address m) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                             |
| ---- | --------- | --------------------------------------- |
| `m`  | `address` | the address of the marketplace contract |

**Returns**

| Name     | Type   | Description                      |
| -------- | ------ | -------------------------------- |
| `<none>` | `bool` | bool true if the address was set |

#### setEtherPrice

sets the ethereum price which is used in rate limiting

```solidity
function setEtherPrice(uint256 p) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description   |
| ---- | --------- | ------------- |
| `p`  | `uint256` | the new price |

**Returns**

| Name     | Type   | Description                    |
| -------- | ------ | ------------------------------ |
| `<none>` | `bool` | bool true if the price was set |

#### mint

mint swaps the sender's principal tokens for Illuminate's ERC5095 tokens in effect, this opens a new fixed rate position for the sender on Illuminate

```solidity
function mint(uint8 p, address u, uint256 m, uint256 a) external nonReentrant unpaused(u, m, p) returns (bool);
```

**Parameters**

| Name | Type      | Description                                                    |
| ---- | --------- | -------------------------------------------------------------- |
| `p`  | `uint8`   | principal value according to the MarketPlace's Principals Enum |
| `u`  | `address` | address of an underlying asset                                 |
| `m`  | `uint256` | maturity (timestamp) of the market                             |
| `a`  | `uint256` | amount being minted                                            |

**Returns**

| Name     | Type   | Description                          |
| -------- | ------ | ------------------------------------ |
| `<none>` | `bool` | bool true if the mint was successful |

#### lend

lend method for the Illuminate and Yield protocols

```solidity
function lend(uint8 p, address u, uint256 m, uint256 a, address y, uint256 minimum)
    external
    nonReentrant
    unpaused(u, m, p)
    matured(m)
    returns (uint256);
```

**Parameters**

| Name      | Type      | Description                                                    |
| --------- | --------- | -------------------------------------------------------------- |
| `p`       | `uint8`   | principal value according to the MarketPlace's Principals Enum |
| `u`       | `address` | address of an underlying asset                                 |
| `m`       | `uint256` | maturity (timestamp) of the market                             |
| `a`       | `uint256` | amount of underlying tokens to lend                            |
| `y`       | `address` | Yield Space Pool for the principal token                       |
| `minimum` | `uint256` | slippage limit, minimum amount to PTs to buy                   |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | uint256 the amount of principal tokens lent out |

#### lend

lend method signature for Swivel

```solidity
function lend(
    uint8 p,
    address u,
    uint256 m,
    uint256[] memory a,
    address y,
    Swivel.Order[] calldata o,
    Swivel.Components[] calldata s,
    bool e,
    uint256 premiumSlippage
) external nonReentrant unpaused(u, m, p) matured(m) returns (uint256);
```

**Parameters**

| Name              | Type                  | Description                                                                  |
| ----------------- | --------------------- | ---------------------------------------------------------------------------- |
| `p`               | `uint8`               | principal value according to the MarketPlace's Principals Enum               |
| `u`               | `address`             | address of an underlying asset                                               |
| `m`               | `uint256`             | maturity (timestamp) of the market                                           |
| `a`               | `uint256[]`           | array of amounts of underlying tokens lent to each order in the orders array |
| `y`               | `address`             | Yield Space Pool for the Illuminate PT in this market                        |
| `o`               | `Order.Swivel[]`      | array of Swivel orders being filled                                          |
| `s`               | `Components.Swivel[]` | array of signatures for each order in the orders array                       |
| `e`               | `bool`                | flag to indicate if returned funds should be swapped in Yield Space Pool     |
| `premiumSlippage` | `uint256`             | slippage limit, minimum amount to PTs to buy                                 |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | uint256 the amount of principal tokens lent out |

#### lend

lend method signature for Element

```solidity
function lend(uint8 p, address u, uint256 m, uint256 a, uint256 r, uint256 d, address e, bytes32 i)
    external
    nonReentrant
    unpaused(u, m, p)
    matured(m)
    returns (uint256);
```

**Parameters**

| Name | Type      | Description                                                    |
| ---- | --------- | -------------------------------------------------------------- |
| `p`  | `uint8`   | principal value according to the MarketPlace's Principals Enum |
| `u`  | `address` | address of an underlying asset                                 |
| `m`  | `uint256` | maturity (timestamp) of the market                             |
| `a`  | `uint256` | amount of underlying tokens to lend                            |
| `r`  | `uint256` | slippage limit, minimum amount to PTs to buy                   |
| `d`  | `uint256` | deadline is a timestamp by which the swap must be executed     |
| `e`  | `address` | Element pool that is lent to                                   |
| `i`  | `bytes32` | the id of the pool                                             |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | uint256 the amount of principal tokens lent out |

#### lend

lend method signature for Pendle

```solidity
function lend(uint8 p, address u, uint256 m, uint256 a, uint256 r, Pendle.ApproxParams calldata g, address market)
    external
    nonReentrant
    unpaused(u, m, p)
    matured(m)
    returns (uint256);
```

**Parameters**

| Name     | Type                  | Description                                                    |
| -------- | --------------------- | -------------------------------------------------------------- |
| `p`      | `uint8`               | principal value according to the MarketPlace's Principals Enum |
| `u`      | `address`             | address of an underlying asset                                 |
| `m`      | `uint256`             | maturity (timestamp) of the market                             |
| `a`      | `uint256`             | amount of underlying tokens to lend                            |
| `r`      | `uint256`             | slippage limit, minimum amount to PTs to buy                   |
| `g`      | `ApproxParams.Pendle` | guess parameters for the swap                                  |
| `market` | `address`             | contract that corresponds to the market for the PT             |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | uint256 the amount of principal tokens lent out |

#### lend

lend method signature for Tempus and APWine

```solidity
function lend(uint8 p, address u, uint256 m, uint256 a, uint256 r, uint256 d, address x)
    external
    nonReentrant
    unpaused(u, m, p)
    matured(m)
    returns (uint256);
```

**Parameters**

| Name | Type      | Description                                                                 |
| ---- | --------- | --------------------------------------------------------------------------- |
| `p`  | `uint8`   | value of a specific principal according to the Illuminate Principals Enum   |
| `u`  | `address` | address of an underlying asset                                              |
| `m`  | `uint256` | maturity (timestamp) of the market                                          |
| `a`  | `uint256` | amount of principal tokens to lend                                          |
| `r`  | `uint256` | minimum amount to return when executing the swap (sets a limit to slippage) |
| `d`  | `uint256` | deadline is a timestamp by which the swap must be executed                  |
| `x`  | `address` | Tempus or APWine AMM that executes the swap                                 |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | uint256 the amount of principal tokens lent out |

#### lend

lend method signature for Sense

*this method can be called before maturity to lend to Sense while minting Illuminate tokens*

*Sense provides a \[divider] contract that splits \[target] assets (underlying) into PTs and YTs. Each \[target] asset has a \[series] of contracts, each identifiable by their \[maturity].*

```solidity
function lend(uint8 p, address u, uint256 m, uint128 a, uint256 r, address x, uint256 s, address adapter)
    external
    nonReentrant
    unpaused(u, m, p)
    matured(m)
    returns (uint256);
```

**Parameters**

| Name      | Type      | Description                                                    |
| --------- | --------- | -------------------------------------------------------------- |
| `p`       | `uint8`   | principal value according to the MarketPlace's Principals Enum |
| `u`       | `address` | address of an underlying asset                                 |
| `m`       | `uint256` | maturity (timestamp) of the market                             |
| `a`       | `uint128` | amount of underlying tokens to lend                            |
| `r`       | `uint256` | slippage limit, minimum amount to PTs to buy                   |
| `x`       | `address` | periphery contract that is used to conduct the swap            |
| `s`       | `uint256` | Sense's maturity for the given market                          |
| `adapter` | `address` | Sense's adapter necessary to facilitate the swap               |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | uint256 the amount of principal tokens lent out |

#### lend

*lend method signature for Notional*

```solidity
function lend(uint8 p, address u, uint256 m, uint256 a, uint256 r)
    external
    nonReentrant
    unpaused(u, m, p)
    matured(m)
    returns (uint256);
```

**Parameters**

| Name | Type      | Description                                                    |
| ---- | --------- | -------------------------------------------------------------- |
| `p`  | `uint8`   | principal value according to the MarketPlace's Principals Enum |
| `u`  | `address` | address of an underlying asset                                 |
| `m`  | `uint256` | maturity (timestamp) of the market                             |
| `a`  | `uint256` | amount of underlying tokens to lend                            |
| `r`  | `uint256` | slippage limit, minimum amount to PTs to buy                   |

**Returns**

| Name     | Type      | Description                                     |
| -------- | --------- | ----------------------------------------------- |
| `<none>` | `uint256` | uint256 the amount of principal tokens lent out |

#### scheduleWithdrawal

allows the admin to schedule the withdrawal of tokens

```solidity
function scheduleWithdrawal(address e) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                          |
| ---- | --------- | ------------------------------------ |
| `e`  | `address` | address of (erc20) token to withdraw |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### blockWithdrawal

emergency function to block unplanned withdrawals

```solidity
function blockWithdrawal(address e) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                          |
| ---- | --------- | ------------------------------------ |
| `e`  | `address` | address of token withdrawal to block |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### scheduleFeeChange

allows the admin to schedule a change to the fee denominators

```solidity
function scheduleFeeChange() external authorized(admin) returns (bool);
```

#### blockFeeChange

Emergency function to block unplanned changes to fee structure

```solidity
function blockFeeChange() external authorized(admin) returns (bool);
```

#### withdraw

allows the admin to withdraw the given token, provided the holding period has been observed

```solidity
function withdraw(address e) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                  |
| ---- | --------- | ---------------------------- |
| `e`  | `address` | Address of token to withdraw |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### withdrawFee

withdraws accumulated lending fees of the underlying token

```solidity
function withdrawFee(address e) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                                 |
| ---- | --------- | ------------------------------------------- |
| `e`  | `address` | address of the underlying token to withdraw |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### pause

pauses a market and prevents execution of all lending for that principal

```solidity
function pause(uint8 p, bool b) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type    | Description                                                    |
| ---- | ------- | -------------------------------------------------------------- |
| `p`  | `uint8` | principal value according to the MarketPlace's Principals Enum |
| `b`  | `bool`  | bool representing whether to pause or unpause                  |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### pauseIlluminate

pauses Illuminate's redeem, mint and lend methods from being used

```solidity
function pauseIlluminate(bool b) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type   | Description                                              |
| ---- | ------ | -------------------------------------------------------- |
| `b`  | `bool` | bool representing whether to pause or unpause Illuminate |

**Returns**

| Name     | Type   | Description                   |
| -------- | ------ | ----------------------------- |
| `<none>` | `bool` | bool true if successfully set |

#### transferFYTs

Tranfers FYTs to Redeemer (used specifically for APWine redemptions)

```solidity
function transferFYTs(address f, uint256 a) external authorized(IMarketPlace(marketPlace).redeemer());
```

**Parameters**

| Name | Type      | Description                              |
| ---- | --------- | ---------------------------------------- |
| `f`  | `address` | FYT contract address                     |
| `a`  | `uint256` | amount of tokens to send to the redeemer |

#### transferPremium

Transfers premium from the market to Redeemer (used specifically for Swivel redemptions)

```solidity
function transferPremium(address u, uint256 m) external authorized(IMarketPlace(marketPlace).redeemer());
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `u`  | `address` | address of an underlying asset     |
| `m`  | `uint256` | maturity (timestamp) of the market |

#### batch

Allows batched call to self (this contract).

```solidity
function batch(bytes[] calldata c) external payable returns (bytes[] memory results);
```

**Parameters**

| Name | Type      | Description                       |
| ---- | --------- | --------------------------------- |
| `c`  | `bytes[]` | An array of inputs for each call. |

#### yield

swaps underlying premium via a Yield Space Pool

*this method is only used by the Yield, Illuminate and Swivel protocols*

```solidity
function yield(address u, address y, uint256 a, address r, address p, uint256 m) internal returns (uint256);
```

**Parameters**

| Name | Type      | Description                                 |
| ---- | --------- | ------------------------------------------- |
| `u`  | `address` | address of an underlying asset              |
| `y`  | `address` | Yield Space Pool for the principal token    |
| `a`  | `uint256` | amount of underlying tokens to lend         |
| `r`  | `address` | the receiving address for PTs               |
| `p`  | `address` | the principal token in the Yield Space Pool |
| `m`  | `uint256` | the minimum amount to purchase              |

**Returns**

| Name     | Type      | Description                                               |
| -------- | --------- | --------------------------------------------------------- |
| `<none>` | `uint256` | uint256 the amount of tokens sent to the Yield Space Pool |

#### swivelAmount

returns the amount of underlying tokens to be used in a Swivel lend

```solidity
function swivelAmount(uint256[] memory a) internal pure returns (uint256);
```

#### swivelVerify

reverts if any orders are not for the market

```solidity
function swivelVerify(Swivel.Order[] memory o, address u) internal pure;
```

#### elementSwap

executes a swap for and verifies receipt of Element PTs

```solidity
function elementSwap(address e, Element.SingleSwap memory s, Element.FundManagement memory f, uint256 r, uint256 d)
    internal
    returns (uint256);
```

#### apwineTokenPath

returns array token path required for APWine's swap method

```solidity
function apwineTokenPath() internal pure returns (uint256[] memory);
```

**Returns**

| Name     | Type        | Description                                      |
| -------- | ----------- | ------------------------------------------------ |
| `<none>` | `uint256[]` | array of uint256\[] as laid out in APWine's docs |

#### apwinePairPath

returns array pair path required for APWine's swap method

```solidity
function apwinePairPath() internal pure returns (uint256[] memory);
```

**Returns**

| Name     | Type        | Description                                      |
| -------- | ----------- | ------------------------------------------------ |
| `<none>` | `uint256[]` | array of uint256\[] as laid out in APWine's docs |

#### principalToken

retrieves the ERC5095 token for the given market

```solidity
function principalToken(address u, uint256 m) internal returns (address);
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `u`  | `address` | address of an underlying asset     |
| `m`  | `uint256` | maturity (timestamp) of the market |

**Returns**

| Name     | Type      | Description                                 |
| -------- | --------- | ------------------------------------------- |
| `<none>` | `address` | address of the ERC5095 token for the market |

#### convertDecimals

converts principal decimal amount to underlying's decimal amount

```solidity
function convertDecimals(address u, address p, uint256 a) internal view returns (uint256);
```

**Parameters**

| Name | Type      | Description                                      |
| ---- | --------- | ------------------------------------------------ |
| `u`  | `address` | address of an underlying asset                   |
| `p`  | `address` | address of a principal token                     |
| `a`  | `uint256` | amount denominated in principal token's decimals |

**Returns**

| Name     | Type      | Description                    |
| -------- | --------- | ------------------------------ |
| `<none>` | `uint256` | uint256 in underlying decimals |

#### rateLimit

limits the amount of funds (in USD value) that can flow through a principal in a day

```solidity
function rateLimit(uint8 p, address u, uint256 a) internal returns (bool);
```

**Parameters**

| Name | Type      | Description                                                           |
| ---- | --------- | --------------------------------------------------------------------- |
| `p`  | `uint8`   | principal value according to the MarketPlace's Principals Enum        |
| `u`  | `address` | address of an underlying asset                                        |
| `a`  | `uint256` | amount being minted which is normalized to 18 decimals prior to check |

**Returns**

| Name     | Type   | Description                                |
| -------- | ------ | ------------------------------------------ |
| `<none>` | `bool` | bool true if successful, reverts otherwise |

### Events

#### Lend

emitted upon lending to a protocol

```solidity
event Lend(
    uint8 principal,
    address indexed underlying,
    uint256 indexed maturity,
    uint256 returned,
    uint256 spent,
    address sender
);
```

#### Mint

emitted upon minting Illuminate principal tokens

```solidity
event Mint(uint8 principal, address indexed underlying, uint256 indexed maturity, uint256 amount);
```

#### ScheduleWithdrawal

emitted upon scheduling a withdrawal

```solidity
event ScheduleWithdrawal(address indexed token, uint256 hold);
```

#### BlockWithdrawal

emitted upon blocking a scheduled withdrawal

```solidity
event BlockWithdrawal(address indexed token);
```

#### SetAdmin

emitted upon changing the admin

```solidity
event SetAdmin(address indexed admin);
```

#### SetFee

emitted upon setting the fee rate

```solidity
event SetFee(uint256 indexed fee);
```

#### ScheduleFeeChange

emitted upon scheduling a fee change

```solidity
event ScheduleFeeChange(uint256 when);
```

#### BlockFeeChange

emitted upon blocking a scheduled fee change

```solidity
event BlockFeeChange();
```

#### PausePrincipal

emitted upon pausing or unpausing of a principal

```solidity
event PausePrincipal(uint8 principal, bool indexed state);
```

#### PauseIlluminate

emitted upon pausing or unpausing minting, lending and redeeming

```solidity
event PauseIlluminate(bool state);
```


# Redeemer

### User Flow

In order for a user to redeem their ERC-5095 tokens within a given market, two steps must be executed.

First, a `redeem` must be called on the external principal that Lender.sol may currently own. Similar to the Lender contract, the Redeemer contract overloads the `redeem` method, and distinguishes which loan to operated on by the `p` (principal) parameter. In addition to the principal, the `u` (underlying), `m` (maturity) and any additional data in order to execute the redemption.

Each principal's redemption method (with the exception of Illuminate) will execute the following flow once called: first, the principal tokens for the market will be transferred from the Lender contract to the Redeemer contract. From there, the principal's redemption will be executed and the Redeemer contract will receive the owed underlying asset in return. Note that for a given market, this method needs to be called only once per principal.

Second, to complete the redemption, a user must call the Illuminate principal's `redeem` on the relevant market (i.e. underlying + maturity tuple). This redeem will burn their ERC-5095 position for the market and send them the owed underlying token proportional to their balance of the ERC-5095 token.

### Motivation

The Redeemer contract facilitates the collection of owed underlying assets from the interest rate swap principals back to the user. At a high level, users should be able to redeem any ERC-5095 token via Illuminate's `redeem` method, and in doing so, this creates an aggregated market for a given underlying asset and maturity.

### Data Organization

Redeemer's data organization reflects Lender's data organization in many ways. Here are the key data it tracks:

* `markets`: This mapping maps tuples of `(uint256, address)` (which represent a unique market) to a list of `address[9]` (which represent principal tokens). These addresses are token contracts for the principal tokens in each of the interest rate swap protocols supported by Illuminate.
* `Principals`: This enum contains the supported interest rate swap protocols by Illuminate. The order matters -- it indicates which position in the `markets` mapping value is being referred to by the user. For example, a user can refer to the Illuminate principal token by using the value `0` because it is the first value in the enum. Note that the Principals enum is defined in the MarketPlace.sol contract.
* `swivelAddr`, `pendleAddr`, `tempusAddr`, and `apwineAddr`:  These `address` attributes are necessary to conduct `redeem` operations on their respective protocols. This means that in addition to the principal token address, these addresses are used to facilitate the redemption of the principal token of that particular protocol to the Redeemer.

Note that the `Principals` enum is defined below:

```
    enum Principals {
        Illuminate,
        Swivel,
        Yield,
        Element,
        Pendle,
        Tempus,
        Sense,
        Apwine,
        Notional
    }
```


# Redeemer.sol

This document describes the functions, attributes and modifiers in Redeemer.sol

## Redeemer

[Git Source](https://github.com/Swivel-Finance/illuminate/blob/7162e4822e4bbebd99b67c43e703ecedf92a2138/src/Redeemer.sol)

**Author:** Sourabh Marathe, Julian Traversa, Rob Robbins

The Redeemer contract is used to redeem the underlying lent capital of a loan.

Users may redeem their ERC-5095 tokens for the underlying asset represented by that token after maturity.

### State Variables

#### HOLD

minimum wait before the admin may withdraw funds or change the fee rate

```solidity
uint256 public constant HOLD = 3 days;
```

#### admin

address that is allowed to set fees and contracts, etc. It is commonly used in the authorized modifier.

```solidity
address public admin;
```

#### marketPlace

address of the MarketPlace contract, used to access the markets mapping

```solidity
address public marketPlace;
```

#### lender

address that custodies principal tokens for all markets

```solidity
address public lender;
```

#### converter

address that converts compounding tokens to their underlying

```solidity
address public converter;
```

#### swivelAddr

third party contract needed to redeem Swivel PTs

```solidity
address public immutable swivelAddr;
```

#### tempusAddr

third party contract needed to redeem Tempus PTs

```solidity
address public immutable tempusAddr;
```

#### feenominator

this value determines the amount of fees paid on auto redemptions

```solidity
uint256 public feenominator;
```

#### feeChange

represents a point in time where the feenominator may change

```solidity
uint256 public feeChange;
```

#### MIN\_FEENOMINATOR

represents a minimum that the feenominator must exceed

```solidity
uint256 public MIN_FEENOMINATOR = 500;
```

#### holdings

mapping that indicates how much underlying has been redeemed by a market

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

#### paused

mapping that determines if a market's iPT can be redeemed

```solidity
mapping(address => mapping(uint256 => bool)) public paused;
```

### Functions

#### authorized

ensures that only a certain address can call the function

```solidity
modifier authorized(address a);
```

**Parameters**

| Name | Type      | Description                                      |
| ---- | --------- | ------------------------------------------------ |
| `a`  | `address` | address that msg.sender must be to be authorized |

#### unpaused

reverts on all markets where the paused mapping returns true

```solidity
modifier unpaused(address u, uint256 m);
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `u`  | `address` | address of an underlying asset     |
| `m`  | `uint256` | maturity (timestamp) of the market |

#### constructor

Initializes the Redeemer contract

```solidity
constructor(address l, address s, address t);
```

**Parameters**

| Name | Type      | Description         |
| ---- | --------- | ------------------- |
| `l`  | `address` | the lender contract |
| `s`  | `address` | the Swivel contract |
| `t`  | `address` | the Tempus contract |

#### setAdmin

sets the admin address

```solidity
function setAdmin(address a) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description            |
| ---- | --------- | ---------------------- |
| `a`  | `address` | Address of a new admin |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### setMarketPlace

sets the address of the marketplace contract which contains the addresses of all the fixed rate markets

```solidity
function setMarketPlace(address m) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                             |
| ---- | --------- | --------------------------------------- |
| `m`  | `address` | the address of the marketplace contract |

**Returns**

| Name     | Type   | Description                      |
| -------- | ------ | -------------------------------- |
| `<none>` | `bool` | bool true if the address was set |

#### setConverter

sets the converter address

```solidity
function setConverter(address c, address[] memory i) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type        | Description                                                 |
| ---- | ----------- | ----------------------------------------------------------- |
| `c`  | `address`   | address of the new converter                                |
| `i`  | `address[]` | a list of interest bearing tokens the redeemer will approve |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### setLender

sets the address of the lender contract which contains the addresses of all the fixed rate markets

```solidity
function setLender(address l) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `l`  | `address` | the address of the lender contract |

**Returns**

| Name     | Type   | Description                      |
| -------- | ------ | -------------------------------- |
| `<none>` | `bool` | bool true if the address was set |

#### setFee

sets the feenominator to the given value

```solidity
function setFee(uint256 f) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                                                                          |
| ---- | --------- | ------------------------------------------------------------------------------------ |
| `f`  | `uint256` | the new value of the feenominator, fees are not collected when the feenominator is 0 |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### scheduleFeeChange

allows the admin to schedule a change to the fee denominators

```solidity
function scheduleFeeChange() external authorized(admin) returns (bool);
```

#### pauseRedemptions

allows admin to stop redemptions of Illuminate PTs for a given market

```solidity
function pauseRedemptions(address u, uint256 m, bool b) external authorized(admin);
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `u`  | `address` | address of an underlying asset     |
| `m`  | `uint256` | maturity (timestamp) of the market |
| `b`  | `bool`    | true to pause, false to unpause    |

#### approve

approves the converter to spend the compounding asset

```solidity
function approve(address i) external authorized(marketPlace);
```

**Parameters**

| Name | Type      | Description                                                    |
| ---- | --------- | -------------------------------------------------------------- |
| `i`  | `address` | an interest bearing token that must be approved for conversion |

#### redeem

redeem method for Yield, Element, Pendle, APWine, Tempus and Notional protocols

```solidity
function redeem(uint8 p, address u, uint256 m) external unpaused(u, m) returns (bool);
```

**Parameters**

| Name | Type      | Description                                                    |
| ---- | --------- | -------------------------------------------------------------- |
| `p`  | `uint8`   | principal value according to the MarketPlace's Principals Enum |
| `u`  | `address` | address of an underlying asset                                 |
| `m`  | `uint256` | maturity (timestamp) of the market                             |

**Returns**

| Name     | Type   | Description                                |
| -------- | ------ | ------------------------------------------ |
| `<none>` | `bool` | bool true if the redemption was successful |

#### redeem

redeem method signature for Swivel

```solidity
function redeem(uint8 p, address u, uint256 m, uint8 protocol) external unpaused(u, m) returns (bool);
```

**Parameters**

| Name       | Type      | Description                                                    |
| ---------- | --------- | -------------------------------------------------------------- |
| `p`        | `uint8`   | principal value according to the MarketPlace's Principals Enum |
| `u`        | `address` | address of an underlying asset                                 |
| `m`        | `uint256` | maturity (timestamp) of the market                             |
| `protocol` | `uint8`   |                                                                |

**Returns**

| Name     | Type   | Description                                |
| -------- | ------ | ------------------------------------------ |
| `<none>` | `bool` | bool true if the redemption was successful |

#### redeem

redeem method signature for Sense

```solidity
function redeem(uint8 p, address u, uint256 m, uint256 s, uint256 a, address periphery)
    external
    unpaused(u, m)
    returns (bool);
```

**Parameters**

| Name        | Type      | Description                                                    |
| ----------- | --------- | -------------------------------------------------------------- |
| `p`         | `uint8`   | principal value according to the MarketPlace's Principals Enum |
| `u`         | `address` | address of an underlying asset                                 |
| `m`         | `uint256` | maturity (timestamp) of the market                             |
| `s`         | `uint256` | Sense's maturity is needed to extract the pt address           |
| `a`         | `uint256` | Sense's adapter index                                          |
| `periphery` | `address` | Sense's periphery contract, used to get the verified adapter   |

**Returns**

| Name     | Type   | Description                                |
| -------- | ------ | ------------------------------------------ |
| `<none>` | `bool` | bool true if the redemption was successful |

#### redeem

burns Illuminate principal tokens and sends underlying to user

```solidity
function redeem(address u, uint256 m) external unpaused(u, m);
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `u`  | `address` | address of an underlying asset     |
| `m`  | `uint256` | maturity (timestamp) of the market |

#### authRedeem

implements the redeem method for the contract to fulfill the ERC-5095 interface

```solidity
function authRedeem(address u, uint256 m, address f, address t, uint256 a)
    external
    authorized(IMarketPlace(marketPlace).markets(u, m, 0))
    unpaused(u, m)
    returns (uint256);
```

**Parameters**

| Name | Type      | Description                                               |
| ---- | --------- | --------------------------------------------------------- |
| `u`  | `address` | address of an underlying asset                            |
| `m`  | `uint256` | maturity (timestamp) of the market                        |
| `f`  | `address` | address from where the underlying asset will be burned    |
| `t`  | `address` | address to where the underlying asset will be transferred |
| `a`  | `uint256` | amount of the Illuminate PT to be burned and redeemed     |

**Returns**

| Name     | Type      | Description                                            |
| -------- | --------- | ------------------------------------------------------ |
| `<none>` | `uint256` | uint256 amount of the underlying asset that was burned |

#### autoRedeem

implements a redeem method to enable third-party redemptions

*expects approvals from owners to redeemer*

```solidity
function autoRedeem(address u, uint256 m, address[] calldata f) external unpaused(u, m) returns (uint256);
```

**Parameters**

| Name | Type        | Description                                           |
| ---- | ----------- | ----------------------------------------------------- |
| `u`  | `address`   | address of the underlying asset                       |
| `m`  | `uint256`   | maturity of the market                                |
| `f`  | `address[]` | address from where the principal token will be burned |

**Returns**

| Name     | Type      | Description                                   |
| -------- | --------- | --------------------------------------------- |
| `<none>` | `uint256` | uint256 amount of underlying yielded as a fee |

#### depositHoldings

Allows for external deposit of underlying for a market

This is to be used in emergency situations where the redeem method is not functioning for a market

```solidity
function depositHoldings(address u, uint256 m, uint256 a) external;
```

**Parameters**

| Name | Type      | Description                          |
| ---- | --------- | ------------------------------------ |
| `u`  | `address` | address of the underlying asset      |
| `m`  | `uint256` | maturity of the market               |
| `a`  | `uint256` | amount of underlying to be deposited |

#### apwineWithdraw

Execute the business logic for conducting an APWine redemption

```solidity
function apwineWithdraw(address p, address u, uint256 a) internal;
```

### Events

#### Redeem

emitted upon redemption of a loan

```solidity
event Redeem(
    uint8 principal,
    address indexed underlying,
    uint256 indexed maturity,
    uint256 amount,
    uint256 burned,
    address sender
);
```

#### SetAdmin

emitted upon changing the admin

```solidity
event SetAdmin(address indexed admin);
```

#### SetConverter

emitted upon changing the converter

```solidity
event SetConverter(address indexed converter);
```

#### SetFee

emitted upon setting the fee rate

```solidity
event SetFee(uint256 indexed fee);
```

#### ScheduleFeeChange

emitted upon scheduling a fee change

```solidity
event ScheduleFeeChange(uint256 when);
```

#### PauseRedemptions

emitted upon pausing of Illuminate PTs

```solidity
event PauseRedemptions(address indexed underlying, uint256 maturity, bool state);
```


# Marketplace

### Motivation

The MarketPlace contract serves two primary utilities:

1. It allows the `admin` to create new lending markets.
2. It routes swaps for Illuminate's ERC-5095 tokens to their respective YieldSpace AMM pool.

These functionalities are critical to the operation of Illuminate. The creation of markets updates the `markets` mapping which is referred to by the Lender and Redeemer when retrieving principal tokens. Additionally, the YieldSpace AMM pools allow for users to exit their debt positions prior to maturation by providing liquidity for each market's ERC-5095 token. `pool`

### User Flow

The MarketPlace contract is not user-facing. It can only be used by the `admin`. That said, its functionality is integral to the Lender and Redeemer, and is worth exploring. This section will describe the methods available to the MarketPlace `admin`.

* `createMarket`: this method creates markets by adding entries to the `markets` mapping. Each market needs to have principal tokens defined for each protocol to work. Additionally, this method mints a new ERC-5095 token for each new market. This token is considered Illuminate's principal token, and is held by users.
* `pause`: this method stops access to YieldSpace pools for any given principal as defined in the `Principals` enum.
* `setAdmin`: this method allows for setting the admin to a new address.
* `setPool`: this method allows for setting an address in the `pools` mapping. The `pools` attribute contains the YieldSpace AMM pool for Illuminate's principal token.

### Data Organization

There are two key mappings that MarketPlace stores:

* `markets`: this mapping maps Markets (which consist of an underlying (`address`) and a maturity (`uint256`)) to a list of principal tokens (`[9]address`). The protocol that the address maps to depends on the `Principals` enum.
* `pools`: this mapping maps Markets to YieldSpace AMM pools (`address`). These pools allow users to swap their ERC-5095 positions for the underlying asset prior to maturity.
* `Principals`: this enum is referenced throughout Illuminate and states which interest rate swap protocols are supported. In addition, this enum defines the index through which the protocols can be referred to when they are stored in lists (as is done in the `markets` mapping).


# Marketplace.sol

This document describes the functions, attributes and modifiers in MarketPlace.sol

## MarketPlace

[Git Source](https://github.com/Swivel-Finance/illuminate/blob/7162e4822e4bbebd99b67c43e703ecedf92a2138/src/Marketplace.sol)

**Author:** Sourabh Marathe, Julian Traversa, Rob Robbins

This contract is in charge of managing the available principals for each loan market.

In addition, this contract routes swap orders between Illuminate PTs and their respective underlying to YieldSpace pools.

### State Variables

#### markets

markets are defined by a tuple that points to a fixed length array of principal token addresses.

```solidity
mapping(address => mapping(uint256 => address[9])) public markets;
```

#### pools

pools map markets to their respective YieldSpace pools for the MetaPrincipal token

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

#### admin

address that is allowed to create markets, set pools, etc. It is commonly used in the authorized modifier.

```solidity
address public admin;
```

#### redeemer

address of the deployed redeemer contract

```solidity
address public immutable redeemer;
```

#### lender

address of the deployed lender contract

```solidity
address public immutable lender;
```

#### creator

address of the deployed creator contract

```solidity
address public immutable creator;
```

### Functions

#### authorized

ensures that only a certain address can call the function

```solidity
modifier authorized(address a);
```

**Parameters**

| Name | Type      | Description                                      |
| ---- | --------- | ------------------------------------------------ |
| `a`  | `address` | address that msg.sender must be to be authorized |

#### constructor

initializes the MarketPlace contract

```solidity
constructor(address r, address l, address c);
```

**Parameters**

| Name | Type      | Description                               |
| ---- | --------- | ----------------------------------------- |
| `r`  | `address` | address of the deployed redeemer contract |
| `l`  | `address` | address of the deployed lender contract   |
| `c`  | `address` | address of the deployed creator contract  |

#### createMarket

creates a new market for the given underlying token and maturity

```solidity
function createMarket(
    address u,
    uint256 m,
    address[8] calldata t,
    string calldata n,
    string calldata s,
    address a,
    address e,
    address h,
    address sensePeriphery
) external authorized(admin) returns (bool);
```

**Parameters**

| Name             | Type         | Description                                                                    |
| ---------------- | ------------ | ------------------------------------------------------------------------------ |
| `u`              | `address`    | address of an underlying asset                                                 |
| `m`              | `uint256`    | maturity (timestamp) of the market                                             |
| `t`              | `address[8]` | principal token addresses for this market                                      |
| `n`              | `string`     | name for the Illuminate token                                                  |
| `s`              | `string`     | symbol for the Illuminate token                                                |
| `a`              | `address`    | address of the APWine router that corresponds to this market                   |
| `e`              | `address`    | address of the Element vault that corresponds to this market                   |
| `h`              | `address`    | address of a helper contract, used for Sense approvals if active in the market |
| `sensePeriphery` | `address`    | address of the Sense periphery contract that must be approved by the lender    |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### setPrincipal

allows the admin to set an individual market

```solidity
function setPrincipal(uint8 p, address u, uint256 m, address a, address h, address sensePeriphery)
    external
    authorized(admin)
    returns (bool);
```

**Parameters**

| Name             | Type      | Description                                                                                                |
| ---------------- | --------- | ---------------------------------------------------------------------------------------------------------- |
| `p`              | `uint8`   | principal value according to the MarketPlace's Principals Enum                                             |
| `u`              | `address` | address of an underlying asset                                                                             |
| `m`              | `uint256` | maturity (timestamp) of the market                                                                         |
| `a`              | `address` | address of the new principal token                                                                         |
| `h`              | `address` | a supplementary address (apwine needs a router, element needs a vault, sense needs interest bearing asset) |
| `sensePeriphery` | `address` | address of the Sense periphery contract that must be approved by the lender                                |

**Returns**

| Name     | Type   | Description                                     |
| -------- | ------ | ----------------------------------------------- |
| `<none>` | `bool` | bool true if the principal set, false otherwise |

#### setAdmin

sets the admin address

```solidity
function setAdmin(address a) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description            |
| ---- | --------- | ---------------------- |
| `a`  | `address` | Address of a new admin |

**Returns**

| Name     | Type   | Description                                 |
| -------- | ------ | ------------------------------------------- |
| `<none>` | `bool` | bool true if the admin set, false otherwise |

#### setPool

sets the address for a pool

```solidity
function setPool(address u, uint256 m, address a) external authorized(admin) returns (bool);
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `u`  | `address` | address of an underlying asset     |
| `m`  | `uint256` | maturity (timestamp) of the market |
| `a`  | `address` | address of the pool                |

**Returns**

| Name     | Type   | Description                                |
| -------- | ------ | ------------------------------------------ |
| `<none>` | `bool` | bool true if the pool set, false otherwise |

#### sellPrincipalToken

sells the PT for the underlying via the pool

```solidity
function sellPrincipalToken(address u, uint256 m, uint128 a, uint128 s) external returns (uint128);
```

**Parameters**

| Name | Type      | Description                                                      |
| ---- | --------- | ---------------------------------------------------------------- |
| `u`  | `address` | address of an underlying asset                                   |
| `m`  | `uint256` | maturity (timestamp) of the market                               |
| `a`  | `uint128` | amount of PTs to sell                                            |
| `s`  | `uint128` | slippage cap, minimum amount of underlying that must be received |

**Returns**

| Name     | Type      | Description                         |
| -------- | --------- | ----------------------------------- |
| `<none>` | `uint128` | uint128 amount of underlying bought |

#### buyPrincipalToken

buys the PT for the underlying via the pool

determines how many underlying to sell by using the preview

```solidity
function buyPrincipalToken(address u, uint256 m, uint128 a, uint128 s) external returns (uint128);
```

**Parameters**

| Name | Type      | Description                                                 |
| ---- | --------- | ----------------------------------------------------------- |
| `u`  | `address` | address of an underlying asset                              |
| `m`  | `uint256` | maturity (timestamp) of the market                          |
| `a`  | `uint128` | amount of PTs to be purchased                               |
| `s`  | `uint128` | slippage cap, maximum number of underlying that can be sold |

**Returns**

| Name     | Type      | Description                       |
| -------- | --------- | --------------------------------- |
| `<none>` | `uint128` | uint128 amount of underlying sold |

#### sellUnderlying

sells the underlying for the PT via the pool

```solidity
function sellUnderlying(address u, uint256 m, uint128 a, uint128 s) external returns (uint128);
```

**Parameters**

| Name | Type      | Description                                               |
| ---- | --------- | --------------------------------------------------------- |
| `u`  | `address` | address of an underlying asset                            |
| `m`  | `uint256` | maturity (timestamp) of the market                        |
| `a`  | `uint128` | amount of underlying to sell                              |
| `s`  | `uint128` | slippage cap, minimum number of PTs that must be received |

**Returns**

| Name     | Type      | Description                    |
| -------- | --------- | ------------------------------ |
| `<none>` | `uint128` | uint128 amount of PT purchased |

#### buyUnderlying

buys the underlying for the PT via the pool

determines how many PTs to sell by using the preview

```solidity
function buyUnderlying(address u, uint256 m, uint128 a, uint128 s) external returns (uint128);
```

**Parameters**

| Name | Type      | Description                                          |
| ---- | --------- | ---------------------------------------------------- |
| `u`  | `address` | address of an underlying asset                       |
| `m`  | `uint256` | maturity (timestamp) of the market                   |
| `a`  | `uint128` | amount of underlying to be purchased                 |
| `s`  | `uint128` | slippage cap, maximum number of PTs that can be sold |

**Returns**

| Name     | Type      | Description                |
| -------- | --------- | -------------------------- |
| `<none>` | `uint128` | uint128 amount of PTs sold |

#### mint

mint liquidity tokens in exchange for adding underlying and PT

*amount of liquidity tokens to mint is calculated from the amount of unaccounted for PT in this contract.*

*A proportional amount of underlying tokens need to be present in this contract, also unaccounted for.*

```solidity
function mint(address u, uint256 m, uint256 b, uint256 p, uint256 minRatio, uint256 maxRatio)
    external
    returns (uint256, uint256, uint256);
```

**Parameters**

| Name       | Type      | Description                                   |
| ---------- | --------- | --------------------------------------------- |
| `u`        | `address` | the address of the underlying token           |
| `m`        | `uint256` | the maturity of the principal token           |
| `b`        | `uint256` | number of base tokens                         |
| `p`        | `uint256` | the principal token amount being sent         |
| `minRatio` | `uint256` | minimum ratio of LP tokens to PT in the pool. |
| `maxRatio` | `uint256` | maximum ratio of LP tokens to PT in the pool. |

**Returns**

| Name     | Type      | Description                                         |
| -------- | --------- | --------------------------------------------------- |
| `<none>` | `uint256` | uint256 number of base tokens passed to the method  |
| `<none>` | `uint256` | uint256 number of yield tokens passed to the method |
| `<none>` | `uint256` | uint256 the amount of tokens minted.                |

#### mintWithUnderlying

Mint liquidity tokens in exchange for adding only underlying

*amount of liquidity tokens is calculated from the amount of PT to buy from the pool, plus the amount of unaccounted for PT in this contract.*

```solidity
function mintWithUnderlying(address u, uint256 m, uint256 a, uint256 p, uint256 minRatio, uint256 maxRatio)
    external
    returns (uint256, uint256, uint256);
```

**Parameters**

| Name       | Type      | Description                                                                                              |
| ---------- | --------- | -------------------------------------------------------------------------------------------------------- |
| `u`        | `address` | the address of the underlying token                                                                      |
| `m`        | `uint256` | the maturity of the principal token                                                                      |
| `a`        | `uint256` | the underlying amount being sent                                                                         |
| `p`        | `uint256` | amount of `PT` being bought in the Pool, from this we calculate how much underlying it will be taken in. |
| `minRatio` | `uint256` | minimum ratio of LP tokens to PT in the pool.                                                            |
| `maxRatio` | `uint256` | maximum ratio of LP tokens to PT in the pool.                                                            |

**Returns**

| Name     | Type      | Description                                         |
| -------- | --------- | --------------------------------------------------- |
| `<none>` | `uint256` | uint256 number of base tokens passed to the method  |
| `<none>` | `uint256` | uint256 number of yield tokens passed to the method |
| `<none>` | `uint256` | uint256 the amount of tokens minted.                |

#### burn

burn liquidity tokens in exchange for underlying and PT.

```solidity
function burn(address u, uint256 m, uint256 a, uint256 minRatio, uint256 maxRatio)
    external
    returns (uint256, uint256, uint256);
```

**Parameters**

| Name       | Type      | Description                                  |
| ---------- | --------- | -------------------------------------------- |
| `u`        | `address` | the address of the underlying token          |
| `m`        | `uint256` | the maturity of the principal token          |
| `a`        | `uint256` | the amount of liquidity tokens to burn       |
| `minRatio` | `uint256` | minimum ratio of LP tokens to PT in the pool |
| `maxRatio` | `uint256` | maximum ratio of LP tokens to PT in the pool |

**Returns**

| Name     | Type      | Description                            |
| -------- | --------- | -------------------------------------- |
| `<none>` | `uint256` | uint256 amount of LP tokens burned     |
| `<none>` | `uint256` | uint256 amount of base tokens received |
| `<none>` | `uint256` | uint256 amount of fyTokens received    |

#### burnForUnderlying

burn liquidity tokens in exchange for underlying.

```solidity
function burnForUnderlying(address u, uint256 m, uint256 a, uint256 minRatio, uint256 maxRatio)
    external
    returns (uint256, uint256);
```

**Parameters**

| Name       | Type      | Description                                   |
| ---------- | --------- | --------------------------------------------- |
| `u`        | `address` | the address of the underlying token           |
| `m`        | `uint256` | the maturity of the principal token           |
| `a`        | `uint256` | the amount of liquidity tokens to burn        |
| `minRatio` | `uint256` | minimum ratio of LP tokens to PT in the pool. |
| `maxRatio` | `uint256` | minimum ratio of LP tokens to PT in the pool. |

**Returns**

| Name     | Type      | Description                                  |
| -------- | --------- | -------------------------------------------- |
| `<none>` | `uint256` | uint256 amount of PT tokens sent to the pool |
| `<none>` | `uint256` | uint256 amount of underlying tokens returned |

#### batch

Allows batched call to self (this contract).

```solidity
function batch(bytes[] calldata c) external payable returns (bytes[] memory results);
```

**Parameters**

| Name | Type      | Description                       |
| ---- | --------- | --------------------------------- |
| `c`  | `bytes[]` | An array of inputs for each call. |

### Events

#### CreateMarket

emitted upon the creation of a new market

```solidity
event CreateMarket(
    address indexed underlying, uint256 indexed maturity, address[9] tokens, address element, address apwine
);
```

#### SetPrincipal

emitted upon setting a principal token

```solidity
event SetPrincipal(address indexed underlying, uint256 indexed maturity, address indexed principal, uint8 protocol);
```

#### Swap

emitted upon swapping with the pool

```solidity
event Swap(
    address indexed underlying,
    uint256 indexed maturity,
    address sold,
    address bought,
    uint256 received,
    uint256 spent,
    address spender
);
```

#### Mint

emitted upon minting tokens with the pool

```solidity
event Mint(
    address indexed underlying,
    uint256 indexed maturity,
    uint256 underlyingIn,
    uint256 principalTokensIn,
    uint256 minted,
    address minter
);
```

#### Burn

emitted upon burning tokens with the pool

```solidity
event Burn(
    address indexed underlying,
    uint256 indexed maturity,
    uint256 tokensBurned,
    uint256 underlyingReceived,
    uint256 principalTokensReceived,
    address burner
);
```

#### SetAdmin

emitted upon changing the admin

```solidity
event SetAdmin(address indexed admin);
```

#### SetPool

emitted upon setting a pool

```solidity
event SetPool(address indexed underlying, uint256 indexed maturity, address indexed pool);
```

### Enums

#### Principals

the available principals

*the order of this enum is used to select principals from the markets mapping (e.g. Illuminate => 0, Swivel => 1, and so on)*

```solidity
enum Principals {
    Illuminate,
    Swivel,
    Yield,
    Element,
    Pendle,
    Tempus,
    Sense,
    Apwine,
    Notional
}
```


# Illuminate Principal Token (ERC5095)

### User Flow

The Illuminate Principal Token (iPT) is the meta-token of the Illuminate ecosystem.

It is a principal token that comprises of various integrated protocol principal tokens and is to be redeemed upon the maturity of an Illuminate market.

Users may obtain the Illuminate Principal Token by purchasing active PTs within the market via `lend` , or by externally acquiring integrated PTs and minting Illuminate Principal Tokens via `mint` calls in the Lender contract.

Upon maturity, users can call `redeem` on the Redeemer contract to obtain their underlying. Assuming the positions were repaid in full across all protocols, the user will receive underlying equivalent to their 1:1 balance of Illuminate Principal Tokens.

### Motivation

The purpose of the iPT is to create a meta-principal token for the various fixed-rate lending protocols in the DeFi ecosystem. In doing so, it unifies the market along a single maturity and underlying for a given market. This has the benefit of consolidating previously fragmented liquidity, and opening up new arbitrage opportunities within the fixed-rate lending market.

In enabling these arbitrage opportunities, iPTs become the implicit best rate-of-return for a given duration of loans in a market. This benefits users by greatly simplifying the process of lending at fixed rates.

### Data Organization

Each iPT contains the following references to facilitate its role within the Illuminate protocol:

* `pool`: This refers to the Yield Space Pool through which the iPT can be traded for the underlying.
* `maturity`: This refers to the timestamp at which the lending operations cease and redemptions begin for the iPT.
* `underlying`: The asset being lent out, and may be used to purchase the iPT.
* `marketPlace`, `lender`, `redeemer`: These refer to the Illuminate protocol's contract federation.


# ERC5095.sol

This document describes the functions, attributes and modifiers in ERC5095.sol

## ERC5095

[Git Source](https://github.com/Swivel-Finance/illuminate/blob/7162e4822e4bbebd99b67c43e703ecedf92a2138/src/tokens/ERC5095.sol)

**Inherits:** ERC20Permit, IERC5095

### State Variables

#### maturity

*unix timestamp when the ERC5095 token can be redeemed*

```solidity
uint256 public immutable override maturity;
```

#### underlying

*address of the ERC20 token that is returned on ERC5095 redemption*

```solidity
address public immutable override underlying;
```

#### lender

*address of the minting authority*

```solidity
address public immutable lender;
```

#### marketplace

*address of the "marketplace" YieldSpace AMM router*

```solidity
address public immutable marketplace;
```

#### pool

*Interface to interact with the pool*

```solidity
address public pool;
```

#### redeemer

*address and interface for an external custody contract (necessary for some project's backwards compatability)*

```solidity
address public immutable redeemer;
```

### Functions

#### authorized

ensures that only a certain address can call the function

```solidity
modifier authorized(address a);
```

**Parameters**

| Name | Type      | Description                                      |
| ---- | --------- | ------------------------------------------------ |
| `a`  | `address` | address that msg.sender must be to be authorized |

#### constructor

```solidity
constructor(
    address _underlying,
    uint256 _maturity,
    address _redeemer,
    address _lender,
    address _marketplace,
    string memory name_,
    string memory symbol_,
    uint8 decimals_
) ERC20Permit(name_, symbol_, decimals_);
```

#### setPool

Allows the marketplace to set the pool

```solidity
function setPool(address p) external authorized(marketplace) returns (bool);
```

**Parameters**

| Name | Type      | Description         |
| ---- | --------- | ------------------- |
| `p`  | `address` | Address of the pool |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool True if successful |

#### approveMarketPlace

Allows the marketplace to spend underlying, principal tokens held by the token

*This is necessary when MarketPlace calls pool methods to swap tokens*

```solidity
function approveMarketPlace() external authorized(marketplace) returns (bool);
```

**Returns**

| Name     | Type   | Description        |
| -------- | ------ | ------------------ |
| `<none>` | `bool` | True if successful |

#### convertToUnderlying

Post or at maturity, converts an amount of principal tokens to an amount of underlying that would be returned.

```solidity
function convertToUnderlying(uint256 s) external view override returns (uint256);
```

**Parameters**

| Name | Type      | Description                               |
| ---- | --------- | ----------------------------------------- |
| `s`  | `uint256` | The amount of principal tokens to convert |

**Returns**

| Name     | Type      | Description                                                        |
| -------- | --------- | ------------------------------------------------------------------ |
| `<none>` | `uint256` | uint256 The amount of underlying tokens returned by the conversion |

#### convertToShares

Post or at maturity, converts a desired amount of underlying tokens returned to principal tokens needed.

```solidity
function convertToShares(uint256 a) external view override returns (uint256);
```

**Parameters**

| Name | Type      | Description                                |
| ---- | --------- | ------------------------------------------ |
| `a`  | `uint256` | The amount of underlying tokens to convert |

**Returns**

| Name     | Type      | Description                                                       |
| -------- | --------- | ----------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of principal tokens returned by the conversion |

#### maxRedeem

Returns user's PT balance

```solidity
function maxRedeem(address o) external view override returns (uint256);
```

**Parameters**

| Name | Type      | Description                                                 |
| ---- | --------- | ----------------------------------------------------------- |
| `o`  | `address` | The address of the owner for which redemption is calculated |

**Returns**

| Name     | Type      | Description                                                             |
| -------- | --------- | ----------------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The maximum amount of principal tokens that `owner` can redeem. |

#### maxWithdraw

Post or at maturity, returns user's PT balance. Prior to maturity, returns a previewRedeem for owner's PT balance.

```solidity
function maxWithdraw(address o) external view override returns (uint256);
```

**Parameters**

| Name | Type      | Description                                                 |
| ---- | --------- | ----------------------------------------------------------- |
| `o`  | `address` | The address of the owner for which withdrawal is calculated |

**Returns**

| Name     | Type      | Description                                                            |
| -------- | --------- | ---------------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 maximum amount of underlying tokens that `owner` can withdraw. |

#### previewDeposit

After maturity, returns 0. Prior to maturity, returns the amount of `shares` when spending `a` in underlying on a YieldSpace AMM.

```solidity
function previewDeposit(uint256 a) public view returns (uint256);
```

**Parameters**

| Name | Type      | Description                    |
| ---- | --------- | ------------------------------ |
| `a`  | `uint256` | The amount of underlying spent |

**Returns**

| Name     | Type      | Description                                                      |
| -------- | --------- | ---------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of PT purchased by spending `a` of underlying |

#### previewMint

After maturity, returns 0. Prior to maturity, returns the amount of `assets` in underlying spent on a purchase of `s` in PT on a YieldSpace AMM.

```solidity
function previewMint(uint256 s) public view returns (uint256);
```

**Parameters**

| Name | Type      | Description                                             |
| ---- | --------- | ------------------------------------------------------- |
| `s`  | `uint256` | The amount of principal tokens bought in the simulation |

**Returns**

| Name     | Type      | Description                                                     |
| -------- | --------- | --------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of underlying required to purchase `s` of PT |

#### previewRedeem

Post or at maturity, simulates the effects of redemption. Prior to maturity, returns the amount of `assets` from a sale of `s` PTs on a YieldSpace AMM.

```solidity
function previewRedeem(uint256 s) public view override returns (uint256);
```

**Parameters**

| Name | Type      | Description                                               |
| ---- | --------- | --------------------------------------------------------- |
| `s`  | `uint256` | The amount of principal tokens redeemed in the simulation |

**Returns**

| Name     | Type      | Description                                                       |
| -------- | --------- | ----------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of underlying returned by `s` of PT redemption |

#### previewWithdraw

Post or at maturity, simulates the effects of withdrawal at the current block. Prior to maturity, simulates the amount of PTs necessary to receive `a` in underlying from the sale of PTs on a YieldSpace AMM.

```solidity
function previewWithdraw(uint256 a) public view override returns (uint256);
```

**Parameters**

| Name | Type      | Description                                                 |
| ---- | --------- | ----------------------------------------------------------- |
| `a`  | `uint256` | The amount of underlying tokens withdrawn in the simulation |

**Returns**

| Name     | Type      | Description                                                               |
| -------- | --------- | ------------------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of principal tokens required for the withdrawal of `a` |

#### deposit

Before maturity spends `a` of underlying, and sends PTs to `r`. Post or at maturity, reverts.

```solidity
function deposit(uint256 a, address r, uint256 m) external returns (uint256);
```

**Parameters**

| Name | Type      | Description                                         |
| ---- | --------- | --------------------------------------------------- |
| `a`  | `uint256` | The amount of underlying tokens deposited           |
| `r`  | `address` | The receiver of the principal tokens                |
| `m`  | `uint256` | Minimum number of shares that the user will receive |

**Returns**

| Name     | Type      | Description                                      |
| -------- | --------- | ------------------------------------------------ |
| `<none>` | `uint256` | uint256 The amount of principal tokens purchased |

#### deposit

Before maturity spends `assets` of underlying, and sends `shares` of PTs to `receiver`. Post or at maturity, reverts.

```solidity
function deposit(uint256 a, address r) external override returns (uint256);
```

**Parameters**

| Name | Type      | Description                               |
| ---- | --------- | ----------------------------------------- |
| `a`  | `uint256` | The amount of underlying tokens deposited |
| `r`  | `address` | The receiver of the principal tokens      |

**Returns**

| Name     | Type      | Description                                                    |
| -------- | --------- | -------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of principal tokens burnt by the withdrawal |

#### mint

Before maturity mints `s` of PTs to `r` by spending underlying. Post or at maturity, reverts.

```solidity
function mint(uint256 s, address r, uint256 m) external returns (uint256);
```

**Parameters**

| Name | Type      | Description                                           |
| ---- | --------- | ----------------------------------------------------- |
| `s`  | `uint256` | The amount of shares being minted                     |
| `r`  | `address` | The receiver of the underlying tokens being withdrawn |
| `m`  | `uint256` | Maximum amount of underlying that the user will spend |

**Returns**

| Name     | Type      | Description                                      |
| -------- | --------- | ------------------------------------------------ |
| `<none>` | `uint256` | uint256 The amount of principal tokens purchased |

#### mint

Before maturity mints `shares` of PTs to `receiver` by spending underlying. Post or at maturity, reverts.

```solidity
function mint(uint256 s, address r) external override returns (uint256);
```

**Parameters**

| Name | Type      | Description                                           |
| ---- | --------- | ----------------------------------------------------- |
| `s`  | `uint256` | The amount of shares being minted                     |
| `r`  | `address` | The receiver of the underlying tokens being withdrawn |

**Returns**

| Name     | Type      | Description                                      |
| -------- | --------- | ------------------------------------------------ |
| `<none>` | `uint256` | uint256 The amount of principal tokens purchased |

#### withdraw

At or after maturity, burns PTs from owner and sends `a` underlying to `r`. Before maturity, sends `a` by selling shares of PT on a YieldSpace AMM.

```solidity
function withdraw(uint256 a, address r, address o, uint256 m) external returns (uint256);
```

**Parameters**

| Name | Type      | Description                                           |
| ---- | --------- | ----------------------------------------------------- |
| `a`  | `uint256` | The amount of underlying tokens withdrawn             |
| `r`  | `address` | The receiver of the underlying tokens being withdrawn |
| `o`  | `address` | The owner of the underlying tokens                    |
| `m`  | `uint256` | Maximum amount of PTs to be sold                      |

**Returns**

| Name     | Type      | Description                                                    |
| -------- | --------- | -------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of principal tokens burnt by the withdrawal |

#### withdraw

At or after maturity, burns PTs from owner and sends `a` underlying to `r`. Before maturity, sends `a` by selling shares of PT on a YieldSpace AMM.

```solidity
function withdraw(uint256 a, address r, address o) external override returns (uint256);
```

**Parameters**

| Name | Type      | Description                                           |
| ---- | --------- | ----------------------------------------------------- |
| `a`  | `uint256` | The amount of underlying tokens withdrawn             |
| `r`  | `address` | The receiver of the underlying tokens being withdrawn |
| `o`  | `address` | The owner of the underlying tokens                    |

**Returns**

| Name     | Type      | Description                                                    |
| -------- | --------- | -------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of principal tokens burnt by the withdrawal |

#### redeem

At or after maturity, burns exactly `s` of Principal Tokens from `o` and sends underlying tokens to `r`. Before maturity, sends underlying by selling `s` of PT on a YieldSpace AMM.

```solidity
function redeem(uint256 s, address r, address o, uint256 m) external returns (uint256);
```

**Parameters**

| Name | Type      | Description                                                            |
| ---- | --------- | ---------------------------------------------------------------------- |
| `s`  | `uint256` | The number of shares to be burned in exchange for the underlying asset |
| `r`  | `address` | The receiver of the underlying tokens being withdrawn                  |
| `o`  | `address` | Address of the owner of the shares being burned                        |
| `m`  | `uint256` | Minimum amount of underlying that must be received                     |

**Returns**

| Name     | Type      | Description                                                           |
| -------- | --------- | --------------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of underlying tokens distributed by the redemption |

#### redeem

At or after maturity, burns exactly `shares` of Principal Tokens from `owner` and sends `assets` of underlying tokens to `receiver`. Before maturity, sells `s` of PT on a YieldSpace AMM.

```solidity
function redeem(uint256 s, address r, address o) external override returns (uint256);
```

**Parameters**

| Name | Type      | Description                                                            |
| ---- | --------- | ---------------------------------------------------------------------- |
| `s`  | `uint256` | The number of shares to be burned in exchange for the underlying asset |
| `r`  | `address` | The receiver of the underlying tokens being withdrawn                  |
| `o`  | `address` | Address of the owner of the shares being burned                        |

**Returns**

| Name     | Type      | Description                                                           |
| -------- | --------- | --------------------------------------------------------------------- |
| `<none>` | `uint256` | uint256 The amount of underlying tokens distributed by the redemption |

#### authBurn

```solidity
function authBurn(address f, uint256 a) external authorized(redeemer) returns (bool);
```

**Parameters**

| Name | Type      | Description          |
| ---- | --------- | -------------------- |
| `f`  | `address` | Address to burn from |
| `a`  | `uint256` | Amount to burn       |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool true if successful |

#### authMint

```solidity
function authMint(address t, uint256 a) external authorized(lender) returns (bool);
```

**Parameters**

| Name | Type      | Description                         |
| ---- | --------- | ----------------------------------- |
| `t`  | `address` | Address recieving the minted amount |
| `a`  | `uint256` | The amount to mint                  |

**Returns**

| Name     | Type   | Description             |
| -------- | ------ | ----------------------- |
| `<none>` | `bool` | bool True if successful |

#### authApprove

```solidity
function authApprove(address o, address s, uint256 a) external authorized(redeemer) returns (bool);
```

**Parameters**

| Name | Type      | Description                        |
| ---- | --------- | ---------------------------------- |
| `o`  | `address` | Address of the owner of the tokens |
| `s`  | `address` | Address of the spender             |
| `a`  | `uint256` | Amount to be approved              |

#### \_deposit

```solidity
function _deposit(address r, uint256 a, uint256 m) internal returns (uint256);
```

#### \_mint

```solidity
function _mint(address r, uint256 s, uint256 m) internal returns (uint256);
```

#### \_withdraw

```solidity
function _withdraw(uint256 a, address r, address o, uint256 m) internal returns (uint256);
```

#### \_redeem

```solidity
function _redeem(uint256 s, address r, address o, uint256 m) internal returns (uint256);
```


# Deployed Contract Addresses

This page contains the current deployments on mainnet and Goerli

## Mainnet

<table><thead><tr><th width="176">Contract</th><th>Address</th></tr></thead><tbody><tr><td>MarketPlace</td><td>0xcd1D02fDa51CD24123e857CE94e4356D5C073b3f</td></tr><tr><td>Lender</td><td>0x429B47C4AEADD42BBcB118651C8984086Bfc4551</td></tr><tr><td>Redeemer</td><td>0x4eA57ef203E91AE8c7D9822aa09CC719a9c01aC6</td></tr></tbody></table>

#### Deployed Market

<table><thead><tr><th width="227"></th><th></th></tr></thead><tbody><tr><td>maturity</td><td>1688342400 (JUN 2023)</td></tr><tr><td>underlying</td><td>0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 (USDC)</td></tr><tr><td>iPT YieldSpace Pool</td><td>0xCC696A6a6174CF592e5CBF680F2aa95b02e98E15</td></tr><tr><td>Illuminate PT</td><td>0x3393f10c89F59d8c2533E559F931D147259A0A1B</td></tr><tr><td>Swivel PT</td><td>0x7918dAf8f0F00c585DDadACd40dd215b6fF11897</td></tr><tr><td>Sense PT</td><td>0x869a70c198c937801b26d2701dc8e4e8c4de354a</td></tr><tr><td>Notional PT</td><td>0x3f4b94D67FA86638f3dB925e4Ce6926471b27953</td></tr></tbody></table>

## Goerli

<table><thead><tr><th width="176">Contract</th><th>Address</th></tr></thead><tbody><tr><td>MarketPlace</td><td>0xDBcaCe3715a2206113a81e6cC02e8aBE907Ece26</td></tr><tr><td>Lender</td><td>0xb338Caa1488c319a1E938af02ab1BBe74dc7Fd17</td></tr><tr><td>Redeemer</td><td>0x8CA4ef1314Ce95Dfb965c31a96C6E3d111Cc1079</td></tr></tbody></table>

####

<table><thead><tr><th width="227"></th><th></th></tr></thead><tbody><tr><td>maturity</td><td>1696115940 (SEP 2023)</td></tr><tr><td>underlying</td><td>0x07865c6E87B9F70255377e024ace6630C1Eaa37F (USDC)</td></tr><tr><td>iPT Yield Space Pool</td><td>0x81B48E253E92f1501DF0277b958CAF8121d05e4e</td></tr><tr><td>Illuminate PT</td><td>0xBa8647Fbc6D11fa6d634289D0627c1eD29d54D07</td></tr><tr><td>Swivel PT</td><td>0xac7e226c324103d8709c63c175a137c1436f5ed5</td></tr><tr><td>Yield PT</td><td>0x868E267912E8E94BF27F91aBCAfA6a4BC283Eb5C</td></tr></tbody></table>


# Critical Attributes

This page documents critical attributes stored by the contract federation

## MarketPlace

* `markets`: maps tuples of underlying (address) and maturity (uint256) to an array of ERC5095 principal tokens
* `Principals`: enum that maps fixed rate protocols to an index value. This is used in the `markets` mapping to determine which protocol should be used for a given principal token in a market
* `pools`: maps markets (an underlying and a maturity) to a Yield Space Pools to facilitate swaps between Illuminate principal tokens and the underlying

## Lender

* `fees`: maps underlying token assets to the amount in fees collected by the Lender contract
* `withdrawals`: maps a token address to a point in time where withdrawals may occur
* `paused`: maps principal tokens using the same structure as `markets` to determine if the principal token may be lent or minted

## Redeemer

* `paused`: maps markets to whether or not they may be redeemed
* `holdings`: maps markets to the amount of underlying has been redeemed by a given market. This is separates different markets that share an underlying based on their maturity. It is also used for partial redemptions in the event that the principal tokens for protocols within a market do not redeem 1:1


# Key Roles

Describes the abilities and roles of the admin

## Admin

Our Lender, Redeemer and MarketPlace contract rely on an `admin` to control certain aspects. They are described on a contract basis below.

### Lender

In the Lender contract, the `admin` has the following privileges:

* `approve`: the admin is responsible for executing the approval of the redeemer contract. This is necessary to facilitate the usage of Principal Tokens by the Redeemer
* `setAdmin`: the admin is the only one that can transfer admin powers
* `setFee`: the admin can see a fee rate. This fee rate has a minimum value (which limits the amount of fees extracted per transaction)
* `setMarketPlace`: the admin can set the MarketPlace contract
* `scheduleWithdrawal` and `scheduleFeeChange`: the admin can schedule these actions (there is a 3 day holding period)
* `blockWithdrawal` and `blockFeeChange`: the admin may block fee changes and withdrawals
* `withdrawFee`: the admin may withdraw fees from the contract. The amount extractable from the contract is limited by the `fees` mapping
* `withdraw`: the admin may withdraw the entire balance of the token (this is an emergency measure)
* `pause`: the admin may pause certain markets. This may be necessary in the event that an integrated principal token experiences insolvency or their own pauses

### Redeemer

In the Redeemer contract, the `admin` has the following privileges:

* `setAdmin`: the admin is the only one that can transfer admin powers
* `setMarketPlace`: the admin can set the MarketPlace contract
* `setConverter`: the admin can set the Converter contract
* `setLender`: the admin can set the Lender contract
* `setFee`: the admin can see a fee rate for automatic redemptions. This fee rate has a minimum value (which limits the amount of fees extracted per transaction)
* `pauseRedemptions`: the admin may pause the redemption process. This is an emergency measure

### MarketPlace

In the MarketPlace contract, the `admin` has the following privileges:

* `createMarket`: the admin can create new markets
* `setPrincipal`: the admin can add principal tokens to a market if one has not already been set for the protocol
* `setPool`: the admin can set a Yield Space Pool for swapping Illuminate principal tokens and the underlying
* `setAdmin`: the admin is the only one that can transfer admin powers

## Lenders

These are the users of the protocol. They will be able to use Illuminate to arbitrage fixed rates markets and lend conveniently via our protocol and API.

### Lender

* `lend`: this method will swap underlying assets for Illuminate's principal tokens in a given market
* `mint`: this method will mint Illuminate principal tokens in exchange for principal tokens
* `batch`: this method allows the user to chain multiple `lend` and `mint` calls together efficiently

### Redeemer

* `redeem`: this method allows the user to swap their Illuminate principal tokens for the underlying asset after maturity

### MarketPlace

* `sellPrincipalToken`: allows user to swap Illuminate principal tokens for the underlying asset prior to maturity
* `buyPrincipalToken`: allows user to swap underlying tokens for Illuminate principal tokens
* `sellUnderlying`: allows user to swap underlying tokens for Illuminate principal tokens
* `buyUnderlying`: allows user to swap Illuminate principal tokens for underlying tokens
* `batch`: this method allows the user to chain multiple swap methods together efficiently

###


# Contract Relationships

Describe how the Lender, Redeemer, MarketPlace and Converter contracts related to one another

## Lender <-> MarketPlace

The Lender is related to the MarketPlace contract. Primarily, it relies on the MarketPlace for information about the available markets. MarketPlace contains a `markets` mapping that stores principal tokens for a given market.

## Redeemer <-> MarketPlace

Similar to the Lender, the Redeemer relies on the MarketPlace contract for information about markets.&#x20;

## Redeemer <-> Converter

The Redeemer relies on the Converter contract to convert redeemed assets to the underlying asset for a given market. Specifically, Pendle and Sense redeem to the compounding asset. As a convenience to users, we convert these assets on behalf of users via the Converter contract.


# Operation Checklists

What each redeem and lend must accomplish to be successful

Note that this refers to non-Illuminate `lend` and `redeem` calls - Illuminate calls are slightly different.

## Lend

* [ ] Extract fee
* [ ] Transfer underlying to lender contract
* [ ] Swap the underlying for PTs
* [ ] Verify receipt of PTs
* [ ] Mint equivalent amount of Illuminate PTs to the user

## Redeem

* [ ] Verify principal
* [ ] Verify token has matured
* [ ] Transfer PTs for the protocol from the Lender to Redeemer
* [ ] Execute the redemption for underlying (if necessary, convert to underlying)
* [ ] Update the holdings mapping (which determines how much underlying has been redeemed, necessary in the event of partial redemptions)


# Deposit Lifecycle

Describes the course of funds as they move through Illuminate

At a high level, users receive Illuminate Principal Tokens that represent their lending position, and upon maturity, may redeem Illuminate Principal Tokens for underlying at a 1:1 ratio.

## Lend

The first step in the deposit lifecycle is calling `lend` on the Lender contract. In doing so, the user sends their underlying to the Lender contract, and in exchange receives Illuminate Principal Tokens. The Lender contract custodies the protocol principal tokens the user elected to use to execute the loan.

As an example, let's say a user calls `lend` on Lender.sol, lending 100 USDC on Notional in the December 2022 market. At the end of the `lend` call, and can receive a return of 5% over the term of the loan:

* Lender: holds 105 Notional (External) PTs
* User: holds 105 Illuminate PTs

## Mint

As an alternative to directly lending through Illuminate, users can also purchase external principal tokens and then wrap them at a 1:1 ratio into Illuminate Principal Tokens.

As an example, let's say a user lends 100 USDC directly on Notional in the December 2022 market at a rate of 5% for one year. This leaves the user with 105 Notional PTs.\
\
By then calling `mint` on Lender.sol, this user can then wrap their 105 Notional PTs into 105 Illuminate PTs (likely in order to perform arbitrage).

* Lender: holds 105 Notional (External) PTs
* User: holds 105 Illuminate PTs

## Redeem (External PT)

Once the lending market has matured, anyone can call protocol `redeem` to retrieve each protocol's principal tokens and convert them to the underlying asset for the matured market. Calling a protocol redeem results in the Lender transferring its principal token holdings to the Redeemer contract. From there, the Redeemer calls the protocol's redeem method to get the underlying asset. In addition, the Redeemer updates a `holdings` mapping which indicates how much of the underlying was redeemed for a particular market.

Following our example, at the end of a `redeem` call for Notional:

* Lender: no longer holds any of Notional's PTs
* Redeemer: now holds 105 USDC (redeemed via Notional)
* User: still holds the original 105 Illuminate PTs

## Redeem (Illuminate PT)

Finally, a user can call `redeem` to redeem their ERC5095 Illuminate principal tokens for the underlying. In calling Illuminates `redeem`, the user transfers their PTs to the Redeemer contract. In turn, the Redeemer burns the tokens and transfers the underlying to the user. At this point, the `holdings` mapping is used to determine the ratio of principal tokens owed to the user. In addition, the `holdings` mapping is updated to reflect that the redemption of the Illuminate PTs has occurred.

Again, from our example, following the Illuminate `redeem` call:

* Lender: no longer holds any PTs for the market
* Redeemer: no longer holds the redeemed underlying asset
* User: now holds the 105 USDC from their loan


# Error Codes

<table><thead><tr><th width="97">Code</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>unauthorized</td></tr><tr><td>1</td><td>paused</td></tr><tr><td>2</td><td>incorrect maturity</td></tr><tr><td>3</td><td>incorrect underlying</td></tr><tr><td>4</td><td>array length mismatch</td></tr><tr><td>5</td><td>marketplace already set</td></tr><tr><td>6</td><td>invalid principal</td></tr><tr><td>7</td><td>market not matured</td></tr><tr><td>8</td><td>lender already set</td></tr><tr><td>9</td><td>market already exists</td></tr><tr><td>10</td><td>pool already exists</td></tr><tr><td>11</td><td>principal tokens not received</td></tr><tr><td>12</td><td>pool does not match principal token</td></tr><tr><td>13</td><td>underlying tokens not received</td></tr><tr><td>14</td><td>minimum fee not paid</td></tr><tr><td>15</td><td>zc token redemption failed</td></tr><tr><td>16</td><td>too much slippage</td></tr><tr><td>17</td><td>redemptions paused</td></tr><tr><td>18</td><td>no withdrawal scheduled</td></tr><tr><td>19</td><td>withdrawal still on hold</td></tr><tr><td>20</td><td>insufficient allowance</td></tr><tr><td>21</td><td>market is past maturity</td></tr><tr><td>22</td><td>decimals do not match</td></tr><tr><td>23</td><td>fee change is not scheduled</td></tr><tr><td>24</td><td>fee change is not ready yet</td></tr><tr><td>25</td><td>fee is set too high</td></tr><tr><td>26</td><td>principal token not set</td></tr><tr><td>27</td><td>pool does not match underlying token</td></tr><tr><td>28</td><td>compound redeem returned error</td></tr><tr><td>29</td><td>invalid periphery contract</td></tr><tr><td>30</td><td>reentrancy not allowed</td></tr><tr><td>31</td><td>rate limit exceeded for protocol</td></tr><tr><td>32</td><td>illuminate PTs may not be minted</td></tr></tbody></table>


# Smart Contract Integration

This page describes how to integrate Illuminate into your smart contracts with examples.

## Looking up markets

We can begin with finding supported tokens and pools within an Illuminate market. A market is defined by a tuple of underlying (address) and maturity (uint256).

```solidity
address marketPlace = 0x9A74762723685c5EEE2f94b80a427dE1bf029426;

// To look up a market, you will need the maturity and underlying for a given market.
// In this example, we'll look up information about the USDC-MAR23 market.
uint256 maturity = 1680393600; // ~April 02, 2023
address underlying = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; // USDC

// First, we'll look up the supported principal tokens for the market.
// To do so, call the markets method on the MarketPlace contract. This method takes
// in an underlying, maturity and principal enum. The enum value, defined below, 
// returns the PT for a given market. A null address is returned if there is no PT
// for that particular market.
enum Principals {
   Illuminate, // 0
   Swivel, // 1
   Yield, // 2
   Element, // 3
   Pendle, // 4
   Tempus, // 5
   Sense, // 6
   Apwine, // 7
   Notional // 8
}

// To look up Pendle's PT for the USDC-MAR23 market:
address pendlePT = IMarketPlace(marketPlace).markets(underlying, maturity, 4);

// Additionally, we can get the Yield Space Pool for the Illuminate principal token
// by calling the pools method:
address iptPool = IMarketPlace(marketPlace).pools(underlying, maturity);

```

## Lending

The Lender contract provides convenience `lend` methods that swap between the underlying and supported PTs. Each protocol has a `lend` method that results in users receiving Illuminate principal tokens (iPTs).

```solidity
address lender = 0x8dF84b03F73a680E04b0A59EE173219026333107;

// This example is for USDC-MAR23 market, lending on Notional
uint8 principal = 8; // Notional's enum value from the MarketPlace contract
uint256 maturity = 1680393600; // ~April 02, 2023
address underlying = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; // USDC
uint256 amount = 100000000; // $100 USDC
uint256 minReceived = 90000000; // Slippage control: receive at least 90 iPTs

// First, approve the Lender to spend the user's underlying
IERC20(underlying).approve(lender, amount);

// Second, lend the underlying via Illuminate. 
// The amount of iPTs is returned by the lend method 
uint256 received = ILender(lender).lend(principal, maturity, underlying, amount, minReceived);
```

## Minting

If a user already has PTs, they can wrap them into iPTs via the Lender contract's `mint` method.

```solidity
address lender = 0x8dF84b03F73a680E04b0A59EE173219026333107;

// In this example, let's assume the user has Swivel's zcToken for this market
uint8 principal = 1; // Swivel's enum value from MarketPlace contract
uint256 maturity = 1680393600; // ~April 02, 2023
address underlying = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; // USDC
uint256 amount = 100000000; // $100 zcTokens
address zcToken = 0x3476303e9038833AeC9ccCd12747BD0E0d026a8B; // Swivel's PT

// First, approve the Lender to spend the user's principal token
IERC20(zcToken).approve(lender, amount);

// Wrap the zcToken in an iPT. The user will receive iPTs 1:1 for each PT sent 
// to the Lender
ILender(lender).mint(principal, underlying, maturity, amount);

```

## Redeeming

Once a market matures, users can `redeem` the underlying asset via the Redeemer contract.

{% hint style="warning" %}
Execution of the redemption should only be done after the Redeemer has redeemed the supported principal tokens from the Lender contract. Redeeming prior to this will result in lost funds.
{% endhint %}

```solidity
address redeemer = 0x7690e18b7c7BE861976fCBb8E5053D2a2ebaB1AD;

// Get the market that has matured
uint256 maturity = 1680393600; // ~April 02, 2023
address underlying = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; // USDC

// Execute the redemption
IRedeemer(redeemer).redeem(underlying, maturity);
```

## Swapping

Prior to maturity, users may swap their iPTs for the underlying, and vise versa via a Yield Space Pool.

```solidity
address marketPlace = 0x9A74762723685c5EEE2f94b80a427dE1bf029426;

// Get the market that will be used to swap on
address iPT = 0x49494b3CB41829011471A059a72A16652D95aD6f; // Illuminate's principal token
uint256 maturity = IERC5095(iPT).maturity(); // e.g. 1680393600 (~April 02, 2023)
address underlying = IERC5095(iPT).underlying(); // e.g. USDC
uint256 amount = 100000000; // $100 USDC (or iPTs, which have the same # of decimals)
uint256 slippage = 101000000; // Minimum number of tokens to receive in the swap

// First example: swap underlying for iPTs
// First, approve the MarketPlace contract to spend the underlying
IERC20(underlying).approve(marketPlace, amount);

// Conduct the swap
IMarketPlace(marketPlace).buyPrincipalToken(underlying, maturity, amount, slippage);

-----------------------------------------

// Second example: swap iPTs for underlying
// First, approve the MarketPlace contract to spend the iPT
IERC20(iPT).approve(marketPlace, amount);

// Conduct the swap
IMarketPlace(marketPlace).sellPrincipalToken(underlying, maturity, amount, slippage);
```

{% hint style="info" %}
Note that there are two other methods that can be used to faciliate swaps: `buyUnderlying` and `sellUnderlying`. These methods provide different slippage configurations, and require a similar flow to execute.
{% endhint %}

## Swapping with EIP4626 (EIP5095) Interfaces

Prior to maturity, users may swap their iPTs for the underlying, and vise versa via a Yield Space Pool.

```solidity
// Get the market that will be used to swap on
address iPT = 0x49494b3CB41829011471A059a72A16652D95aD6f; // Illuminate's principal token
uint256 maturity = IERC5095(iPT).maturity(); // e.g. 1680393600 (~April 02, 2023)
address underlying = IERC5095(iPT).underlying(); // e.g. USDC
uint256 amount = 100000000; // $100 USDC (or iPTs, which have the same # of decimals)
uint256 slippage = 101000000; // Minimum number of tokens to receive in the swap

// First example: swap underlying for iPTs
// First, approve the iPT contract to spend the underlying
IERC20(underlying).approve(iPT, amount);

// Conduct the swap through EIP5095 interfaces -- 
// Spends `amount` on iPTs through a YieldSpace pool, receiving at minimum `slippage`
IERC5095(iPT).deposit(address(this), amount, slippage);
```

## Checking for Paused States

Integrated protocols are subject to being paused on a principal or market basis by the `admin` of each respective contract. Below, we demonstrate how to check the paused state of the contracts.

```solidity
// The Lender contract stores the halted variable, which stops the
// entire Illuminate protocol.
address lender = 0x8dF84b03F73a680E04b0A59EE173219026333107;

// Fetch the halted flag
bool isIlluminateHalted = ILender(lender).halted();

// To determine if a particular protocol is stopped, check the paused mapping.
// This mapping uses the enum mapping from the MarketPlace to define the protocol.
// In this example, we check if Sense is paused on Illuminate.
bool isSensePaused = ILender(lender).paused(6);

// The MarketPlace may also pause a market, by setting the iPT address to 0 via the
// setPrincipal call. To check if a market is paused, call markets.
address marketPlace = 0x9A74762723685c5EEE2f94b80a427dE1bf029426;

// In this example, we'll check if the USDC-MAR23 market has been paused
uint256 maturity = 1680393600; // ~April 02, 2023
address underlying = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; // USDC
address isUSDCMAR23Paused = IMarketPlace(marketPlace).markets(underlying, maturity, 0);
requre(isUSDCMAR23Paused != address(0), 'market paused');

// In addition, the Redeemer contract can pause the redemption of iPT on a market
// basis. This can be looked up via the maturity and underlying pair.
address redeemer = 0x7690e18b7c7BE861976fCBb8E5053D2a2ebaB1AD;

// In this example, we'll look up the USDC-MAR23 market from above.
bool isPTRedemptionPaused = IRedeemer(redeemer).paused(underlying, maturity);

```


# IlluminAPI

The endpoints under the Illuminate API section all share the same base URL `https://illumigate.swivel.exchange` no matter on the environment that is being used.&#x20;

There are two active, live environments so base URL should be changed accordingly:

* Testnet base URL **<https://illumigate-dev.swivel.exchange>**
* Mainnet base URL **<https://illumigate-main.swivel.exchange>.**


# GET

All GET endpoints are documented here. Base URLs should be changed in relation to the environment that is used: Testnet or Mainnet.

{% content-ref url="/pages/wxxbHGBKDdm2ZDButDxs" %}
[Get Markets](/illuminapi/get/get-markets)
{% endcontent-ref %}

{% content-ref url="/pages/LYArBJmr1VwapnFwj2bl" %}
[Get Quotes](/illuminapi/get/get-quotes)
{% endcontent-ref %}

{% content-ref url="/pages/cxSJkZQiHPP5v6HQKRmh" %}
[Get Best Quote](/illuminapi/get/get-best-quote)
{% endcontent-ref %}

{% content-ref url="/pages/FIS57e1XbWwuKbxJqYrh" %}
[Get Pools](/illuminapi/get/get-pools)
{% endcontent-ref %}

{% content-ref url="/pages/6bDZVHIMUCSjLg4ib49Y" %}
[Get Pool](/illuminapi/get/get-pool)
{% endcontent-ref %}

{% content-ref url="/pages/UtLzSU5x9Qjl6rucQko2" %}
[Get Raw Pool APYs](/illuminapi/get/get-raw-pool-apys)
{% endcontent-ref %}

{% content-ref url="/pages/Kp8DRHM4P9sTQaxXPHqc" %}
[Get User Positions](/illuminapi/get/get-user-positions)
{% endcontent-ref %}

{% content-ref url="/pages/4erki9R4COGedrxBfJcs" %}
[Get Status](/illuminapi/get/get-status)
{% endcontent-ref %}


# Get Markets

## Get Markets

<mark style="color:blue;">`GET`</mark> `https://illumigate.swivel.exchange/v1/markets?status=s&depth=d`

This endpoint allows you to request a list of markets.

#### Query Parameters

| Name   | Type    | Description                      |
| ------ | ------- | -------------------------------- |
| status | string  | **active** or **matured**        |
| depth  | integer | The number of markets to return. |

{% tabs %}
{% tab title="200: OK " %}

```javascript
[
  {
    "underlying": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
    "maturity": "1688085200",
    "principals": [
      "0x1234",
      "0x2345",
      "0x3456",
      "0x4567",
      "0x5678",
      "0x6789",
      "0x7890",
      "0x8910",
      "0x8012"
    ],
    "created": "1671841482",
    "element": "0x1023",
    "apwine": "0x2340"
  }
]
```

{% endtab %}
{% endtabs %}


# Get Quotes

<mark style="color:blue;">`GET`</mark> `https://illumigate.swivel.exchange/v1/quotes?underlying=u&maturity=m&amount=a`

This endpoint allows you to request a set of lending quotes from the following integrated protocols:

**`0`** - Illuminate

`1` - Swivel

`2` - Yield

`3` - Element

`4` - Pendle

`5` - Tempus

`6` - Sense

`7` - Apwine

`8` - Notional.

#### Query Parameters

| Name       | Type   | Description                                                           |
| ---------- | ------ | --------------------------------------------------------------------- |
| amount     | string | The lend amount.                                                      |
| underlying | string | The underlying token contract being transacted. E.g. USDC, DAI, etc., |
| maturity   | string | The maturity of market in unix seconds.                               |

{% tabs %}
{% tab title="200: OK " %}

```javascript
[
  {
    "amount": "1000000000",
    "pt": {
      "amount": "1014027026",
      "decimals": 6,
      "maturity": "1688085200",
      "address": "0xeB325a92EA85dA6fDE3150e1055D7Dc74b4dC276",
      "meta": {
        "poolAddress": "0xA7711623026dAcDfcB0471185C6E9331f50cabff"
      }
    },
    "underlying": {
      "address": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
      "decimals": 6
    },
    "maturity": "1688085200",
    "principal": 0,
    "apy": "0.03338371764"
  },
  ...
]  
```

{% endtab %}
{% endtabs %}


# Get Best Quote

<mark style="color:blue;">`GET`</mark> `https://illumigate.swivel.exchange/v1/quotes/best?amount=a`

This endpoint allows you to request the best lending quote from the following integrated protocols:

**`0`** - Illuminate

**`1`** - Swivel

**`2`** - Yield

**`3`** - Element

**`4`** - Pendle

**`5`** - Tempus

**`6`** - Sense

**`7`** - Apwine

**`8`** - Notional.

#### Query Parameters

| Name                                     | Type   | Description      |
| ---------------------------------------- | ------ | ---------------- |
| amount<mark style="color:red;">\*</mark> | string | The lend amount. |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "amount": "1000000000",
  "pt": {
    "amount": "1014027026",
    "decimals": 6,
    "maturity": "1688085200",
    "address": "0xeB325a92EA85dA6fDE3150e1055D7Dc74b4dC276",
    "meta": {
      "poolAddress": "0xA7711623026dAcDfcB0471185C6E9331f50cabff"
    }
  },
  "underlying": {
    "address": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
    "decimals": 6
  },
  "maturity": "1688085200",
  "principal": 0,
  "apy": "0.03338371764"
}
```

{% endtab %}
{% endtabs %}


# Get Pools

<mark style="color:blue;">`GET`</mark> `https://illumigate.swivel.exchange/v1/pools`

This endpoint allows you to request a list of pools.

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "address": "0xA7711623026dAcDfcB0471185C6E9331f50cabff",
  "underlying": "0x07865c6E87B9F70255377e024ace6630C1Eaa37F",
  "pt": "0xeB325a92EA85dA6fDE3150e1055D7Dc74b4dC276",
  "maturity": "1688085200",
  "created": 1671842352,
  "apy": "0.092813867560339144"
}
```

{% endtab %}
{% endtabs %}


# Get Pool

<mark style="color:blue;">`GET`</mark> `https://illumigate.swivel.exchange/v1/pools/:address`

This endpoint allows you to request a specific pool.

#### Path Parameters

| Name                                      | Type   | Description       |
| ----------------------------------------- | ------ | ----------------- |
| address<mark style="color:red;">\*</mark> | string | The pool address. |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}


# Get Raw Pool APYs

<mark style="color:blue;">`GET`</mark> `https://illumigate.swivel.exchange/v1/pools/:address/apys?start=s&end=e`

This endpoint allows you to request a list of pool raw APYs for the specified interval.

#### Path Parameters

| Name                                      | Type   | Description       |
| ----------------------------------------- | ------ | ----------------- |
| address<mark style="color:red;">\*</mark> | string | The pool address. |

#### Query Parameters

| Name                                    | Type   | Description                                |
| --------------------------------------- | ------ | ------------------------------------------ |
| start<mark style="color:red;">\*</mark> | string | The start of the interval in unix seconds. |
| end                                     | string | The end of the interval in unix seconds.   |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "address": "0xA7711623026dAcDfcB0471185C6E9331f50cabff",
    "start": "1673308600",
    "end": "1673395300",
    "rawApys": [
        {
            "value": "0.000032123671905683",
            "created": "1673308800"
        },
        {
            "value": "0.000002851707469372",
            "created": "1673395200"
        }
    ]
}
```

{% endtab %}
{% endtabs %}


# Get User Positions

<mark style="color:blue;">`GET`</mark> `https://illumigate.swivel.exchange/v1/users/:address/positions?type=t&status=s`

This endpoint allows you to request a list of user lending and pooling positions.

#### Path Parameters

| Name    | Type   | Description                 |
| ------- | ------ | --------------------------- |
| address | string | User public address in hex. |

#### Query Parameters

| Name   | Type   | Description                                                                                                        |
| ------ | ------ | ------------------------------------------------------------------------------------------------------------------ |
| type   | string | Positions type: **lending** or **pooling**. If not specified, both lending and pooling positions will be returned. |
| status | string | Market status: **active** or **matured**. If not specified, only positions for active markets will be returned.    |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "id": "0xD83F3CE852bcC65231054099A2270642700ADADD",
  "lending": {
    "0x07865c6E87B9F70255377e024ace6630C1Eaa37F": {
      "1688085200": {
        "totalSpent": "707882988",
        "totalReturned": "719523434",
        "costBasis": "0.983822",
        "lastPrice": "0.984748",
        "interestEarned": "11640446"
      },
      "1696115940": {
        "totalSpent": "120000000",
        "totalReturned": "119880000",
        "costBasis": "1.001001",
        "lastPrice": "1.001001",
        "interestEarned": "-120000"
      }
    }
  },
  "pooling": {
    "0x07865c6E87B9F70255377e024ace6630C1Eaa37F": {
      "1688085200": {
        "created": "1673380691"
      }
    },
    "0x2899a03ffDab5C90BADc5920b4f53B0884EB13cC": {
      "1688086200": {
        "created": "1674069975"
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Get Status

<mark style="color:blue;">`GET`</mark> `https://illumigate.swivel.exchange/status`

This endpoint allows you to request a status of the API and the protocol.

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
  "status": "Illuminate protocol is active",
  "started": 1674757292,
  "illuminatePaused": false,
  "protocolsPaused": [
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false
  ]
}
```

{% endtab %}
{% endtabs %}


# POST


# Illuminate-js


# Media Kit

### PNG Logos

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FBoihQLUSfSlVyRLz2gMe%2FIlluminate%20wordmark%20blue.png?alt=media&amp;token=6ce5dda9-4c47-400c-9e7e-f4d83123ea7a" alt=""><figcaption><p>Wordmark in branded blue</p></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FDchbqM1Y5zGdAMNPiRot%2FIlluminate%20wordmark%20light.png?alt=media&amp;token=8e2edc02-08a6-4b29-825d-29d4b10de0b4" alt=""><figcaption><p>Wordmark in light greyscale for use against dark BG</p></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2F8wA3zBSPJtF9duqkuSYe%2FIlluminate%20wordmark%20dark.png?alt=media&amp;token=179e6b47-6826-43ba-90a1-801bde6f2f52" alt=""><figcaption><p>Wordmark in dark greyscale for use against light BG</p></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FbZeLDFE4C85Pw16083JA%2Flogo-blue.png?alt=media&amp;token=6e71077c-60d1-4546-b925-4f05bca94b93" alt=""><figcaption><p>Logo by itself in blue</p></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2F3zVkjbSq7zMKl6ph0cAy%2Flogo-light.png?alt=media&amp;token=b1c57324-18ca-4639-9e5a-309c8e75613f" alt=""><figcaption><p>Logo by itself in light greyscale</p></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2Fzk8PGLP8bjsfHjXtkezB%2Flogo-dark.png?alt=media&amp;token=b4d915d8-9598-4049-bb11-72577008542d" alt=""><figcaption><p>Logo by itself in dark greyscale</p></figcaption></figure>

### SVG Logos

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FVZKeQuUlRl9CpTBNDOn6%2FIlluminate%20wordmark%20blue%20vector.svg?alt=media&amp;token=09a0fd14-5951-4bea-9845-5ca13c6b52b4" alt=""><figcaption><p>Scalable wordmark in branded blue</p></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FZCeOAme9ZgrFV9xtwOZ0%2FIlluminate%20wordmark%20light%20vector.svg?alt=media&amp;token=dca4de66-3f8e-4af7-acbc-f3131773edf3" alt=""><figcaption><p>Scalable wordmark in light greysacle for use with dark BG</p></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2F02CeuRMmIHVfkANGek2c%2FIlluminate%20wordmark%20dark%20vector.svg?alt=media&amp;token=ecc7858f-ad68-4a53-8939-69d36489bab6" alt=""><figcaption><p>Scalable wordmark in dark greysacle for use with light BG</p></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FPfVkwkpZN9MQfNbECbp7%2Flogo-blue.svg?alt=media&amp;token=a3f9ed42-ef71-41f6-af3b-0f52f770010b" alt="Scalable logo alone in branded blue"><figcaption></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2FOH7ukjXiztIm7w2MWOjP%2Flogo-light.svg?alt=media&amp;token=3f405f00-173c-40c0-a089-3060db7a7b9f" alt="Scalable logo alone in light greysacle for use with dark BG"><figcaption></figcaption></figure>

<figure><img src="https://694408789-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fhpe4cn6nUrSwzD5udpkV%2Fuploads%2Fr0FDHYMbesADIVjTyULR%2Flogo-dark.svg?alt=media&amp;token=f3f9c43a-087b-4fe9-a2bb-6ee19ac7cab8" alt="Scalable wordmark in dark greysacle for use with light BG"><figcaption></figcaption></figure>

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


# Misc


# FAQ

Frequently Asked Questions

### **What are PT's ?**

PT's are Principal Tokens. Lending platforms use PTs to represent the redeemable principal of your lent capital.

### **What are iPTs?**

The core mechanism behind the Illuminate Protocol is the wrapping of external principal tokens into "meta" principal tokens, "Illuminate PTs" (iPTs) which comply with  EIP-5095. \
\
They are redeemable at a 1:1 ratio for the underlying assets upon maturity, and follow a standard interface allowing easy integration of Illuminate into any dApp or wallet.&#x20;

### **How is the rate of return calculated?**

The rate of return is a function of the discounted price paid for principal tokens and their full redeeming price upon market maturity. The difference in proceeds is represented as a fixed rate return.&#x20;

For example, if an USDC-based iPT due to mature in one year trades at .95, it would represent a 5.25% fixed-APY return for the lender.

### **Where do the fixed rates come from?**

As a fixed-yield aggregator, our yield comes from the various available overcollateralized fixed-yield lending protocols. These include: Swivel, Element, Notional, Yield, APWine, Tempus, Sense, Pendle, and more as they release.

These protocols then source their yields either from direct overcollateralized lending (Yield & Notional), or through the “Yield Tokenization” of overcollateralized lending markets Aave, Compound and Euler.

### **When I lend on Illuminate, where is my money held?**

Your principal is sent directly to the protocol with the highest yield available. This could be a single protocol, or a blend of several sources. *(Link to Ecosystem explainer)*

1. Illuminate accesses several sources of Principal Tokens, making them available and interchangeable via a wrapped metaPrincipal token (see [iPTs](#what-are-ipts)).
2. The fixed rate protocols Illuminate integrates use different market mechanics to price their PTs, but all use [Tokenized Yield](#what-is-tokenized-yield) to create fixed lending products.
3. Your deposits ultimately lie on overcollateralized lending or liquid staking protocols, passing through the most efficient fixed rate marketplace at the time of deposit, securing a lending agreement for the redemption of your principal and your future yield at a 1 to 1 rate.

### **What is Tokenized Yield?**

Tokenized Yield involves depositing to overcollateralized lending/liquid staking protocols (such as Lido, Rocketpool, Frax, Compound, Aave, Yearn, Rari, Fraxlend, & future EIP-4626 compliant protocols.), and tokenizing the deposit into the redeemable principal lent ([Principal Tokens](#what-are-pts)) and the tokenized cash flow of the lending platform's variable rate (names vary by protocol, but often called Yield Tokens, Notional Tokens, etc.)

### **What risks are associated with lending/pooling on Illuminate?**

Illuminate shares the same core risks that come with all DeFi protocols: Smart Contract Bugs + Reviewer Oversight, Oracle Liveliness, and Liquidator Liveliness. Should any of our external integrations face a shortfall event, iPTs may then become partially collateralized.

### **What is Pooling?**

Illuminate makes it possible to trade the PT's of several fixed rate protocols because of the [iPT](#what-are-ipts) wrapper. Liquid pools of iPT plus Underlying for each market enables easy and efficient transactions.&#x20;

Anyone can pool PTs plus the underlying asset for a specific market in exchange for LP tokens, earning [pool rewards](#how-are-pool-rewards-calculated).

### **How are Pool rewards calculated?**

### **What happens if Illuminate or one of its integrations is hacked?**

Should any of our external integrations face a shortfall event, iPTs may become partially collateralized. We also provide insurance with a baseline coverage of up to $10,000,000 through our partnership with Sherlock.

### **How do you ensure your smart contracts are safe?**

Through Audits, and Insurance:

* Audits: We work to reduce these risks through diligent audits alongside Code4rena and Sherlock(TBD). For a report of our first audit with code4rena, check out the official report, and our blog post review: Code4rena: [Link](https://code4rena.com/contests/2022-06-illuminate-contest)

(Disclaimer: audits should not be considered an advertisement of safety, and are only one indicator of the safety of a protocol.)

* We also provide insurance through our safety module (Information TBD) and a baseline coverage of up to $10,000,000 through our partnership with Sherlock (TBD).

### **What is the difference between market maturities?**

Markets with more time until maturity have more time for yield to generate, and typically the PTs are sold at higher discount, translating to better overall yields if the position is held until maturity.

Markets closer to maturity have less time to accrue yield, so they typically produce less return overall under normal market circumstances.

### **How do you guarantee the best rate?**

Illuminate uses oracles alongside an API that perpetually determines which integrated protocol has the most discounted Principal Tokens for a given market, for the transaction amount quoted.

### **Why is yield at maturity less than the APY percent of the amount lent?**

APY is a rate standard that simplifies comparisons for lenders seeking better returns, and reflects the rate of return for investments held for one year. Not every market has a year left to maturity, or even that long of a term, and so APY is not a measure of guaranteed return, but a standardized basis for comparison.


