eTokens
Each asset supported by the Eco DeFi Protocol is integrated through a eToken contract, which is an EIP-20 compliant representation of balances supplied to the protocol. By minting eTokens, users (1) earn interest through the eToken's exchange rate, which increases in value relative to the underlying asset, and (2) gain the ability to use eTokens as collateral.
eTokens are the primary means of interacting with the Eco DeFi Protocol; when a user mints, redeems, borrows, repays a borrow, liquidates a borrow, or transfers eTokens, he/she will do so using the eToken contract.
There are currently two types of eTokens: EBEP20 and EBNB. Though both types expose the EIP-20 interface, EBEP20 wraps an underlying BEP-20 asset, while BNB simply wraps Ether itself. As such, the core functions which involve transferring an asset into the protocol have slightly different interfaces depending on the type, each of which is shown below.

Redeem

The redeem function converts a specified quantity of eTokens into the underlying asset, and returns them to the user. The amount of underlying tokens received is equal to the quantity of eTokens 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

EBEP20 / EBNB

function redeem(uint redeemTokens) returns (uint)
  • msg.sender: The account to which redeemed funds shall be transferred
  • redeemTokens: The number of eTokens to be redeemed
  • RETURN: 0 on success, otherwise an Error code
Solidity
Web3 1.0
EToken eToken = EToken (0x3FDB...);
require(eToken.redeem(7) == 0, "something went wrong");
​
const eToken = EBEP20.at(0x3FDA...);
eToken.methods.redeemUnderlying(10).send({from: ...});
​

Redeem Underlying

The redeem underlying function converts eTokens into a specified quantity of the underlying asset, and returns them to the user. The amount of eTokens 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.

EBEP20 / EBNB

function redeemUnderlying(uint redeemAmount) returns (uint)
  • msg.sender: The account to which redeemed funds shall be transferred
  • redeemAmount: The amount of underlying to be redeemed
  • RETURN: 0 on success, otherwise an Error code
Solidity
Web3 1.0
EToken eToken = EToken (0x3FDB...);
​
require(eToken.redeemUnderlying(50) == 0, "something went wrong");
​
const eToken = EBEP20.at(0x3FDA...);
​
eToken.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 EBNB, the borrower must be 'payable' (solidity).

EBEP20 / EBNB

function borrow(uint borrowAmount) returns (uint)
  • msg.sender: The account to which borrowed funds shall be transferred.
  • borrowAmount : The amount of the underlying asset to be borrowed.
  • RETURN: 0 on success, otherwise an Error code
Solidity
Second Tab
EToken eToken = EToken (0x3FDB...);
​
require(eToken.borrow(100) == 0, "got collateral?");
​
const eToken = EBEP20.at(0x3FDB...);
​
await eToken.methods.borrow(50).send({from: 0xMyAccount});
​

Repay Borrow

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

EBEP20

