# Principal Token

The Principal Token is the main contract of Spectra. It is EIP [5095](https://eips.ethereum.org/EIPS/eip-5095), and [2612](https://eips.ethereum.org/EIPS/eip-2612) compliant.&#x20;

Users deposit the [IBT](/glossary.md#ibt) (or underlying token of the IBT) and receive the Principal Token (PT) and the [Yield Token](/glossary.md#yield-token) (YT) in return. For example, user deposits aDAI (or DAI) and receives the PT and YT of the aDAI position with a certain expiry.

The user can also [withdraw](#withdraw) and [redeem](#redeem) after and before expiry. For more information, see the [Tokenising Yield](/guides/tokenizing-yield.md) guide.

Code for PrincipalToken.sol can be found on [GitHub](https://github.com/perspectivefi/spectra-core/blob/main/src/tokens/PrincipalToken.sol).

## Methods

### deposit

```solidity
function deposit(
    uint256 assets,
    address receiver
) public returns (uint256 shares)
```

Deposits the amount of the underlying `assets` (e.g. DAI or USDC etc) and mints an amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) and [Yield Tokens](/glossary.md#yield-token) for the `receiver`.

{% hint style="warning" %}
`msg.sender` must approve the relevant allowance of the underlying asset before calling this method.
{% endhint %}

{% hint style="warning" %}
`deposit` must be called before the [`expiry`](#maturity) of the Principal Token.
{% endhint %}

<table><thead><tr><th width="190.33333333333331">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td><p>The amount of the underlying assets to deposit. </p><p>See also <a href="#asset"><code>asset()</code></a></p></td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">PT</a> and <a href="/pages/4zYR05giizVJ8mW5t1Ht#yield-token">YT</a>.<br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr></tbody></table>

<table><thead><tr><th width="189.33333333333331">Return Parameter</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) and <a href="/pages/4zYR05giizVJ8mW5t1Ht#yield-token">Yield Tokens</a> that were minted for the <code>receiver</code>.</td></tr></tbody></table>

### deposit

```solidity
function deposit(
        uint256 assets,
        address ptReceiver,
        address ytReceiver
) external returns (uint256 shares);
```

Deposits amount of `assets` in the PT vault specifying the PT receiver (`ptReceiver`) and the YT receiver (`ytReceiver`).

{% hint style="warning" %}
`msg.sender` must approve the relevant allowance of the underlying asset before calling this method.
{% endhint %}

{% hint style="warning" %}
`deposit` must be called before the [`expiry`](#maturity) of the Principal Token.
{% endhint %}

<table><thead><tr><th width="190.33333333333331">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td><p>The amount of the underlying assets to deposit. </p><p>See also <a href="#asset"><code>asset()</code></a></p></td></tr><tr><td><code>ptReceiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">PT</a><br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr><tr><td><code>ytReceiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/5dOBrIC1j37RFhQGMWuS">YT</a><br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr></tbody></table>

<table><thead><tr><th width="189.33333333333331">Return Parameter</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) and <a href="/pages/4zYR05giizVJ8mW5t1Ht#yield-token">Yield Tokens</a> that were minted for the <code>receiver</code>.</td></tr></tbody></table>

### deposit

```solidity
function deposit(
    uint256 assets,
    address ptReceiver,
    address ytReceiver,
    uint256 minShares
) external returns (uint256 shares);
```

Deposits amount of `assets` with a lower bound on shares received (`minShares`).

{% hint style="warning" %}
`msg.sender` must approve the relevant allowance of the underlying asset before calling this method.
{% endhint %}

{% hint style="warning" %}
`deposit` must be called before the [`expiry`](#maturity) of the Principal Token.
{% endhint %}

<table><thead><tr><th width="190.33333333333331">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td><p>The amount of the underlying assets to deposit. </p><p>See also <a href="#asset"><code>asset()</code></a></p></td></tr><tr><td><code>ptReceiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">PT</a><br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr><tr><td><code>ytReceiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/5dOBrIC1j37RFhQGMWuS">YT</a><br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr><tr><td><code>minShares</code></td><td>uint256</td><td>The minimum amount of shares the caller expect to receive from the posit</td></tr></tbody></table>

<table><thead><tr><th width="189.33333333333331">Return Parameter</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) and <a href="/pages/4zYR05giizVJ8mW5t1Ht#yield-token">Yield Tokens</a> that were minted for the <code>receiver</code>.</td></tr></tbody></table>

### depositIBT

```solidity
function depositIBT(
    uint256 ibts,
    address receiver
) public returns (uint256 shares)
```

Deposits the `ibts` of the [Interest Bearing Token](/glossary.md#ibt) (e.g. aDAI or aUSDC etc) and mints an amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) and [Yield Tokens](/glossary.md#yield-token) for the `receiver`.

{% hint style="warning" %}
`msg.sender` must approve the relevant allowance of the IBT before calling this method.
{% endhint %}

{% hint style="warning" %}
`deposit` must be called before the [`expiry`](#maturity) of the Principal Token.
{% endhint %}

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>ibts</code></td><td>uint256</td><td><p>The amount of the PrincipalToken's IBT assets to deposit. </p><p>See also <a href="#getibt">getIBT()</a></p></td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">PT</a> and <a href="/pages/4zYR05giizVJ8mW5t1Ht#yield-token">YT</a>.<br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) and <a href="/pages/4zYR05giizVJ8mW5t1Ht#yield-token">Yield Tokens</a> that were minted for the <code>receiver</code>.</td></tr></tbody></table>

### depositIBT

```solidity
function depositIBT(
        uint256 ibts,
        address ptReceiver,
        address ytReceiver
) external returns (uint256 shares);
```

Deposits the `ibts` of the [Interest Bearing Token](/glossary.md#ibt) (e.g. aDAI or aUSDC etc) and mints an amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) for the `ptReceiver` and [Yield Tokens](/glossary.md#yield-token) for the `ytReceiver`.

{% hint style="warning" %}
`msg.sender` must approve the relevant allowance of the IBT before calling this method.
{% endhint %}

{% hint style="warning" %}
`deposit` must be called before the [`expiry`](#maturity) of the Principal Token.
{% endhint %}

<table><thead><tr><th width="190.33333333333331">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>ibts</code></td><td>uint256</td><td><p>The amount of the PrincipalToken's IBT assets to deposit. </p><p>See also <a href="#getibt">getIBT()</a></p></td></tr><tr><td><code>ptReceiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">PT</a><br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr><tr><td><code>ytReceiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/5dOBrIC1j37RFhQGMWuS">YT</a><br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr></tbody></table>

<table><thead><tr><th width="189.33333333333331">Return Parameter</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) and <a href="/pages/4zYR05giizVJ8mW5t1Ht#yield-token">Yield Tokens</a> that were minted for the <code>receiver</code>.</td></tr></tbody></table>

### depositIBT

```solidity
function depositIBT(
        uint256 ibts,
        address ptReceiver,
        address ytReceiver,
        uint256 minShares
) external returns (uint256 shares);
```

Deposits the `ibts` of the [Interest Bearing Token](/glossary.md#ibt) (e.g. aDAI or aUSDC etc) and mints an amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) for the `ptReceiver` and [Yield Tokens](/glossary.md#yield-token) for the `ytReceiver`.

{% hint style="warning" %}
`msg.sender` must approve the relevant allowance of the IBT before calling this method.
{% endhint %}

{% hint style="warning" %}
`deposit` must be called before the [`expiry`](#maturity) of the Principal Token.
{% endhint %}

<table><thead><tr><th width="190.33333333333331">Input Parameter</th><th width="115">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>ibts</code></td><td>uint256</td><td><p>The amount of the PrincipalToken's IBT assets to deposit. </p><p>See also <a href="#getibt">getIBT()</a></p></td></tr><tr><td><code>ptReceiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">PT</a><br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr><tr><td><code>ytReceiver</code></td><td>address</td><td>The address that will receive the minted <a href="/pages/5dOBrIC1j37RFhQGMWuS">YT</a><br>Note: This can be different from <code>msg.sender</code> if depositing on behalf of another address.</td></tr><tr><td><code>minShares</code></td><td>uint256</td><td>The minimum amount of shares the caller expect to receive from the posit</td></tr></tbody></table>

<table><thead><tr><th width="189.33333333333331">Return Parameter</th><th width="121">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) and <a href="/pages/4zYR05giizVJ8mW5t1Ht#yield-token">Yield Tokens</a> that were minted for the <code>receiver</code>.</td></tr></tbody></table>

### redeem

```solidity
function redeem(
    uint256 shares,
    address receiver,
    address owner
) returns (uint256 assets)
```

Redeems (by burning tokens) the amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) from `owner`, redeeming an amount of `assets` of the underlying [asset](#asset).

{% hint style="warning" %}
The first caller to Redeem after expiry will make an implicit call to [`StoreRatesAtExpiry()`](#storeratesatexpiry)to store the rates after expiry. This is done only once for all.
{% endhint %}

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that the user wants to redeem/burn.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the redeemed <a href="#asset">assets</a>.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The address of the owner of the <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that are to be redeemed.<br>This must be the same as <code>msg.sender</code>.</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td>The amount of underlying <a href="#asset">assets</a> that are redeemed.</td></tr></tbody></table>

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standards.*

### redeem

```solidity
function redeem(
        uint256 shares,
        address receiver,
        address owner,
        uint256 minAssets
) external returns (uint256 assets);
```

Redeems (by burning tokens) the amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) from `owner`, redeeming an amount of `assets` of the underlying [asset](#asset), while also specifying the minimum asset (`minAssets`) amount that the caller expects the `receiver` to receive.

I.e. converts PT to the underlying asset, using the number of PT to burn, after expiry.

{% hint style="warning" %}
The first caller to Redeem after expiry will make an implicit call to [`StoreRatesAtExpiry()`](#storeratesatexpiry)to store the rates after expiry. This is done only once for all.
{% endhint %}

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that the user wants to redeem/burn.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the redeemed <a href="#asset">assets</a>.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The address of the owner of the <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that are to be redeemed.<br>This must be the same as <code>msg.sender</code>.</td></tr><tr><td><code>minAssets</code></td><td>uint256</td><td>The minimum asset amount that the caller expects the <code>receiver</code> to receive.</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td>The amount of underlying <a href="#asset">assets</a> that are redeemed.</td></tr></tbody></table>

### redeemForIBT

```solidity
function redeemForIBT(
    uint256 shares,
    address receiver,
    address owner
) returns (uint256 ibts)
```

Redeems (by burning tokens) the amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) from `owner`, redeeming an amount of `ibts` of the [IBT](/glossary.md#ibt).

{% hint style="warning" %}
The first caller to Redeem after expiry will make an implicit call to [`StoreRatesAtExpiry()`](#storeratesatexpiry)to store the rates after expiry. This is done only once for all.
{% endhint %}

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that the user wants to redeem/burn.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the redeemed tokens.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The address of the owner of the <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that are to be redeemed.<br>This must be the same as <code>msg.sender</code>.</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>ibts</code></td><td>uint256</td><td>The amount of <a href="/pages/4zYR05giizVJ8mW5t1Ht#ibt">IBT</a>s that are redeemed.</td></tr></tbody></table>

### redeemForIBT

```solidity
function redeemForIBT(
        uint256 shares,
        address receiver,
        address owner,
        uint256 minIbts
) external returns (uint256 ibts);
```

Redeems (by burning tokens) the amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) from `owner`, redeeming an amount of `ibts` of the [IBT](/glossary.md#ibt), while also specifying the minimum asset (`minIbts`) amount that the caller expects the `receiver` to receive.

{% hint style="warning" %}
The first caller to Redeem after expiry will make an implicit call to [`StoreRatesAtExpiry()`](#storeratesatexpiry)to store the rates after expiry. This is done only once for all.
{% endhint %}

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that the user wants to redeem/burn.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the redeemed tokens.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The address of the owner of the <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that are to be redeemed.<br>This must be the same as <code>msg.sender</code>.</td></tr><tr><td><code>minIbts</code></td><td>uint256</td><td>The minimum asset amount that the caller expects the <code>receiver</code> to receive.</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>ibts</code></td><td>uint256</td><td>The amount of <a href="/pages/4zYR05giizVJ8mW5t1Ht#ibt">IBT</a>s that are redeemed.</td></tr></tbody></table>

### withdraw

```solidity
function withdraw(
    uint256 assets,
    address receiver,
    address owner
) returns (uint256 shares)
```

Withdraws the amount of underlying `assets` of a position of `owner`, withdrawing those `assets` to `receiver`.  This is done by burning `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) and remaining [Yield Tokens](/glossary.md#yield-token) of `owner`.

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td>The amount of <a href="#asset">assets</a> that the user wants to withdraw.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the redeemed <a href="#asset">assets</a>.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The address of the owner of the <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that are to be withdrawn/burned.<br>This must be the same as <code>msg.sender</code>.</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of the <code>owner</code> shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that were burned from the withdrawal.</td></tr></tbody></table>

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standards.*

### withdraw

```solidity
function withdraw(
        uint256 assets,
        address receiver,
        address owner,
        uint256 maxShares
) external returns (uint256 shares)
```

Withdraws the amount of underlying `assets` of a position of `owner`, withdrawing those `assets` to `receiver`.  This is done by burning `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) and remaining [Yield Tokens](/glossary.md#yield-token) of `owner`, while specifying the maximum amount (`maxShares`) of shares to withdraw.

I.e. converts PT and YT to the underlying asset, using the number of underlying assets to withdraw, before expiry.

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>assets</code></td><td>uint256</td><td>The amount of <a href="#asset">assets</a> that the user wants to withdraw.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the redeemed <a href="#asset">assets</a>.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The address of the owner of the <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that are to be withdrawn/burned.<br>This must be the same as <code>msg.sender</code>.</td></tr><tr><td><code>maxShares</code></td><td>uint256</td><td>The maximum amount of shares allowed to be burnt</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of the <code>owner</code> shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that were burned from the withdrawal.</td></tr></tbody></table>

### withdrawIBT

```solidity
function withdrawIBT(
    uint256 ibts,
    address receiver,
    address owner
) returns (uint256 shares)
```

Withdraws the amount of [IBT](/glossary.md#ibt)s of a position of `owner`, withdrawing those `ibts` to `receiver`.  This is done by burning `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) and remaining [Yield Tokens](/glossary.md#yield-token) of `owner`.

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>ibts</code></td><td>uint256</td><td>The amount of <a href="/pages/4zYR05giizVJ8mW5t1Ht#ibt">IBT</a>s that the user wants to withdraw.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the withdrawn tokens.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The address of the owner of the <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that are to be withdrawn/burned.<br>This must be the same as <code>msg.sender</code>.</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of the <code>owner</code> shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that were burned from the withdrawal.</td></tr></tbody></table>

### withdrawIBT

```solidity
function withdrawIBT(
        uint256 ibts,
        address receiver,
        address owner,
        uint256 maxShares
) external returns (uint256 shares)
```

Withdraws the amount of [IBT](/glossary.md#ibt)s of a position of `owner`, withdrawing those `ibts` to `receiver`.  This is done by burning `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) and remaining [Yield Tokens](/glossary.md#yield-token) of `owner`, while specifying the maximum amount (`maxShares`) of shares to withdraw.

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>ibts</code></td><td>uint256</td><td>The amount of <a href="/pages/4zYR05giizVJ8mW5t1Ht#ibt">IBT</a>s that the user wants to withdraw.</td></tr><tr><td><code>receiver</code></td><td>address</td><td>The address that will receive the withdrawn tokens.</td></tr><tr><td><code>owner</code></td><td>address</td><td>The address of the owner of the <code>shares</code> (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that are to be withdrawn/burned.<br>This must be the same as <code>msg.sender</code>.</td></tr><tr><td><code>maxShares</code></td><td>uint256</td><td>The maximum amount of shares allowed to be burnt</td></tr></tbody></table>

<table><thead><tr><th width="197.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>shares</code></td><td>uint256</td><td>The amount of the <code>owner</code> shares (i.e. <a href="/pages/4zYR05giizVJ8mW5t1Ht#principal-token">Principal Tokens</a>) that were burned from the withdrawal.</td></tr></tbody></table>

### claimYield

```solidity
function claimYield(address _receiver) public returns (uint256)
```

Claims the yield of `msg.sender` based on their current balance of YT. Send the yield as underlying tokens.

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>_receiver</code></td><td>address</td><td>The address that will receive the yield.</td></tr></tbody></table>

<table><thead><tr><th width="214.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>yieldInAsset</code></td><td>uint256</td><td>The amount of yield claimed in the underlying <a href="#asset">asset</a>.</td></tr></tbody></table>

### claimYieldInIBT

```solidity
function claimYieldInIBT(address _receiver) public returns (uint256)
```

Claims the yield of `msg.sender` based on their current balance of YT. Send the yield as [IBT](/glossary.md#ibt) tokens.

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>_receiver</code></td><td>address</td><td>The address that will receive the yield.</td></tr></tbody></table>

<table><thead><tr><th width="214.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>yieldInIBT</code></td><td>uint256</td><td>The amount of yield claimed (in <a href="/pages/4zYR05giizVJ8mW5t1Ht#ibt">IBT</a>).</td></tr></tbody></table>

### updateYield

```solidity
function updateYield(address _user) external returns (uint256 updatedUserYieldInRay)
```

Updates `_user` yield with the latest yield in IBT generated since the previous update.&#x20;

{% hint style="info" %}
This method should not be used by users. This method is called implicitely before each action to deposit, redeem, withdraw and sending receiving YT tokens.
{% endhint %}

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>_user</code></td><td>address</td><td>The address of the user to compute the yield</td></tr></tbody></table>

<table><thead><tr><th width="274.3333333333333">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>updatedUserYieldInRay</code></td><td>uint256</td><td>The unclaimed yield (amount of <a href="/pages/4zYR05giizVJ8mW5t1Ht#ibt">IBT</a> tokens) of the <code>_user</code> in Ray decimals. The user can get this yield by calling <a href="#claimyield"><code>claimYield()</code></a> .</td></tr></tbody></table>

### flashLoan

```solidity
function flashLoan(
        IERC3156FlashBorrower _receiver,
        address _token,
        uint256 _amount,
        bytes calldata _data
    ) external override returns (bool)
```

The flashLoan method is used to swap PT for YT tokens by borrowing the IBT of the PT contract to swap PT for YTs.

{% hint style="warning" %}
The transaction reverts if the trade is not profitable and the borrower is unable to repay the loan.
{% endhint %}

<table><thead><tr><th width="195.33333333333331">Input Parameter</th><th width="227">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>_receiver</code></td><td>IERC3156FlashBorrower</td><td>The receiver of the tokens in the loan, and the receiver of the callback.</td></tr><tr><td><code>_token</code></td><td>address</td><td>The loan currency.</td></tr><tr><td><code>_amount</code></td><td>uint256</td><td>The amount of tokens lent.</td></tr><tr><td><code>_data</code></td><td>bytes calldata</td><td>Arbitrary data structure, intended to contain user-defined parameters.</td></tr></tbody></table>

<table><thead><tr><th width="214.33333333333331">Return Parameter</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td></td><td>bool</td><td>If successful, <code>flashLoan</code> return <code>true</code>.</td></tr></tbody></table>

*Conforms to* [*EIP-3156*](https://eips.ethereum.org/EIPS/eip-3156) *standards.*

### StoreRatesAtExpiry

Store the rates at the time of expiry.&#x20;

{% hint style="warning" %}
This can only be called **after** [expiry](#maturity)[/maturity](#maturity) of the position.&#x20;
{% endhint %}

```solidity
function storeRatesAtExpiry() external
```

## View Methods

### previewDeposit

```solidity
function previewDeposit(uint256 assets) public view returns (uint256)
```

Calculates the amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) and [Yield Tokens](/glossary.md#yield-token) that would be minted for [depositing](#deposit) amount of `assets.`Only available if position is not [expired/reached maturity.](#maturity)

### maxDeposit

```solidity
function maxDeposit(address) public view returns (uint256)
```

This function returns the maximum amount of underlying assets that can be deposited in a single [`deposit`](#deposit) call by the `receiver`.

### previewDepositIBT

```solidity
function previewDepositIBT(uint256 ibts) public view returns (uint256)
```

Calculates the amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) and [Yield Tokens](/glossary.md#yield-token) that would be minted for [depositing](#deposit) amount of `ibts.`Only available if position is not [expired/reached maturity.](#maturity)

### previewWithdraw

```solidity
function previewWithdraw(uint256 assets) public view returns (uint256)
```

Calculates the amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) that would be burned for [withdrawing](#withdraw) an amount of `assets`.

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standards.*

### previewWithdrawIBT

```solidity
function previewWithdrawInIBT(uint256 ibts) public view returns (uint256)
```

Calculates the amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)) that would be burned for [withdrawing](#withdraw) an amount of `ibts`.

### maxWithdraw

```solidity
function maxWithdraw(address owner) public returns (uint256)
```

Calculates the maximum amount of underlying [assets](#asset) that can [withdrawn](#withdraw) by the `owner`.

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standards.*

### maxWithdrawIBT

```solidity
function maxWithdraw(address owner) public returns (uint256)
```

Calculates the maximum amount of [IBT](/glossary.md#ibt)s that can [withdrawn](#withdraw) by the `owner`.

### previewRedeem

```solidity
function previewRedeem(uint256 shares) public view returns (uint256)
```

Calculates the amount of [assets](#asset) that would be [redeemed](#redeem) for an amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)).

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standards.*

### previewRedeemForIBT

```solidity
function previewRedeemForIBT(uint256 shares) public view returns (uint256)
```

Calculates the amount of IBTs that would be [redeemed](#redeem) for an amount of `shares` (i.e. [Principal Tokens](/glossary.md#principal-token)).

### maxRedeem

```solidity
function maxRedeem(address owner) public view returns (uint256)
```

Calculations the maximum amount of shares (i.e. [Principal Tokens](/glossary.md#principal-token)) that the `owner` can currently [redeem](#redeem)/burn.

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standards.*

### convertToPrincipal

```solidity
function convertToPrincipal(uint256 underlyingAmount) public view returns (uint256 principalAmount)
```

Calculates the amount of principal tokens that are equivalent to the amount of `underlyingAmount`.&#x20;

*Conforms to* [*EIP-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standard.*

### convertToUnderlying

```solidity
function convertToUnderlying(uint256 principalAmount) public view returns (uint256)
```

Same as [`convertToAssets()`](#converttoassets).

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standard.*

### underlying

```solidity
function underlying() public view virtual override returns (address)
```

Returns the address of the underlying ERC20 or ERC777 asset.&#x20;

E.g. if the IBT is aDAI, then the asset is DAI. If the IBT is cUSDC, then the asset is USDC.

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standard.*

### totalAssets

```solidity
function totalAssets() public view virtual override returns (uint256)
```

Returns the total balance of the underlying assets in the [Principal Token](/glossary.md#principal-token). Useful for TVL calculations.

### decimals

```solidity
function decimals() public view returns (uint8)
```

Returns the decimals of the [IBT](#ibt).

### maturity

```solidity
function maturity() public view returns (uint256)
```

Returns the expiry/maturity of the position in unix timestamp, at or after which the [Principal Tokens](/glossary.md#principal-token) can be redeemed for their underlying [asset](#asset).

*Conforms to* [*ERC-5095*](https://eips.ethereum.org/EIPS/eip-5095) *standard.*

### getDuration

```solidity
function getDuration() public view returns (uint256)
```

Returns the total duration of the principal token period in seconds.

### getIBT

```solidity
function getIBT() public view returns (address)
```

Returns the address of the IBT ([Interest Bearing Token](/glossary.md#ibt)).

E.g. if the underlying asset is DAI, the IBT could be aDAI (for Aave deposited DAI) or cDAI (for Compound deposited DAI), etc.

### getYT

```solidity
function getYT() public view returns (address)
```

Returns the address of the YT ([Yield Token](/glossary.md#yield-token)).

### getIBTRate

```solidity
function getIBTRate() public view returns (uint256)
```

Returns the ibtRate.

### getPTRate

```solidity
function getPTRate() public view returns (uint256)
```

Returns the ptRate.

### getIBTUnit

```solidity
function getIBTUnit() public view returns (uint256)
```

Returns the number used for one unit (10^decimals) of the [IBT](#ibt).

### getAssetUnit

```solidity
function getAssetUnit() public view returns (uint256)
```

Returns the number used for one unit (10^decimals) of the [asset](#asset).

### getIBTRateAtExpiry

```solidity
function getIBTRateAtExpiry() public view returns (uint256)
```

Returns the IBT rate at expiry. Only valid after [maturity](#maturity).

### getPTRateAtExpiry

```solidity
function getPTRateAtExpiry() public view returns (uint256)
```

Returns the PT rate at expiry. Only valid after [maturity](#maturity).

### getCurrentYieldOfUserInIBT

```solidity
function getCurrentYieldOfUserInIBT(address _user) public view returns (uint256 _yieldOfUserInIBT)
```

Returns the yield of `_user` in [IBT](/glossary.md#ibt) tokens.

## Internal Methods

### \_computeYield

```solidity
function _computeYield(
    address _user,
    uint256 _oldIBTRate,
    uint256 _ibtRate,
    uint256 _oldPTRate,
    uint256 _ptRate
) internal view returns (uint256)
```

Computes the yield generated by a user given old and new rates. For more information, see the [Yield Calculations](/technical-reference/yield-calculations.md) page.


---

# 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://dev.spectra.finance/technical-reference/contract-functions/principal-token.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.
