# Fuse

The Fuse platform enables anyone to instantly create their own lending and borrowing pool. Below you will find documentation for the Fuse platform. Each Fuse pool is essentially a fork of the Compound protocol.

# General

# Interpreting Exchange Rates

The fToken exchange rate is scaled by the difference in decimals between the fToken and the underlying asset.

const onefTokenInUnderlying =
  exchangeRateCurrent / ((1 * 10) ^ (18 + underlyingDecimals - fTokenDecimals));

Here is an example of finding the value of 1 fBAT in BAT with Web3.js JavaScript.

const fTokenDecimals = 8; // all fTokens have 8 decimal places

const underlying = new web3.eth.Contract(erc20Abi, batAddress);

const fToken = new web3.eth.Contract(fTokenAbi, fBATAddress);

const underlyingDecimals = await underlying.methods.decimals().call();

const exchangeRateCurrent = await fToken.methods.exchangeRateCurrent().call();

const mantissa = 18 + parseInt(underlyingDecimals) - fTokenDecimals;

const onefTokenInUnderlying = exchangeRateCurrent / Math.pow(10, mantissa);

console.log("1 fBAT can be redeemed for", onefTokenInUnderlying, "BAT");

There is no underlying contract for ETH, so to do this with fETH, set underlyingDecimals to 18.

To find the number of underlying tokens that can be redeemed for fTokens, multiply the number of fTokens by the above value onefTokenInUnderlying.

const underlyingTokens = fTokenAmount * onefTokenInUnderlying;

# Calculating Accrued Interest

Interest rates for each market update on any block in which the ratio of borrowed assets to supplied assets in the market has changed. The amount interest rates are changed depends on the interest rate model smart contract implemented for the market, and the amount of change in the ratio of borrowed assets to supplied assets in the market.

See the interest rate data visualization notebook on Observable (opens new window) to visualize which interest rate model is currently applied to each market.

Historical interest rates can be retrieved from the MarketHistoryService API (opens new window).

Interest accrues to all suppliers and borrowers in a market when any Ethereum address interacts with the market’s fToken contract, calling one of these functions: mint, redeem, borrow, or repay. Successful execution of one of these functions triggers the accrueInterest method, which causes interest to be added to the underlying balance of every supplier and borrower in the market. Interest accrues for the current block, as well as each prior block in which the accrueInterest method was not triggered (no user interacted with the fToken contract). Interest compounds only during blocks in which the fToken contract has one of the aforementioned methods invoked.

Here is an example of supply interest accrual:

Alice supplies 1 ETH to the Fuse protocol. At the time of supply, the supplyRatePerBlock is 37893605 Wei, or 0.000000000037893605 ETH per block. No one interacts with the fETHer contract for 3 Ethereum blocks. On the subsequent 4th block, Bob borrows some ETH. Alice’s underlying balance is now 1.000000000151574420 ETH (which is 37893605 Wei times 4 blocks, plus the original 1 ETH). Alice’s underlying ETH balance in subsequent blocks will have interest accrued based on the new value of 1.000000000151574420 ETH instead of the initial 1 ETH. Note that the supplyRatePerBlock value may change at any time.

# Calculating the APY Using Rate Per Block

The Annual Percentage Yield (APY) for supplying or borrowing in each market can be calculated using the value of supplyRatePerBlock (for supply APY) or borrowRatePerBlock (for borrow APY) in this formula:

Rate = fToken.supplyRatePerBlock(); // Integer

Rate = 37893566

ETH Mantissa = 1 * 10 ^ 18 (ETH has 18 decimal places)

Blocks Per Day = 6500 (https://ycharts.com/indicators/ethereum_blocks_per_day)

Days Per Year = 365

APY = ((((Rate / ETH Mantissa * Blocks Per Day + 1) ^ Days Per Year)) - 1) * 100

Here is an example of calculating the supply and borrow APY with Web3.js JavaScript:

const ethMantissa = 1e18;

const blocksPerDay = 6500;

const daysPerYear = 365;

const fToken = new web3.eth.Contract(fETHAbi, fETHAddress);

const supplyRatePerBlock = await fToken.methods.supplyRatePerBlock().call();

const borrowRatePerBlock = await fToken.methods.borrowRatePerBlock().call();

const supplyApy =
  (Math.pow(
    (supplyRatePerBlock / ethMantissa) * blocksPerDay + 1,
    daysPerYear
  ) -
    1) *
  100;

const borrowApy =
  (Math.pow(
    (borrowRatePerBlock / ethMantissa) * blocksPerDay + 1,
    daysPerYear
  ) -
    1) *
  100;

console.log(`Supply APY for ETH ${supplyApy} %`);

console.log(`Borrow APY for ETH ${borrowApy} %`);

# Gas Costs

The gas usage of the protocol functions may fluctuate by market and user. External calls, such as to underlying ERC-20 tokens, may use an arbitrary amount of gas. Any calculations that involve checking account liquidity, have gas costs that increase with the number of entered markets. Thus, while it can be difficult to provide any guarantees about costs, we provide the table below for guidance:

Function Typical Gas Cost
Mint < 150K, fDAI < 300k
Redeem, Transfer < 250K if borrowing, otherwise < 90K
Borrow < 300K
Repay Borrow < 90K
Liquidate Borrow < 400K

# fToken(s)

# 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 fTokens equal to the underlying tokens supplied, divided by the current Exchange Rate.

# fERC20

function mint(uint mintAmount) returns (uint)
  • msg.sender: The account which shall supply the asset, and own the minted fTokens.
  • 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 (opens new window) the fToken to access their token balance.

# fEther

function mint() payable
  • msg.value: The amount of ether to be supplied, in wei.
  • msg.sender: The account which shall supply the ether, and own the minted fTokens.
  • RETURN: No return, reverts on error.

# Solidity

Erc20 underlying = Erc20(0xToken...);     // get a handle for the underlying asset contract

fERC20 fToken = fERC20(0x3FDA...);        // get a handle for the corresponding fToken contract

underlying.approve(address(fToken), 100); // approve the transfer

assert(fToken.mint(100) == 0);            // mint the fTokens and assert there is no error

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

await fToken.methods.mint().send({from: myAccount, value: 50});

# Redeem

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

# fERC20 / fEther

function redeem(uint redeemTokens) returns (uint)
  • msg.sender: The account to which redeemed funds shall be transferred.
  • redeemTokens: The number of fTokens to be redeemed.
  • RETURN: 0 on success, otherwise an Error code

# Solidity

fEther fToken = fEther(0x3FDB...);

require(fToken.redeem(7) == 0, "something went wrong");

# Web3 1.0

const fToken = fERC20.at(0x3FDA...);

fToken.methods.redeem(1).send({from: ...});

# Redeem Underlying

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

# fERC20 / fEther

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

fEther fToken = fEther(0x3FDB...);

require(fToken.redeemUnderlying(50) == 0, "something went wrong");

# Web3 1.0

const fToken = fERC20.at(0x3FDA...);

fToken.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).

