iToken Introduction

Introduction

Each asset supported by Iron Bank is integrated through a iToken contract, which is an EIP-20 compliant representation of balances supplied to the protocol. By minting iTokens, users (1) earn interest through the iToken's exchange rate, which increases in value relative to the underlying asset, and (2) gain the ability to use iTokens as collateral.

iTokens are the primary means of interacting with Iron Bank; when user mints, redeems, borrows, repays a borrow, liquidates a borrow, or transfers iTokens, they will do so using the iToken contract.

Iron Bank GitHub Organization: https://github.com/ibdotxyz

All mentions of CErc20 refer to https://github.com/ibdotxyz/compound-protocol/blob/eth/contracts/CCollateralCapErc20.sol

Mint

The mint function transfers an asset into the protocol, which begins accumulating interest based on the current Supply Rate for the asset. The user receives a quantity of iTokens equal to the underlying tokens supplied, divided by the current Exchange Rate.

CErc20

function mint(uint mintAmount) returns (uint)

msg.sender: The account which shall supply the asset, and own the minted cTokens.

mintAmount: The amount of the asset to be supplied, in units of the underlying asset.

RETURN: 0 on success, otherwise an Error code

Before supplying an asset, users must first approve the iToken to access their token balance.

Solidity

Erc20 underlying = Erc20(0xToken...);     // get a handle for the underlying asset contract
CErc20 iToken = CErc20(0x3FDA...);        // get a handle for the corresponding cToken contract
underlying.approve(address(cToken), 100); // approve the transfer
assert(iToken.mint(100) == 0);            // mint the cTokens and assert there is no error

Web3 1.0

const underlying = Erc20.at(0xToken...); 
const iToken = CErc20.at(0x3FDB...);
await underlying.methods.approve(cToken, 100).send({from: myAccount});
await iToken.methods.mint(100).send({from: myAccount});

Redeem

The redeem function converts a specified quantity of iTokens into the underlying asset, and returns them to the user. The amount of underlying tokens received is equal to the quantity of iTokens redeemed, multiplied by the current Exchange Rate. The amount redeemed must be less than the user's Account Liquidity and the market's available liquidity.

CErc20

function redeem(uint redeemTokens) returns (uint)

msg.sender: The account to which redeemed funds shall be transferred.

redeemTokens: The number of iTokens to be redeemed.

RETURN: 0 on success, otherwise an Error code

Solidity

CErc20 iToken = CErc20(0x3FDB...);
require(iToken.redeem(7) == 0, "something went wrong");

Web3 1.0

const iToken = CErc20.at(0x3FDA...);
iToken.methods.redeem(1).send({from: ...});

Redeem Underlying

The redeem underlying function converts iTokens into a specified quantity of the underlying asset, and returns them to the user. The amount of iTokens redeemed is equal to the quantity of underlying tokens received, divided by the current Exchange Rate. The amount redeemed must be less than the user's Account Liquidity and the market's available liquidity.

CErc20

function redeemUnderlying(uint redeemAmount) returns (uint)

Solidity

CErc20 iToken = CErc20(0x3FDB...);
require(iToken.redeemUnderlying(50) == 0, "something went wrong");

Web3 1.0

const iToken = CErc20.at(0x3FDA...);
iToken.methods.redeemUnderlying(10).send({from: ...});

Borrow

The borrow function transfers an asset from the protocol to the user, and creates a borrow balance which begins accumulating interest based on the Borrow Rate for the asset. The amount borrowed must be less than the user's Account Liquidity and the market's available liquidity.

To borrow Ether, the borrower must be 'payable' (solidity).

CErc20

function borrow(uint borrowAmount) returns (uint)

msg.sender: The account to which redeemed funds shall be transferred.

borrowAmount: The number of iTokens to be borrowed

RETURN: 0 on success, otherwise an Error code

Solidity

CErc20 iToken = CErc20(0x3FDB...);
require(iToken.redeemUnderlying(50) == 0, "got collateral?");

Web3 1.0

const iToken = CErc20.at(0x3FDA...);
await iToken.methods.borrow(50).send({from: 0xMyAccount});

