Inception Vault Dev Details

The Inception Protocol is implemented via Inception vault — a vault based on the EIP-4626 standard. The protocol supports several LSTs (Liquid Staking Token) as collateral, and for each token, we created a corresponding Inception vault instance and Inception LRT (Liquid Restaking Token).

The supported LSTs and corresponding LRTs are:

  • ankrETH -> inankrETH

  • cbETH -> incbETH

  • ETHx -> inETHx

  • lsETH -> inlsETH

  • mETH -> inmETH

  • oETH -> inoETH

  • osETH -> inosETH

  • rETH -> inrETH

  • sfrxETH -> insfrxETH

  • sthETH -> instETH

  • swETH -> inswETH

  • wBETH -> inwbETH

The vault functions cover 3 atomic operations:

  • Deposit

  • Withdraw

  • Redeem

Before delving into the details, let's check the requirements and smart contracts powering the protocol!

Requirements

  • Unstake time — up to 15 days.

Smart Contracts

The involved smart contracts are:

Redemption Price

Inception’s Redemption Price gives you access to the most recent valuation dynamics on our platform. It provides up-to-the-minute ratios, allowing you to precisely determine the redemption price of your Liquid Restaking Tokens (LRTs).

This critical formula, as detailed in the following explanation of Redemption Prices, ensures clarity of information so you can make informed decisions about your digital assets.

What is the Redemption Price?

The Redemption Price on Inception is the exact amount of assets that users receive when redeeming their Liquid Restaking Tokens (LRTs) after the applicable unbounding period. It also determines the number of Liquid Restaking Tokens (LRTs) that users receive when they stake their Liquid Staking Tokens (LRTs) on the Inception Dapp.

The formula is:

  • Liquid Staking Token Calculation:

When a user unstakes their assets, the following formula applies:

liquid_staking_token = liquid_restaking_token / ratio

This results in the user obtaining more original assets (LSTs), than the number of redeemed Liquid Restaking Tokens (LRTs)

  • When a user stakes their assets, they use the formula:

liquid_restaking_token = liquid_staking_token * ratio

This results in the user receiving the correspondent Liquid Restaking Tokens (LRTs), adjusting the value of the original asset (LSTs).

This dynamic occurs because the value of Liquid restaking Tokens appreciate over time relative to the initially staked assets, driven by the formula:

Ratio = supply / (TVL + rewards * (1-fee))

Redemption Price

To get the Redemption price for an LRT, use the following RateProvider contracts:

  • instETH: 0x343281Bb5029C4b698fE736D800115ac64D5De39

  • inrETH: 0xD6d553327b16dd6076D69c2DAEc91A50dD1E9F66

  • inoETH: 0xbd600020f943f7C61a8123fE2720A05434A3B38b

  • inosETH: 0x1F27848Ae927Ba278eE575e4A55f6c7ED7BFFe8C

  • inankrETH: 0x8bC73134A736437da780570308d3b37b67174ddb

  • incbETH: 0xa1Bb72c5915a7e2C85BaeA2C563858eaCB3F7A45

  • inwbETH: 0x69c59c3DD7566eb12792203f8F832ca81a050eB1

  • inswETH: 0xebFa0353DFF1801F5c8Ea07448771D6FadD1E721

  • inETHx: 0xd812bA3543f9aB64b2BCBcE34fb3b00bFF2bA2FC

  • insfrxETH: 0x07f86901057F392fd3A508b8AbcbaafB08c13B1e

  • inmETH: 0xA22A7A8c550760574Fd7b722C9f7100902D57707

  • inlsETH: 0x20f6d8e1e821Bd5B94f7bF725AF304Bc5ef09c36

(All contracts are on the Ethereum Network)

Deposit

The deposit() function allows users to restake a supported asset on EigenLayer.

Users are allowed to deposit a supported asset to the corresponding vault in any amount that is greater than minAmount.

function deposit(uint256 amount, address receiver) public returns (uint256);

// returns the min deposit amount (100 wei in the current version)
function minAmount() public returns(uint256);

Before sending a deposit transaction, ensure that the vault has sufficient allowances for spending your assets (utilizing the transferFrom() function). A successful deposit transaction results in minting an appropriate amount of the corresponding LRT and a Deposit event:

event Deposit(
      address indexed sender,
      address indexed receiver,
      uint256 amount,
      uint256 iShares
);

To determine the minted amount of LRT, use the following formula (amount – deposited amount of LST):

const mintedAmount = amount * ratio / 1e18;

Code Sample

Let’s say the user wants to restake and decided on a specific amount of the LST and receiverAddress that will be issued the mintedAmount of LRT.

await iVault.connect(staker).deposit(amount, receiverAddress);

Workflow

  1. User deposits into InceptionVault.

  2. Vault deposits the user amount directly to EigenLayer via strategyManager::delegateIntoStrategy().

  3. InceptionVault mints a corresponding amount of the LRT (instETH or inrETH respectively) for the user’s wallet.

See the example transaction on Ethereum Mainnet.

Withdraw

The withdraw() function allows users to unstake from the corresponding vault on EigenLayer, burning the user LRTs to get back the original asset.

During the withdrawal process, the corresponding vault instance stores the pending withdrawal amounts. Let us make the withdrawal process grandma-clear. It may be divided into the following steps:

  1. The vault burns the input amount of an appropriate LRT at the user’s address (no approval needed).

  2. The vault updates the global pending withdrawal state and the user’s pending withdrawal state with the corresponding receiverAddress and asset amount. The amount will be received to the receiverAddress upon the redeeming process.

  3. The vault emits a withdrawal event with the pending amount:

    event Withdraw(
          address indexed sender,
          address indexed receiver,
          address indexed owner,
          uint256 amount,
          uint256 iShares
    );

    In order to get the pending withdraw amount use the following function in iVault:

    function withdraw(uint256 iShares, address receiver) external;
    
    /// returns the amount of assets to be claimed and the receiver
    function getPendingWithdrawalOf(address claimer) public view returns (uint256, address)

See the example transaction on Ethereum Mainnet.

Redeem

The redeem() functions is applied at the final step, in which the user receives the pending asset amount that becomes available after the next rebalancing procedure.

Workflow

  1. The user (anyone) calls iVault::redeem() with a proper receiverAddress (that persists in the global state).

  2. The Inception vault calls iVault::isAbleToRedeem() to ensure that the user is able to claim at least one pending withdrawal.

    // returns whether the user is able to redeem their assets (true/false)
    // returns an array of index positions of the withdrawal queue (claimerWithdrawalsQueue)
    function isAbleToRedeem(address receiverAddress) public view returns (bool able, uint256[] memory);
  3. If able to redeem, the vault adds up all the available corresponding withdrawals, transfers the resulting amount to receiverAddress, and updates the global withdrawal state.

See the example transaction on Ethereum Mainnet.

Known Issues

  • On each transfer, stEth loses 1–2 wei.

Last updated