function repayBorrow(uint repayAmount) returns (uint)
  • msg.sender: The account which borrowed the asset, and shall repay the borrow.
  • repayAmount: The amount of the underlying borrowed asset to be repaid. A value of -1 (i.e. 2256 - 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 eToken to access their token balance.

EBNB

function repayBorrow() payable
  • msg.valuepayable: The amount of BNB to be repaid, in wei.
  • msg.sender: The account which borrowed the asset, and shall repay the borrow.
  • RETURN: No return, reverts on error.
Solidity
Second Tab
EToken eToken = EToken (0x3FDB...);
​
require(eToken.repayBorrow.value(100)() == 0, "transfer approved?");
​
const eToken = EBEP20.at(0x3FDA...);
​
eToken.methods.repayBorrow(10000).send({from: ...});
​

Repay Borrow Behalf

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

EBEP20

function repayBorrowBehalf(address borrower, uint repayAmount) returns (uint)
  • msg.sender: The account which shall repay the borrow.
  • borrower: 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. 2256 - 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 eToken to access their token balance.

EBNB

function repayBorrowBehalf(address borrower) payable
  • msg.valuepayable: The amount of bnb to be repaid, in wei.
  • msg.sender: The account which shall repay the borrow.
  • borrower: The account which borrowed the asset to be repaid.
  • RETURN: No return, reverts on error.
Solidity
Second Tab
EToken eToken = EToken(0x3FDB...);
​
require(eToken.repayBorrowBehalf.value(100)(0xBorrower) == 0, "transfer approved?");
​
const eToken = EBEP20.at(0x3FDA...);
​
await eToken.methods.repayBorrowBehalf(0xBorrower, 10000).send({from: 0xPayer});

Transfer

Transfer is BEP20 method that allows accounts to send tokens to other BNB addresses. eToken transfer will fail if the account has entered that eToken market and the transfer would have put the account into a state of negative liquidity.

EBEP20 / EBNB

function transfer(address recipient, uint256 amount) returns (bool)
  • recipient: The transfer recipient address.
  • amount: The amount of eTokens to transfer.
  • RETURN: Returns a boolean value indicating whether or not the operation succeeded.
Solidity
Web3 1.0
EToken eToken = EToken(0x3FDB...);
​
eToken.transfer(0xABCD..., 100000000000);
​
const eToken = EBEP20.at(0x3FDA...);
​
await eToken.methods.transfer(0xABCD..., 100000000000).send({from: 0xSender});
​

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 transferes eTokens, which may redeem the same as if they had supplied the asset themselves. Users must approve each eToken contract before calling liquidate (i.e. on the borrowed asset which they are repaying), as they are transferring funds into the contract.

EBEP20

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.
  • eTokenCollateral: The address of the eToken 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 eToken to access their token balance.

EBNB

function liquidateBorrow(address borrower, address eTokenCollateral) payable
  • msg.valuepayable: The amount of ether to be repaid and converted into collateral, in wei.
  • 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.
  • eTokenCollateral: The address of the eToken currently held as collateral by a borrower, that the liquidator shall seize.
  • RETURN: No return, reverts on error.
Solidity
Web3 1.0
EToken eToken = EToken(0x3FDB...);
​
EBEP20 eTokenCollateral = EBEP20(0x3FDA...);
​
require(eToken.liquidateBorrow.value(100)(0xBorrower, eTokenCollateral) == 0, "borrower underwater??");
​
const eToken = EBEP20.at(0x3FDA...);
​
const eTokenCollateral = EBNB.at(0x3FDB...);
​
await eToken.methods.liquidateBorrow(0xBorrower, 33, eTokenCollateral).send({from: 0xLiquidator});
​

Key Events

Event
Description
Mint(address minter, uint mintAmount, uint mintTokens)
Emitted upon a successful Mint.
Redeem(address redeemer, uint redeemAmount, uint redeemTokens)
Emitted upon a successful Redeem.
Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows)
Emitted upon a successful Borrow.
RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows)
Emitted upon a successful Repay Borrow.
LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens)
Emitted upon a successful Liquidate Borrow.

Error Codes

Name
Description
NO_ERROR
Not a failure.
UNAUTHORIZED
The sender is not authorized to perform this action.
BAD_INPUT
An invalid argument was supplied by the caller.
ESGTROLLER_REJECTION
The action would violate the esgtroller policy.
ESGTROLLER_CALCULATION_ERROR
An internal calculation has failed in the esgtroller.
INTEREST_RATE_MODEL_ERROR
The interest rate model returned an invalid value.
INVALID_ACCOUNT_PAIR
The specified combination of accounts is invalid.
INVALID_CLOSE_AMOUNT_REQUESTED
The amount to liquidate is invalid.
INVALID_COLLATERAL_FACTOR
The collateral factor is invalid.
MATH_ERROR
A math calculation error occurred.
MARKET_NOT_FRESH
Interest has not been properly accrued.
MARKET_NOT_LISTED
The market is not currently listed by its esgtroller.
TOKEN_INSUFFICIENT_ALLOWANCE
BEP-20 contract must allow Money Market contract to call transferFrom. The current allowance is either 0 or less than the requested supply, repayBorrow or liquidate amount.
TOKEN_INSUFFICIENT_BALANCE
Caller does not have sufficient balance in the BEP-20 contract to complete the desired action.
TOKEN_INSUFFICIENT_CASH
The market does not have a sufficient cash balance to complete the transaction. You may attempt this transaction again later.
TOKEN_TRANSFER_IN_FAILED
Failure in BEP-20 when transfering token into the market.
TOKEN_TRANSFER_OUT_FAILED
Failure in BEP-20 when transfering token out of the market.