# fERC20 / fEther

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

fERC20 fToken = fERC20(0x3FDA...);

require(fToken.borrow(100) == 0, "got collateral?");

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

await fToken.methods.borrow(50).send({from: 0xMyAccount});

# Repay Borrow

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

# fERC20

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 (opens new window) the fToken to access their token balance.

# fEther

function repayBorrow() payable
  • msg.value: The amount of ether 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

fEther fToken = fEther(0x3FDB...);

require(fToken.repayBorrow.value(100)() == 0, "transfer approved?");

# Web3 1.0

const fToken = fERC20.at(0x3FDA...);

fToken.methods.repayBorrow(10000).send({from: ...});

# Repay Borrow Behalf

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

# fERC20

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 (opens new window) the fToken to access their token balance.

# fEther

function repayBorrowBehalf(address borrower) payable
  • msg.value: The amount of ether 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

fEther fToken = fEther(0x3FDB...);

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

# Web3 1.0

const fToken = fERC20.at(0x3FDA...);

await fToken.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. Unlike in v1, liquidators must interact with each fToken contract in which they wish to repay a borrow and seize another asset as collateral. When collateral is seized, the liquidator is transferred fTokens, which they may redeem the same as if they had supplied the asset themselves. Users must approve each fToken contract before calling liquidate (i.e. on the borrowed asset which they are repaying), as they are transferring funds into the contract.

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.
  • fTokenCollateral: The address of the fToken currently held as collateral by a borrower, that the liquidator shall seize.
  • RETURN: 0 on success, otherwise an Error code

# Transfer

Transfer is an ERC-20 method that allows accounts to send tokens to other Ethereum addresses. A fToken transfer will fail if the account has entered that fToken market and the transfer would have put the account into a state of negative liquidity.

# fERC20 / fEther

function transfer(address recipient, uint256 amount) returns (bool)
  • recipient: The transfer recipient address.
  • amount: The amount of fTokens to transfer.
  • RETURN: Returns a boolean value indicating whether or not the operation succeeded.

# Solidity

fEther fToken = fEther(0x3FDB...);

fToken.transfer(0xABCD..., 100000000000);

# Web3 1.0

const fToken = fERC20.at(0x3FDA...);

await fToken.methods.transfer(0xABCD..., 100000000000).send({from: 0xSender});

# fERC20

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.
  • collateral: The address of the fToken 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 (opens new window) the fToken to access their token balance.

# fEther

function liquidateBorrow(address borrower, address fTokenCollateral) payable
  • msg.value: 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.
  • collateral: The address of the fToken currently held as collateral by a borrower, that the liquidator shall seize.
  • RETURN: No return, reverts on error.

# Solidity

fEther fToken = fEther(0x3FDB...);

fERC20 fTokenCollateral = fERC20(0x3FDA...);

require(fToken.liquidateBorrow.value(100)(0xBorrower, fTokenCollateral) == 0, "borrower underwater??");

# Web3 1.0

const fToken = fERC20.at(0x3FDA...);

const fTokenCollateral = fEther.at(0x3FDB...);

await fToken.methods.liquidateBorrow(0xBorrower, 33, fTokenCollateral).send({from: 0xLiquidator});

# Exchange Rate

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

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

# fERC20 / fEther

