# Introduction

### **What is Paribus?** <a href="#d4d8" id="d4d8"></a>

Paribus is a comprehensive, decentralized, cross-chain lending and borrowing protocol. Apart from being holistic, the solution is interoperable and inventive. Where there is value, this value can be leveraged. Nearly any asset can be represented in a non-fungible form to have its value represented on-chain. Paribus is indiscriminate in this regard as we aim for users to unlock the full potential of digitizable assets. With our underlying framework blockchain-agnostic, the ability to interact with assets from other ecosystems will be mission critical in creating marketplaces.

Paribus believes there are methodologies to tap into the value of less conventional crypto-assets from NFTs to LP tokens and what still lies ahead. The potential to generate passive income from liquidity positions, synthetics, and other yield-bearing assets are in the works and may come to represent a future economy where individuals can take ownership of earning yields. These catalysts for the evolution of DeFi and in the bigger picture, a sort of “ValueFi,” is a world where assets can be fully leveraged by way of sharing for mutual benefit.


# Step-by-step Guide

1. The first step is ensuring you have a wallet suitable to connect to the governance platform. We always recommend to use a hardware wallet like Ledger or Trezor. This can be connected via MetaMask -> Connect Hardware wallet.

2. Once installed, head over to our governance page by following this link: <https://governance.paribus.io>

3. Users are greeted by the governance dashboard with a familiar look and feel for those who have used our Mainnet V1. From the dashboard, you can see the rewards distribution, your voting power, your rewards, recent proposals, and an overview.

4. A button to connect your wallet is in the top right corner of the screen. When you click on this, a pop-up will ask you to connect your wallet - either MetaMask or Wallet Connect. We recommend MetaMask.

5. If you click the MetaMask button, your browser will go through the stages of connecting your wallet and ask for your approval. It will also likely say your wallet isn’t on the Arbitrum network. If this is the case, a message stating you are on an unsupported network will appear, allowing you to switch to this network.

6. After clicking ‘Switch,’ it will open MetaMask for your approval to switch to the network. Once switched to the Arbitrum network, it will return you to the Governance Dashboard, which shows you the Governance Proposals. You can click to return to the Overview screen from here.

7. You need to bridge your PBX to Arbitrum. This can be done via <https://bridge.arbitrum.io> from Ethereum to Arbitrum or use [https://app.chainport.io](https://app.chainport.io/) if you want to bridge from Cardano to Arbtrium. Until then, you won’t be able to raise or vote on any proposals. However, you can still explore the module.

8. From the main dashboard, clicking on ‘Rewards Distribution’ will show you how the rewards from staking are being distributed. This rewards are optional and only distributed when an reward campaign is active.

9. From the main dashboard, clicking on ‘My Voting Power’ takes users to the voting power screen to stake their PBX tokens in return for vePBX. The amount of vePBX users can generate from staking PBX is proportional to the term. For instance, if a user stakes 10,000 PBX for the maximum allowable time, they will receive 10,000 vePBX, which can be used for voting. The lower the staking period, the less vePBX is generated.

10. From the main dashboard, clicking on ‘My Rewards’ takes users to a screen showing the amount of PBX available to be claimed as a reward for staking. This differs from vePBX, which is generated at the point of staking. Rewards are standard PBX tokens generated from the fees Paribus collects, which are then distributed to stakers.&#x20;

11. From the main dashboard, clicking on ‘Recent Proposals’ will show you the latest proposals. All new proposals will appear here.

12. The actions section shows the smart contract instructions that will be executed once the proposal passes the vote. Beneath that is a description that explains the proposal in plain English. Beneath the description is the proposal history, which details any updates or changes to the proposal and the date and time they were made. Clicking on the ‘Proposal Created’ text takes you through to Etherscan, where you can see the transaction details for the proposal.

13. Also within the proposal screen is a brief overview, showing whether it is pending, passed, or canceled, along with other helpful information. Beneath these are voting details that show how many wallets have voted for or against the proposal, the number of votes each wallet cast, and their address.&#x20;

14. On the main dashboard, next to ‘Recent Proposals’ is an overview showing the total number of proposals and voting addresses. Beneath this are the top three voting addresses showing their wallet address, the number of votes they have, their vote weight as an overall percentage of wallets with voting rights, and the number of proposals they have voted for.

15. Beneath the top three voting wallets is a ‘SEE LEADERBOARD’ button, which takes users to a leaderboard that shows all of the wallets with voting rights and the same information as above.

16. A ‘SEE ALL PROPOSALS’ button takes users to a page showing all the proposals raised on the governance platform. This shows the current pending proposals and historic ones that have either passed or failed, along with a tally of the number that have succeeded or been canceled.&#x20;

17. A ‘Proposal Creation’ section on this screen allows users with sufficient voting rights to draft and submit a proposal.


# Supply & Distribution