Failure Info

Name
ACCEPT_ADMIN_PENDING_ADMIN_CHECK
ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED
ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED
ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED
ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED
ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED
ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED
BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED
BORROW_ACCRUE_INTEREST_FAILED
BORROW_CASH_NOT_AVAILABLE
BORROW_FRESHNESS_CHECK
BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED
BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED
BORROW_MARKET_NOT_LISTED
BORROW_ETROLLER_REJECTION
LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED
LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED
LIQUIDATE_COLLATERAL_FRESHNESS_CHECK
LIQUIDATE_ESGTROLLER_REJECTION
LIQUIDATE_E SGTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED
LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX
LIQUIDATE_CLOSE_AMOUNT_IS_ZERO
LIQUIDATE_FRESHNESS_CHECK
LIQUIDATE_LIQUIDATOR_IS_BORROWER
LIQUIDATE_REPAY_BORROW_FRESH_FAILED
LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED
LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED
LIQUIDATE_SEIZE_ESGTROLLER_REJECTION
LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER
LIQUIDATE_SEIZE_TOO_MUCH
MINT_ACCRUE_INTEREST_FAILED
MINT_ESGTROLLER_REJECTION
MINT_EXCHANGE_CALCULATION_FAILED
MINT_EXCHANGE_RATE_READ_FAILED
MINT_FRESHNESS_CHECK
MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED
MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED
MINT_TRANSFER_IN_FAILED
MINT_TRANSFER_IN_NOT_POSSIBLE
REDEEM_ACCRUE_INTEREST_FAILED
REDEEM_ESGTROLLER_REJECTION
REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED
REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED
REDEEM_EXCHANGE_RATE_READ_FAILED
REDEEM_FRESHNESS_CHECK
REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED
REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED
REDEEM_TRANSFER_OUT_NOT_POSSIBLE
REDUCE_RESERVES_ACCRUE_INTEREST_FAILED
REDUCE_RESERVES_ADMIN_CHECK
REDUCE_RESERVES_CASH_NOT_AVAILABLE
REDUCE_RESERVES_FRESH_CHECK
REDUCE_RESERVES_VALIDATION
REPAY_BEHALF_ACCRUE_INTEREST_FAILED
REPAY_BORROW_ACCRUE_INTEREST_FAILED
REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED
REPAY_BORROW_ESGTROLLER_REJECTION
REPAY_BORROW_FRESHNESS_CHECK
REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED
REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED
REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE
SET_COLLATERAL_FACTOR_OWNER_CHECK
SET_COLLATERAL_FACTOR_VALIDATION
SET_ESGTROLLER_OWNER_CHECK
SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED
SET_INTEREST_RATE_MODEL_FRESH_CHECK
SET_INTEREST_RATE_MODEL_OWNER_CHECK
SET_MAX_ASSETS_OWNER_CHECK
SET_ORACLE_MARKET_NOT_LISTED
SET_PENDING_ADMIN_OWNER_CHECK
SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED
SET_RESERVE_FACTOR_ADMIN_CHECK
SET_RESERVE_FACTOR_FRESH_CHECK
SET_RESERVE_FACTOR_BOUNDS_CHECK
TRANSFER_ESGTROLLER_REJECTION
TRANSFER_NOT_ALLOWED
TRANSFER_NOT_ENOUGH
TRANSFER_TOO_MUCH

Exchange Rate

Each eToken is convertible into an ever increasing quantity of the underlying asset, as interest accrues in the market. The exchange rate between a eToken and the underlying asset is equal to:
exchangeRate = (getCash() + totalBorrows() - totalReserves()) / totalSupply()

EBEP20 / EBNB