Repay Borrow

The repay function transfers an asset into the protocol, reducing the user's borrow balance.

CErc20

function repayBorrow(uint borrowAmount) returns (uint)

msg.sender: The account to which borrowed the asset, and shall repay the borrow.

borrowAmount: The amount of the underlying borrowed asset to be repaid. A value of -1 (i.e. 2^256 - 1) can be used to repay the full amount.

RETURN: 0 on success, otherwise an Error code

Before repaying an asset, users must first approve the iToken to access their token balance.

Solidity

CErc20 iToken = CErc20(0x3FDB...);
require(iToken.repayBorrow.value(100() == 0, "transfer approved?");
iToken.methods.repayBorrow(10000).send({from: ...});

Web3 1.0

const iToken = CErc20.at(0x3FDA...);
await iToken.methods.borrow(50).send({from: 0xMyAccount});

Repay Borrow Behalf

The repay function transfers an asset into the protocol, reducing the target user's borrow balance.

CErc20

function repayBorrowBehalf(address borrower, uint repayAmount) returns (uint)

msg.sender: The account to which shall repay the borrow

borrowAmount: The account which borrowed the asset to be repaid.

repayAmount: The amount of the underlying borrowed asset to be repaid. A value of -1 (i.e. 2^256 - 1) can be used to repay the full amount.

RETURN: 0 on success, otherwise an Error code

Before repaying an asset, users must first approve the iToken to access their token balance.

Solidity

CErc20 iToken = CErc20(0x3FDB...);
require(iToken.repayBorrowBehalf.value(100)(0xBorrower) == 0, "transfer approved?");

Web3 1.0

const iToken = CErc20.at(0x3FDA...);
await iToken.methods.repayBorrowBehalf(0xBorrower, 10000).send({from: 0xPayer});

Liquidate Borrow

A user who has negative account liquidity is subject to liquidation by other users of the protocol to return his/her account liquidity back to positive (i.e. above the collateral requirement). When a liquidation occurs, a liquidator may repay some or all of an outstanding borrow on behalf of a borrower and in return receive a discounted amount of collateral held by the borrower; this discount is defined as the liquidation incentive.

A liquidator may close up to a certain fixed percentage (i.e. close factor) of any individual outstanding borrow of the underwater account. When collateral is seized, the liquidator is transferred iTokens which they may redeem the same as if they had supplied the asset themselves. Users must approve each iToken contract before calling liquidate (i.e. on the borrowed asset which they are repaying), as they are transferring funds into the contract.

CErc20

function liquidateBorrow(address borrower, uint amount, address collateral) returns (uint)

msg.sender: The account which shall liquidate the borrower by repaying their debt and seizing their collateral.

borrower: The account with negative account liquidity that shall be liquidated.

repayAmount: The amount of the borrowed asset to be repaid and converted into collateral, specified in units of the underlying borrowed asset.

cTokenCollateral: The address of the iToken currently held as collateral by a borrower, that the liquidator shall seize.

RETURN: 0 on success, otherwise an Error code

Before supplying an asset, users must first approve the iToken to access their token balance.

Solidity

CErc20 iToken = CErc20(0x3FDB...);
CErc20 iTokenCollateral = CErc20(0x3FDA...);
require(iToken.liquidateBorrow(0xBorrower, repayAmount, iTokenCollateral) == 0, "borrower underwater??");

Web3 1.0

const iToken = CErc20.at(0x3FDA...);
const iTokenCollateral = CErc20.at(0x3FDB...);
await iToken.methods.liquidateBorrow(0xBorrower, repayAmount, iTokenCollateral).send({from: 0xLiquidator});

Exchange Rate

Each iToken is convertible into an ever increasing quantity of the underlying asset, as interest accrues in the market. The exchange rate between a iToken and the underlying asset is equal to:

exchangeRate = (getCash() + totalBorrows() - totalReserves()) / totalSupply()

CErc20

function exchangeRateCurrent() returns (uint)

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint exchangeRateMantissa = iToken.exchangeRateCurrent();

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const exchangeRate = (await iToken.methods.exchangeRateCurrent().call()) / 1e18;

Tip: note the use of call vs. send to invoke the function from off-chain without incurring gas costs.

Get Cash

Cash is the amount of underlying balance owned by this iToken contract. One may query the total amount of cash currently available to this market.

CErc20

function getCash() returns (unit)

RETURN: The quantity of underlying asset owned by the contract.

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint cash = iToken.getCash();

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const cash = (await iToken.methods.getCash().call());

Total Borrow

Total Borrows is the amount of underlying currently loaned out by the market, and the amount upon which interest is accumulated to suppliers of the market.

CErc20

function totalBorrowCurrent() returns (unit)

RETURN: The total amount of borrowed underlying, with interest.

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint borrows = iToken.totalBorrowsCurrent();

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const borrows = (await iToken.methods.totalBorrowsCurrent().call());

Borrow Balance

A user who borrows assets from the protocol is subject to accumulated interest based on the current borrow rate. Interest is accumulated every block and integrations may use this function to obtain the current value of a user's borrow balance with interest.

CErc20

function borrowBalanceCurrent(addressacount) returns (unit)

RETURN: The total amount of borrowed underlying, with interest.

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint borrows = iToken.borrowBalanceCurrent(msg.caller);

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const borrows = await iToken.methods.totalBorrowsCurrent(account).call();

Borrow Rate

At any point in time one may query the contract to get the current borrow rate per block.

CErc20

function borrowRatePerBlock() returns (unit)

RETURN: The total amount of borrowed underlying, with interest.

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint borrowRateMantissa = iToken.borrowRatePerBlock();

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const borrowRate = (await iToken.methods.borrowRatePerBlock().call());

Total Supply

Total Supply is the number of tokens currently in circulation in this iToken market. It is part of the EIP-20 interface of the iToken contract.

CErc20

function totalSupply() returns (unit)

RETURN: The total number of tokens in circulation for the market.

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint tokens = iToken.totalSupply();

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const tokens = (await iToken.methods.totalSupply().call());

Underlying Balance

The user's underlying balance, representing their assets in the protocol, is equal to the user's iToken balance multiplied by the Exchange Rate.

CErc20

function balanceOfUnderlying(address account) returns (unit)

account: The account to get the underlying balance of.

RETURN: The amount of underlying currently owned by the account.

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint tokens = iToken.balanceOfUnderlying(msg.caller);

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const tokens = await iToken.methods.balanceOfUnderlying(account).call();

Supply Rate

At any point in time one may query the contract to get the current supply rate per block. The supply rate is derived from the borrow rate, reserve factor and the amount of total borrows.

CErc20

function supplyRatePerBlock() returns (unit)

RETURN: The current supply rate as an unsigned integer, scaled by 1e18.

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint supplyRateMantissa = iToken.supplyRatePerBlock();

Web3 1.0

const cToken = CErc20.at(0x3FDB...);
const supplyRate = (await cToken.methods.supplyRatePerBlock().call()) / 1e18;

Total Reserves

Reserves are an accounting entry in each iToken contract that represents a portion of historical interest set aside as cash which can be withdrawn or transferred through the protocol's governance. A small portion of borrower interest accrues into the protocol, determined by the reserve factor.

CErc20

function totalReserves() returns (unit)

RETURN: The total amount of reserves held in the market

Solidity

CErc20 iToken = CErc20(0x3FDA...);
uint reserves = iToken.totalReserves();

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const reserves = (await iToken.methods.totalReserves().call());

Reserve Factor

The reserve factor defines the portion of borrower interest that is converted into reserves.

CErc20

function reserveFactorMantissa() returns (unit)

RETURN: The current reserve factor as an unsigned itneger, scaled by 1e18.

Solidity

CErc20 iToken = CErc20(0x3FDA...);
const reserveFactor = (await cToken.methods.reserveFactorMantissa().call()) / 1e18;

Web3 1.0

const iToken = CErc20.at(0x3FDB...);
const reserves = (await iToken.methods.totalReserves().call());

Last updated