function exchangeRateCurrent() returns (uint)
  • RETURN: The current exchange rate as an unsigned integer, scaled by 1e18.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint exchangeRateMantissa = fToken.exchangeRateCurrent();

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const exchangeRate = (await fToken.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 fToken contract. One may query the total amount of cash currently available to this market.

# fERC20 / fEther

function getCash() returns (uint)
  • RETURN: The quantity of underlying asset owned by the contract.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint cash = fToken.getCash();

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const cash = (await fToken.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.

# fERC20 / fEther

function totalBorrowsCurrent() returns (uint)
  • RETURN: The total amount of borrowed underlying, with interest.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint borrows = fToken.totalBorrowsCurrent();

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const borrows = (await fToken.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.

# fERC20 / fEther

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

fERC20 fToken = fToken(0x3FDA...);

uint borrows = fToken.borrowBalanceCurrent(msg.caller);

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const borrows = await fToken.methods.borrowBalanceCurrent(account).call();

# Borrow Rate

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

# fERC20 / fEther

function borrowRatePerBlock() returns (uint)
  • RETURN: The current borrow rate as an unsigned integer, scaled by 1e18.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint borrowRateMantissa = fToken.borrowRatePerBlock();

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const borrowRate = (await fToken.methods.borrowRatePerBlock().call()) / 1e18;

# Total Supply

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

# fERC20 / fEther

function totalSupply() returns (uint)
  • RETURN: The total number of tokens in circulation for the market.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint tokens = fToken.totalSupply();

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const tokens = (await fToken.methods.totalSupply().call());

# Underlying Balance

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

# fERC20 / fEther

function balanceOfUnderlying(address account) returns (uint)
  • account: The account to get the underlying balance of.
  • RETURN: The amount of underlying currently owned by the account.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint tokens = fToken.balanceOfUnderlying(msg.caller);

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const tokens = await fToken.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.

# fERC20 / fEther

function supplyRatePerBlock() returns (uint)
  • RETURN: The current supply rate as an unsigned integer, scaled by 1e18.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint supplyRateMantissa = fToken.supplyRatePerBlock();

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const supplyRate = (await fToken.methods.supplyRatePerBlock().call()) / 1e18;

# Total Reserves

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

# fERC20 / fEther

function totalReserves() returns (uint)
  • RETURN: The total amount of reserves held in the market.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint reserves = fToken.totalReserves();

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const reserves = (await fToken.methods.totalReserves().call());

# Reserve Factor

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

# fERC20 / fEther

function reserveFactorMantissa() returns (uint)
  • RETURN: The current reserve factor as an unsigned integer, scaled by 1e18.

# Solidity

fERC20 fToken = fToken(0x3FDA...);

uint reserveFactorMantissa = fToken.reserveFactorMantissa();

# Web3 1.0

const fToken = fEther.at(0x3FDB...);

const reserveFactor = (await fToken.methods.reserveFactorMantissa().call()) / 1e18;

# 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 fTokenCollateral, uint seizeTokens) Emitted upon a successful Liquidate Borrow.

# Error Codes

Code Name Description
0 NO_ERROR Not a failure.
1 UNAUTHORIZED The sender is not authorized to perform this action.
2 BAD_INPUT An invalid argument was supplied by the caller.
4 COMPTROLLER_CALCULATION_ERROR An internal calculation has failed in the comptroller.
5 INTEREST_RATE_MODEL_ERROR The interest rate model returned an invalid value.
6 INVALID_ACCOUNT_PAIR The specified combination of accounts is invalid.
7 INVALID_CLOSE_AMOUNT_REQUESTED The amount to liquidate is invalid.
8 INVALID_COLLATERAL_FACTOR The collateral factor is invalid.
9 MATH_ERROR A math calculation error occurred.
10 MARKET_NOT_FRESH Interest has not been properly accrued.
11 MARKET_NOT_LISTED The market is not currently listed by its comptroller.
12 TOKEN_INSUFFICIENT_ALLOWANCE ERC-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.
13 TOKEN_INSUFFICIENT_BALANCE Caller does not have sufficient balance in the ERC-20 contract to complete the desired action.
14 TOKEN_INSUFFICIENT_CASH The market does not have a sufficient cash balance to complete the transaction. You may attempt this transaction again later.
15 TOKEN_TRANSFER_IN_FAILED Failure in ERC-20 when transfering token into the market.
16 TOKEN_TRANSFER_OUT_FAILED Failure in ERC-20 when transfering token out of the market.
17 UTILIZATION_ABOVE_MAX No more of this token can be borrowed right now.
10XX DETAILED_COMPTROLLER_REJECTION The action would violate the comptroller policy. To get more detail, subtract 1000 from the error code and use the difference as the enum index to lookup the corresponding Comptroller error.

# Failure Info

Code Name
0 ACCEPT_ADMIN_PENDING_ADMIN_CHECK
1 ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED
2 ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED
3 ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED
4 ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED
5 ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED
6 ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED
7 BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED
8 BORROW_ACCRUE_INTEREST_FAILED
9 BORROW_CASH_NOT_AVAILABLE
10 BORROW_FRESHNESS_CHECK
11 BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED
12 BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED
13 BORROW_MARKET_NOT_LISTED
14 BORROW_COMPTROLLER_REJECTION
15 LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED
16 LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED
17 LIQUIDATE_COLLATERAL_FRESHNESS_CHECK
18 LIQUIDATE_COMPTROLLER_REJECTION
19 LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED
20 LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX
21 LIQUIDATE_CLOSE_AMOUNT_IS_ZERO
22 LIQUIDATE_FRESHNESS_CHECK
23 LIQUIDATE_LIQUIDATOR_IS_BORROWER
24 LIQUIDATE_REPAY_BORROW_FRESH_FAILED
25 LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED
26 LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED
27 LIQUIDATE_SEIZE_COMPTROLLER_REJECTION
28 LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER
29 LIQUIDATE_SEIZE_TOO_MUCH
30 MINT_ACCRUE_INTEREST_FAILED
31 MINT_COMPTROLLER_REJECTION
32 MINT_EXCHANGE_CALCULATION_FAILED
33 MINT_EXCHANGE_RATE_READ_FAILED
34 MINT_FRESHNESS_CHECK
35 MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED
36 MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED
37 MINT_TRANSFER_IN_FAILED
38 MINT_TRANSFER_IN_NOT_POSSIBLE
39 REDEEM_ACCRUE_INTEREST_FAILED
40 REDEEM_COMPTROLLER_REJECTION
41 REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED
42 REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED
43 REDEEM_EXCHANGE_RATE_READ_FAILED
44 REDEEM_FRESHNESS_CHECK
45 REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED
46 REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED
47 REDEEM_TRANSFER_OUT_NOT_POSSIBLE
48 REDUCE_RESERVES_ACCRUE_INTEREST_FAILED
49 REDUCE_RESERVES_ADMIN_CHECK
50 REDUCE_RESERVES_CASH_NOT_AVAILABLE
51 REDUCE_RESERVES_FRESH_CHECK
52 REDUCE_RESERVES_VALIDATION
53 REPAY_BEHALF_ACCRUE_INTEREST_FAILED
54 REPAY_BORROW_ACCRUE_INTEREST_FAILED
55 REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED
56 REPAY_BORROW_COMPTROLLER_REJECTION
57 REPAY_BORROW_FRESHNESS_CHECK
58 REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED
59 REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED
60 REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE
61 SET_COLLATERAL_FACTOR_OWNER_CHECK
62 SET_COLLATERAL_FACTOR_VALIDATION
63 SET_COMPTROLLER_OWNER_CHECK
64 SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED
65 SET_INTEREST_RATE_MODEL_FRESH_CHECK
66 SET_INTEREST_RATE_MODEL_OWNER_CHECK
67 SET_MAX_ASSETS_OWNER_CHECK
68 SET_ORACLE_MARKET_NOT_LISTED
69 SET_PENDING_ADMIN_OWNER_CHECK
70 SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED
71 SET_RESERVE_FACTOR_ADMIN_CHECK
72 SET_RESERVE_FACTOR_FRESH_CHECK
73 SET_RESERVE_FACTOR_BOUNDS_CHECK
74 TRANSFER_COMPTROLLER_REJECTION
75 TRANSFER_NOT_ALLOWED
76 TRANSFER_NOT_ENOUGH
77 TRANSFER_TOO_MUCH
78 ADD_RESERVES_ACCRUE_INTEREST_FAILED
79 ADD_RESERVES_FRESH_CHECK,
80 ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE

# Comptroller

The Comptroller is the risk management layer of the Fuse protocol; it determines how much collateral a user is required to maintain, and whether (and by how much) a user can be liquidated. Each time a user interacts with a fToken, the Comptroller is asked to approve or deny the transaction.

The Comptroller maps user balances to prices (via the Price Oracle) to risk weights (called Collateral Factors) to make its determinations. Users explicitly list which assets they would like included in their risk scoring, by calling Enter Markets and Exit Market.

# Architecture

The Comptroller is implemented as an upgradeable proxy. The Unitroller proxies all logic to the Comptroller implementation, but storage values are set on the Unitroller. To call Comptroller functions, use the Comptroller ABI on the Unitroller address.

# Enter Markets

Enter into a list of markets - it is not an error to enter the same market more than once. In order to supply collateral or borrow in a market, it must be entered first.

function enterMarkets(address[] calldata fTokens) returns (uint[] memory)
  • msg.sender: The account which shall enter the given markets.
  • fTokens: The addresses of the fToken markets to enter.
  • RETURN: For each market, returns an error code indicating whether or not it was entered. Each is 0 on success, otherwise an Error code.

# Solidity

Comptroller troll = Comptroller(0xABCD...);

fToken[] memory fTokens = new fToken[](2);

fTokens[0] = fErc20(0x3FDA...);

fTokens[1] = fEther(0x3FDB...);

uint[] memory errors = troll.enterMarkets(fTokens);

# Web3 1.0

const troll = Comptroller.at(0xABCD...);

const fTokens = [fErc20.at(0x3FDA...), fEther.at(0x3FDB...)];

const errors = await troll.methods.enterMarkets(fTokens).send({from: ...});

# Exit Market

Exit a market - it is not an error to exit a market which is not currently entered. Exited markets will not count towards account liquidity calculations.

function exitMarket(address fToken) returns (uint)
  • msg.sender: The account which shall exit the given market.
  • fToken: The addresses of the fToken market to exit.
  • RETURN: 0 on success, otherwise an Error code.

# Solidity

Comptroller troll = Comptroller(0xABCD...);

uint error = troll.exitMarket(fToken(0x3FDA...));

# Web3 1.0

const troll = Comptroller.at(0xABCD...);

const errors = await troll.methods.exitMarket(fEther.at(0x3FDB...)).send({from: ...});

# Get Assets In

Get the list of markets an account is currently entered into. In order to supply collateral or borrow in a market, it must be entered first. Entered markets count towards account liquidity calculations.

function getAssetsIn(address account) returns (address[] memory)
  • account: The account whose list of entered markets shall be queried.
  • RETURN: The address of each market which is currently entered into.

# Solidity

Comptroller troll = Comptroller(0xABCD...);

address[] memory markets = troll.getAssetsIn(0xMyAccount);

# Web3 1.0

const troll = Comptroller.at(0xABCD...);

const markets = await troll.methods.getAssetsIn(fTokens).call();

# Collateral Factor

A fToken's collateral factor can range from 0-90%, and represents the proportionate increase in liquidity (borrow limit) that an account receives by minting the fToken.

Generally, large or liquid assets have high collateral factors, while small or illiquid assets have low collateral factors. If an asset has a 0% collateral factor, it can't be used as collateral (or seized in liquidation), though it can still be borrowed.

Collateral factors can be increased (or decreased) by the pool creator.

function markets(address fTokenAddress) returns (bool, uint, bool)
  • fTokenAddress: The address of the fToken to check if listed and get the collateral factor for.
  • RETURN: Tuple of values (isListed, collateralFactorMantissa, isComped); isListed represents whether the comptroller recognizes this fToken; collateralFactorMantissa, scaled by 1e18, is multiplied by a supply balance to determine how much value can be borrowed.

# Solidity

Comptroller troll = Comptroller(0xABCD...);

(bool isListed, uint collateralFactorMantissa, bool isComped) = troll.markets(0x3FDA...);

# Web3 1.0

const troll = Comptroller.at(0xABCD...);

const result = await troll.methods.markets(0x3FDA...).call();

const {0: isListed, 1: collateralFactorMantissa, 2: isComped} = result;

# Get Account Liquidity

Account Liquidity represents the USD value borrowable by a user, before it reaches liquidation. Users with a shortfall (negative liquidity) are subject to liquidation, and can’t withdraw or borrow assets until Account Liquidity is positive again.

For each market the user has entered into, their supplied balance is multiplied by the market’s collateral factor, and summed; borrow balances are then subtracted, to equal Account Liquidity. Borrowing an asset reduces Account Liquidity for each USD borrowed; withdrawing an asset reduces Account Liquidity by the asset’s collateral factor times each USD withdrawn.

Because the Fuse Protocol exclusively uses unsigned integers, Account Liquidity returns either a surplus or shortfall.

function getAccountLiquidity(address account) returns (uint, uint, uint)
  • account: The account whose liquidity shall be calculated.
  • RETURN: Tuple of values (error, liquidity, shortfall). The error shall be 0 on success, otherwise an error code. A non-zero liquidity value indicates the account has available account liquidity. A non-zero shortfall value indicates the account is currently below his/her collateral requirement and is subject to liquidation. At most one of liquidity or shortfall shall be non-zero.

# Solidity

Comptroller troll = Comptroller(0xABCD...);

(uint error, uint liquidity, uint shortfall) = troll.getAccountLiquidity(msg.caller);

require(error == 0, "join the Discord");

require(shortfall == 0, "account underwater");

require(liquidity > 0, "account has excess collateral");

# Web3 1.0

const troll = Comptroller.at(0xABCD...);

const result = await troll.methods.getAccountLiquidity(0xBorrower).call();

const {0: error, 1: liquidity, 2: shortfall} = result;

# Close Factor

The percent, ranging from 0% to 100%, of a liquidatable account's borrow that can be repaid in a single liquidate transaction. If a user has multiple borrowed assets, the closeFactor applies to any single borrowed asset, not the aggregated value of a user’s outstanding borrowing.

function closeFactorMantissa() returns (uint)
  • RETURN: The closeFactor, scaled by 1e18, is multiplied by an outstanding borrow balance to determine how much could be closed.

# Solidity

Comptroller troll = Comptroller(0xABCD...);

uint closeFactor = troll.closeFactorMantissa();

# Web3 1.0

const troll = Comptroller.at(0xABCD...);

const closeFactor = await troll.methods.closeFactorMantissa().call();

# Liquidation Incentive

The additional collateral given to liquidators as an incentive to perform liquidation of underwater accounts. For example, if the liquidation incentive is 1.1, liquidators receive an extra 10% of the borrowers collateral for every unit they close.

function liquidationIncentiveMantissa() returns (uint)
  • RETURN: The liquidationIncentive, scaled by 1e18, is multiplied by the closed borrow amount from the liquidator to determine how much collateral can be seized.

# Solidity

Comptroller troll = Comptroller(0xABCD...);

uint closeFactor = troll.liquidationIncentiveMantissa();

# Web3 1.0

const troll = Comptroller.at(0xABCD...);

const closeFactor = await troll.methods.liquidationIncentiveMantissa().call();

# Key Events

Event Description
MarketEntered(fToken fToken, address account) Emitted upon a successful Enter Market.
MarketExited(fToken fToken, address account) Emitted upon a successful Exit Market.

# Error Codes

Code Name Description
0 NO_ERROR Not a failure.
1 UNAUTHORIZED The sender is not authorized to perform this action.
2 COMPTROLLER_MISMATCH Liquidation cannot be performed in markets with different comptrollers.
3 INSUFFICIENT_SHORTFALL The account does not have sufficient shortfall to perform this action.
4 INSUFFICIENT_LIQUIDITY The account does not have sufficient liquidity to perform this action.
5 INVALID_CLOSE_FACTOR The close factor is not valid.
6 INVALID_COLLATERAL_FACTOR The collateral factor is not valid.
7 INVALID_LIQUIDATION_INCENTIVE The liquidation incentive is invalid.
8 MARKET_NOT_ENTERED The market has not been entered by the account.
9 MARKET_NOT_LISTED The market is not currently listed by the comptroller.
10 MARKET_ALREADY_LISTED An admin tried to list the same market more than once.
11 MATH_ERROR A math calculation error occurred.
12 NONZERO_BORROW_BALANCE The action cannot be performed since the account carries a borrow balance.
13 PRICE_ERROR The comptroller could not obtain a required price of an asset.
14 REJECTION The comptroller rejects the action requested by the market.
15 SNAPSHOT_ERROR The comptroller could not get the account borrows and exchange rate from the market.
16 TOO_MANY_ASSETS Attempted to enter more markets than are currently supported.
17 TOO_MUCH_REPAY Attempted to repay more than is allowed by the protocol.
15 SNAPSHOT_ERROR The comptroller could not get the account borrows and exchange rate from the market.
16 TOO_MANY_ASSETS Attempted to enter more markets than are currently supported.
17 TOO_MUCH_REPAY Attempted to repay more than is allowed by the protocol.
18 SUPPLIER_NOT_WHITELISTED The comptroller could not get the account borrows and exchange rate from the market.
19 BORROW_BELOW_MIN Attempted to enter borrow less than the maximum allowed amount.
20 SUPPLY_ABOVE_MAX Attempted to supply more than the maximum allowed amount.

# Failure Info

Code Name
0 ACCEPT_ADMIN_PENDING_ADMIN_CHECK
1 ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK
2 EXIT_MARKET_BALANCE_OWED
3 EXIT_MARKET_REJECTION
4 SET_CLOSE_FACTOR_OWNER_CHECK
5 SET_CLOSE_FACTOR_VALIDATION
6 SET_COLLATERAL_FACTOR_OWNER_CHECK
7 SET_COLLATERAL_FACTOR_NO_EXISTS
8 SET_COLLATERAL_FACTOR_VALIDATION
9 SET_COLLATERAL_FACTOR_WITHOUT_PRICE
10 SET_IMPLEMENTATION_OWNER_CHECK
11 SET_LIQUIDATION_INCENTIVE_OWNER_CHECK
12 SET_LIQUIDATION_INCENTIVE_VALIDATION
13 SET_MAX_ASSETS_OWNER_CHECK
14 SET_PENDING_ADMIN_OWNER_CHECK
15 SET_PENDING_IMPLEMENTATION_OWNER_CHECK
16 SET_PRICE_ORACLE_OWNER_CHECK
17 SUPPORT_MARKET_EXISTS
18 SUPPORT_MARKET_OWNER_CHECK
19 SET_PAUSE_GUARDIAN_OWNER_CHECK
20 UNSUPPORT_MARKET_OWNER_CHECK
21 UNSUPPORT_MARKET_DOES_NOT_EXIST
22 UNSUPPORT_MARKET_IN_USE

# Fuse Pool Lens

# Get Public Pools With Data

Gets all public Fuse pools.

function getPublicPoolsWithData() returns (uint256[], FusePool[], uint256[], uint256[],address[][], string[][], bool[])
  • RETURN:
    • uint256[]: Pool ID for each pool.
    • FusePool[]`: Pool data for each pool.
    • uint256[]: Total supplied in each pool denominated in ether (18 decimals).
    • uint256[]: Total borrowed in each pool denominated in ether (18 decimals).
    • address[][]: The underlying tokens in each pool.
    • string[][]: The underlying symbols of each token in each pool.
    • bool[]: A bool indicating if fetching data about the pool failed.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( uint256[]   indexes,
  FusePool[]  fusePools[],
  uint256[]   totalSupplys,
  uint256[]   totalBorrows,
  address[][] underlyingTokens,
  string[][]  underlyingSymbols,
  bool[]      errors) = lens.getPublicPoolsWithData();

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const pools = await FusePoolLens.methods.getPoolsByAccountWithData(0xEFGH);

# Get Pools By Account With Data

Gets all pools in which an account is active.

function getPoolsByAccountWithData(address account) returns (
  uint256[],
  FusePool[],
  uint256[],
  uint256[],
  address[][],
  string[][],
  bool[])
  • account: User address to get data about.
  • RETURN:
    • uint256[]: Pool ID for each pool.
    • FusePool[]: Pool data for each pool.
    • uint256[]: Total supplied in each pool denominated in ether (18 decimals).
    • uint256[]: Total borrowed in each pool denominated in ether (18 decimals).
    • address[][]: The underlying tokens in each pool.
    • string[][]: The underlying symbols of each token in each pool.
    • bool[]: A bool indicating if fetching data about the pool failed.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( uint256[]   indexes,
  FusePool[]  fusePools,
  uint256[]   totalSupplys,
  uint256[]   totalBorrows,
  address[][] underlyingTokens,
  string[][]  underlyingSymbols,
  bool[]      errors ) = lens.getPoolsByAccountWithData(0xEFGH...)

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const usrPools = await FusePoolLens.methods.getPoolsByAccountWithData(0xEFGH);

# Get Pool Summary

Gets a pool's metadata.

function getPoolSummary(address comptroller) returns (uint256, uint256, address[], string[])
  • comptroller: Pool to get data about.
  • RETURN:
    • uint256: Total supplied in the pool denominated in ether (18 decimals).
    • uint256: Total borrowed in the pool denominated in ether (18 decimals).
    • address[]: The underlying tokens in the pool.
    • string[]: The underlying symbols of each token in the pool.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( uint256   totalSupply,
  uint256   totalBorrow,
  address[] underlyingTokens,
  string[]  underlyingSymbols ) = lens.getPoolSummary(0xEFGH...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const poolInfo = await FusePoolLens.methods.getPoolSummary(0xEFGH...)

# Get Pool Assets With Data

Gets the tokens in a Fuse pool.

function getPoolAssetsWithData(address comptroller) returns (FusePoolAsset[])

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

FusePoolAsset[] fusePoolAssets = lens.getPoolAssetsWithData(0xEFGH...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const assets = await FusePoolLens.methods.getPoolAssetsWithData(0xEFGH...);

# Get Public Pool Users With Data

Gets users and their data in a Fuse pool under a given account health.

function getPublicPoolUsersWithData(uint256 maxHealth) returns (address[], FusePoolUser[][], uint256[], uint256[], bool)
  • maxHealth: Maximum account health users returned should have.
  • RETURN:
    • address[]: Comptrollers with users below the max health.
    • FusePoolUser[][]: Users below the max health in each pool.
    • uint256[]: Close factor associated with each comptroller. 18 decimals, where 1e18 is 100% and 0 is 0%.
    • uint256[]: Liquidation incentive associated with each comptroller. 18 decimals, where 1e18 is 100% and 0 is 0%.
    • bool[]: Will be true if fetching data about a pool caused an error.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( address[]        comptrollers,
  FusePoolUser[][] fusePoolUsers,
  uint256[]        closeFactors,
  uint256[]        liquidationIncentives,
  bool[]           errors ) = lens.getPublicPoolUsersWithData(101010...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const users = await FusePoolLens.methods.getPublicPoolUsersWithData(101010...);

# Get Pool Users With Data

Gets users and their data in a Fuse pool under a given account health.

function getPoolUsersWithData(
  address comptroller,
  uint256 maxHealth
  ) returns (FusePoolUser[], uint256, uint256)
  • comptroller: Pool to get data about.
  • maxHealth: Maximum account health to include.
  • RETURN:
    • FusePoolUser[]: Users below the maxHealth in the pool.
    • uint256: Close factor associated with the pool. 18 decimals, where 1e18 is 100% and 0 is 0%.
    • uint256: Liquidation incentive associated with the pool. 18 decimals, where 1e18 is 100% and 0 is 0%.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( FusePoolUser[] fusePoolUsers,
  uint256        closeFactor,
  uint256        liquidationIncentive ) = lens.getPoolUsersWithData(0xEFGH..., 101010...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const users = await FusePoolLens.methods.getPoolUsersWithData(0xEFGH..., 101010...);

# Get Pools By Supplier

Gets pools that an address is supplying in.

function getPoolsBySupplier(address account) returns (uint256[], FusePool[])
  • account: Supplier account to find pools for.
  • RETURN:

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( uint256[] ids, FusePool[] pools ) = lens.getPoolsBySupplier(0xEFGH...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const pools = await FusePoolLens.methods.getPoolsBySupplier(0xEFGH...);

# Get Pools By Supplier With Data

Gets pools that an address is supplying to.

function getPoolsBySupplier(address account) returns (
  uint256[],
  FusePool[],
  uint256[],
  uint256[],
  address[][],
  string[][],
  bool[])
  • account: Account to fetch find pools for.
  • RETURN:
    • uint256[]: Pool ID for each pool.
    • FusePool[]: Pool data for each pool.
    • uint256[]: Total supplied in each pool denominated in ether (18 decimals).
    • uint256[]: Total borrowed in each pool denominated in ether (18 decimals).
    • address[][]: The underlying tokens in each pool.
    • string[][]: The underlying symbols of each token in each pool.
    • bool[]: A bool indicating if fetching data about the pool failed.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( uint256[]   ids,
  FusePool[]  pools,
  uint256[]   totalSupplys,
  uint256[]   totalBorrows,
  address[][] underlyingTokens,
  string[][]  underlyingSymbols,
  bool[]      errors ) = lens.getPoolsBySupplierWithData(0xEFGH...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const users = await FusePoolLens.methods.getPoolsBySupplierWithData(0xEFGH...);

# Get User Summary

Gets supply and borrow metadata for a user/account

function getUserSummary(address account) returns (uint256, uint256, bool)
  • account: Account to fetch data about.
  • RETURN:
    • uint256: Total supplied across all Fuse pools in Ether (18 decimals).
    • uint256: Total borrowed across all Fuse pools in Ether (18 decimals).
    • bool: Whether there was an error fetching this data.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( uint256 supplyBalance,
  uint256 borrowBalance,
  bool    error ) = lens.getUserSummary(0xEFGH...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const userSummary = await FusePoolLens.methods.getUserSummary(0xEFGH...);

# Get Pool User Summary

Gets supply and borrow metadata for a user/account in a pool.

function getPoolUserSummary(address comptroller, address account) returns (uint256, uint256)
  • comptroller: Pool to fetch data about.
  • account: Account to fetch data for.
  • RETURN:
    • uint256: Balance supplied in the pool denominated Ether (18 decimals).
    • uint256: Balance borrowed in the pool denominated in Ether (18 decimals).
    • bool: Whether there was an error fetching this data.

# Solidity

fusePoolLens lens = fusePoolLens(0xABCD...);

( uint256 supplyBalance,
  uint256 borrowBalance,
  bool    error ) = lens.getPoolUserSummary(0xEFGH..., 0xIJKL...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const userSummary = await FusePoolLens.methods.getPoolUserSummary(0xEFGH..., 0xIJKL...);

# Get Whitelisted Pools By Account

Gets whitelisted pools an account is participating in.

function getWhitelistedPoolsByAccount(address account) returns (uint256[], FusePool[])
  • account: User to fetch pools for.
  • RETURN:

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

( uint256[] ids, FusePool[] pools ) = lens.getWhitelistedPoolsByAccount(0xEFGH...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const pools = await FusePoolLens.methods.getWhitelistedPoolsByAccount(0xEFGH...);

# Get Whitelisted Pools By Account With Data

Gets whitelisted pools an account is participating in with metadata.

function getWhitelistedPoolsByAccountWithData(address account) returns (
  uint256[],
  FusePool[],
  uint256[],
  uint256[],
  address[][],
  string[][],
  bool[])
  • account: User to fetch pools for.
  • RETURN:
    • uint256[]: Pool ID for each pool.
    • FusePool[]: Pool data for each pool.
    • uint256[]: Total supplied in each pool denominated in ether (18 decimals).
    • uint256[]: Total borrowed in each pool denominated in ether (18 decimals).
    • address[][]: The underlying tokens in each pool.
    • string[][]: The underlying symbols of each token in each pool.
    • bool[]: A bool indicating if fetching data about the pool failed.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

(
  uint256[]   ids,
  FusePool[]  fusePools,
  uint256[]   totalSupplys,
  uint256[]   totalBorrows,
  address[][] underlyingTokens,
  string[][]  underlyingSymbols,
  bool[]      errors ) = lens.getWhitelistedPoolsByAccountWithData(0xEFGH...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const pools = await FusePoolLens.methods.getWhitelistedPoolsByAccountWithData(0xEFGH...);

# Get Pool Ownership

Gets information about the owner of a pool.

function getPoolOwnership(address comptroller) returns (
  address,
  bool,
  bool,
  CTokenOwnership[])
  • comptroller: Pool to fetch data about.
  • RETURN:
    • address: The admin of the pool.
    • bool: Does the admin have rights over the pool.
    • bool: Does the global Fuse admin have rights over the pool.
    • CTokenOwnership[]: fTokens in the pool that have different pool ownership parameters than the comptroller.

# Solidity

FusePoolLens lens = fusePoolLens(0xABCD...);

(
  address compAdmin,
  bool compAdminHasRights,
  bool compFuseAdminHasRights,
  CTokenOwnership[] outliers ) = lens.getPoolOwnership(0xEFGH...);

# Web3 1.0

const FusePoolLens = new Web3.eth.Contract(FUSE_POOL_LENS_ABI, 0xABCD...);

const ownerInfo = await FusePoolLens.methods.getPoolOwnership(0xEFGH...);

# Return Value Glossary

# FusePool

values[]
  • [0] string name: Name of the Fuse pool.
  • [1] address creator: Creator of the Fuse pool.
  • [2] address comptroller: Comptroller of the Fuse pool.
  • [3] uint256 blockPosted: Block in which the pool was created.
  • [4] uint256 timestampPosted: Timestamp when the pool was created.

# FusePoolAsset

values []
  • [0] address fToken: The fToken's address.
  • [1] address underlyingToken: The token the fToken is redeemable for.
  • [2] string underlyingName: Name of the underlying token.
  • [3] string underlyingSymbol: Symbol of the underlying token.
  • [4] uint256 underlyingDecimals: Decimals of underlying token (ETH is 18).
  • [5] uint256 underlyingBalance: How much of the underlying token the user of interest holds in their wallet.
  • [6] uint256 supplyRatePerBlock: Supply interest rate for the token in the pool. Can be converted to APY/APR as shown here.
  • [7] uint256 borrowRatePerBlock: Borrow interest rate for the token in the pool. Can be converted to APY/APR as shown here.
  • [8] uint256 totalSupply: Amount of the underlying token supplied in the pool. Scaled by underlyingDecimals.
  • [9]uint256 totalBorrow: Amount of the underlying token being borrowed in pool. Scaled by underlyingDecimals.
  • [10] uint256 supplyBalance: Amount of the underlying token the user of interest has supplied to the pool. Scaled by underlyingDecimals.
  • [11]uint256 borrowBalance: Amount of the underlying token the user of interest has borrowed from the pool. Scaled by underlyingDecimals.
  • [12] uint256 liquidity: Amount of the underlying token that is unborrowed in the pool. Scaled by underlyingDecimals.
  • [13] bool membership: If the user of interest has enabled the asset as collateral in the pool.
  • [14] uint256 exchangeRate: How much underlying one fToken can be redeemed for.
  • [15] uint256 underlyingPrice: Price of underlying tokens denominated in ETH. Its decimals are a function of underlyingDecimals: 1e(36 - underlyingDecimals). This is so multiplying the underlyingPrice and supplyBalance/totalSupply/totalBorrow/borrowBalance and dividing the result by 1e36 returns the Ether value of the underlying asset.
  • [16] address oracle: Oracle from which this asset's price is fetched.
  • [17] unt256 collateralFactor: A percentage representing how much of the asset's value in USD can be borrowed against if the asset is lent as collateral. 18 decimals (where 1e18 is 100% and 0 is 0%).
  • [18]uint256 reserveFactor: Proportion of borrow interest that is converted into reserves. 18 decimals (where 1e18 is 100% and 0 is 0%).
  • [19] uint256 adminFee: Proportion of borrow interest that is converted into admin fees. 18 decimals (where 1e18 is 100% and 0 is 0%).
  • [20] uint256 fuseFee: Proportion of borrow interest that is converted into fees for the Rari Capital DAO. 18 decimals (where 1e18 is 100% and 0 is 0%).

# FusePoolUser

values []
  • [0] address account: User's Ethereum address.
  • [1] uint256 totalBorrow: The user's total borrow balance in the pool, dominated in Ether (scaled by 18 decimals).
  • [2] uint256 totalCollateral: The user's total supply balance in the pool, dominated in Ether (scaled by 18 decimals).
  • [3] uint256 health: Represents how overcollateralized the user is in the pool (totalCollateral/totalBorrow). 18 decimals (where 1e18 is 100% and 0 is 0%). At 1e18 or lower the user is eligible for liquidation.
  • [4] FusePoolAsset[] assets: fTokens supplied/borrowed by the user in the pool.

# CTokenOwnership

values []
  • [0] address cToken: The fToken in question.
  • [1] address admin: The fToken's admin.
  • [2] bool adminHasRights: Does the admin have rights over the pool.
  • [3] bool fuseAdminHasRights: Does the global Fuse admin have rights over the pool.

# Fuse Safe Liquidator

# Safe Liquidate (c/fToken)

Self-funded-liquidate a Fuse ERC20 position.

function   safeLiquidate(
  address  borrower,
  uint256  repayAmount,
  CErc20   cErc20,
  CToken   cTokenCollateral,
  uint256  minOutputAmount,
  address  exchangeSeizedTo)
  • borrower: The borrower's Ethereum address.
  • repayAmount: The amount to repay to liquidate the unhealthy loan.
  • cErc20: The borrowed cErc20 to repay.
  • cTokenCollateral: The cToken collateral to be liquidated.
  • minOutputAmount: The minimum amount of collateral to seize (or the minimum exchange output if applicable) required for execution. Reverts if this condition is not met.
  • exchangeSeizedTo: If set to an address other than cTokenCollateral, exchange seized collateral to this ERC20 token contract address (or the zero address for ETH).

# Solidity

FuseSafeLiquidator liq = fuseSafeLiquidator(0xABCD...);

liq.safeLiquidate(0xEFGH..., 010101..., cErc20, cTokenCollateral, 010101..., 0xHIJK...);

# Web3 1.0

const FuseSafeLiquidator = new Web3.eth.Contract(FUSE_SAFE_LIQUIDATOR_ABI, 0xABCD...);

FuseSafeLiquidator.methods.safeLiquidate(0xEFGH..., 010101..., cErc20, cTokenCollateral, 010101..., 0xHIJK...);

# Safe Liquidate (ETH)

Self-funded-liquidate a Fuse ETH position.

 function safeLiquidate(
   address borrower,
   CEther  cEther,
   CErc20  cErc20Collateral,
   uint256 minOutputAmount,
   address exchangeSeizedTo)
  • borrower: The borrower's Ethereum address.
  • cEther: The borrowed cEther contract to repay.
  • cErc20Collateral: The cErc20 collateral contract to be liquidated.
  • minOutputAmount: The minimum amount of collateral to seize (or the minimum exchange output if applicable) required for execution. Reverts if this condition is not met.
  • exchangeSeizedTo: If set to an address other than cTokenCollateral, exchange seized collateral to this ERC20 token contract address (or the zero address for ETH).

# Solidity

FuseSafeLiquidator liq = fuseSafeLiquidator(0xABCD...);

liq.safeLiquidate(0xEFGH..., cEther, cErc20Collateral, 010101..., 0xHIJK...);

# Web 3 1.0

const FuseSafeLiquidator = new Web3.eth.Contract(FUSE_SAFE_LIQUIDATOR_ABI, 0xABCD...);

FuseSafeLiquidator.methods.safeLiquidate(0xEFGH..., cEther, cErc20Collateral, 010101..., 0xHIJK...);

# Safe Liquidate To Tokens With Flash Loan (ERC20)

Flash-loan-funded liquidate a Fuse ERC20 position.

function safeLiquidateToTokensWithFlashLoan(
  address borrower,
  uint256 repayAmount,
  CErc20  cErc20,
  CToken  cTokenCollateral,
  uint256 minProfitAmount,
  address exchangeProfitTo)
  • borrower: The borrower's Ethereum address.
  • repayAmount: The amount to repay to liquidate the unhealthy loan.
  • cErc20: The borrowed cErc20 to repay.
  • cTokenCollateral: The cToken collateral to be liquidated.
  • minProfitAmount: The minimum amount of profit required for execution (in terms of exchangeProfitTo). Reverts if this condition is not met.
  • exchangeProfitTo: If set to an address other than cTokenCollateral, exchange seized collateral to this ERC20 token contract address (or the zero address for ETH).

# Solidity

FuseSafeLiquidator liq = fuseSafeLiquidator(0xABCD...);

liq.safeLiquidateToTokensWithFlashLoan(
  0xEFGH...,
  010101...,
  cErc20,
  cTokenCollateral,
  010101...,
  0xHIJK...);

# Web3 1.0

const FuseSafeLiquidator = new Web3.eth.Contract(FUSE_SAFE_LIQUIDATOR_ABI, 0xABCD...);

FuseSafeLiquidator.methods.safeLiquidateToTokensWithFlashLoan(0xEFGH..., 010101..., cErc20, cTokenCollateral, 010101..., 0xHIJK...);

# Safe Liquidate To ETH With Flash Loan

Flash-loan-funded liquidate a Fuse ETH position.

function safeLiquidateToEthWithFlashLoan(
  address borrower,
  uint256 repayAmount,
  CEther  cEther,
  CErc20  cErc20Collateral,
  uint256 minProfitAmount,
  address exchangeProfitTo)
  • borrower: The borrower's Ethereum address.
  • repayAmount: The amount to repay to liquidate the unhealthy loan.
  • cEther: The borrowed cEther to repay.
  • cErc20Collateral: The cErc20 collateral to be liquidated.
  • minProfitAmount: The minimum amount of profit required for execution (in terms of exchangeProfitTo). Reverts if this condition is not met.
  • exchangeProfitTo: If set to an address other than cErc20Collateral, exchange seized collateral to this ERC20 token contract address (or the zero address for ETH).

# Solidity

FuseSafeLiquidator liq = fuseSafeLiquidator(0xABCD...);

liq.safeLiquidateToEthWithFlashLoan(
  0xEFGH...,
  010101...,
  cEther,
  cErc20Collateral,
  010101...,
  0xHIJK...);

# Web3 1.0

const FuseSafeLiquidator = new Web3.eth.Contract(FUSE_SAFE_LIQUIDATOR_ABI, 0xABCD...);

lens.methods.safeLiquidateToEthWithFlashLoan(0xEFGH..., 010101..., cEther, cErc20Collateral, 010101..., 0xHIJK...);