# Getting Started

Introduction to the DeFiPIE lending protocol

## Introduction

The DeFiPIE protocol is a series of interest rate pools running on a variety of blockchains. When users and applications deposit their assets to the DeFIPIE Protocol, they begin earning a variable interest rate instantly. Interest accrues every block (for Ethereum \~13 seconds, for Binance Smart Chain \~3 seconds), and users can withdraw their principal plus interest anytime.

On the other hand, users can borrow tokens from the pool by paying an interest rate to all pool lenders

When users deposit assets, they receive pTokens from DeFiPIE in exchange. pTokens are [ERC20 tokens](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) that can be redeemed for their underlying assets at any time. As interest accrues to the assets deposited, pTokens are redeemable at an exchange rate (relative to the underlying asset) that constantly increases over time, based on the rate of interest earned by the underlying asset.

## Networks

The DeFiPIE Protocol is currently deployed on the following networks:

{% tabs %}
{% tab title="Ethereum mainnet" %}

| Contract              | Address                                                                                                               |
| --------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Controller            | [0x36de5Bbc618A04c9B471208Ef52eE2b1F536E92d](https://etherscan.io/address/0x36de5bbc618a04c9b471208ef52ee2b1f536e92d) |
| Registry              | [0x1135270BbB0627e769a7a2e24f2b2C7F14B3d83A](https://etherscan.io/address/0x1135270bbb0627e769a7a2e24f2b2c7f14b3d83a) |
| Factory               | [0x54f04010FcfCfc95eC8Fd19Fe4cF57ADfBbb6136](https://etherscan.io/address/0x54f04010FcfCfc95eC8Fd19Fe4cF57ADfBbb6136) |
| UniswapPriceOracle    | [0x21790F2a8C6117CD93E65c30F55C6BB99Cb6c16D](https://etherscan.io/address/0x21790F2a8C6117CD93E65c30F55C6BB99Cb6c16D) |
| BaseInterestRateModel | [0xd47d39A66bb4912D127fBfC1b90884fCB3546137](https://etherscan.io/address/0xd47d39A66bb4912D127fBfC1b90884fCB3546137) |
| claimCalc             | [0x466CF3EA420237cD1669d78efd9519caAFe5a73a](https://etherscan.io/address/0x466CF3EA420237cD1669d78efd9519caAFe5a73a) |
| Maximillion           | [0x1913B2A20ae5CC0A177af1faaeCCDb267423c3B6](https://etherscan.io/address/0x1913B2A20ae5CC0A177af1faaeCCDb267423c3B6) |
| PIE                   | [0x607C794cDa77efB21F8848B7910ecf27451Ae842](https://etherscan.io/address/0x607c794cda77efb21f8848b7910ecf27451ae842) |
| {% endtab %}          |                                                                                                                       |

{% tab title="Rinkeby" %}

| Contract              | Address                                                                                                                       |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Controller            | [0xD204bE259F703503EF2eA03eB401Ce6E07254d96](https://rinkeby.etherscan.io/address/0xD204bE259F703503EF2eA03eB401Ce6E07254d96) |
| Registry              | [0xC5B3cfcC8aD60565997cAEed1Cce6CC915A08B90](https://rinkeby.etherscan.io/address/0xC5B3cfcC8aD60565997cAEed1Cce6CC915A08B90) |
| Factory               | [0x12FfF44587bA55992A9eDe625D4033385F708584](https://rinkeby.etherscan.io/address/0x12FfF44587bA55992A9eDe625D4033385F708584) |
| UniswapPriceOracle    | [0x155aE77115DE61AE5755aBD2C12CFD020Eb9d37E](https://rinkeby.etherscan.io/address/0x155aE77115DE61AE5755aBD2C12CFD020Eb9d37E) |
| BaseInterestRateModel | [0x2CaD4031C013Fa66E1F2F15baA135f1B2E45208e](https://rinkeby.etherscan.io/address/0x2CaD4031C013Fa66E1F2F15baA135f1B2E45208e) |
| claimCalc             | [0x6871F928713814ba2C6EB2789C3CfF24F817606E](https://rinkeby.etherscan.io/address/0x6871F928713814ba2C6EB2789C3CfF24F817606E) |
| Maximillion           | [0x4A6cbFb03Ada1F38186F494ad475536b6Ef73679](https://rinkeby.etherscan.io/address/0x4A6cbFb03Ada1F38186F494ad475536b6Ef73679) |
| PIE                   | [0xb36Afc9F38d8ac6F991bb9939d3EE8D45A7A1285](https://rinkeby.etherscan.io/address/0xb36afc9f38d8ac6f991bb9939d3ee8d45a7a1285) |
| {% endtab %}          |                                                                                                                               |

{% tab title="BSC mainnet" %}

| Contract              | Address                                                                                                              |
| --------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Controller            | [0x8ca3BD13BbF3468D48369DF508b9B614D9aa1802](https://bscscan.com/address/0x8ca3BD13BbF3468D48369DF508b9B614D9aa1802) |
| Registry              | [0xF2F88D8e974D07A2E27943310780B108f01a18b2](https://bscscan.com/address/0xF2F88D8e974D07A2E27943310780B108f01a18b2) |
| Factory               | [0xd6eAC7cf547002d289dC85954Ec0ABE217A9b80D](https://bscscan.com/address/0xd6eAC7cf547002d289dC85954Ec0ABE217A9b80D) |
| UniswapPriceOracle    | [0x2eC8BF5BeA6736EF549dd89c80BA3CFdc6d7BdfE](https://bscscan.com/address/0x2eC8BF5BeA6736EF549dd89c80BA3CFdc6d7BdfE) |
| BaseInterestRateModel | [0xDD2F62B666684226Fbe7a648E411B51b3D3c78f8](https://bscscan.com/address/0xDD2F62B666684226Fbe7a648E411B51b3D3c78f8) |
| claimCalc             | [0x1Ea24b8cFcf26C9d7b134f3fBDCA0A920655b17C](https://bscscan.com/address/0x1Ea24b8cFcf26C9d7b134f3fBDCA0A920655b17C) |
| Maximillion           | [0x9CeC0108803FB54dD83e58eE61bebB26F171b9f8](https://bscscan.com/address/0x9CeC0108803FB54dD83e58eE61bebB26F171b9f8) |
| PIE                   | [0xC4B35d3A24E3e8941c5d87fD21D0725642F50308](https://bscscan.com/address/0xC4B35d3A24E3e8941c5d87fD21D0725642F50308) |
| {% endtab %}          |                                                                                                                      |

{% tab title="BSC testnet" %}

| Contract              | Address                                                                                                                      |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Controller            | [0x660E1093AA3D7CB0f6A8dE172F85d0d7b010ef26](https://testnet.bscscan.com/address/0x660E1093AA3D7CB0f6A8dE172F85d0d7b010ef26) |
| Registry              | [0xddf147af5Bb55B1bE9bf6c37BFA5FEAf08Ac6Abd](https://testnet.bscscan.com/address/0xddf147af5Bb55B1bE9bf6c37BFA5FEAf08Ac6Abd) |
| Factory               | [0xcD686fFCFFf135AC7d0021E5a0bcAAD25f3ae4bf](https://testnet.bscscan.com/address/0xcD686fFCFFf135AC7d0021E5a0bcAAD25f3ae4bf) |
| UniswapPriceOracle    | [0xB76B79A327EC69a1F91e9Ba60fB2EA72979f6732](https://testnet.bscscan.com/address/0xB76B79A327EC69a1F91e9Ba60fB2EA72979f6732) |
| BaseInterestRateModel | [0xc09481E51Ca917EfF5b2Ff164e65560Ca10Bf0b8](https://testnet.bscscan.com/address/0xc09481E51Ca917EfF5b2Ff164e65560Ca10Bf0b8) |
| claimCalc             | [0x6ef8E32ea4623aC0439Bace0E3564BBE23f13CcF](https://testnet.bscscan.com/address/0x6ef8E32ea4623aC0439Bace0E3564BBE23f13CcF) |
| Maximillion           | [0x80978b220789e0d6336673aC9D826e114FCdAb78](https://testnet.bscscan.com/address/0x80978b220789e0d6336673aC9D826e114FCdAb78) |
| PIE                   | [0xd50da88069c69BF093e8dca1532Cc81711D9e0F4](https://testnet.bscscan.com/address/0xd50da88069c69BF093e8dca1532Cc81711D9e0F4) |
| {% endtab %}          |                                                                                                                              |
| {% endtabs %}         |                                                                                                                              |

## Protocol Math

The DeFiPIE protocol contracts use a system of exponential math, [Exponential.sol](https://github.com/DefiPie/defipie-protocol/blob/master/contracts/Exponential.sol), in order to represent fractional quantities with sufficient precision.

Most numbers are represented as a mantissa, an unsigned integer scaled by 1 \* 10 ^ 18, in order to perform basic math at a high level of precision.

### pToken and Underlying Decimals

Prices and exchange rates are scaled by the decimals unique to each asset; pTokens are ERC-20 tokens with 8 decimals In most cases (there are several pTokens exceptions in Ethereum network with 18 decimals), while their underlying tokens vary, and have a public member named decimals.

**pTokens exceptions in Ethereum network:**

| **pToken** | decimals |
| ---------- | -------- |
| pPIE       | 18       |
| pETH       | 18       |
| pDAI       | 18       |

### Interpreting Exchange Rates

The pToken Exchange Rate is scaled by the difference in decimals between the pToken and the underlying asset.

```
onePTokenInUnderlying = exchangeRateCurrent / (1 * 10 ^ (18 + underlyingDecimals - pTokenDecimals))
```

Here is an example of finding the value of 1 pPIE in PIE with Web3.js JavaScript.

```
const underlying = new web3.eth.Contract(erc20Abi, pieAddress);
const pToken = new web3.eth.Contract(pTokenAbi, pPieAddress);
const underlyingDecimals = await underlying.methods.decimals().call();
const pTokenDecimals = await pToken.methods.decimals().call();
const exchangeRateCurrent = await pToken.methods.exchangeRateCurrent().call();
const mantissa = 18 + parseInt(underlyingDecimals) - parseInt(pTokenDecimals);
const onePTokenInUnderlying = exchangeRateCurrent / Math.pow(10, mantissa);
console.log('1 pPIE can be redeemed for', onePTokenInUnderlying, 'PIE');
```

There is no underlying contract for ETH and BNB, so to do this with pETH and pBNB, set underlyingDecimals to 18.

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

```
underlyingTokens = pTokenAmount * onePTokenInUnderlying
```

### Calculating Accrued Interest

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

Interest accrues to all lenders and borrowers in a pool when any Ethereum address interacts with the pool’s pToken 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 lender and borrower in the pool. 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 pToken contract). Interest compounds only during blocks in which the pToken contract has one of the aforementioned methods invoked.

Here is an example of supply interest accrual:

Alice deposits 1 ETH to the DeFiPIE protocol. At the time of deposit, the supplyRatePerBlock is 37893605 Wei, or 0.000000000037893605 ETH per block. No one interacts with the pEther 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 lending or borrowing in each pool can be calculated using the value of supplyRatePerBlock (for deposit APY) or borrowRatePerBlock (for borrow APY) in this formula:

```
Rate = pToken.supplyRatePerBlock(); // Integer
Rate = 37893566
ETH Mantissa = 1 * 10 ^ 18 (ETH has 18 decimal places)
Blocks Per Day = 4 * 60 * 24 (based on 4 blocks occurring every minute)
Days Per Year = 365

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

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

```
const ethMantissa = 1e18;
const blocksPerDay = 4 * 60 * 24;
const daysPerYear = 365;

const pToken = new web3.eth.Contract(pEthAbi, pEthAddress);
const supplyRatePerBlock = await pToken.methods.supplyRatePerBlock().call();
const borrowRatePerBlock = await pToken.methods.borrowRatePerBlock().call();
const depositApy = (((Math.pow((supplyRatePerBlock / ethMantissa * blocksPerDay) + 1, daysPerYear))) - 1) * 100;
const borrowApy = (((Math.pow((borrowRatePerBlock / ethMantissa * blocksPerDay) + 1, daysPerYear))) - 1) * 100;
console.log(`Deposit APY for ETH ${depositApy} %`);
console.log(`Borrow APY for ETH ${borrowApy} %`);
```


# pTokens

## Introduction

Each asset supported by the DeFiPIE Protocol is integrated through a pToken contract, which is an [EIP-20](https://eips.ethereum.org/EIPS/eip-20) compliant representation of balances supplied to the protocol. By minting pTokens, users (1) earn interest through the pToken's exchange rate, which increases in value relative to the underlying asset, and (2) gain the ability to use pTokens as collateral.

pTokens are the primary means of interacting with the DeFiPIE Protocol; when a user mints, redeems, borrows, repays a borrow, liquidates a borrow, or transfers pTokens, he/she will do so using the pToken contract.

There are currently two types of pTokens: PErc20 and PEther. Though both types expose the EIP-20 interface, PErc20 wraps an underlying ERC-20 asset, while PEther 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.

### How do pTokens earn interest?

Each [pool](https://app.defipie.com/) has its own Deposit interest rate (APR). Interest isn't distributed; instead, simply by holding pTokens, you'll earn interest.

pTokens accumulates interest through their exchange rate — over time, each pToken becomes convertible into an increasing amount of it's underlying asset, even while the number of pTokens in your wallet stays the same.

### Do I need to calculate the pToken exchange rate?

When a pool is launched, the pToken exchange rate (how much ETH one cETH is worth) begins at 0.020000 — and increases at a rate equal to the compounding pool interest rate. For example, after one year, the exchange rate might equal 0.021591.

Each user has the same pToken exchange rate; there’s nothing unique to your wallet that you have to worry about.

### Can you walk me through an example?

Let’s say you deposit 1,000 DAI to the DeFiPIE protocol, when the exchange rate is 0.020070; you would receive 49,825.61 pDAI (1,000/0.020070).

A few months later, you decide it’s time to withdraw your DAI from the protocol; the exchange rate is now 0.021591:

* Your 49,825.61 cDAI is now equal to 1,075.78 DAI (49,825.61 \* 0.021591)
* You could withdraw 1,075.78 DAI, which would redeem all 49,825.61 pDAI
* Or, you could withdraw a portion, such as your original 1,000 DAI, which would redeem 46,315.59 pDAI (keeping 3,510.01 pDAI in your wallet)

### How do I view my pTokens?

Each pToken is visible on Etherscan, and you should be able to view them in the list of tokens associated with your address

You can add pToken by its address in any wallet (Metamask, Trust Wallet etc.) as a simple ERC-20 token.

### Can I transfer pTokens?

Yes, but exercise caution! By transferring pTokens, you’re transferring your balance of the underlying asset inside the DeFiPIE protocol. If you send a pToken to your friend, your balance (viewable in the [DeFiPIE Interface](https://app.defipie.com/)) will decline, and your friend will see their balance increase.

A pToken transfer will fail if the account has entered that pToken pool and the transfer would have put the account into a state of negative liquidity.

## Mint

The mint function transfers an asset into the protocol, which begins accumulating interest based on the current [Supply Rate](https://doc.defipie.com/ptokens#supply-rate) for the asset. The user receives a quantity of pTokens equal to the underlying tokens deposited, divided by the current [Exchange Rate](https://doc.defipie.com/ptokens#exchange-rate).

#### **PErc20**

```
function mint(uint mintAmount) returns (uint)
```

* `msg.sender`: The account which shall deposit the asset, and own the minted pTokens.
* `mintAmount`: The amount of the asset to be deposited, in units of the underlying asset.
* `RETURN`: 0 on success, otherwise an [Error code](https://doc.defipie.com/ptokens#error-codes)

Before depositing an asset, users must first [approve](https://eips.ethereum.org/EIPS/eip-20#approve) the pToken to access their token balance.

#### **PEther**

```
function mint() payable
```

* `msg.value` (payable): The amount of ether to be deposited, in wei.
* `msg.sender`: The account which shall deposit the ether, and own the minted pTokens.
* `RETURN`: No return, reverts on error.

#### **Solidity**

```
Erc20 underlying = Erc20(0xToken...);     // get a handle for the underlying asset contract
PErc20 pToken = PErc20(0x3FDA...);        // get a handle for the corresponding PToken contract
underlying.approve(address(pToken), 100); // approve the transfer
assert(pToken.mint(100) == 0);            // mint the pTokens and assert there is no error
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
await pToken.methods.mint().send({from: myAccount, value: 50});
```

## Redeem

The redeem function converts a specified quantity of pTokens into the underlying asset, and returns them to the user. The amount of underlying tokens received is equal to the quantity of pTokens redeemed, multiplied by the current [Exchange Rate](https://doc.defipie.com/ptokens#exchange-rate). The amount redeemed must be less than the user's Account Liquidity and the pool's available liquidity.

#### **PErc20 / PEther**

```
function redeem(uint redeemTokens) returns (uint)
```

* `msg.sender`: The account to which redeemed funds shall be transferred.
* `redeemTokens`: The number of pTokens to be redeemed.
* `RETURN`: 0 on success, otherwise an [Error code](https://doc.defipie.com/ptokens#error-codes).

#### **Solidity**

```
PEther pToken = PEther(0x3FDB...);
require(pToken.redeem(7) == 0, "something went wrong");
```

#### **Web3 1.0**

```
const pToken = PErc20.at(0x3FDA...);
pToken.methods.redeem(1).send({from: ...});
```

## Redeem Underlying

The redeem underlying function converts pTokens into a specified quantity of the underlying asset, and returns them to the user. The amount of pTokens redeemed is equal to the quantity of underlying tokens received, divided by the current [Exchange Rate](https://doc.defipie.com/ptokens#exchange-rate). The amount redeemed must be less than the user's Account Liquidity and the pool's available liquidity.

#### **PErc20 / PEther**

```
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](https://doc.defipie.com/ptokens#error-codes).

#### **Solidity**

```
PEther pToken = PEther(0x3FDB...);
require(pToken.redeemUnderlying(50) == 0, "something went wrong");
```

#### **Web3 1.0**

```
const pToken = PErc20.at(0x3FDA...);
pToken.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](https://doc.defipie.com/ptokens#borrow-rate) for the asset. The amount borrowed must be less than the user's Account Liquidity and the pool's available liquidity.

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

#### **PErc20 / PEther**

```
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](https://doc.defipie.com/ptokens#error-codes)

#### **Solidity**

```
PErc20 pToken = PErc20(0x3FDA...);
require(pToken.borrow(100) == 0, "got collateral?");
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
await pToken.methods.borrow(50).send({from: 0xMyAccount});
```

## Repay Borrow

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

#### **PErc20**

```
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. 2^256 - 1) can be used to repay the full amount.
* `RETURN`: 0 on success, otherwise an [Error code](https://doc.defipie.com/ptokens#error-codes).

Before repaying an asset, users must first [approve](https://eips.ethereum.org/EIPS/eip-20#approve) the pToken to access their token balance.

#### **PEther**

```
function repayBorrow() payable
```

* `msg.value` (payable): 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**

```
PEther pToken = PEther(0x3FDB...);
require(pToken.repayBorrow.value(100)() == 0, "transfer approved?");
```

#### **Web3 1.0**

```
const pToken = PErc20.at(0x3FDA...);
pToken.methods.repayBorrow(10000).send({from: ...});
```

## Repay Borrow Behalf

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

#### **PErc20**

```
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. 2^256 - 1) can be used to repay the full amount.
* `RETURN`: 0 on success, otherwise an [Error code](https://doc.defipie.com/ptokens#error-codes)

Before repaying an asset, users must first [approve](https://eips.ethereum.org/EIPS/eip-20#approve) the pToken to access their token balance.

#### **PEther**

```
function repayBorrowBehalf(address borrower) payable
```

* `msg.value` (payable): 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**

```
PEther pToken = PEther(0x3FDB...);
require(pToken.repayBorrowBehalf.value(100)(0xBorrower) == 0, "transfer approved?");
```

#### **Web3 1.0**

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

## Transfer

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

#### **PErc20 / PEther**

```
function transfer(address recipient, uint256 amount) returns (bool)
```

* `recipient`: The transfer recipient address.
* `amount`: The amount of pTokens to transfer.
* `RETURN`: Returns a boolean value indicating whether or not the operation succeeded.

#### **Solidity**

```
PEther pToken = PEther(0x3FDB...);
pToken.transfer(0xABCD..., 100000000000);
```

#### **Web3 1.0**

```
const pToken = PErc20.at(0x3FDA...);
await pToken.methods.transfer(0xABCD..., 100000000000).send({from: 0xSender});
```

## Liquidate Borrow

A user who has negative account liquidity is subject to [liquidation](https://doc.defipie.com/ptokens#liquidate-borrow) 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. Liquidators must interact with each pToken contract in which they wish to repay a borrow and seize another asset as collateral. When collateral is seized, the liquidator is transferred pTokens, which they may redeem the same as if they had deposited the asset themselves. Users must approve each pToken contract before calling liquidate (i.e. on the borrowed asset which they are repaying), as they are transferring funds into the contract.

#### **PErc20**

```
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.
* `pTokenCollateral`: The address of the pToken currently held as collateral by a borrower, that the liquidator shall seize.
* `RETURN`: 0 on success, otherwise an [Error code](https://doc.defipie.com/ptokens#error-codes).

Before liquidating a loan, users must first [approve](https://eips.ethereum.org/EIPS/eip-20#approve) the pToken to access their token balance.

#### **PEther**

```
function liquidateBorrow(address borrower, address pTokenCollateral) payable
```

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

#### **Solidity**

```
PEther pToken = PEther(0x3FDB...);
PErc20 pTokenCollateral = PErc20(0x3FDA...);
require(pToken.liquidateBorrow.value(100)(0xBorrower, pTokenCollateral) == 0, "borrower underwater??");
```

#### **Web3 1.0**

```
const pToken = PErc20.at(0x3FDA...);
const pTokenCollateral = PEther.at(0x3FDB...);
await pToken.methods.liquidateBorrow(0xBorrower, 33, pTokenCollateral).send({from: 0xLiquidator});
```

## Key Events

| Event                                                                                                                                                                                               | Description                                                                                     |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| <p><code>Mint(address minter,</code> </p><p><code>uint mintAmount, uint mintTokens)</code></p>                                                                                                      | Emitted upon a successful [Mint](https://doc.defipie.com/ptokens#mint).                         |
| <p><code>Redeem(address redeemer,</code> </p><p><code>uint redeemAmount, uint redeemTokens)</code></p>                                                                                              | Emitted upon a successful [Redeem](https://doc.defipie.com/ptokens#redeem).                     |
| <p><code>Borrow(address borrower,</code></p><p><code>uint borrowAmount, uint accountBorrows,</code></p><p><code>uint totalBorrows)</code></p>                                                       | Emitted upon a successful [Borrow](https://doc.defipie.com/ptokens#borrow).                     |
| <p><code>RepayBorrow(address payer,</code> </p><p><code>address borrower, uint repayAmount,</code> </p><p><code>uint accountBorrows, uint totalBorrows)</code></p>                                  | Emitted upon a successful [Repay Borrow](https://doc.defipie.com/ptokens#repay-borrow).         |
| <p><code>LiquidateBorrow(address liquidator,</code> </p><p><code>address borrower, uint repayAmount,</code> </p><p><code>address pTokenCollateral,</code> </p><p><code>uint seizeTokens)</code></p> | Emitted upon a successful [Liquidate Borrow](https://doc.defipie.com/ptokens#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.                                                                                                                           |
| 3    | `CONTROLLER_REJECTION`           | The action would violate the controller policy.                                                                                                                           |
| 4    | `CONTROLLER_CALCULATION_ERROR`   | An internal calculation has failed in the controller.                                                                                                                     |
| 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 pool is not currently listed by its controller.                                                                                                                       |
| 12   | `TOKEN_INSUFFICIENT_ALLOWANCE`   | ERC-20 contract must *allow* pToken contract to call transferFrom. The current allowance is either 0 or less than the requested deposit, 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 pool 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 pool.                                                                                                                   |
| 16   | `TOKEN_TRANSFER_OUT_FAILED`      | Failure in ERC-20 when transfering token out of the pool.                                                                                                                 |

## 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_CONTROLLER_REJECTION`                                |
| 15   | `LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED`                    |
| 16   | `LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED`                |
| 17   | `LIQUIDATE_COLLATERAL_FRESHNESS_CHECK`                       |
| 18   | `LIQUIDATE_CONTROLLER_REJECTION`                             |
| 19   | `LIQUIDATE_CONTROLLER_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_CONTROLLER_REJECTION`                       |
| 28   | `LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER`                     |
| 29   | `LIQUIDATE_SEIZE_TOO_MUCH`                                   |
| 30   | `MINT_ACCRUE_INTEREST_FAILED`                                |
| 31   | `MINT_CONTROLLER_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_CONTROLLER_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_CONTROLLER_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_CONTROLLER_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_CONTROLLER_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`                      |
| 81   | `SET_NEW_IMPLEMENTATION`                                     |

## Exchange Rate

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

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

#### **PErc20 / PEther**

```
function exchangeRateCurrent() returns (uint)
```

* `RETURN`: The current exchange rate as an unsigned integer, scaled by 1e18.

#### **Solidity**

```
PErc20 pToken = PToken(0x3FDA...);
uint exchangeRateMantissa = pToken.exchangeRateCurrent();
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const exchangeRate = (await pToken.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 pToken contract. One may query the total amount of cash currently available to this pool.

#### **PErc20 / PEther**

```
function getCash() returns (uint)
```

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

#### **Solidity**

```
PErc20 pToken = PToken(0x3FDA...);
uint cash = pToken.getCash();
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const cash = (await pToken.methods.getCash().call());
```

## Total Borrow

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

#### **PErc20 / PEther**

```
function totalBorrowsCurrent() returns (uint)
```

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

#### **Solidity**

```
PErc20 pToken = PToken(0x3FDA...);
uint borrows = pToken.totalBorrowsCurrent();
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const borrows = (await pToken.methods.totalBorrowsCurrent().call());
```

## Borrow Balance

A user who borrows assets from the protocol is subject to accumulated interest based on the current [borrow rate](https://doc.defipie.com/ptokens#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.

#### **PErc20 / PEther**

```
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**

```
PErc20 pToken = PToken(0x3FDA...);
uint borrows = pToken.borrowBalanceCurrent(msg.caller);
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const borrows = await pToken.methods.borrowBalanceCurrent(account).call();
```

## Borrow Rate

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

#### **PErc20 / PEther**

```
function borrowRatePerBlock() returns (uint)
```

* `RETURN`: The current borrow rate as an unsigned integer, scaled by 1e18.

#### **Solidity**

```
PErc20 pToken = PToken(0x3FDA...);
uint borrowRateMantissa = pToken.borrowRatePerBlock();
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const borrowRate = (await pToken.methods.borrowRatePerBlock().call()) / 1e18;
```

## Total Supply

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

#### **PErc20 / PEther**

```
function totalSupply() returns (uint)
```

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

#### **Solidity**

```
PErc20 pToken = PToken(0x3FDA...);
uint tokens = pToken.totalSupply();
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const tokens = (await pToken.methods.totalSupply().call());
```

## Underlying Balance

The user's underlying balance, representing their assets in the protocol, is equal to the user's pToken balance multiplied by the [Exchange Rate](https://doc.defipie.com/ptokens#exchange-rate).

**PErc20 / PEther**

```
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**

```
PErc20 pToken = PToken(0x3FDA...);
uint tokens = pToken.balanceOfUnderlying(msg.caller);
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const tokens = await pToken.methods.balanceOfUnderlying(account).call();
```

## Supply Rate

At any point in time one may query the contract to get the current supply (deposit) rate per block. The supply rate is derived from the [borrow rate](https://doc.defipie.com/ptokens#borrow-rate), [reserve factor](https://doc.defipie.com/ptokens#reserve-factor) and the amount of [total borrows](https://doc.defipie.com/ptokens#total-borrow).

#### **PErc20 / PEther**

```
function supplyRatePerBlock() returns (uint)
```

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

#### **Solidity**

```
PErc20 pToken = PToken(0x3FDA...);
uint supplyRateMantissa = pToken.supplyRatePerBlock();
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const supplyRate = (await pToken.methods.supplyRatePerBlock().call()) / 1e18;
```

## Total Reserves

Reserves are an accounting entry in each pToken contract that represents a portion of historical interest set aside as [cash](https://doc.defipie.com/ptokens#get-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](https://doc.defipie.com/ptokens#reserve-factor).

#### **PErc20 / PEther**

```
function totalReserves() returns (uint)
```

* `RETURN`: The total amount of reserves held in the pool.

#### **Solidity**

```
PErc20 pToken = PToken(0x3FDA...);
uint reserves = pToken.totalReserves();
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const reserves = (await pToken.methods.totalReserves().call());
```

## Reserve Factor

The reserve factor defines the portion of borrower interest that is converted into [reserves](https://doc.defipie.com/ptokens#total-reserves).

#### **PErc20 / PEther**

```
function reserveFactorMantissa() returns (uint)
```

* `RETURN`: The current reserve factor as an unsigned integer, scaled by 1e18.

#### **Solidity**

```
PErc20 pToken = PToken(0x3FDA...);
uint reserveFactorMantissa = pToken.reserveFactorMantissa();
```

#### **Web3 1.0**

```
const pToken = PEther.at(0x3FDB...);
const reserveFactor = (await pToken.methods.reserveFactorMantissa().call()) / 1e18;
```


# Controller

## Introduction

The Controller is the risk management layer of the DeFiPIE 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 pToken, the Controller is asked to approve or deny the transaction.

The Controller maps user balances to prices (via the Price Oracle) to risk weights (called [Collateral Factors](https://doc.defipie.com/controller#collateral-factor)) to make its determinations. Users explicitly list which assets they would like included in their risk scoring, by calling [Enter Markets](https://doc.defipie.com/controller#enter-markets) and [Exit Market](https://doc.defipie.com/controller#exit-market).

## Architecture

The Controller is implemented as an upgradeable proxy. The Unitroller proxies all logic to the Controller implementation, but storage values are set on the Unitroller. To call Controller functions, use the Controller 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 deposit collateral or borrow in a market, it must be entered first.

#### **Controller**

```
function enterMarkets(address[] calldata pTokens) returns (uint[] memory)
```

* `msg.sender`: The account which shall enter the given markets.
* `pTokens`: The addresses of the pToken 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**

```
Controller troll = Controller(0xABCD...);
PToken[] memory pTokens = new PToken[](2);
pTokens[0] = PErc20(0x3FDA...);
pTokens[1] = PEther(0x3FDB...);
uint[] memory errors = troll.enterMarkets(pTokens);
```

#### **Web3 1.0**

```
const troll = Controller.at(0xABCD...);
const pTokens = [PErc20.at(0x3FDA...), PEther.at(0x3FDB...)];
const errors = await troll.methods.enterMarkets(pTokens).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.

#### **Controller**

```
function exitMarket(address pToken) returns (uint)
```

* `msg.sender`: The account which shall exit the given market.
* `pTokens`: The addresses of the pToken market to exit.
* `RETURN`: 0 on success, otherwise an Error code.

#### **Solidity**

```
Controller troll = Controller(0xABCD...);
uint error = troll.exitMarket(PToken(0x3FDA...));
```

#### **Web3 1.0**

```
const troll = Controller.at(0xABCD...);
const errors = await troll.methods.exitMarket(PEther.at(0x3FDB...)).send({from: ...});
```

## Get Assets In

Get the list of markets an account is currently entered into. In order to deposit collateral or borrow in a market, it must be entered first. Entered markets count towards [account liquidity](https://doc.defipie.com/controller#get-account-liquidity) calculations.

#### **Controller**

```
function getAssetsIn(address account) view 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**

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

#### **Web3 1.0**

```
const troll = Controller.at(0xABCD...);
const markets = await troll.methods.getAssetsIn(pTokens).call();
```

## Collateral Factor

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

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.

{% hint style="warning" %}
Collateral factors can be increased (or decreased) through Governance, as market conditions change.
{% endhint %}

#### **Controller**

```
function markets(address pTokenAddress) view returns (bool, uint, bool)
```

* `pTokenAddress`: The address of the pToken to check if listed and get the collateral factor for.
* `RETURN`: Tuple of values (isListed, collateralFactorMantissa, isPied); isListed represents whether the controller recognizes this pToken; collateralFactorMantissa, scaled by 1e18, is multiplied by a deposit balance to determine how much value can be borrowed. The isPied boolean indicates whether or not suppliers and borrowers are distributed PIE tokens.

#### **Solidity**

```
Controller troll = Controller(0xABCD...);
(bool isListed, uint collateralFactorMantissa, bool isPied) = troll.markets(0x3FDA...);
```

#### **Web3 1.0**

```
const troll = Controller.at(0xABCD...);
const result = await troll.methods.markets(0x3FDA...).call();
const {0: isListed, 1: collateralFactorMantissa, 2: isPied} = 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](https://doc.defipie.com/controller#enter-markets) into, their deposited balance is multiplied by the market’s [collateral factor](https://doc.defipie.com/controller#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 DeFiPIE Protocol exclusively uses unsigned integers, Account Liquidity returns either a surplus or shortfall.

#### **Controller**

```
function getAccountLiquidity(address account) view 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](https://doc.defipie.com/controller#get-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**

```
Controller troll = Controller(0xABCD...);
(uint error, uint liquidity, uint shortfall) = troll.getAccountLiquidity(msg.caller);
require(error == 0, "contact support");
require(shortfall == 0, "account underwater");
require(liquidity > 0, "account has excess collateral");
```

#### **Web3 1.0**

```
const troll = Controller.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.

#### **Controller**

```
function closeFactorMantissa() view returns (uint)
```

* `RETURN`: The closeFactor, scaled by 1e18, is multiplied by an outstanding borrow balance to determine how much could be closed.

#### **Solidity**

```
Controller troll = Controller(0xABCD...);
uint closeFactor = troll.closeFactorMantissa();
```

#### **Web3 1.0**

```
const troll = Controller.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.

#### **Controller**

```
function liquidationIncentiveMantissa() view 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**

```
Controller troll = Controller(0xABCD...);
uint closeFactor = troll.liquidationIncentiveMantissa();
```

#### **Web3 1.0**

```
const troll = Controller.at(0xABCD...);
const closeFactor = await troll.methods.liquidationIncentiveMantissa().call();
```

## Key Events

| Event                                           | Description                                                                                 |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `MarketEntered(PToken pToken, address account)` | Emitted upon a successful [Enter Market](https://doc.defipie.com/controller#enter-markets). |
| `MarketExited(PToken pToken, address account)`  | Emitted upon a successful [Exit Market](https://doc.defipie.com/controller#exit-market).    |

## Error Codes

| Code |                                 | Description                                                                         |
| ---- | ------------------------------- | ----------------------------------------------------------------------------------- |
| 0    | `NO_ERROR`                      | Not a failure.                                                                      |
| 1    | `UNAUTHORIZED`                  | The sender is not authorized to perform this action.                                |
| 2    | `CONTROLLER_MISMATCH`           | Liquidation cannot be performed in markets with different controllers.              |
| 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 controller.                               |
| 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 controller could not obtain a required price of an asset.                       |
| 15   | `REJECTION`                     | The comptroller rejects the action requested by the market.                         |
| 16   | `SNAPSHOT_ERROR`                | The controller could not get the account borrows and exchange rate from the market. |
| 17   | `TOO_MANY_ASSETS`               | Attempted to enter more markets than are currently supported.                       |
| 18   | `TOO_MUCH_REPAY`                | Attempted to repay more than is allowed by the protocol.                            |

## 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_PAUSE_GUARDIAN_OWNER_CHECK`              |
| 15   | `SET_PENDING_ADMIN_OWNER_CHECK`               |
| 16   | `SET_PENDING_IMPLEMENTATION_OWNER_CHECK`      |
| 17   | `SET_PRICE_ORACLE_OWNER_CHECK`                |
| 18   | `SUPPORT_MARKET_EXISTS`                       |
| 19   | `SUPPORT_MARKET_OWNER_CHECK`                  |

## PIE Distribution Speeds

### PIE Speed

The "PIE speed" unique to each market is an unsigned integer that specifies the amount of PIE that is distributed, per block, to suppliers and borrowers in each market. This number can be changed for individual markets by calling the \_setPieSpeed method through a successful DeFiPIE Governance proposal.

The following is the formula for calculating the rate that PIE is distributed to each supported market.

```
utility = pTokenTotalBorrows * assetPrice

utilityFraction = utility / sumOfAllPIEedMarketUtilities

marketPieSpeed = pieRate * utilityFraction
```

### PIE Distributed Per Block (All Markets)

The Controller contract’s pieRate is an unsigned integer that indicates the rate at which the protocol distributes PIE to markets’ suppliers or borrowers, every Ethereum block. The value is the amount of PIE (in wei), per block, allocated for the markets. Note that not every market has PIE distributed to its participants (see Market Metadata).

The pieRate indicates how much PIE goes to the suppliers or borrowers, so doubling this number shows how much PIE goes to all suppliers and borrowers combined. The code examples implement reading the amount of PIE distributed, per Ethereum block, to all markets.

#### **Controller**

```
uint public pieRate;
```

#### **Solidity**

```
Controller troll = Controller(0xABCD...);

// PIE issued per block to suppliers OR borrowers * (1 * 10 ^ 18)
uint pieRate = troll.pieRate();

// Approximate PIE issued per day to suppliers OR borrowers * (1 * 10 ^ 18)
uint pieRatePerDay = pieRate * 4 * 60 * 24;

// Approximate PIE issued per day to suppliers AND borrowers * (1 * 10 ^ 18)
uint pieRatePerDayTotal = pieRatePerDay * 2;
```

#### **Web3 1.0**

```
const controller = new web3.eth.Contract(controllerAbi, controllerAddress);

let pieRate = await controller.methods.pieRate().call();
pieRate = pieRate / 1e18;

// PIE issued to suppliers OR borrowers
const pieRatePerDay = pieRate * 4 * 60 * 24;

// PIE issued to suppliers AND borrowers
const pieRatePerDayTotal = pieRatePerDay * 2;
```

### PIE Distributed Per Block (Single Market)

The Controller contract has a mapping called `pieSpeeds`. It maps pToken addresses to an integer of each market’s PIE distribution per Ethereum block. The integer indicates the rate at which the protocol distributes PIE to markets’ suppliers or borrowers. The value is the amount of PIE (in wei), per block, allocated for the market. Note that not every market has PIE distributed to its participants (see Market Metadata).

The speed indicates how much PIE goes to the suppliers or the borrowers, so doubling this number shows how much PIE goes to market suppliers and borrowers combined. The code examples implement reading the amount of PIE distributed, per Ethereum block, to a single market.

#### **Controller**

```
mapping(address => uint) public pieSpeeds;
```

#### **Solidity**

```
Controller troll = Controller(0x123...);
address pToken = 0xabc...;

// PIE issued per block to suppliers OR borrowers * (1 * 10 ^ 18)
uint pieSpeed = troll.pieSpeeds(pToken);

// Approximate PIE issued per day to suppliers OR borrowers * (1 * 10 ^ 18)
uint pieSpeedPerDay = pieSpeed * 4 * 60 * 24;

// Approximate PIE issued per day to suppliers AND borrowers * (1 * 10 ^ 18)
uint pieSpeedPerDayTotal = pieSpeedPerDay * 2;
```

#### **Web3 1.0**

```
const pTokenAddress = '0xabc...';

const controller = new web3.eth.Contract(controllerAbi, controllerAddress);

let pieSpeed = await controller.methods.pieSpeeds(pTokenAddress).call();
pieSpeed = pieSpeed / 1e18;

// PIE issued to suppliers OR borrowers
const pieSpeedPerDay = pieSpeed * 4 * 60 * 24;

// PIE issued to suppliers AND borrowers
const pieSpeedPerDayTotal = pieSpeedPerDay * 2;
```

## Claim PIE

Every DeFiPIE user accrues PIE for each block they are supplying to or borrowing from the protocol. Users may call the Controller's claimPie method at any time to transfer PIE accrued to their address.

#### **Controller**

```
// Claim all the PIE accrued by holder in all markets
function claimPie(address holder) public

// Claim all the PIE accrued by holder in specific markets
function claimPie(address holder, PToken[] memory pTokens) public

// Claim all the PIE accrued by specific holders in specific markets for their supplies and/or borrows
function claimPie(address[] memory holders, PToken[] memory pTokens, bool borrowers, bool suppliers) public
```

#### **Solidity**

```
Controller troll = Controller(0xABCD...);
troll.claimPie(0x1234...);
```

#### **Web3 1.0**

```
const controller = new web3.eth.Contract(controllerAbi, controllerAddress);
await controller.methods.claimPie("0x1234...").send({ from: sender });
```

## Market Metadata

The Controller contract has an array called getAllMarkets that contains the addresses of each pToken contract. Each address in the getAllMarkets array can be used to fetch a metadata struct in the Controller’s markets constant. See the [Controller Storage contract](https://github.com/DefiPie/defipie-protocol/blob/master/contracts/ControllerStorage.sol) for the Market struct definition.

#### **Controller**

```
PToken[] public getAllMarkets;
```

#### **Solidity**

```
Controller troll = Controller(0xABCD...);
PToken pTokens[] = troll.getAllMarkets();
```

#### **Web3 1.0**

```
const controller = new web3.eth.Contract(controllerAbi, controllerAddress);
const pTokens = await controller.methods.getAllMarkets().call();
const pToken = pTokens[0]; // address of a pToken
```


# Registry

## Introduction

The Registry contract contains mapping with all pToken addresses, it allows get the pToken address by the underlying asset address. The Registry also contains the address of the current implementation of the pToken, which is used by all proxy pools.

## Get pToken address

The Registry contract has a mapping called `pTokens`. It maps underlying asset addresses to pToken addresses.

#### Registry

```
mapping (address => address) public pTokens;
```

#### **Solidity**

```
Registry registry = Registry(0x123...);
address asset = 0xabc...;
address pool = registry.pTokens(asset);
```

#### **Web3 1.0**

```
const asset = '0xabc...';
const registry = new web3.eth.Contract(registryAbi, registryAddress);
const pool = await registry.methods.pTokens(asset).call();
```


# PTokenFactory

## Introduction

The PTokenFactory contract is for creating new pools.

## Create pToken

Before creating a new pToken, the factory will check the conditions necessary to create a new pool, and if the asset meets all the conditions, the pToken will be create&#x64;**,** otherwise, the function will return an error.

#### PTokenFactory

```
function createPToken(address underlying_) external returns (uint)
```

* `underlying_`: The underlying asset address.
* `RETURN`: 0 on success, otherwise an Error code

#### **Solidity**

```
Erc20 underlying = Erc20(0xToken...);
PTokenFactory factory = PTokenFactory(0xABCD...);
require(factory.createPToken(address(underlying)) == 0, "something went wrong");
```

#### **Web3 1.0**

```
const underlying = "0xToken..."
const factory = PTokenFactory.at(0x3FDB...);
factory.methods.createPToken(underlying).send({from: ...});
```

## Checking asset liquidity

One of the main requirements for creating a new pToken is the availability of sufficient liquidity on Uniswap v2 or other DEX (clones Uniswap v2). This function checks liquidity and returns `true` if it is greater than or equal to the `minUniswapLiquidity` parameter.

#### PTokenFactory

```
function checkPair(address asset) public view returns (bool)
```

* asset: The underlying asset address.
* `RETURN`: true or false

#### **Solidity**

```
Erc20 underlying = Erc20(0xToken...);
PTokenFactory factory = PTokenFactory(0xABCD...);
require(factory.checkPair(address(underlying)) == 0, "not enough liquidity");
```

#### **Web3 1.0**

```
const underlying = "0xToken..."
const factory = PTokenFactory.at(0x3FDB...);
factory.methods.checkPair(underlying).call();
```


# UniswapPriceOracle

## Introduction

DeFiPIE protocol uses UniswapPriceOracle to get time-weighted average prices from Uniswap v2 or other DEX (clones Uniswap v2).

Every time the user interacts with a pool, the protocol gets the current price from Uniswap and averages it with the previously stored price, thereby achieving the Time-weighted average price effect, which in turn protects the protocol from price manipulation through flash loans.

## **Update price by pToken**

Updating the price of an asset by the pToken address.

#### UniswapPriceOracle

```
function updateUnderlyingPrice(address pToken) public override returns (uint)
```

* `pToken`: pToken address.
* `RETURN`: 0 on success, otherwise an Error code.

#### **Solidity**

```
UniswapPriceOracle oracle = UniswapPriceOracle(0xABCD...);
PErc20 pToken = PErc20(0x3FDB...);
oracle.updateUnderlyingPrice(address(pToken));
```

#### **Web3 1.0**

```
const oracle = UniswapPriceOracle.at(0xABCD...);
const pToken = PErc20.at(0x3FDB...);
oracle.methods.updateUnderlyingPrice(pToken).send({from: ...});
```

## Update price by an asset.

Updating the price of an asset by the asset address.

#### UniswapPriceOracle

```
function update(address asset) public returns (uint)
```

* `asset`: asset address.
* `RETURN`: 0 on success, otherwise an Error code.

#### **Solidity**

```
UniswapPriceOracle oracle = UniswapPriceOracle(0xABCD...);
Erc20 token = Erc20(0x3FDB...);
oracle.update(address(token));
```

#### **Web3 1.0**

```
const oracle = UniswapPriceOracle.at(0xABCD...);
const token = Erc20.at(0x3FDB...);
oracle.methods.update(token ).send({from: ...});
```

## Get asset price in ETH

Get an average asset price in ETH with 18 decimals of precision.

#### UniswapPriceOracle

```
function getCourseInETH(address asset) public view returns (uint)
```

* `asset`: asset address.
* `RETURN`: asset price.

#### **Solidity**

```
UniswapPriceOracle oracle = UniswapPriceOracle(0xABCD...);
Erc20 token = Erc20(0x3FDB...);
uint price = oracle.getCourseInETH(address(token));
```

#### **Web3 1.0**

```
const oracle = UniswapPriceOracle.at(0xABCD...);
const token = Erc20.at(0x3FDB...);
const price = oracle.methods.getCourseInETH(token).call();
```

## Get asset price in USD

Get an average asset price in USD with 18 decimals of precision.

#### UniswapPriceOracle

```
function getPriceInUSD(address asset) public view virtual returns (uint)
```

* `asset`: asset address.
* `RETURN`: asset price.

#### **Solidity**

```
UniswapPriceOracle oracle = UniswapPriceOracle(0xABCD...);
Erc20 token = Erc20(0x3FDB...);
uint price = oracle.getPriceInUSD(address(token));
```

#### **Web3 1.0**

```
const oracle = UniswapPriceOracle.at(0xABCD...);
const token = Erc20.at(0x3FDB...);
const price = oracle.methods.getPriceInUSD(token).call();
```


# API

DeFiPIE API

## Get all pools

<mark style="color:blue;">`GET`</mark> `https://api.defipie.com/:network/pools`

This endpoint allows you to get all pools.

#### Path Parameters

| Name    | Type   | Description                                                                                                                                                                                       |
| ------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| network | string | <p><strong>network name</strong><br>"main" - Ethereum mainnet<br>"rinkeby" - Ethereum Rinkeby testnet<br>"bsc-main" - Binance Smart Chain mainnet<br>"bsc-test"  -Binance Smart Chain testnet</p> |

{% tabs %}
{% tab title="200 " %}

```
{
	"total": 16,
	"items": [
		{
			"address": "0x24B6F00a2b5652cB81ea5B9fb5358cd759107145",
			"decimals": 18,
			"totalBorrows": "2037607438259529965606683",
			"totalBorrowsUSD": "180787.041676482",
			"totalSupply": "299244028086948488135433248",
			"totalSupplyUSD": "541808.546311476",
			"exchangeRate": "20405754202561353",
			"depositApy": "10.045329",
			"borrowApy": "36.381577",
			"totalReserves": "9312295796471308574953",
			"totalReservesUSD": "826.2349148287433737379172396510455474481",
			"availableLiquidity": "4078004941263578081935774",
			"availableLiquidityUSD": "361821.6322759919151421248277653098754784398",
			"reserveFactor": "100000000000000000",
			"collateralFactor": "50",
			"utilizationRate": "0.34267243319999685662",
			"baseRatePerBlock": "9512937595",
			"multiplierPerBlock": "404299847792",
			"lastUpdate": "2021-04-08T12:02:50.759Z",
			"token": {
				"address": "0x607C794cDa77efB21F8848B7910ecf27451Ae842",
				"name": "DeFiPIE Token",
				"symbol": "PIE",
				"decimal": 18,
				"imageUrl": null,
				"price": 0.000042818955594137,
				"priceUsd": 0.08872515788661128
			}
		}
	]
}
```

{% endtab %}
{% endtabs %}

## Get token list

<mark style="color:blue;">`GET`</mark> `https://api.defipie.com/:network/tokens`

Whitelist of approved tokens

#### Path Parameters

| Name    | Type   | Description  |
| ------- | ------ | ------------ |
| network | string | network name |

{% tabs %}
{% tab title="200 " %}

```
{
	"total": 19,
	"items": [
		{
			"address": "0x607C794cDa77efB21F8848B7910ecf27451Ae842",
			"name": "DeFiPIE Token",
			"symbol": "PIE",
			"decimal": 18,
			"imageUrl": null,
			"price": 0.000042818955594137,
			"priceUsd": 0.08872515788661128
		}
	]
}
```

{% endtab %}
{% endtabs %}

## Get account balances

<mark style="color:blue;">`GET`</mark> `https://api.defipie.com/:network/user-balance/:address`

#### Path Parameters

| Name    | Type   | Description  |
| ------- | ------ | ------------ |
| network | string | network name |
| address | string | user address |

{% tabs %}
{% tab title="200 User balance for each pool" %}

```
{
	"0x82aa580e4dDE8e750363962d057feA6FFb138b57": {
		"borrow": "0",
		"borrowUsd": "0",
		"supply": "80960396240176966434491",
		"supplyUsd": "289357.9910293859810594",
		"supplyCollateralUsd": "143084.3605688388897536",
		"supplyPToken": "4041415119023511235139946",
		"isCollateral": true,
		"lastUpdate": "2021-04-08T16:44:45.004Z",
		"exchangeRate": "20032685051106222",
		"exchangeRateCalc": "0.020032685051106222"
	},
	"0xb91B6e944F7d0c8FC96F57D4d44bc9aa818b4571": {
		"borrow": "602427793471258409940",
		"borrowUsd": "388736.1602275576127511",
		"supply": "826859509950256977664",
		"supplyUsd": "543253.9320154421822597",
		"supplyCollateralUsd": "268633.1253871655601664",
		"supplyPToken": "36052860343814206996919",
		"isCollateral": true,
		"lastUpdate": "2021-04-08T16:44:45.004Z",
		"exchangeRate": "22934643799826161",
		"exchangeRateCalc": "0.022934643799826161"
	},
}
```

{% endtab %}
{% endtabs %}

## Get user history

<mark style="color:blue;">`GET`</mark> `https://api.defipie.com/:network/history?address=:address`

Get all user transactions

#### Path Parameters

| Name    | Type   | Description  |
| ------- | ------ | ------------ |
| network | string | network name |

#### Query Parameters

| Name    | Type   | Description    |
| ------- | ------ | -------------- |
| address | string | user address   |
| limit   | number | limit for list |
| offset  | number | offset in list |

{% tabs %}
{% tab title="200 " %}

```
{
	"total": 382,
	"data": [
		{
			"blockNumber": 8355665,
			"address": "0x82aa580e4dde8e750363962d057fea6ffb138b57",
			"userAddress": "0x3d6fdba796859f04cf5446ae25b243b35a2e775b",
			"eventName": "Mint",
			"txHash": "0x8b46943e379c108c88e7c988da5172b134cefb6cfe0ccd29d3fac040406ed1eb",
			"returnValues": {
				"0": "0x3d6FDba796859f04CF5446Ae25b243b35a2e775b",
				"1": "100000000000000000000",
				"2": "4991842067411937975839",
				"minter": "0x3d6FDba796859f04CF5446Ae25b243b35a2e775b",
				"mintAmount": "100000000000000000000",
				"mintTokens": "4991842067411937975839"
			},
			"blockTimestamp": "2021-04-04T20:36:41.000Z",
			"assetSymbol": "PIE",
			"assetName": "DeFiPIE Token",
			"assetDecimal": 18
		},
	]
}
```

{% endtab %}
{% endtabs %}

## Pool statistic

<mark style="color:blue;">`GET`</mark> `https://api.defipie.com/:network/statistic?address=:address`

Get pool statistics for the previous 30 days

#### Path Parameters

| Name    | Type   | Description  |
| ------- | ------ | ------------ |
| network | string | network name |

#### Query Parameters

| Name    | Type   | Description  |
| ------- | ------ | ------------ |
| address | string | user address |

{% tabs %}
{% tab title="200 " %}

```
[
	{
		"borrowApy": "26.4737597777009377",
		"supplyApy": "5.5089582891273637",
		"utilizationRate": "25.36302313",
		"date": "2021-03-09"
	},
	{
		"borrowApy": "26.6462295725894405",
		"supplyApy": "5.5781096129651988",
		"utilizationRate": "25.52377269",
		"date": "2021-03-10"
	},
	{
		"borrowApy": "26.6102001139841173",
		"supplyApy": "5.5638203632713323",
		"utilizationRate": "25.49009850",
		"date": "2021-03-11"
	},
	{
		"borrowApy": "26.0076370578130007",
		"supplyApy": "5.3246193587260127",
		"utilizationRate": "24.92705876",
		"date": "2021-03-12"
	}
]
```

{% endtab %}
{% endtabs %}

## Get user distribution rewards

<mark style="color:blue;">`GET`</mark> `https://api.defipie.com/:network/distribution`

#### Path Parameters

| Name    | Type   | Description  |
| ------- | ------ | ------------ |
| network | string | network name |

{% tabs %}
{% tab title="200 " %}

```
{
	"calculateTimestamp": "2021-04-08T17:25:37.341Z",
	"pieSpeed": "700000000000000000",
	"distributionSize": "9198.47908745247148288973",
	"totalDistributed": "523549439204328237475616",
	"items": [
		{
			"assetName": "DeFiPIE Token",
			"assetSymbol": "PIE",
			"assetPrice": "0.000042818955594137",
			"calcAssetPrice": "0.000042818955594137",
			"assetPriceUSD": "0.08852592878340269321644733",
			"address": "0x24B6F00a2b5652cB81ea5B9fb5358cd759107145",
			"underlyingAddress": "0x607C794cDa77efB21F8848B7910ecf27451Ae842",
			"underlyingDecimal": 18,
			"utility": "12917566122572762027377232253706.1533000546654680520008429556413254944",
			"pieSpeed": "440987180950584240",
			"exchangeRate": "20405754202561353",
			"totalBorrows": "2037607438259530130844460",
			"totalSupply": "291399430004861028043191863",
			"piePerDay": "2897.43668700612002555133",
			"pieBorrowApy": "67.98",
			"pieSupplyApy": "19.46",
			"piePriceCalc": "1",
			"distributedSupplierPie": "347442791638687481613428",
			"distributedBorrowerPie": "97260271645636299251213",
			"borrowRatePerBlock": "148055350180.27301662680006885872"
		},
	]
}
```

{% endtab %}
{% endtabs %}

## Get underwater account

<mark style="color:blue;">`GET`</mark> `https://api.defipie.com/:network/underwater`

Get accounts to be liquidated

#### Path Parameters

| Name    | Type   | Description  |
| ------- | ------ | ------------ |
| network | string | network name |

{% tabs %}
{% tab title="200 " %}

```
[
	{
		"borrowerAddress": "0x9029b8907dea021414eda6325e3b9ed9ba7fe1ec",
		"totalBorrowUsd": 1333.0038913466049,
		"totalCollateralUsd": 1271.6930384329,
		"healthFactor": 0.9540054959241204,
		"borrows": [
			{
				"address": "0xd8bf76686f818d5cb0ffcfa67f68aff8b69dc2dc",
				"symbol": "DAI",
				"tokenName": "DeFiPie Dai Stablecoin",
				"decimal": 18,
				"price": "0.000502114877857198",
				"usdPrice": "1.03809598579652439752279782",
				"usd": "1333.0038913466047542",
				"amount": "1284085389897967780738",
				"currentBorrow": "1284085389897967780738",
				"collaterals": [
					{
						"address": "0x24b6f00a2b5652cb81ea5b9fb5358cd759107145",
						"symbol": "pPIE",
						"tokenName": "DeFiPie PIE",
						"decimal": 18,
						"usd": "1271.6930384329",
						"amount": "1456245763992188540477438",
						"price": "0.000042818955594137",
						"usdPrice": "0.08852592878340269321644733",
						"exchangeRate": "0.020405754202561353"
					}
				]
			}
		]
	}
]
```

{% endtab %}
{% endtabs %}