function exchangeRateCurrent() returns (uint)
  • RETURN: The current exchange rate as an unsigned integer, scaled by 1 * 10^(18 - 8 + Underlying Token Decimals).
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint exchangeRateMantissa = eToken.exchangeRateCurrent();
​
const eToken = EToken.at(0x3FDB...);
​
const exchangeRate = (await eToken.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 eToken contract. One may query the total amount of cash currently available to this market.

EBEP20 / EBNB

function getCash() returns (uint)
  • RETURN: The quantity of underlying asset owned by the contract.
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint cash = eToken.getCash();
​
const eToken = EToken.at(0x3FDB...);
​
const cash = (await eToken.methods.getCash().call());
​

Total Borrows

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.

EBEP20 / EBNB

function totalBorrowsCurrent() returns (uint)
  • RETURN: The total amount of borrowed underlying, with interest.
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint borrows = eToken.totalBorrowsCurrent();
​
const eToken = EToken.at(0x3FDB...);
​
const borrows = (await eToken.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.

EBEP20 / EBNB

function borrowBalanceCurrent(address account) returns (uint)
  • account: The account which borrowed the assets.
  • RETURN: The user's current borrow balance (with interest) in units of the underlying asset
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint borrows = eToken.borrowBalanceCurrent(msg.caller);
​
const eToken = EToken.at(0x3FDB...);
​
const borrows = await eToken.methods.borrowBalanceCurrent(account).call();
​

Borrow Rate

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

EBEP20 / EBNB

function borrowRatePerBlock() returns (uint)
  • RETURN: The current borrow rate as an unsigned integer, scaled by 1e18.
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint borrowRateMantissa = eToken.borrowRatePerBlock();
​
const eToken = EToken.at(0x3FDB...);
​
const borrowRate = (await eToken.methods.borrowRatePerBlock().call()) / 1e18;
​

Total Supply

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

EBEP20 / EBNB

function totalSupply() returns (uint)
  • RETURN: The total number of tokens in circulation for the market.
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint tokens = eToken.totalSupply();
​
const eToken = EToken.at(0x3FDB...);
​
const tokens = (await eToken.methods.totalSupply().call());
​

Underlying Balance

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

EBEP20 / EBNB

function balanceOfUnderlying(address account) returns (uint)
  • account: The account to get the underlying balance.
  • RETURN: The amount of underlying currently owned by the account.
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint tokens = eToken.balanceOfUnderlying(msg.caller);
​
const eToken = EToken.at(0x3FDB...);
​
const tokens = await eToken.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.

EBEP20 / EBNB

function supplyRatePerBlock() returns (uint)
  • RETURN: The current supply rate as an unsigned integer, scaled by 1e18.
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint supplyRateMantissa = eToken.supplyRatePerBlock();
​
const eToken = EToken.at(0x3FDB...);
​
const supplyRate = (await eToken.methods.supplyRatePerBlock().call()) / 1e18;
​

Total Reserves

Reserves are an accounting entry in each eToken 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.

EBEP20 / EBNB

function totalReserves() returns (uint)
  • RETURN: The total amount of reserves held in the market.
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint reserves = eToken.totalReserves();
​
const eToken = EToken.at(0x3FDB...);
​
const reserves = (await eToken.methods.totalReserves().call());
​

Reserve Factor

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

EBEP20 / EBNB

function reserveFactorMantissa() returns (uint)
  • RETURN: The current reserve factor as an unsigned integer, scaled by 1e18.
Solidity
Web3 1.0
EBEP20 eToken = EToken(0x3FDA...);
​
uint reserveFactorMantissa = eToken.reserveFactorMantissa();
​
const eToken = EToken.at(0x3FDB...);
​
const reserveFactor = (await eToken.methods.reserveFactorMantissa().call()) / 1e18;
​
Copy link
Outline
Redeem
Redeem Underlying
Borrow
Repay Borrow
Repay Borrow Behalf
Transfer
Liquidate Borrow
Key Events
Error Codes
Failure Info
Exchange Rate
Get Cash
Total Borrows
Borrow Balance
Borrow Rate
Total Supply
Underlying Balance
Supply Rate
Total Reserves
Reserve Factor