![](https://miro.medium.com/max/1400/1*mh8EI_rGwyrYlxUD0P7BEw.jpeg)

### Token Supply <a href="#a292" id="a292"></a>

Paribus has a total token supply of 10B PBX and the distribution is as follows:

* Total Supply: 10B
* Sale In Aggregate: 4B
* Ecosystem: 3.3B
* Foundation: 1.5B
* Strategic/Advisory: 700M
* Liquidity Provisioning: 500M

Despite a relatively straight forward distribution, the rationale effectively weighed a number of considerations:

* The larger ecosystem is designed to reward and stimulate users. Given more exotic assets have less defined marketplaces, encouraging trading by way of community support is essential.
* A sizable sale allows the Paribus team to strategically distribute the token to value add investors as well as the public. The team believes this will ultimately facilitate platform usage.
* The remaining is relatively traditional but the team is anticipating platform needs. For example, additional liquidity may be required when going cross chain, while worthy partners, content creators and centralized exchange partners can add considerable value.

### Token Sale Distribution <a href="#id-5a81" id="id-5a81"></a>

* **Seed: 1.4B PBX @.0002**
* **Private: 2.1 PBX @.00027**
* **Public: 500M PBX @.0003**

While the seed and private rounds ensure that sufficient funding will be made available, the relative price uniformity speaks to the belief in the Paribus project. Typically, there is a multiple levied against the public sale buyers while team PBX was able to attract value-add investors and keep the buy-in price points equitable and fair.

The team feels that ultimately, a wider distribution of PBX will be the driver in sustaining market demand while in the near term, the price parity and value add of strategic backing will secure a smooth rollout.

### Vesting <a href="#id-62b9" id="id-62b9"></a>

The rate at which tokens are released can impact the market. This is a given. The distribution of PBX has been considered their roadmap to best align distributions with milestones that can create functional demand for PBX.

**Foundation**: 6 month cliff, then 10% released monthly for 10 months

**Ecosystem**: 1 week cliff, then 16.67% released monthly for 6 months

**Strategic/Advisory**: 6 month cliff, then 10% released monthly for 10 months

**Liquidity**: 100% locked for 12 months

**Seed**: 7.5% upon TGE, weekly release 1 month after for 7 months

**Private**:10% upon TGE, weekly release 1 month after TGE for 7 months

**Public**: 50% released initially, then 50% released 1 month after TGE

In order to create a fairer marketplace, the largest distribution of circulating tokens will come from the public round, with 250M being put “in the wild,” following the IDO.

### Additional Numbers: <a href="#id-5b7c" id="id-5b7c"></a>

* Circulating Supply Following TGE: 565M PBX
* Listing Price: .0003USD
* Hard Cap: 997K
* Market Cap At TGE (based on public price): 169.5K\*\*

\*\*The market cap at TGE uses the public price vs. a blended average of seed, private and public. Calculating actual price paid and releases across rounds will produce a market cap of 152.7K.

Additionally, it is worth noting that liquidity is not included in this calculation as it is impossible to know how much of that will be tapped. Certainly, we can expect some of the 500M tokens put up to become circulating but can not possibly anticipate an actual number. Furthermore, this liquidity, represented in PBX and pair, is locked for a minimum of 12 months


# Getting Started

## Getting Started

### Introduction to Paribus Protocol

You're currently viewing the Paribus documentation.

The Paribus Protocol is based on the Compound Protocol, the codebase is [open-source](https://github.com/Paribus/paribus-protocol-contracts), and currently maintained by the Paribus team.

The interface hosted at <https://app.paribus.io> is at the moment closed source and maintained by the Paribus team.

### Guides

### Networks

The Paribus Protocol is currently deployed on the following networks:

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

### Ethereum Mainnet

<table><thead><tr><th width="166">Contract Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>PBX</td><td><a href="https://etherscan.io/token/0xd528cf2e081f72908e086f8800977df826b5a483">0xD528cf2E081f72908e086F8800977df826B5a483</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Arbitrum" %}

### Arbitrum Mainnet&#x20;

<table><thead><tr><th width="166">Contract Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>PBX</td><td><a href="https://arbiscan.io/address/0xbad58ed9b5f26a002ea250d7a60dc6729a4a2403">0xbAD58ed9b5f26A002ea250D7A60dC6729a4a2403</a></td></tr><tr><td>pARB</td><td><a href="https://arbiscan.io/address/0xfc2737a742a741d13fe6326011a78cd881de3eb9">0xFc2737a742A741d13fE6326011a78cd881dE3Eb9</a></td></tr><tr><td>pETH</td><td><a href="https://arbiscan.io/address/0xAffd437801434643B734D0B2853654876F66f7D7">0xAffd437801434643B734D0B2853654876F66f7D7</a></td></tr><tr><td>pUSDT</td><td><a href="https://arbiscan.io/address/0xFB1dcFc67cC496Eb0cC592050AF7Fdf3bF3b5C13">0xFB1dcFc67cC496Eb0cC592050AF7Fdf3bF3b5C13</a></td></tr><tr><td>pWBTC</td><td><a href="https://arbiscan.io/address/0x1c762e00f1d9317a4214d22b2576995c427f61c9">0x1c762E00f1D9317a4214d22b2576995C427F61c9</a></td></tr></tbody></table>

### Arbitrum Sepolia

<table><thead><tr><th width="166">Contract Name</th><th>Contract Address</th></tr></thead><tbody><tr><td>PBX</td><td><a href="https://sepolia.arbiscan.io/address/0x71d6b4acb0af56e7b2378e9f2fd1b7a419490edf">0x71d6B4ACB0AF56e7B2378E9F2fd1b7A419490eDF</a></td></tr></tbody></table>
{% endtab %}

{% tab title="Cardano" %}

### Cardano Mainnet

<table><thead><tr><th width="166">Contract Name</th><th>Policy Id</th></tr></thead><tbody><tr><td>PBX</td><td><a href="https://cardanoscan.io/token/cc8d1b026353022abbfcc2e1e71159f9e308d9c6e905ac1db24c7fb650617269627573">cc8d1b026353022abbfcc2e1e71159f9e308d9c6e905ac1db24c7fb6</a></td></tr></tbody></table>
{% endtab %}
{% endtabs %}

### Protocol Math

The Paribus Protocol contracts use a system of exponential math, [ExponentialNoError.sol](https://github.com/Paribus/paribus-protocol-contracts/blob/mainnet-mvp/contracts/Utils/ExponentialNoError.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, while their underlying tokens vary, and have a public member named *decimals*.

| pToken | pToken Decimals | Underlying | Underlying Decimals |
| ------ | --------------- | ---------- | ------------------- |
| pARB   | 8               | ARB        | 18                  |
| pETH   | 8               | ETH        | 18                  |
| pUSDC  | 8               | USDC       | 6                   |
| pUSDT  | 8               | USDT       | 6                   |
| pWBTC  | 8               | WBTC       | 8                   |

#### 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 cBAT in BAT with Web3.js JavaScript.

```js
const pTokenDecimals = 8; // all pTokens have 8 decimal places
const underlying = new web3.eth.Contract(erc20Abi, batAddress);
const pToken = new web3.eth.Contract(pTokenAbi, cBatAddress);
const underlyingDecimals = await underlying.methods.decimals().call();
const exchangeRateCurrent = await pToken.methods.exchangeRateCurrent().call();
const mantissa = 18 + parseInt(underlyingDecimals) - pTokenDecimals;
const onepTokenInUnderlying = exchangeRateCurrent / Math.pow(10, mantissa);
console.log('1 cBAT can be redeemed for', onepTokenInUnderlying, 'BAT');
```

There is no underlying contract for ETH, so to do this with pETH, 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 market update on any block in which the ratio of borrowed assets to supplied assets in the market has changed. The amount of interest rate changes are dependent 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.

Interest accrues to all suppliers and borrowers in a market when any Ethereum address interacts with the market’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 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 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 supplies 1 ETH to the Paribus Protocol. At the time of supply, 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 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 = pToken.supplyRatePerBlock(); // Integer
Rate = 37893566
ETH Mantissa = 1 * 10 ^ 18 (ETH has 18 decimal places)
Blocks Per Day = 7200 (12 seconds per block)
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:

```js
const ethMantissa = 1e18;
const blocksPerDay = 7200; // 12 seconds per block
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 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} %`);
```


# pTokens

### Introduction

Each asset supported by the Paribus 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 Paribus Protocol; when a user mints, redeems, borrows, repays a borrow, liquidates a borrow, or transfers pTokens, 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.

### Mint

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

**PErc20**

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

* `msg.sender`: The account which shall supply the asset, and own the minted pTokens.
* `mintAmount`: The amount of the asset to be supplied, in units of the underlying asset.
* `RETURN`: 0 on success, otherwise an [Error code](#error-codes) Before supplying an asset, users must first [approve](https://eips.ethereum.org/EIPS/eip-20#approve) the pToken to access their token balance.

**PEther**

```solidity
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 pTokens.
* `RETURN`: No return, reverts on error.

**Solidity**

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

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

{% hint style="warning" %}
{% code overflow="wrap" %}

```
First MINIMUM_LIQUIDITY minted pTokens gets locked on address(0) to prevent totalSupply being 0, this prevents a critical hack reported by other compound forks. 
A minimal loss of 0.0001 pTokens, for example starting exchange rate of pWBTC is 1 WBTC = 50 pWBTC, loss in WBTC is 0.000002, just to give an idea its 0.2 USD if BTC is priced $100,000/BTC.
```

{% endcode %}
{% endhint %}

### 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](#exchange-rate). The amount redeemed must be less than the user's [Account Liquidity](/for-developers/comptroller#get-account-liquidity) and the market's available liquidity.

**PErc20 / PEther**

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

**Solidity**

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

**Web3 1.0**

```js
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](#exchange-rate). The amount redeemed must be less than the user's [Account Liquidity](/for-developers/comptroller#get-account-liquidity) and the market's available liquidity.

**PErc20 / PEther**

```solidity
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](#error-codes)

**Solidity**

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

**Web3 1.0**

```js
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](#borrow-rate) for the asset. The amount borrowed must be less than the user's [Account Liquidity](/for-developers/comptroller#get-account-liquidity) and the market's available liquidity. To borrow Ether, the borrower must be 'payable' (solidity).

**PErc20 / PEther**

```solidity
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](#error-codes)

**Solidity**

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

**Web3 1.0**

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

```solidity
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](#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**

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

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

**Web3 1.0**

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

```solidity
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](#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**

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

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

**Web3 1.0**

```js
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](/for-developers/comptroller#enter-markets) that pToken market and the transfer would have put the account into a state of negative [liquidity](/for-developers/comptroller#get-account-liquidity).

**PErc20 / PEther**

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

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

**Web3 1.0**

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

### Liquidate Borrow

A user who has negative [account liquidity](/for-developers/comptroller#get-account-liquidity) is subject to [liquidation](#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. Unlike in v1, 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 supplied 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**

```solidity
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](/for-developers/comptroller#get-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](#error-codes) Before supplying an asset, users must first [approve](https://eips.ethereum.org/EIPS/eip-20#approve) the pToken to access their token balance.

**PEther**

```solidity
function liquidateBorrow(address borrower, address pTokenCollateral) 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](/for-developers/comptroller#get-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**

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

**Web3 1.0**

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

### Key Events

<table><thead><tr><th width="472">Event</th><th>Description</th></tr></thead><tbody><tr><td><code>Mint(address minter, uint mintAmount, uint mintTokens)</code></td><td>Emitted upon a successful <a href="#mint">Mint</a>.</td></tr><tr><td><code>Redeem(address redeemer, uint redeemAmount, uint redeemTokens)</code></td><td>Emitted upon a successful <a href="#redeem">Redeem</a>.</td></tr><tr><td><code>Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows)</code></td><td>Emitted upon a successful <a href="#borrow">Borrow</a>.</td></tr><tr><td><code>RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows)</code></td><td>Emitted upon a successful <a href="#repay-borrow">Repay Borrow</a>.</td></tr><tr><td><code>LiquidateBorrow(address liquidator, address borrower, uint repayAmount, address pTokenCollateral, uint seizeTokens)</code></td><td>Emitted upon a successful <a href="#liquidate-borrow">Liquidate Borrow</a>.</td></tr></tbody></table>

### 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    | `COMPTROLLER_REJECTION`          | The action would violate the comptroller policy.                                                                                                                                 |
| 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.                                                                                                                      |

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

### Exchange Rate

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

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

**PErc20 / PEther**

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

* `RETURN`: The current exchange rate as an unsigned integer, scaled by 1 \* 10^(18 - 8 + Underlying Token Decimals).

**Solidity**

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

**Web3 1.0**

```js
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 market.

**PErc20 / PEther**

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

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

**Solidity**

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

**Web3 1.0**

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

### Total Borrows

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

**PErc20 / PEther**

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

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

**Solidity**

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

**Web3 1.0**

```js
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](#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**

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

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

**Web3 1.0**

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

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

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

**Solidity**

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

**Web3 1.0**

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

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

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

**Solidity**

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

**Web3 1.0**

```js
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](#exchange-rate).

**PErc20 / PEther**

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

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

**Web3 1.0**

```js
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 rate per block. The supply rate is derived from the [borrow rate](#borrow-rate), [reserve factor](#reserve-factor) and the amount of [total borrows](#total-borrows).

**PErc20 / PEther**

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

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

**Solidity**

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

**Web3 1.0**

```js
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](#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.](#reserve-factor)

**PErc20 / PEther**

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

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

**Solidity**

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

**Web3 1.0**

```js
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](#total-reserves).

**PErc20 / PEther**

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

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

**Solidity**

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

**Web3 1.0**

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


# Comptroller

### Introduction

The Comptroller is the risk management layer of the Paribus 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 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](#collateral-factor)) to make its determinations. Users explicitly list which assets they would like included in their risk scoring, by calling [Enter Markets](#enter-markets) and [Exit Market](#exit-market).

### Architecture

The Comptroller is made out of two parts, `ComptrollerPart1` as well as `ComptrollerPart2`. This is due to block size limitations. The Comptroller is implemented as 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.

**Comptroller**

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

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

**Web3 1.0**

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

**Comptroller**

```solidity
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](#error-codes).

**Solidity**

```solidity
Comptroller troll = Comptroller(0xABCD...);
uint error = troll.exitMarket(pToken(0x3FDA...));
```

**Web3 1.0**

```js
const troll = Comptroller.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 supply collateral or borrow in a market, it must be entered first. Entered markets count towards [account liquidity](#get-account-liquidity) calculations.

**Comptroller**

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

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

**Web3 1.0**

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

Collateral factors will be increased (or decreased) in the future through Paribus Governance.

**Comptroller**

```solidity
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, isComped); isListed represents whether the comptroller recognizes this pToken; collateralFactorMantissa, scaled by 1e18, is multiplied by a supply balance to determine how much value can be borrowed. The isComped boolean indicates whether or not suppliers and borrowers are distributed COMP tokens.

**Solidity**

```solidity
Comptroller troll = Comptroller(0xABCD...);
(bool isListed, uint collateralFactorMantissa, bool isComped) = troll.markets(0x3FDA...);
```

**Web3 1.0**

```js
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](#enter-markets) into, their supplied balance is multiplied by the market’s [collateral factor](#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 Paribus Protocol exclusively uses unsigned integers, Account Liquidity returns either a surplus or shortfall.

**Comptroller**

```solidity
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](#error-codes). A non-zero liquidity value indicates the account has available [account liquidity](#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**

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

```js
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.

**Comptroller**

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

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

**Web3 1.0**

```js
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. A portion of this is given to the collateral pToken reserves as determined by the seize share. The seize share is assumed to be 0 if the pToken does not have a `protocolSeizeShareMantissa` constant. For example, if the liquidation incentive is 1.08, and the collateral's seize share is 1.028, liquidators receive an extra 5.2% of the borrower's collateral for every unit they close, and the remaining 2.8% is added to the pToken's reserves.

**Comptroller**

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

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

**Web3 1.0**

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

### Key Events

| Event                                           | Description                                               |
| ----------------------------------------------- | --------------------------------------------------------- |
| `MarketEntered(pToken pToken, address account)` | Emitted upon a successful [Enter Market](#enter-markets). |
| `MarketExited(pToken pToken, address account)`  | Emitted upon a successful [Exit Market](#exit-market).    |

{: .key-events-table }

### 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.                             |

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

### PBX Distribution Speeds

#### PBX Distributed Per Block (Single Borrow Market)

The Comptroller contract has a mapping called `PBXBorrowSpeeds`. It maps pToken addresses to an integer of each market’s PBX distribution per Ethereum block. The integer indicates the rate at which the protocol distributes PBX to markets’ borrowers. The value is the amount of PBX (in wei), per block, allocated for the market. Note that not every market has PBX distributed to its participants (see Market Metadata). The speed indicates how much PBX goes to the borrowers. The code examples implement reading the amount of PBX distributed, per Ethereum block, to a single borrow market.

**Comptroller**

```solidity
mapping(address => uint) public PBXBorrowSpeeds;
```

**Solidity**

```solidity
Comptroller troll = Comptroller(0x123...);
address pToken = 0xabc...;
// PBX issued per block to borrowers * (1 * 10 ^ 18)
uint pbxBorrowSpeed = troll.PBXBorrowSpeeds(pToken);
// Approximate PBX issued per day to borrowers * (1 * 10 ^ 18)
uint pbxBorrowSpeedPerDay = pbxBorrowSpeed * 4 * 60 * 24;
```

**Web3 1.2.6**

```js
const pTokenAddress = '0xabc...';
const comptroller = new web3.eth.Contract(comptrollerAbi, comptrollerAddress);
let pbxBorrowSpeed = await comptroller.methods
  .PBXBorrowSpeeds(pTokenAddress)
  .call();
pbxBorrowSpeed = pbxBorrowSpeed / 1e18;
// PBX issued to borrowers
const pbxBorrowSpeedPerDay = pbxBorrowSpeed * 4 * 60 * 24;
```

#### PBX Distributed Per Block (Single Supply Market)

The Comptroller contract has a mapping called `PBXSupplySpeeds`. It maps pToken addresses to an integer of each market’s PBX distribution per Ethereum block. The integer indicates the rate at which the protocol distributes PBX to markets’ suppliers. The value is the amount of PBX (in wei), per block, allocated for the market. Note that not every market has PBX distributed to its participants (see Market Metadata). The speed indicates how much PBX goes to the suppliers. The code examples implement reading the amount of PBX distributed, per Ethereum block, to a single supplier market.

**Comptroller**

```solidity
mapping(address => uint) public PBXSupplySpeeds;
```

**Solidity**

```solidity
Comptroller troll = Comptroller(0x123...);
address pToken = 0xabc...;
// PBX issued per block to suppliers * (1 * 10 ^ 18)
uint pbxSupplySpeed = troll.PBXSupplySpeeds(pToken);
// Approximate PBX issued per day to suppliers * (1 * 10 ^ 18)
uint pbxSupplySpeedPerDay = pbxSupplySpeed * 4 * 60 * 24;
```

**Web3 1.2.6**

```js
const pTokenAddress = '0xabc...';
const comptroller = new web3.eth.Contract(comptrollerAbi, comptrollerAddress);
let pbxSupplySpeed = await comptroller.methods
  .PBXSupplySpeeds(pTokenAddress)
  .call();
pbxSupplySpeed = pbxSupplySpeed / 1e18;
// PBX issued to suppliers
const pbxSupplySpeedPerDay = pbxSupplySpeed * 4 * 60 * 24;
```

### Claim PBX

Every Paribus user accrues PBX for each block they are supplying to or borrowing from the protocol. Users may call the Comptroller's `claimPBX` method at any time to transfer PBX accrued to their address.

**Comptroller**

```solidity
// Claim all the PBX accrued by holder in all markets
function claimPBXReward(address holder) external;
// Claim all the PBX accrued by holder in specific markets
function claimPBXSingle(address holder, PToken[] memory pTokens) public;
// Claim all the PBX accrued by specific holders in specific markets for their supplies and/or borrows
function claimPBX(address[] memory holders, PToken[] memory pTokens, bool borrowers, bool suppliers) public;
```

**Solidity**

```solidity
Comptroller troll = Comptroller(0xABCD...);
troll.claimPBX(0x1234...);
```

**Web3 1.2.6**

```js
const comptroller = new web3.eth.Contract(comptrollerAbi, comptrollerAddress);
await comptroller.methods.claimPBX('0x1234...').send({ from: sender });
```

### Market Metadata

The Comptroller 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 Comptroller’s markets constant. See the [ComptrollerPart1 contract](https://github.com/Paribus/paribus-protocol-contracts/blob/mainnet-mvp/contracts/Comptroller/ComptrollerPart1.sol) for the Market struct definition.

**Comptroller**

```solidity
pToken[] public getAllMarkets;
```

**Solidity**

```solidity
Comptroller troll = Comptroller(0xABCD...);
pToken pTokens[] = troll.getAllMarkets();
```

**Web3 1.2.6**

```js
const comptroller = new web3.eth.Contract(comptrollerAbi, comptrollerAddress);
const pTokens = await comptroller.methods.getAllMarkets().call();
const pToken = pTokens[0]; // address of a pToken
```


# Governance

### Introduction

The Paribus protocol is governed and upgraded by PBX token-holders, using three distinct components; the [PBX](https://arbiscan.io/token/0xbad58ed9b5f26a002ea250d7a60dc6729a4a2403) token, governance module ([Governor Delegator](https://arbiscan.io/)), and [Timelock](https://arbiscan.io/). Together, these contracts allow the community to propose, vote, and implement changes through the administrative functions of a pToken or the Comptroller. Proposals can modify system parameters, support new markets, or add entirely new functionality to the protocol.

Holders of PBX tokens may stake their tokens in order to get voting rights. Proposals for governance may be made by addresses having at least 10.000.000 voting power.

When a governance proposal is created, it enters a 2 day review period, after which the voting begins. Voting lasts for 5 days; if a majority, and at least 100.000.000 votes are cast for the proposal, it is queued in the Timelock, and can be implemented threedays later. In total, any change to the protocol takes at least 10 days.

### PBX

PBX is an [ERC-20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) token that allows the owner to delegate voting rights to themselve by locking it up for a certain period by using the Governor Delegator.

### Key Events

<table><thead><tr><th width="519">Event</th><th>Description</th></tr></thead><tbody><tr><td><code>ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, uint endBlock, string title, string description)</code></td><td>An event emitted when a new <a href="#propose">proposal</a> is created.</td></tr><tr><td><code>VoteCast(address voter, uint proposalId, bool support, uint votes, string reason)</code></td><td>An event emitted when a <a href="#cast-vote">vote has been cast</a> on a proposal.</td></tr><tr><td><code>ProposalCanceled(uint id)</code></td><td>An event emitted when a proposal has been <a href="#cancel">canceled</a>.</td></tr><tr><td><code>ProposalQueued(uint id, uint eta)</code></td><td>An event emitted when a proposal has been <a href="#queue">queued</a> in the <a href="#timelock">Timelock</a>.</td></tr><tr><td><code>ProposalExecuted(uint id)</code></td><td>An event emitted when a proposal has been <a href="#execute">executed</a> in the <a href="#timelock">Timelock</a>.</td></tr><tr><td><code>NewPBXStake(address indexed account, uint PBXAmount, uint startsAtTimestamp, uint endsAtTimestamp)</code></td><td>An event emitted when an account <a href="#stake-pbx">stake PBX</a> for votes.</td></tr><tr><td><code>PBXWithdrawal(address indexed account, uint PBXAmount, uint startsAtTimestamp, uint endsAtTimestamp)</code></td><td>An event emitted when an account <a href="#withdraw-pbx-stake">withdraw staked PBX</a>.</td></tr><tr><td><code>PBXRewardCampaignStarted(uint startsAtTimestamp, uint endsAtTimestamp, uint PBXRewardsAmount)</code></td><td>An event emitted when a <a href="#start-pbx-reward-campaign">reward campaign</a> started.</td></tr></tbody></table>

### Governor Delegator

Governor Delegator is the governance module of the protocol; it allows addresses with more than 10.000.000 voting power to propose changes to the protocol. Addresses that held voting weight, at the start of the proposal, invoked through the getpriorvotes function, can submit their votes during a 3 day voting period. If a majority, and at least 400,000 votes are cast for the proposal, it is queued in the Timelock, and can be implemented after 2 days.

### Start PBX Reward campaign

Launch PBX Rewards Campaign that is distributed among activate participants of the governance.

**Governor Delegator**

```solidity
function startPBXRewardsCampaign(uint endsAtTimestamp, uint PBXRewardsAmount)
```

* `endsAtTimestamp`: PBX Rewards Campaign end time.
* `PBXRewardsAmount`: Total PBX amount to be distributed
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.startPBXRewardsCampaign(endTime, rewardAmount);
```

**Web3 1.2.6**

```solidity
const endTimestamp = 1735490002; // end of campaign
const rewards = 1000000 * e18 // 100.000 PBX as reward

const tx = gov.methods
  .startPBXRewardsCampaign(endTimestamp, rewards)
  .send({ from: sender });
```

### Calculate PBX Reward

Calculate the amount of PBX that a given account has pending from participating in Governance during an on-going campaign

**Governor Delegator**

```solidity
function calculatePBXReward(address account) returns (uint)
```

* `account`: Account to check for pending rewards
* `RETURN`: The amount of pending PBX for withdraw

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.calculatePBXReward(0x123 ...);
```

**Web3 1.2.6**

```solidity
const account = '0x123...'; // contract address

const rewards = await gov.methods.calculatePBXReward(account).call();
```

### Withdraw PBX Reward

Withdraw the PBX that a given account has pending from participating in Governance during an on-going campaign

**Governor Delegator**

```solidity
function withdrawPBXReward()
```

* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.withdrawPBXReward();
```

**Web3 1.2.6**

```solidity
const tx = gov.methods
  .withdrawPBXReward().send({ from: sender });
```

### Stake PBX

Stake PBX to receive votes. Votes received depends on the staking period.

**Governor Delegator**

```solidity
function stakePBXForVotes(uint addPBXAmount, uint newStakePeriodLenSecs)
```

* `addPBXAmount`: PBX amount to be transferred. Can be 0 when updating existing stakePeriodLen only, without changing the amount
* `newStakePeriodLenSecs`: Stake period length in seconds. Use 0 when updating existing stake without changing existing stakePeriodLen
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.stakePBXForVotes(pbxAmount, stakingPeriod);
```

**Web3 1.2.6**

```solidity
const pbxAmount = 1000000 * e18 // 100.000 PBX to stake
const stakingPeriod = 60 * 24 * 24 * 7 * 13; // 13 weeks

const tx = gov.methods
  .stakePBXForVotes(pbxAmount, stakingPeriod)
  .send({ from: sender });
```

### Withdraw PBX Stake

Withdraw staked PBX after the lockup period finished

**Governor Delegator**

```solidity
function withdrawPBXStake()
```

* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.withdrawPBXStake();
```

**Web3 1.2.6**

```solidity

const tx = gov.methods
  .withdrawPBXStake()
  .send({ from: sender });
```

### Get Current Votes

Gets the balance of votes for an account as of the current block.

**PBX**

```solidity
function getVotes(address account) returns (uint)
```

* `account`: Address of the account in which to retrieve the number of votes.
* `RETURN`: The number of votes (integer).

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint votes = gov.getVotes(0xabc...);
```

**Web3 1.2.6**

```solidity
const account = '0x123...'; // contract address
const votes = await gov.methods.getVotes(account).call();
```

### Get Hypothetical Votes

Get hypothetical number of votes for a given account after staking PBX.

**PBX**

```solidity
function getHypotheticalVotes(address account, uint addPBXAmount, uint newStakePeriodLenSecs) returns (uint votes)
```

* `account`: Address of the account in which to retrieve the number of votes.
* `addPBXAmount`: New stake amount. Can be 0 when updating existing stakePeriodLen only, without changing the amount
* `newStakePeriodLenSecs`: New stake period length in blocks. Use 0 when updating existing stake without changing existing stakePeriodLen
* `RETURN`: The number of votes (integer).

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint votes = gov.getHypotheticalVotes(0xabc..., pbxAmount, stakingPeriod);
```

**Web3 1.2.6**

```solidity
const account = '0x123...'; // contract address
const pbxAmount = 1000000 * e18 // 100.000 PBX to stake
const stakingPeriod = 60 * 24 * 24 * 7 * 13; // 13 weeks

const votes = await gov.methods.
  getHypotheticalVotes(account, pbxAmount, stakingPeriod).call();
```

### Quorum Votes

The required minimum number of votes in support of a proposal for it to succeed.

**Governor Delegator**

```solidity
function quorumVotes() public pure returns (uint)
```

* `RETURN`: The minimum number of votes required for a proposal to succeed.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint quorum = gov.quorumVotes();
```

**Web3 1.2.6**

```js
const quorum = await gov.methods.quorumVotes().call();
```

### Proposal Threshold

The minimum number of votes required for an account to create a proposal. This can be changed through governance.

**Governor Delegator**

```solidity
function proposalThreshold() returns (uint)
```

* `RETURN`: The minimum number of votes required for an account to create a proposal.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint threshold = gov.proposalThreshold();
```

**Web3 1.2.6**

```js
const threshold = await gov.methods.proposalThreshold().call();
```

### Proposal Max Operations

The maximum number of actions that can be included in a proposal. Actions are functions calls that will be made when a proposal succeeds and executes.

**Governor Delegator**

```solidity
function proposalMaxOperations() returns (uint)
```

* `RETURN`: The maximum number of actions that can be included in a proposal.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint operations = gov.proposalMaxOperations();
```

**Web3 1.2.6**

```js
const operations = await gov.methods.proposalMaxOperations().call();
```

### Voting Delay

The number of Ethereum blocks to wait before voting on a proposal may begin. This value is added to the current block number when a proposal is created. This can be changed through governance.

* `MINIMUM_DELAY`: 2 days
* `MAXIMUM_DELAY`: 30 days

**Governor Delegator**

```solidity
function votingDelay() returns (uint)
```

* `RETURN`: Number of blocks to wait before voting on a proposal may begin.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint blocks = gov.votingDelay();
```

**Web3 1.2.6**

```js
const blocks = await gov.methods.votingDelay().call();
```

### Voting Period

The duration of voting on a proposal, in Ethereum blocks. This can be changed through governance.

**Governor Delegator**

```solidity
function votingPeriod() returns (uint)
```

* `RETURN`: The duration of voting on a proposal, in Ethereum blocks.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint blocks = gov.votingPeriod();
```

**Web3 1.2.6**

```js
const blocks = await gov.methods.votingPeriod().call();
```

### Grace Period

The duration after which a queued proposal becomes invalid.

* `GRACE_PERIOD`: 14 days

### Propose

Create a Proposal to change the protocol. E.g., A proposal can set a cToken's interest rate model or risk parameters on the Comptroller. Proposals will be voted on by delegated voters. If there is sufficient support before the voting period ends, the proposal shall be automatically enacted. Enacted proposals are queued and executed in the Compound Timelock contract.

The sender must hold more PBX than the current proposal threshold (`proposalThreshold()`) as of the immediately previous block. The proposal can have up to 10 actions (based on `proposalMaxOperations()`).

The proposer cannot create another proposal if they currently have a pending or active proposal. It is not possible to queue two identical actions in the same block (due to a restriction in the Timelock), therefore actions in a single proposal must be unique, and unique proposals that share an identical action must be queued in different blocks.

**Governor Delegator**

```solidity
function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) returns (uint)
```

* `targets`: The ordered list of target addresses for calls to be made during proposal execution. This array must be the same length as all other array parameters in this function.
* `values`: The ordered list of values (i.e. msg.value) to be passed to the calls made during proposal execution. This array must be the same length as all other array parameters in this function.
* `signatures`: The ordered list of function signatures to be passed during execution. This array must be the same length as all other array parameters in this function.
* `calldatas`: The ordered list of data to be passed to each individual function call during proposal execution. This array must be the same length as all other array parameters in this function.
* `description`: A human readable description of the proposal and the changes it will enact.
* `RETURN`: The ID of the newly created proposal.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint proposalId = gov.propose(targets, values, signatures, calldatas, description);
```

**Web3 1.2.6**

```js
const tx = gov.methods
  .propose(targets, values, signatures, calldatas, description)
  .send({ from: sender });
```

### Queue

After a proposal has succeeded, it is moved into the Timelock waiting period using this function. The waiting period (e.g. 2 days) begins when this function is called. The queue function can be called by any Ethereum address.

**Governor Delegator**

```solidity
function queue(uint proposalId)
```

* `proposalId`: ID of a proposal that has succeeded.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.queue(proposalId);
```

**Web3 1.2.6**

```js
const tx = gov.methods.queue(proposalId).send({ from: sender });
```

### Execute

After the Timelock waiting period has elapsed, a proposal can be executed using this function, which applies the proposal changes to the target contracts. This will invoke each of the actions described in the proposal. The execute function can be called by any Ethereum address. Note: this function is *payable*, so the Timelock contract can invoke payable functions that were selected in the proposal.

**Governor Delegator**

```solidity
function execute(uint proposalId) payable
```

* `proposalId`: ID of a succeeded proposal to execute.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.execute(proposalId).value(999).gas(999)();
```

**Web3 1.2.6**

```js
const tx = gov.methods.execute(proposalId).send({ from: sender, value: 1 });
```

### Cancel

A proposal is eligible to be cancelled at any time prior to its execution, including while queued in the Timelock, using this function.

The cancel function can be called by the proposal creator, or any Ethereum address, if the proposal creator fails to maintain more delegated votes than the proposal threshold (e.g. 25,000).

**Governor Delegator**

```solidity
function cancel(uint proposalId)
```

* `proposalId`: ID of a proposal to cancel. The proposal cannot have already been executed.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.cancel(proposalId);
```

**Web3 1.2.6**

```js
const tx = gov.methods.cancel(proposalId).send({ from: sender });
```

### Get Actions

Gets the actions of a selected proposal. Pass a proposal ID and get the targets, values, signatures and calldatas of that proposal.

**Governor Delegator**

```solidity
function getActions(uint proposalId) returns (uint proposalId) public view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas)
```

* `proposalId`: ID of a proposal in which to get its actions.
* `RETURN`: Reverts if the proposal ID is invalid. If successful, the following 4 references are returned.

1. Array of addresses of contracts the proposal calls.
2. Array of unsigned integers the proposal uses as values.
3. Array of strings of the proposal’s signatures.
4. Array of calldata bytes of the proposal.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
uint proposalId = 123;
(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas) = gov.getActions(proposalId);
```

**Web3 1.2.6**

```js
const {
  0: targets,
  1: values,
  2: signatures,
  3: calldatas,
} = gov.methods.getActions(proposalId).call();
```

### Get Receipt

Gets a proposal ballot receipt of the indicated voter.

**Governor Delegator**

```solidity
function getReceipt(uint proposalId, address voter) returns (Receipt memory)
```

* `proposalId`: ID of the proposal in which to get a voter’s ballot receipt.
* `voter`: Address of the account of a proposal voter.
* `RETURN`: Reverts on error. If successful, returns a Receipt struct for the ballot of the voter address.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
Receipt ballot = gov.getReceipt(proposalId, voterAddress);
```

**Web3 1.2.6**

```js
const proposalId = 11;
const voterAddress = '0x123...';
const result = await gov.methods.getReceipt(proposalId, voterAddress).call();
const { hasVoted, support, votes } = result;
```

### State

Gets the proposal state for the specified proposal. The return value, `ProposalState` is an enumerated type defined in the Governor Delegator contract.

**Governor Delegator**

```solidity
function state(uint proposalId) returns (ProposalState)
```

* `proposalId`: ID of a proposal in which to get its state.
* `RETURN`: Enumerated type ProposalState. The types are Pending, Active, Canceled, Defeated, Succeeded, Queued, Expired, and Executed.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
GovernorDelegator.ProposalState state = gov.state(123);
```

**Web3 1.2.6**

```js
const proposalStates = [
  'Pending',
  'Active',
  'Canceled',
  'Defeated',
  'Succeeded',
  'Queued',
  'Expired',
  'Executed',
];
const proposalId = 123;
result = await gov.methods.state(proposalId).call();
const proposalState = proposalStates[result];
```

### Cast Vote

Cast a vote on a proposal. The account's voting weight is determined by the number of votes the account had delegated to it at the time the proposal state became active.

**Governor Delegator**

```solidity
function castVote(uint proposalId, uint8 support)
```

* `proposalId`: ID of a proposal in which to cast a vote.
* `support`: An integer of 0 for against, 1 for in-favor, and 2 for abstain.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.castVote(proposalId, 1);
```

**Web3 1.2.6**

```js
const tx = gov.methods.castVote(proposalId, 0).send({ from: sender });
```

### Cast Vote With Reason

Cast a vote on a proposal with a reason attached to the vote.

**Governor Delegator**

```solidity
function castVoteWithReason(uint proposalId, uint8 support, string calldata reason)
```

* `proposalId`: ID of a proposal in which to cast a vote.
* `support`: An integer of 0 for against, 1 for in-favor, and 2 for abstain.
* `reason`: A string containing the voter's reason for their vote selection.
* `RETURN`: No return, reverts on error.

**Solidity**

```solidity
GovernorDelegator gov = GovernorDelegator(0x123...); // contract address
gov.castVoteWithReason(proposalId, 2, "I think...");
```

**Web3 1.2.6**

```js
const tx = gov.methods
  .castVoteWithReason(proposalId, 0, 'I think...')
  .send({ from: sender });
```

### Timelock

Each protocol contract is controlled by the [Timelock contract](https://github.com/paribus), which can modify system parameters, logic, and contracts in a 'time-delayed, opt-out' upgrade pattern. The Timelock has a hard-coded minimum delay which is the least amount of notice possible for a governance action. The Timelock contract queues and executes proposals that have passed a Governance vote.

### Pause Guardian

The Comptroller contract designates a Pause Guardian address capable of disabling protocol functionality. Used only in the event of an unforeseen vulnerability, the Pause Guardian has one and only one ability: to disable a select set of functions: Mint, Borrow, Transfer, and Liquidate. The Pause Guardian cannot unpause an action, nor can it ever prevent users from calling Redeem, or Repay Borrow to close positions and exit the protocol. PBX token-holders designate the Pause Guardian address, which is held by the [Community Multi-Sig](https://arbiscan.io).


# Security

### Introduction

The security of the Paribus Protocol is our highest priority; our development team, alongside third-party auditors and consultants, has invested considerable effort to create a protocol that we believe is safe and dependable. All contract code and balances are publicly verifiable, and security researchers are eligible for a bug bounty for reporting undiscovered vulnerabilities.

We believe that size, visibility, and time are the true test for the security of a smart contract; please exercise caution, and make your own determination of security and suitability.

### Audits

The Paribus Protocol has been reviewed & audited by [Hacken](https://www.hacken.io/).

1. [Hacken - May 2022](https://hacken.io/wp-content/uploads/2022/06/Paribus_25052022_SCAudit_Report_2.pdf)
2. [Hacken - March 2023](https://wp.hacken.io/wp-content/uploads/2022/06/Paribus_SC-Audit-Report_13032023_SA-908-3.pdf)
3. [Hacken - December 2023 - WIP](https://hacken.io)

### Bug Bounty Program

Security is core to our values, and we value the input of hackers acting in good faith to help us maintain the highest standard for the security and safety of the Ethereum ecosystem. The Paribus Protocol, while it has gone through professional audits and formal verification, depends on new technology that may contain undiscovered vulnerabilities.

Paribus encourages the community to audit our contracts and security; we also encourage the responsible disclosure of any issues. This program is intended to recognize the value of working with the community of independent security researchers, and sets out our definition of good faith in the context of finding and reporting vulnerabilities, as well as what you can expect from us in return.

More informations about the scope, rewards as well as terms and conditions can be found at [Immunefi.com](https://immunefi.com/bounty/paribus/)

**All reward determinations, including eligibility and payment amount, are made at Paribus’s sole discretion. Paribus reserves the right to reject submissions and alter the terms and conditions of this program.**


# Frequently Asked Questions

Here is a list of most frequent questions. If you see an important answer is missing, feel free to get in touch.


# Borrow & Lending

## pTokens

### How do pTokens earn interest?

Each market has its own Supply 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 market is launched, the pToken exchange rate (how much ETH one pETH is worth) begins at 0.020000 — and increases at a rate equal to the compounding market 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 supply 1,000 DAI to the Paribus 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:

* &#x20;Your 49,825.61 pDAI is now equal to 1,075.78 DAI (49,825.61 \* 0.021591)
* &#x20;You could withdraw 1,075.78 DAI, which would redeem all 49,825.61 pDAI
* &#x20;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 Arbiscan, and you should be able to view them in the list of tokens associated with your address.

You can find a list of all pTokens under the [network list](/for-developers/getting-started#networks).

### Can I transfer pTokens?

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

A pToken transfer will fail if the account has [entered](/for-developers/comptroller#enter-markets) that pToken market and the transfer would have put the account into a state of negative [liquidity](/for-developers/comptroller#get-account-liquidity).


# Staking (finished)

![](https://miro.medium.com/max/1400/1*RGp6MkFE20kbuB_mGMqlNg.jpeg)

As we approach the release of native staking for PBX holders we decided to give a broad overview of how Paribus staking will work. This article takes you through some of the key concepts behind PBX staking and why this is such a rare opportunity.

### What is staking? <a href="#ddfd" id="ddfd"></a>

Staking is based on a smart contract that locks in a set number of PBX tokens for a given period of time. When the contract has been completed the tokens that were staked and the reward tokens are released. You can then choose whether to sell, hold, or further invest your tokens. The unusual aspect with PBX staking is that it’s a one-off event, after the pools are filled there will never be another opportunity to stake your PBX, even after the contract has been successfully completed.

### Why should I stake PBX? <a href="#id-77ec" id="id-77ec"></a>

Before the staking program was developed the only way people could earn a return on their tokens would involve trying to guess the market by selling highs and re-buying the lows. The difficulty with this approach is that it’s an easy way to lose tokens rather than grow them. Despite the wild claims of certain Crypto-Twitter and YouTube influencers, timing the market is incredibly difficult and fraught with risk. By staking your tokens they remain secure and increase in quantity. Deniz, the CEO of Paribus said, “This gives everyone an opportunity to earn PBX as an early supporter thus better their return prospects as the project grows.”

### How is PBX staking different from ADA staking? <a href="#id-1811" id="id-1811"></a>

In general, there are two types of cryptocurrency models, called Proof of Work (PoW) and Proof of Stake (PoS), which use different approaches to secure and validate transactions on their blockchains. Bitcoin has a PoW structure whilst Cardano is PoS. When you stake ADA tokens on the Cardano network they’re delegated to a particular stake pool and the level of ADA staked within a pool is used to validate transactions, so staking is essential for the continued functioning of the network. However, as Paribus is a DeFi protocol rather than a blockchain it doesn’t require any staking of PBX in order to function, so from the point of view of functionality PBX staking is very different from ADA staking. In addition, the yield you would expect to get from PoS staking would be around 6%APY whereas the yield from PBX staking is 5 times greater at up to 30%APY.

### How is the reward worked out? <a href="#id-4723" id="id-4723"></a>

To help people make the clearest decisions about how they choose to stake we’ve expressed the rewards as an industry-standard APY percentage. APY stands for Annual Percentage Yield and PBX staking rewards vary between 20–30% APY. The important aspect for people to understand is that APY is based on a yearly figure, so 20% APY in a 90-day staking contract doesn’t mean that you exit with 20% more PBX as the actual number of tokens your reward will amount to is pro-rata. So 100,000 PBX at 20%APY for 90-days doesn’t mean you would exit with a reward of 20,000 PBX, it would instead be just below 5,000PBX. \[20,000/365 x 90 = 4,931.5]. Likewise, if you staked 1,000,000 PBX in the Aurum pool it would be locked for the full 365-days and your reward would be 300,000 PBX. In deciding which pool to stake you’ll want to take into account both the APY% and the duration of the staking contract — the higher both are the higher the end rewards will be.

### What are the pools? <a href="#id-26e3" id="id-26e3"></a>

The three pools are Aereus, Argenti, and Aurum.

Aereus allows you to stake anywhere from 50,000 to 2,000,000 PBX, locked for just 90 days with an incredible reward level of 20% APY.

Argenti allows you to stake between 500,000 and 3,000,000 PBX, locked for 180 days in return for a substantial reward level of 25% APY.

The largest pool, Aurum, allows you to stake from 1,000,000 to 6,000,000 PBX for 365 days in return for a jaw-dropping 30% APY reward level.

### What are the pool sizes? <a href="#id-9ba6" id="id-9ba6"></a>

The pool capacity for Aereus is 250 million PBX, for Argenti, it’s 375 million PBX, and for Aurum, the maximum pool capacity is 500 million PBX. In total up to 1.125 billion PBX (over 50% of the circulating supply) will be locked out of circulation. As Deniz, the CEO of Paribus explains, “We have set our pool limits so each pool can accommodate the desired amount of unique wallets. Without limits a single “whale” can fill up the largest pools and this is not something we want as we want PBX in the hands of as many people as possible.”

### Why are there minimum entry levels, it seems unfair? <a href="#id-8b80" id="id-8b80"></a>

Anytime a barrier to entry exists it necessarily prevents some people from taking part and that can seem contradictory with the ethos of Paribus at first glance, but we can assure you it’s there for good reasons. The main reason for a minimum limit of 50,000PBX for staking isn’t to encourage participation only from people who can afford to buy that number of tokens, it’s simply due to the difficulties of being an ERC-20 token. For various reasons, we’ll address in later articles, Paribus has started life as an ERC-20 token, as such any transactions are subject to Ethereum gas fees. Because of the generally high and unpredictable costs of gas fees on Ethereum it means that low quantities of PBX staked could be counterproductive because it could end up costing people more in gas fees than they make in rewards. Likewise, we thought long and hard about the time lock periods and came to the conclusion of a higher entry to the longest lock period. If someone can afford to buy and hold 1million PBX they would be more likely to be able to lock them away for a year. The last thing we wanted would be to incentivize long lock periods for those who couldn’t afford to tie their funds up for the duration of them. Nothing in life is perfect but we hope that following this logic maximizes the number of people within the Paribus community that can participate in staking. Deniz explained, “We looked at our token holder’s chart on etherscan and got a sense of average holding amounts. Based on this figure and token release schedules we came up with these pools to accommodate for users across the spectrum.”

### How and where do I stake? <a href="#id-4911" id="id-4911"></a>

Staking will be available through the Paribus website. Once live you’ll find exactly how to stake your PBX tokens through the official Paribus staking app. It’s incredibly user-friendly and our developers have worked hard to make it as easy and accessible as possible.

### When can I stake? <a href="#d779" id="d779"></a>

As a special holiday gift, we’re releasing the live staking app on Tuesday 28th December at 2:00 pm GMT. You can stake from this point onwards provided there’s still space in the pool for you to stake to.

### Why develop a staking program? <a href="#id-4f49" id="id-4f49"></a>

Originally we had no concrete plans to develop native staking of the PBX token and all our efforts were focused on our main app development. However, soon after the launch of PBX a community began forming, much faster and larger than anything we’d anticipated. There were growing calls for a way to stake the tokens people were holding so we felt we had to honor this desire and give the community a staking program. For Paribus the benefit is that it reduces some of the volatility we’ve seen with people trying to scalp and swing trade and it incentivizes HODLing. Many people within the community share our passion and vision and we wanted to give them something back to show how blown away we’ve been by their huge levels of support. As well as giving the community a place to securely grow their PBX we’ve structured the pools to maximize the number of people that can get involved. Once all the slots are filled we’ll have locked up over 50% of the entire circulating supply of PBX.

### What if I want to stake later? <a href="#id-9bc7" id="id-9bc7"></a>

Although we’ve tried to maximize the pools to give everyone the chance to take part we can’t guarantee how long the opportunity will last. The staking program is a one-off chance to give the community a way to earn passive income with their tokens until we have the MVP available, so it won’t be repeated again in the future. Even the MVP yield won’t be on the scale of the staking rewards, so this really is a once-in-a-lifetime opportunity for PBX holders.

### Can I re-stake after my initial 90 Days? <a href="#id-0b08" id="id-0b08"></a>

Unfortunately not. As each time lock expires that pool will cease to exist. We’d recommend people choose carefully, bearing in mind how many PBX they want to stake and how long they can realistically afford to stake for. We want everyone to have the opportunity to benefit as much as possible from the staking program

<br>


# Terms and Conditions

Paribus (The “Company,” “Us,” “Our” or “We”), by and through [https://paribus.io](https://paribus.io/) (the “Site”), operates, hosts and monitors PBX Staking, PBX Borrow and Lending platform (as defined below, the “Services”). Paribus provides Services pursuant to, and in accordance with, the following terms and conditions (this “Agreement” or “Terms of Use”). By utilizing any of the Services as provided and offered by Paribus, you hereby consent and agree to be bound by these Terms of Use, as contained herein.

You (“Client”) agree to be bound by these Terms of Use and all other operating rules, policies and procedures that may be published by Us from time to time on the Site, each of which is incorporated by reference and each of which may be updated by Us from time to time without notice to you. Your use of the Site is governed by the version of these Terms of Use in effect on the date of use.

### 1. Definitions

“Blockchain” means a digital ledger in which transactions made with a Cryptocurrency are recorded chronologically.

“Cryptocurrency” means a digital currency, operating independently of a central bank, in which encryption techniques are used to regulate the generation of units of currency and verify the transfer of funds.

“Client Data” means all data, files and information that Client provides to Paribus in the course of using the Services.

“Client Funds” means the Cryptocurrency funds held by Client.

“Net Revenue” means Staking Rewards minus any Slashing Penalties assessed, if applicable.

“Slashing Penalty” means any penalty assessed by the Cryptocurrency for unavailability or slow, incorrect or malicious performance.

“Staking” or “to Stake” means committing Cryptocurrency holdings as a monetary guarantee of the correct and performant operation of a designated Staking Node.

“Staking Rewards” means all Cryptocurrency generated by operating Staking Nodes, including, but not limited to, block rewards, endorser rewards, transaction fees and any other direct payments as a result of operating a Staking Node.

“Supported Protocol” means a Cryptocurrency for which Paribus operates.

“Revenue Share Payments” means the percentage of Net Revenue paid to Client as set forth.

“Unbonding Period” means the Cryptocurrency imposed waiting period, during which the Client Funds and End Users Funds may not be withdrawn or sold.

### 2. PARIBUS RESPONSIBILITIES

a. Revenue Share Payments: Paribus will pay Client a percentage of Net Revenue directly attributable to Client Funds. All Payments will be made in the same Cryptocurrency in which the Client Funds or End Users Funds are denominated, as applicable.

b. Reporting: Paribus will provide regular reports through our dashboard detailing the performance of the Services to Client. Such reports will provide mutually agreeable detail to enable the accurate calculation of Net Revenue.

### 3. CLIENT RESPONSIBILITIES

a. Stake Delegation. Client will have the sole right to determine the amount of Client Funds and End Users Funds which will be Staked pursuant to this Agreement, in accordance with the pool and personal limits.

b. Withdrawals. Client acknowledges and agrees that Client Funds and End Users Funds which have been Staked pursuant hereto may be withdrawn prior to the conclusion of the Unbonding Period, but are subject to a Slashing Penalty.

c. Taxes: Client shall be responsible for payment of all applicable taxes, if any, to which the Revenue Share Payments might be subject and any and all other taxes which may apply to Client; Paribus makes no representations in this regard. Client agrees to indemnify and hold Paribus harmless against any taxes, including penalties, duties and interest levied by any government on the Revenue Share Payments.

### 4. LICENSE GRANT; RESTRICTIONS

a. Proprietary Rights. Client acknowledges and agrees that this license conveys no title or ownership rights to the Paribus Services. Client does not acquire any rights in the Services, express or implied, other than those expressly granted in this Agreement and all rights not expressly granted to Client are reserved by Paribus. Paribus retains all right, title and interest in and to the Paribus Services, including without limitation, all unpatented inventions, patent applications, patents, design rights, copyrights, trademarks, service marks, trade names, know-how and other trade secret rights, and all other intellectual property rights, derivatives or improvements thereof.

b. Restrictions. Client will not, and will not permit any other third party to modify, reproduce, copy, reverse engineer, decompile, reverse assemble or otherwise attempt to discover the source code or algorithms for the Paribus Services. The Paribus Services may not be used in any jurisdiction for unlawful, obscene, offensive or fraudulent content or activity, such as advocating or causing harm, interfering with or violating the integrity or security of a network or system, evading filters, sending unsolicited, abusive, or deceptive messages, viruses or harmful code, or violating third party rights. If there is a complaint or notice of violation, use may be suspended until resolved, and terminated if not resolved promptly.

### 5. TERM & TERMINATION

a. Term. Agreement will commence upon the Effective Date and, unless earlier terminated as set forth below, continue for a period denoted in the pool timeline (the “Initial Term”). Thereafter, the Agreement will automatically terminate. As used herein, “Term” means the Initial Term.

b. Effect of Termination. Upon termination or expiration of this Agreement: (i) all rights and obligations of both parties, including all licenses granted hereunder, shall immediately terminate, (ii) ii) together any payment obligations existing as of the effective date of termination, will survive.

### 6. CONFIDENTIALITY

The parties acknowledge that the terms of this Agreement will be confidential. Data or information will be considered Confidential Information if: (a) a party has marked it as such; (b) a party, orally or in writing, has advised the other party of its confidential or proprietary nature, or © due to its character and nature, a reasonable person under like circumstances would treat it as confidential. Neither party will either (i) publish, disclose or otherwise divulge any of the other party’s Confidential Information to any person, except its officers, employees or agents with a need to know who are under a contractual or professional duty to maintain the confidentiality of such information consistent with the obligations imposed hereunder; or (ii) permit its officers, employees or agents to divulge any of the other party’s Confidential Information without the express prior written consent of the other party. The receiving party will protect the disclosing party’s Confidential Information with the same degree of care that the receiving party protects its own information of a similar nature, but in no event less than reasonable care. Neither party will use the other party’s Confidential Information except in the course of performing its duties under this Agreement. The foregoing obligations will not apply to any Confidential Information that (1) is already known to the receiving party; (2) is or becomes publicly known through no wrongful act of the receiving party; (3) is independently developed by the receiving party without benefit of the disclosing party’s Confidential Information; (4) is received from a third party without similar restriction and without breach of any obligation of confidentiality; or (5) is required or reasonably necessary to be disclosed to comply with laws, statutes, regulations, orders, and other governmental rules. Additionally, neither party will be prohibited from disclosing the terms and conditions of this Agreement to financial institutions when required to obtain financing or to a third party involved with a potential merger or acquisition (either as target or acquirer). The obligations of confidentiality described above will expire three years after the expiration or termination of this Agreement.

### 7. REPRESENTATIONS & WARRANTIES

a. Representations and Warranties by Paribus. Paribus represents and warrants to Client that: (i) it has the power and authority to enter into this Agreement, (ii) entering into this Agreement will not be a breach or violation of any other contract or agreement to which Paribus is bound, (iii) it provides the Services using commercially reasonable care and skill in accordance with the service levels outlined

b. Representations and Warranties by Client. Client represents and warrants to Paribus that: (i) it has the power and authority to enter into this Agreement, and (ii) entering into this Agreement will not be a breach or violation of any other contract or agreement to which Client is bound.

c. Disclaimer. EXCEPT FOR THE EXPRESS WARRANTIES STATED IN THIS SECTION 7, NEITHER PARTY MAKES, AND EACH PARTY EXPRESSLY DISCLAIMS, ALL WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, WITH RESPECT TO THE SERVICES AND THE SUBJECT MATTER OF THIS AGREEMENT, INCLUDING WITHOUT LIMITATION IMPLIED WARRANTIES OF ACCESS, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND IMPLIED WARRANTIES ARISING FROM COURSE OF DEALING OR COURSE OF PERFORMANCE. EXCEPT AS STATED IN THIS SECTION 7(a), THE SERVICES ARE PROVIDED TO CLIENT ON AN “AS IS” AND “AS AVAILABLE” BASIS, AND ARE FOR COMMERCIAL USE ONLY. Client understands that while Paribus employs measures to ensure that the Services are accessible 24 hours a day/7 days a week, Paribus cannot guarantee the uninterrupted or error-free operation performance of the Services or that Paribus will correct all defects or prevent third party disruptions or unauthorized third party access. In the event of any inaccessibility of the Paribus Services, Paribus’s sole liability and obligation will as described in Exhibit A, which is hereby incorporated by reference. Paribus warranties will not apply if there has been misuse, modification, damage not caused by Paribus, failure to comply with instructions provided by Paribus, or if otherwise stated in Exhibit A.

### 8. LIMITATION OF LIABILITY

PARIBUS’S ENTIRE LIABILITY FOR ALL CLAIMS RELATED TO THE AGREEMENT WILL NOT EXCEED THE AMOUNT OF ANY ACTUAL DIRECT DAMAGES INCURRED BY CLIENT, UP TO THE NET REVENUES ACTUALLY RECEIVED BY PARIBUS IN THE PRIOR 12 MONTHS (OR OTHERWISE STATED LENGTH) WITH RESPECT TO THE SERVICES THAT ARE THE SUBJECT OF THE CLAIM, REGARDLESS OF THE BASIS OF THE CLAIM. PARIBUS WILL NOT BE LIABLE FOR SPECIAL, INCIDENTAL, EXEMPLARY, INDIRECT, OR ECONOMIC CONSEQUENTIAL DAMAGES, OR LOST PROFITS, BUSINESS, VALUE, REVENUE, GOODWILL, OR ANTICIPATED SAVINGS. THESE LIMITATIONS APPLY COLLECTIVELY TO PARIBUS, ITS AFFILIATES, CONTRACTORS AND END USERS. NOTWITHSTANDING THE FOREGOING, THE ABOVE LIMITATIONS ON LIABILITY SHALL NOT APPLY TO: (A) A BREACH OF SECTION 2(C) OR A BREACH OF SECTION 6, OR (B) A CLAIM FOR INDEMNIFICATION UNDER SECTION 9.

### 9. INDEMNIFICATION

Client agrees to indemnify, defend and hold harmless Paribus, its partners, agents, officers, directors and employees, from and against any loss, cost, expense, claim, injury or damage (including, without limitation, reasonable attorneys’ fees and expenses) (collectively, “Losses”) incurred due to third party claims arising from any breach by Client of any representation, warranty, or provision in this Agreement. Paribus shall indemnify, defend and hold Client harmless from and against any Losses incurred due to third party claims arising from any breach by Paribus of any representation, warranty, or provision contained in this Agreement.

### 10. RELATIONSHIP OF PARTIES

Neither this Agreement, the relationship created between the parties hereto pursuant to this Agreement, nor any course of dealing between the parties hereto is intended to create, or shall create, an employment relationship, a joint venture, partnership or any similar relationship. Each party is solely responsible for the payroll taxes, workman’s compensation insurance, and any other benefits owed to their own employees.

### 11. COMPLIANCE WITH LAWS

Each party shall comply, at its own expense, with all statutes, regulations, rules, ordinances, and orders of any governmental body, department or agency that apply to or result from its obligations under this Agreement. If Client receives any notice or becomes aware of any violation of any law, statute, rule, regulation or ordinance with respect to the Services hereof, Client shall promptly notify Paribus of such notice or violation.

### 12. GENERAL TERMS

a. This Agreement (and any Exhibits hereto) constitutes the entire agreement between the parties with respect to the subject matter hereof, and may not be modified without the prior written consent of both parties.

b. This Agreement will be governed and interpreted in accordance with the laws of the State of New York without reference to conflicts of laws principles.

c. Paribus will not be liable for any delay or failure to perform any of its obligations set forth in this Agreement due to causes beyond its reasonable control.

d. No failure of either party to enforce any of its rights under this Agreement will act as a waiver of such rights.

e. Neither party will bring a legal action arising out of or related to the Agreement more than one year after the cause of action arose.

f. If one or more provisions of this Agreement are held to be unenforceable under applicable law, then such provision(s) shall be excluded from this Agreement, and the balance of the Agreement shall be enforceable in accordance with its terms.

g. Any notice, demand or request required or permitted to be given under this Agreement shall be in writing and shall be deemed sufficient when sent by email to <hello@paribus.io>. Notice will be effective on receipt.

h. Headings and captions are for convenience only and are not to be used in the interpretation of the Agreement.


