# Smart Contract Integration

## 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);

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.illuminate.finance/smart-contracts/smart-contract-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
