# The Inverse Bonding Curve

The inverse bonding curve implementation is the first demonstration of inverse bonding curves; used for minting assets that devalue as bought and rise in value as sold. **The tokens minted via the inverse bonding curve implementation, ibAssets, are the first asset class in history that follows the exact inverse of regular market dynamics.**

<figure><img src="/files/cMIh71DiMWpWW3fDkXvA" alt=""><figcaption></figcaption></figure>

Inverse bonding curves are a brand new DeFi primitive derived from bonding curves. The pricing algorithm enforced by the inverse bonding curve shows various unique traits, one of them being its arbitrage characteristics. Arbitrage of ibAssets forces ibAssets to devalue per every purchase, regardless of where the purchase was made (CEX, Uniswap, etc. ). **Altogether, the distinctive properties of inverse bonding curves allow for the creation of DeFi mechanisms previously unthought of, one of which is an** [**oracle-free derivatives protocol**](https://exponents.fi/)**.**

The purpose of the inverse bonding curve implementation is to increase awareness and understanding of this new primitive, which will help spark DeFi innovations that leverage its features.

## Basic Protocol Functions

Three participant types power the inverse bonding curve implementation: ibAsset Minters / Stakers, Liquidity Providers (LPs), and Curve Initializers. ibAssets (e.g. ibETH) can be minted by providing reserve assets (e.g. ETH) to the inverse bonding curve, from which new ibAssets are minted into existence and given to the minter. LPs can provide additional reserve assets to improve the market liquidity of the inverse bonding curve.

New ibAsset types can be created for an ERC20 reserve asset of choice. Curve Initializers specify the reserve asset to be used, providing the initial reserve amounts to generate a new inverse bonding curve & ibAsset pair. Initializations are permissionless and can be executed by anyone.

Each participant contains the following characteristics:

### ibAsset Minters / Stakers

* Their position value increases as more ibAssets are burnt following the mint.
* Their position value decreases as more ibAssets are minted following the mint.
* Mints and burns incur a fee, distributed to ibAsset stakers and LPs.
* Staked ibAssets accrue prorated fees from mints and burns and LP adds and removals.
* Later entrants can acquire a higher stake of fees as their mint price is lower.

### Liquidity Providers (LPs)

* Their position value increases as the price deviates from the price at the time of LP.
* LPs can maintain only one position per account / address at any given time.
* LPs must close their previous position in full before modifying their position size.
* Adding and removing liquidity incur a fee, distributed to ibAsset stakers and LPs.
* LPs accrue prorated fees from mints and burns and LP adds and removals.
* LPs may be required to provide or receive additional ibAssets in order for LP removal.

### Curve Initializers

* Creates new ibAssets for promising reserve assets.
* Curve initializers can be the early users of a new ibAsset, including LPing.
* Provides the initial reserves for a new ibAsset and receives a LP position.
* A small fee is taken from the provided initial reserves.
* The initial LP amount can be removed only after an additional LP joins.


# Bonding Curves

Inverse bonding curves take inspiration from bonding curves, acting as their theoretical extension. A brief explainer on bonding curves is written for those unfamiliar with the concept.

Bonding curves are an algorithmic pricing methodology that defines the relationship between the price and supply of an asset. They are generally paired with continuous tokens models - where assets can be minted and burnt on demand, instead of having a fixed supply schedule. Asset mints via bonding curves are performed following an algorithmically-set exchange rate, defined as a function of asset supply.

A smart contract implementation of a bonding curve retains a pool of reserve assets (e.g. ETH) which is used to facilitate the mints and burns. Acting as the sole counterparty, the bonding curve mints new assets as it receives reserve assets and returns reserve assets as minted assets are burnt.

Such assets usually (but not always) contain the following properties:

* **Unbounded supply**: there exists no limit to the number of tokens that can be minted.
* **Deterministic price**: the asset price is set from a predefined function of supply.
* **Continuous price**: prices move smoothly without any jumps or breaks.
* **Monotonic price**: the price changes in a way that it always increases with mints.
* **Instant liquidity**: assets can be minted or burnt instantaneously at any time.

Bonding curves are often visualized using a price-to-supply graph. For example, a bonding curve of `price=1/6 * supply^2` visualizes as:

<figure><img src="/files/cXllM2cfJeYwEFmhzTIU" alt="" width="375"><figcaption></figcaption></figure>

The spot prices of assets and the amount of reserve assets required for their minting is all calculated based on the bonding curve, the amount of reserve assets required corresponding to the definite integral of the bonding curve from the supply prior to mint and to the supply following the mint (equivalent to the area below the bonding curve).

On the above example of `price=1/6 * supply^2` at a starting supply of $$1$$, the minting of $$2$$ tokens leads to a spot price increase from $$0.166...$$ to $$1.5$$, and consumes $$1.444...$$ amount of reserve assets.

Bonding curves can exist in various shapes and sizes:

<figure><img src="/files/WtvzB2l9hISrq7MY3bU1" alt="" width="375"><figcaption><p><code>price=1/2 * supply</code></p></figcaption></figure>

<figure><img src="/files/Ar8mfA5LQcteDK3eBCpA" alt="" width="375"><figcaption><p><code>price=2 sqrt(supply)</code></p></figcaption></figure>

<figure><img src="/files/B79aEfy9hjhycDHg6ESw" alt="" width="375"><figcaption><p><code>price=exp(supply/3)-1</code></p></figcaption></figure>


# Inverse Bonding Curves (IBCs)

Inverse bonding curves (IBCs) further extend the work done on regular bonding curves. Assets (e.g. ibETH) minted through bonding curves, named ibAssets, also generally follow the 5 characteristics of continuous tokens (unbounded supply, deterministic price, continuous price, monotonic price, instant liquidity), with the only change being that in contrast to regular bonding curves, where prices monotonically increase with asset mints, **prices on IBCs monotonically decrease as assets are minted**.

ibAssets minted via IBCs start from an infinite (or otherwise high) price and and approach 0 as an infinite amount of tokens are minted. The resulting curve looks as if a regular bonding curve has been flipped upside-down, hence its name of inverse bonding curves.

ibAssets display market properties never observed anywhere else. Unlike regular assets which increases in price as bought and decreases in price as sold, ibAssets strictly follow the inverse: its price decreases as bought and increases as sold.

## Analysis

Although IBCs can exist in various forms (just like regular bonding curves), the analysis here centres around its polynomial variant of:

$$
P=\frac{m}{S^k}
$$

With $$P$$ being the spot price at a minted supply of $$S$$, $$m$$ being a price multiplier value, and $$k$$ being the exponent determining the curve's curvature.

<figure><img src="/files/QA5PMtoOu7aUzxsXSnOT" alt="" width="375"><figcaption></figcaption></figure>

Just like regular bonding curves, the area under IBCs also represent the amount of reserve assets (e.g. ETH) required for minting. This value, the integral of the IBC curve. comes out as (for minting from $$0$$ supply to $$x$$):

$$
\int\_0^x\frac{m}{x^k}dx=\frac{m{x}^{1-k}}{1-k}
$$

In order for the IBC to exist, it must only consume a finite amount of reserve assets to mint from $$0$$ supply to $$x$$. The exponent value $$k$$ thus must be in the range of:

$$
0\<k<1
$$

Where a $$k$$ value below $$0$$ yields a non-inverse regular bonding curve and a value above $$1$$ requires an infinite amount of reserve assets to mint any number of ibAssets thereby making its practical existence impossible.


# Curve Initialization

Any user is able to generate an IBC curve by providing an initial amount of an ERC20 token as the selected reserve asset. An IBC is created per reserve asset type, and only one IBC can exist per reserve asset type.

An IBC using ETH as the reserve asset is created at protocol genesis, with ibETH (the minted ibAsset) marking the first history of assets that follow inversed market dynamics. Other types of ibAssets can be generated by any user providing ERC20 reserve assets.

The provided initial parameter values of initial liquidity reserves ($$R\_0$$) is used to compute the initial minted supply ($$S\_0$$), and the starting spot price ($$P\_0$$).

## Initial Parameters

The curve initializes to contain the provided $$R\_0$$ amount of liquidity reserves. The generated IBC starts off with a price curve equation of:

$$
price=\frac{1}{\sqrt{supply}}
$$

Where the price starts as $$1$$ ibAsset = $$1$$ reserve asset at a minted ibAsset supply of $$1$$.

The initial minted supply and price values are then calculated as:

$$
S\_0=\frac{{R\_0}^{2}}{4}
$$

$$
P\_0=\frac{2}{R\_0}
$$

### Minimum Initial Reserve

A minimum amount of initial reserves is enforced, preventing rounding errors during further interactions. The minimum initial reserve is set as $$0.0002$$ reserve assets for all initializing IBCs. Furthermore, a small reserve amount from the minimum initial reserve is deducted away and made non-withdrawable and is locked in the IBC eternally in order to prevent further rounding errors and disallow the reserve being drained to zero.

### Initial LP Token Supply

The IBC also starts with an initial minted supply of LP tokens, later used to calculate the LP token mint amounts to those providing liquidity to the initialized curve. The initial LP token amount is calculated as:

$$
P\_0\left(R\_0-P\_0S\_0\right)
$$

Which is equal to the initial price, times the specified amount of virtual reserves minus the amount of virtual reserves that would be needed to fully back the initial virtual minted supply at the initial price.

The LP token amount minted for a small deduction of the minimum initial reserve is also made non-removable, preventing potential rounding errors and total drainage of the reserve.

### Curve Formation

Following from a generic IBC of $$\frac{m}{x^k}$$, the initialized curve must show a spot price of $$P\_0$$ at a minted virtual supply of $$S\_0$$:

$$
\frac{m}{{S\_0}^k}=P\_0
$$

The curve should also contain a liquidity reserve of $$R\_0$$ at a minted supply of $$S\_0$$:

$$
\int\_{0}^{S\_0}\frac{m}{x^{k}}dx=\frac{m{S\_0}^{1-k}}{1-k}=R\_0
$$

Whereby combining the two yields the values for $$m$$and $$k$$:

$$
m=P\_0{S\_0}^{1-\frac{P\_0S\_0}{R\_0}},,k=1-\frac{P\_0S\_0}{R\_0}
$$

The curve is then defined as the below:

$$
P(x)=P\_0{\left(\frac{S\_0}{S\_0+x}\right)}^{1-\frac{P\_0S\_0}{R\_0}}
$$

Where $$x$$ is the amount of ibAssets being minted by further interactions post-initialization.

### Curve Invariant

The generated IBC is observed to have the below invariant ($$i$$) as mints and burns occur. $$i$$ does not update during mints and burns, but updates with LP additions and withdraws.

$$
i=\frac{R}{S^{u}}
$$

$$u$$ represents the utilization of provided liquidity vs. liquidity used to back minted ibAssets at the current spot price. $$u$$ is defined at curve initialization and is made to never update. $$u$$ is defined as:

$$
u=\frac{PS}{R}=0.5
$$

For all initialized IBCs, $$u$$ is always set to have a value of $$0.5$$.

With initialized values of $$R\_0$$, $$S\_0$$, $$P\_0$$, the values $$i$$ and $$u$$ are set as:

$$
i=\frac{R\_0}{{S\_0}^{u}},,u=\frac{P\_0S\_0}{R\_0}=0.5
$$

The newly added values of $$i$$ and $$u$$ allow the price curve to also be written as:

$$
P(x)=\frac{iu}{{\left(S\_0+x\right)}^{1-u}}
$$

The invariant is used extensively in the IBC's implementation.


# Minting / Burning

Just like bonding curves, users may buy (mint) / sell (burn) ibAsset to / from an initialized IBC. The IBC acts as the counterparty for such trades, utilizing its liquidity reserve as market liquidity.

Just like regular bonding curves, the amount of reserve assets required to mint a certain amount of ibAssets is equivalent to the area under the IBC's price curve (integral of the curve). While values for minting and burning can be calculated with integration, it can also be derived from the curve's invariant with ease:

$$
i=\frac{R}{S^u}=\frac{R+\Delta R}{{\left(S+\Delta S\right)}^u}=const.
$$

## Minting

New ibAssets can be minted (bought) by supplying reserve assets to the relevant IBC, from which the IBC of the reserve asset calculates the amount to be minted. If the amount of reserve assets supplied is $$\Delta R$$ and the amount being minted is $$\Delta S$$, the below must be satisfied.

$$
\frac{S}{S+\Delta S}={\left(\frac{R}{R+\Delta R}\right)}^{\frac{1}{u}}
$$

Thereby yielding $$\Delta S$$ as:

$$
\Delta S={\left(1+\frac{\Delta R}{R}\right)}^{\frac{1}{u}}S-S
$$

The spot price post-mint is the updated to become the below:

$$
\frac{iu}{{\left(S+\Delta S\right)}^{1-u}}
$$

## Burning

Users may also burn minted ibAssets via the relevant IBC to receive reserve assets. The amount of ibAssets burnt ($$\Delta S$$) and the amount of reserve assets given ($$\Delta R$$) has the relationship of:

$$
\frac{R}{R-\Delta R}={\left(\frac{S}{S-\Delta S}\right)}^{u}
$$

From which $$\Delta R$$ comes out as:

$$
\Delta R=R-{\left(1-\frac{\Delta S}{S}\right)}^{u}R
$$

The post-burn price then becomes:

$$
\frac{iu}{{\left(S-\Delta S\right)}^{1-u}}
$$


# Liquidity Providing

Similar to those in xyk automated market makers (AMMs), external capital can be provided to enhance the liquidity of an IBC. Liquidity providers (LPs), entities that perform the act of providing liquidity, provide additional reserve assets to an IBC. The provided reserve assets are then utilized by the IBC to facilitate the minting and burning of ibAssets.

Providing liquidity on the IBC functions in a way such that the liquidity utilization value of the curve remains the same at **0.5** both before and after the liquidity add. The addition or removal of liquidity updates both the minted ibAsset supply and curve invariant values - however, the current spot price (as well as the liquidity utilization) remains unchanged.

The added liquidity triggers the current slope of IBCs to be updated - in a way that greater market depth is given to those to mints and burns of the same size. Minting a certain supply of ibAssets after an LP thus requires **more** reserve assets than prior to the LP. Similiarly, burning a specific number of ibAssets after an LP returns **less** reserve assets than before the LP, showing the exact opposite behavior of adding liquidity on a regular xyk AMM.

## LP Positions

Providers of liquidity are given freshly created LP positions, which contain information about the user's share of provided liquidity and its related values. An LP position entails the following data:

* **LP Token Amount**: represents the LP's pro-rata share of total curve reserves.
* **ibAsset Credit**: represents the amount of ibAssets that are considered to be "owned" (but not yet available) by the LP.
* **Reward Index**: used for computing the LP rewards of the position.

LP positions on IBCs have differing characteristics with the widely known LP tokens of xyk AMMs, the major differences being:

* **Only Reserve Assets Required**: Only reserve assets are needed when adding liquidity.
* **Not a Token**: LP positions are not tokenized but instead just recorded state values per LP.
* **Non-fungible**: LP positions are not fungible LP positions due to the existence of ibAsset credit.
* **Non-transferrable**: LP positions are not transferrable to a different account.
* **One Position Per Account**: there can only exist one LP position per LP.
* **Opened / Closed in Full**: positions cannot be modified and must be opened or closed in full.
* **Restricted Withdrawals**: LPs may be required to post additional ibAssets to remove positions.
* **Non-compounding rewards**: rewards distributed to LP positions do not auto-compound.

### LP Token Amount

The LP token amount of an LP position represents the amount of liquidity that was provided by the LP. This value is not an actual token (e.g. ERC20) balance, but instead simply a numerical value. The LP token amount value is used when calculating the amount of liquidity an LP can later withdraw. The minting amounts of LP tokens are determined based the changes of the total LP token supply ($$L$$), which is computed as:

$$
L=P(R-PS)
$$

Rewritten using the liquidity utilization value, this becomes:

$$
L=P(1-u)R
$$

Where the minted LP token amount ($$\Delta L$$) is simply the difference in the total LP token supply before ($$L\_{before}$$) and after ($$L\_{after}$$) the LP:

$$
\Delta L=L\_{after}-L\_{before}
$$

It can be seen that similar to LP tokens of a regular xyk AMM, the amount of withdrawable liquidity of a position is a simple pro-rata value of the curve's total reserves.

An LP's LP token amount is also used as the basis for distributing rewards to LPs. This distribution is made prorated to the LP token amount of the position.

### ibAsset Credit

To retain the same liquidity utilization value pre and post LP, as reserve assets are added the ibAsset supply must also increase via minting. This amount increase is not made readily available to the LP but instead "virtually" minted (token supply increases without an actual mint), although the virtually minted amount is considered to be under the ownership of the LP and thus "credited" to its LP position. This credited amount is later made for use when removing liquidity.

### Reward Index

The reward index of a position is used to track how much LP rewards the position has available for claim. Two reward indexes exist, one a global value and the other a user-specific value. The global index value is updated every time the rewards are distributed to all relevant users, tracking the amount of rewards distributed per LP token amount since protocol genesis.

During a reward claim, the accrued reward amount of an LP is calculated as:

$$
rewardAmount=\left(globalRewardIndex - userRewardIndex\right)\times lpTokenAmount
$$

After which the user-specific index updates to the current global index value.

### Adding Liquidity

The addition of reserve liquidity first introduces an increase in the curve's reserves. This, combined with the need to retain the liquidity utilization as a constant value tells that the addition of liquidity must cause an increase in the minted ibAsset supply. This supply increase is not made available to the LP right away, but instead minted virtually. The virtually minted supply however is "credited" to the LP, later made available at the time of LP removal.

With the addition of $$\Delta R$$ amount of reserve assets, the below should be satisfied together with a minted ibAsset supply increase of $$\Delta S$$:

$$
u=\frac{P\left(S+\Delta S\right)}{R+\Delta R}=\frac{PS}{R}
$$

Since the LP's action does not incur a change in spot price, the supply increase gives out as:

$$
\Delta S=\frac{\Delta R}{R}S
$$

This $$\Delta S$$ of supply increase is thought to be minted, and is credited to the LP.

The invariant $$i$$ also updates to a new value of $$i^{\prime}$$:

$$
i^{\prime}=\frac{R+\Delta R}{{\left(S+\Delta S\right)}^{u}}
$$

The curve subsequently updates to:

$$
P(x)=\frac{{i}^{\prime}{u}}{{\left(S+\Delta S+x\right)}^{1-{u}}}
$$

Showing this in graph format looks like the below.

<figure><img src="/files/VHpAWvOgyeee6x3Bi4i4" alt="" width="375"><figcaption></figcaption></figure>

Where the red curve representing the IBC prior to the LP addition and the blue curve corresponding to the curve after adding liquidity. As seen on the graph, the increased market depth requires users to spend more reserve assets per ibAsset minted and retrieve less reserve assets per ibAsset burnt.

Additionally, the LP is minted LP tokens of the below amount of $$\Delta L$$:

$$
\Delta L=\frac{\Delta R}{R}L
$$

Where $$L$$ is the total LP token supply prior to the LP.

## Removing Liquidity

Similar to when liquidity is added, the removal of liquidity should lead to the decrease in the minted ibAsset supply in order to preserve the utilization as a constant. This amount of supply decrease (named as the LP's ibAsset debt) is dependent on the curve's state at the time of liquidity removal, and thus its value may be different from the amount of ibAsset credit that the LP has.

If the ibAsset debt amount is greater than the LP's ibAsset credit, then the curve requires LPs to post additional ibAsset tokens to cover the difference. Once the tokens are received, the debt amount is burnt and removed from supply. The debt amount may also be lesser than the LP's credit. In this scenario the debt amount is burnt, and the remaining ibAsset credit is transferred to the LP.

The removal of $$\Delta L$$ amount of LP tokens of a LP position from a total LP token supply of $$L$$ should result in the removal of $$\Delta R$$ amount of reserve liquidity, computed as:

$$
\Delta R=\frac{\Delta L}{L}R
$$

And since the utilization value should remain unchanged, a supply decrease of $$\Delta S$$ should follow, in a way that satisfies:

$$
u=\frac{P\left(S-\Delta S\right)}{R-\Delta R}=\frac{PS}{R}
$$

$$\Delta S$$ thus gives out as:

$$
\Delta S=\frac{\Delta R}{R}S=\frac{\Delta L}{L}S
$$

If $$\Delta S$$ is calculated to be greater than the position's ibAsset credit, the difference is required to be provided by the LP. On the other hand, if the position's ibAsset credit is greater than $$\Delta S$$, the difference is sent over to the LP.

Curve invariant $$i$$ then updates to a new value of $$i^{\prime}$$:

$$
i^{\prime}=\frac{R-\Delta R}{{\left(S-\Delta S\right)}^{u}}
$$

After which the curve updates to:

$$
P(x)=\frac{{i}^{\prime}{u}}{{\left(S-\Delta S+x\right)}^{1-{u}}}
$$

Showing this in graph format looks like the below.

<figure><img src="/files/ht2IAInT8qxHcPlqdw8p" alt="" width="375"><figcaption></figcaption></figure>

With the red curve showing the IBC prior to LP withdrawal and the blue curve being the IBC post-withdrawal. The new curve shows decreased market depth, with less reserve assets required to mint the same amount of ibAssets, and more reserve assets returned per ibAsset burnt.

## LP Value

The value of a LP position changes as ibAssets are minted and burnt. Mints and burns increase and decrease the reserve balance, thus causing the differing value. In contrast to a LP position of a regular xyk AMM (e.g. Uniswap V2), **LP positions of IBCs increase in value as price deviations occur.**

A LP position's value can be said to be of the value of withdrawable reserves plus / minus any differences of the position's debt and credit:

$$
\text{lpValue}=\text{withdrawableReserves}-\text{priceAtWithrawal}\left(\text{debt}-\text{credit}\right)
$$

Given a LP position that has been created at a spot price of $$P\_0$$ to mint $$\Delta L$$ amount of LP tokens, its value at a spot price of $$P$$ is calculated as:

$$
\left(\frac{1}{P}+\frac{P}{{P\_{0}}^{2}}\right)\Delta L
$$

Plotting this over as a lp-value-to-price graph looks like ($$P\_0=1,,\Delta L=0.5$$):

<figure><img src="/files/Ccv6qGAZT1YaOFH4kclt" alt="" width="375"><figcaption></figcaption></figure>


# Inverse Bonded Assets (ibAssets)

ibAssets are tokens minted via IBCs. ibAssets are utilized to showcase the characteristics of IBCs, and serves no utility (including governance controls) in or out of the protocol aside from fee accruals from staking or providing liquidity.

<figure><img src="/files/OOmLbBwnn3wdVDoJcxh6" alt="" width="188"><figcaption><p>Reference logo for ibAssets</p></figcaption></figure>

The first ibAsset to exist is ibETH, which uses ETH as its reserve asset. ibETH is generated at protocol genesis, being the first asset to show inversed market properties.

<figure><img src="/files/4bbgmxXLMMrbfjnuLb3a" alt="" width="188"><figcaption><p>ibETH logo</p></figcaption></figure>

## Characteristics

All ibAssets in existence are minted through IBCs and thus contains the following properties:

### Algorithmic, inversed pricing

The price of ibAssets relative to their reserve assets is algorithmically set by the IBC. Contrary to the regular market behavior of an asset price increasing with buying demand and decreasing with selling demand, the IBC enforces a market behavior of the exact inverse - prices of ibAssets (denominated in their reserve assets) decreases with buying demand and increases with selling demand.

### Dynamic, unbounded supply through instant liquidity

At any point in time, any user is able to mint new ibAssets into existence by supplying reserve assets to the IBC implementation. Similarly, any user at any time can burn existing ibAssets via the IBC implementation to receive its reserve assets.

The ibAsset supply starts from a genesis supply (supply minted from initial reserves) and increases as users choose to mint. An infinite amount of ibAssets can be minted although requiring an infinite supplement of reserve assets.

### Staking

ibAssets can be staked to accrue fees generated from the IBC implementation. Fees are distributed to stakers pro-rata to their stake. ibAsset staking, combined with ibAssets' inverse pricing characteristics gives rise to an interesting result - later entrants can acquire a higher stake of distributed fees, with earlier participants having dilution rates of increasing speed as more users enter staking. This prevents potential rent-seeking behaviors from early entrants.


# Fees

Interactions with IBCs incur a fee which are then distributed to three entities, LPs, ibAsset stakers, and the protocol creator. The fee rates may differ based on the interaction type.

## Minting

A flat fee rate is taken from the minted ibAsset amount.

Fee denomination: ibAsset

| Distributed To  | Fee Rate |
| --------------- | -------- |
| LPs             | 0.25%    |
| ibAsset Stakers | 0.25%    |
| Protocol        | 0.5%     |

## Burning

A flat fee rate is taken from the returned reserve asset amount.

Fee denomination: ibAsset

| Distributed To  | Fee Rate |
| --------------- | -------- |
| LPs             | 0.25%    |
| ibAsset Stakers | 0.25%    |
| Protocol        | 0.5%     |

## Adding Liquidity

A flat fee rate is taken from the added reserve asset amount.

Fee denomination: reserve asset

| Distributed To  | Fee Rate |
| --------------- | -------- |
| LPs             | 0.25%    |
| ibAsset Stakers | 0.25%    |
| Protocol        | 0.5%     |

## Removing Liquidity

A flat fee rate is taken from the removed reserve asset amount. Additionally if the LP is given ibAssets from their credit, a flat fee rate is also applied to this amount.

Fee denomination: reserve asset / ibAsset

| Distributed To  | Fee Rate |
| --------------- | -------- |
| LPs             | 0.25%    |
| ibAsset Stakers | 0.25%    |
| Protocol        | 0.5%     |


# Deployed Contracts

The smart contracts that constitute the inverse bonding curve implementation are deployed on the Ethereum blockchain, and can be found on the below networks:

## Networks

| Classification | Name             | Chain ID |
| -------------- | ---------------- | -------- |
| Mainnet        | Ethereum Mainnet | 1        |

## Contract Addresses

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

#### Core IBC Contracts

| Name        | Address                                      |
| ----------- | -------------------------------------------- |
| IBC Factory | `0x7957F57deafe60b2D0CCdEdBBED85da6f5374adB` |
| IBC Router  | `0x24a60379c53D90c6E154D7f20EDD25EDbd542b57` |
| IBC Admin   | `0xE42F7aeA4788CF7198149e8E5f2a557Af475C97d` |

#### ibETH-Related Contracts

| Name                              | Address                                      |
| --------------------------------- | -------------------------------------------- |
| ibETH InverseBondingCurve (Proxy) | `0x5594B3D6EbeAbbc13aFC39f569961521e9425262` |
| ibETH (ERC20)                     | `0xE73EE64adB39a443A251c910e4e3B56f7a4130DC` |
| {% endtab %}                      |                                              |
| {% endtabs %}                     |                                              |

## Admin Controls

IBCs are a novel mechanism that hasn't existed anywhere before. All novel mechanisms contain the risk of unexpected / unwanted logic executions. Although the IBC implementation has been audited, certain admin controls are added to mitigate the possibility of such risks:

* **Pausability**: the admin can pause the implementation, disallowing further interactions.
* **Upgradability**: the admin can upgrade the implementation code.

These admin controls are temporary and are planned to be removed as the implementation stabilizes.


# Inverse Bonding Curve

The Inverse Bonding Curve contract is responsible for handling mints and burns of ibAssets. The contract stores the balance of the relevant reserve assets, used for the mints and burns.

A Inverse Bonding Curve contract is deployed per ibAsset type. New Inverse Bonding Curve contracts are deployed through the [IBC Factory](/smart-contracts/ibc-factory) contract.

## Events

### `CurveInitialized`

Emitted at inverse bonding curve initialization.

```solidity
event CurveInitialized(
    address indexed from,
    address indexed reserveTokenAddress
    uint256 reserve,
    uint256 supply,
    uint256 initialPrice,
    uint256 parameterInvariant
);
```

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

| Parameter             | Type    | Description                       |
| --------------------- | ------- | --------------------------------- |
| from\*                | address | Address of initializer            |
| reserveTokenAddress\* | address | Contract address of reserve asset |
| reserve               | uint256 | Reserve value at initialization   |
| supply                | uint256 | Supply value at initialization    |
| initialPrice          | uint256 | ibAsset price at initialization   |
| parameterInvariant    | uint256 | Curve invariant at initialization |

\* = indexable
{% endtab %}
{% endtabs %}

### `LiquidityAdded`

Emitted when new liquidity has been added to the inverse bonding curve.

```solidity
event LiquidityAdded(
    address indexed from, 
    address indexed recipient, 
    uint256 amountIn, 
    uint256 amountOut, 
    uint256 newParameterInvariant
); 
```

{% tabs %}
{% tab title="First Tab" %}

| Parameter             | Type    | Description                            |
| --------------------- | ------- | -------------------------------------- |
| from\*                | address | Address of LP                          |
| recipient\*           | address | Address that received minted LP tokens |
| amountIn              | uint256 | Amount of reserve assets added         |
| amountOut             | uint256 | Amount of LP tokens minted             |
| newParameterInvariant | uint256 | Curve invariant after LP addition      |

\* = indexable
{% endtab %}
{% endtabs %}

### `LiquidityRemoved`

Emitted when liquidity has been removed from the inverse bonding curve.

```solidity
event LiquidityRemoved(
    address indexed from, 
    address indexed recipient, 
    uint256 amountIn, 
    uint256 reserveAmountOut, 
    uint256 inverseTokenCredit, 
    uint256 inverseTokenBurned, 
    uint256 newParameterInvariant
); 
```

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

| Parameter             | Type    | Description                            |
| --------------------- | ------- | -------------------------------------- |
| from\*                | address | Address of LP                          |
| recipient\*           | address | Address that received removed reserves |
| amountIn              | uint256 | Amount of LP tokens burnt              |
| reserveAmountOut      | uint256 | Amount of reserve assets withdrawn     |
| inverseTokenCredit    | uint256 | ibAsset credit of LP prior to removal  |
| inverseTokenBurned    | uint256 | Amount of ibAssets burnt               |
| newParameterInvariant | uint256 | Curve invariant after LP removal       |

\* = indexable
{% endtab %}
{% endtabs %}

### `TokenStaked`

Emitted when ibAssets are staked.

```solidity
event TokenStaked(
    address indexed from, 
    address indexed recipient, 
    uint256 amount
); 
```

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

| Parameter   | Type    | Description                  |
| ----------- | ------- | ---------------------------- |
| from\*      | address | Address of staker            |
| recipient\* | address | Address to stake ibAssets to |
| amount      | uint256 | Stake amount                 |

\* = indexable
{% endtab %}
{% endtabs %}

### `TokenUnstaked`

Emitted when ibAssets are unstaked.

```solidity
event TokenUnstaked(
    address indexed from, 
    address indexed recipient, 
    uint256 amount
); 
```

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

| Parameter   | Type    | Description                          |
| ----------- | ------- | ------------------------------------ |
| from\*      | address | Address of unstaker                  |
| recipient\* | address | Address to receive unstaked ibAssets |
| amount      | uint256 | Unstake amount                       |

\* = indexable
{% endtab %}
{% endtabs %}

### `TokenBought`

Emitted when ibAssets are bought / minted.

```solidity
event TokenBought(
    address indexed from, 
    address indexed recipient, 
    uint256 amountIn, 
    uint256 amountOut
); 
```

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

| Parameter   | Type    | Description                      |
| ----------- | ------- | -------------------------------- |
| from\*      | address | Address of buyer / minter        |
| recipient\* | address | Receiver of minted ibAssets      |
| amountIn    | uint256 | Reserve asset amount used in buy |
| amountOut   | uint256 | ibAsset amount minted from buy   |

\* = indexable
{% endtab %}
{% endtabs %}

### `TokenSold`

Emitted when ibAssets are sold / burnt.

```solidity
event TokenSold(
    address indexed from, 
    address indexed recipient, 
    uint256 amountIn, 
    uint256 amountOut
); 
```

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

| Parameter   | Type    | Description                           |
| ----------- | ------- | ------------------------------------- |
| from\*      | address | Address of seller / burner            |
| recipient\* | address | Receiver of returned reserve assets   |
| amountIn    | uint256 | ibAsset amount burnt in sell          |
| amountOut   | uint256 | Reserve asset amount returned in sell |

\* = indexable
{% endtab %}
{% endtabs %}

### `RewardClaimed`

Emitted when accrued LP and ibAsset staking rewards are claimed.

```solidity
event RewardClaimed(
    address indexed from, 
    address indexed recipient, 
    uint256 inverseTokenAmount, 
    uint256 reserveAmount
); 
```

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

| Parameter          | Type    | Description                         |
| ------------------ | ------- | ----------------------------------- |
| from\*             | address | Address of reward claimer           |
| recipient\*        | address | Address receiving claimed rewards   |
| inverseTokenAmount | uint256 | Amount of rewards in ibAssets       |
| reserveAmount      | uint256 | Amount of rewards in reserve assets |

\* = indexable
{% endtab %}
{% endtabs %}

## State-Changing Functions

### `addLiquidity`

Adds liquidity reserves to the inverse bonding curve.

```solidity
function addLiquidity(
    address recipient, 
    uint256 reserveIn, 
    uint256[2] memory priceLimits
) external whenNotPaused 
```

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

| Parameter     | Type        | Description                                                                                                          |
| ------------- | ----------- | -------------------------------------------------------------------------------------------------------------------- |
| recipient     | address     | Address to receive LP tokens                                                                                         |
| reserveIn     | uint256     | Amount of reserve assets provided for liquidity add                                                                  |
| priceLimits   | uint256\[2] | Minimum and maximum ibAsset prices to conduct LP - reverts if ibAsset price is lower or higher than specified values |
| {% endtab %}  |             |                                                                                                                      |
| {% endtabs %} |             |                                                                                                                      |

### `removeLiquidity`

Removes liquidity reserves from the inverse bonding curve.

```solidity
function removeLiquidity(
    address recipient, 
    uint256 inverseTokenIn, 
    uint256[2] memory priceLimits
) external whenNotPaused 
```

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

| Parameter      | Type        | Description                                                                                                          |
| -------------- | ----------- | -------------------------------------------------------------------------------------------------------------------- |
| recipient      | address     | Address to receive removed reserve assets                                                                            |
| inverseTokenIn | uint256     | Amount of additional ibAssets posted for LP removal                                                                  |
| priceLimits    | uint256\[2] | Minimum and maximum ibAsset prices to conduct LP - reverts if ibAsset price is lower or higher than specified values |
| {% endtab %}   |             |                                                                                                                      |
| {% endtabs %}  |             |                                                                                                                      |

### `buyTokens`

Buys / mints new ibAsset tokens with provided reserve assets.

```solidity
function buyTokens(
    address recipient, 
    uint256 reserveIn, 
    uint256 exactAmountOut, 
    uint256[2] memory priceLimits, 
    uint256[2] memory reserveLimits
) external whenNotPaused 
```

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

| Parameter      | Type        | Description                                                                                                                          |
| -------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| recipient      | address     | Address to receive minted ibAssets                                                                                                   |
| reserveIn      | uint256     | Amount of reserve assets provided for minting                                                                                        |
| exactAmountOut | uint256     | Exact amount ibAssets to be minted                                                                                                   |
| priceLimits    | uint256\[2] | Minimum and maximum effective ibAsset buy prices to conduct buy - reverts if buy price is lower or higher than specified values      |
| reserveLimits  | uint256\[2] | Minimum and maximum curve reserve amounts to conduct buy - reverts if the curve's reserves are lower or higher than specified values |
| {% endtab %}   |             |                                                                                                                                      |
| {% endtabs %}  |             |                                                                                                                                      |

### `sellTokens`

Sells / burns ibAsset tokens to receive reserve assets.

```solidity
function sellTokens(
    address recipient, 
    uint256 inverseTokenIn, 
    uint256[2] memory priceLimits, 
    uint256[2] memory reserveLimits
) external whenNotPaused 
```

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

| Parameter      | Type        | Description                                                                                                                           |
| -------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| recipient      | address     | Address to receive reserve assets                                                                                                     |
| inverseTokenIn | uint256     | Amount of ibAssets to burn                                                                                                            |
| priceLimits    | uint256\[2] | Minimum and maximum effective ibAsset sell prices to conduct sell - reverts if sell price is lower or higher than specified values    |
| reserveLimits  | uint256\[2] | Minimum and maximum curve reserve amounts to conduct sell - reverts if the curve's reserves are lower or higher than specified values |
| {% endtab %}   |             |                                                                                                                                       |
| {% endtabs %}  |             |                                                                                                                                       |

### `stake`

Stakes specified amount of ibAssets.

```solidity
function stake(address recipient, uint256 amount) external whenNotPaused 
```

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

| Parameter     | Type    | Description                  |
| ------------- | ------- | ---------------------------- |
| recipient     | address | Address to stake ibAssets to |
| amount        | uint256 | Amount of ibAssets to stake  |
| {% endtab %}  |         |                              |
| {% endtabs %} |         |                              |

### `unstake`

Unstakes specified amount of ibAssets.

```solidity
function unstake(address recipient, uint256 amount) external whenNotPaused 
```

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

| Parameter     | Type    | Description                          |
| ------------- | ------- | ------------------------------------ |
| recipient     | uint256 | Address to receive unstaked ibAssets |
| amount        | uint256 | Amount of ibAssets to unstake        |
| {% endtab %}  |         |                                      |
| {% endtabs %} |         |                                      |

### `claimReward`

Claims accrued LP and staking rewards.

```solidity
function claimReward(address recipient) external whenNotPaused 
```

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

| Parameter     | Type    | Description                        |
| ------------- | ------- | ---------------------------------- |
| recipient     | address | Address to receive accrued rewards |
| {% endtab %}  |         |                                    |
| {% endtabs %} |         |                                    |

## Read-Only Functions

### `liquidityPositionOf`

Gets the LP position data for the specified address.

```solidity
function liquidityPositionOf(address account) external view returns (
    uint256 lpTokenAmount, 
    uint256 inverseTokenCredit
)
```

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

| Parameter    | Type    | Description                                         |
| ------------ | ------- | --------------------------------------------------- |
| account      | address | Address of account to fetch LP position information |
| {% endtab %} |         |                                                     |

{% tab title="Return Values" %}

| Parameter          | Type    | Description                               |
| ------------------ | ------- | ----------------------------------------- |
| lpTokenAmount      | uint256 | Amount of LP Tokens owned by account      |
| inverseTokenCredit | uint256 | Amount of ibAsset credit owned by account |
| {% endtab %}       |         |                                           |
| {% endtabs %}      |         |                                           |

### `stakingBalanceOf`

Gets the staked ibAsset amount for the specified address.

```solidity
function stakingBalanceOf(address account) external view returns (uint256) 
```

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

| Parameter    | Type    | Description                                      |
| ------------ | ------- | ------------------------------------------------ |
| account      | address | Address of holder to get ibAsset staking balance |
| {% endtab %} |         |                                                  |

{% tab title="Return Values" %}

| Type          | Description               |
| ------------- | ------------------------- |
| uint256       | Amount of staked ibAssets |
| {% endtab %}  |                           |
| {% endtabs %} |                           |

### `inverseTokenAddress`

Gets the contract address of the relevant ibAsset token contract.

```solidity
function inverseTokenAddress() external view returns (address)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                                             |
| ------------- | ------------------------------------------------------- |
| address       | Contract address of the relevant ibAsset token contract |
| {% endtab %}  |                                                         |
| {% endtabs %} |                                                         |

### `reserveTokenAddress`

Gets the contract address of the relevant reserve asset token contract.

```solidity
function reserveTokenAddress() external view returns (address)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                                                   |
| ------------- | ------------------------------------------------------------- |
| address       | Contract address of the relevant reserve asset token contract |
| {% endtab %}  |                                                               |
| {% endtabs %} |                                                               |

### `curveParameters`

Gets the parameter values of the inverse bonding curve.

```solidity
function curveParameters() external view returns (CurveParameter memory parameters) 
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Parameter  | Type           | Description                      |
| ---------- | -------------- | -------------------------------- |
| parameters | CurveParameter | Inverse bonding curve parameters |

#### CurveParameters

```solidity
struct CurveParameter {
    uint256 reserve;
    uint256 supply;
    uint256 lpSupply; 
    uint256 price;
    uint256 parameterInvariant;
}
```

| Parameter          | Type    | Description                       |
| ------------------ | ------- | --------------------------------- |
| reserve            | uint256 | Liquidity reserve of curve        |
| supply             | uint256 | ibAsset minted supply             |
| lpSupply           | uint256 | Current total supply of LP tokens |
| price              | uint256 | Current spot price of ibAsset     |
| parameterInvariant | uint256 | Current curve invariant of curve  |
| {% endtab %}       |         |                                   |
| {% endtabs %}      |         |                                   |

### `rewardOf`

Gets the accrued reward amounts for the specified address.

```solidity
function rewardOf(address recipient) external view returns (
    uint256 inverseTokenForLp, 
    uint256 inverseTokenForStaking, 
    uint256 reserveForLp, 
    uint256 reserveForStaking, 
)
```

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

| Parameter    | Type    | Description                      |
| ------------ | ------- | -------------------------------- |
| recipient    | address | Address to check accrued rewards |
| {% endtab %} |         |                                  |

{% tab title="Return Values" %}

| Parameter              | Type    | Description                                       |
| ---------------------- | ------- | ------------------------------------------------- |
| inverseTokenForLp      | uint256 | Accrued ibAsset rewards for LP position           |
| inverseTokenForStaking | uint256 | Accrued ibAsset rewards for staked ibAssets       |
| reserveForLp           | uint256 | Accrued reserve asset rewards for LP position     |
| reserveForStaking      | uint256 | Accrued reserve asset rewards for staked ibAssets |
| {% endtab %}           |         |                                                   |
| {% endtabs %}          |         |                                                   |

### `rewardOfProtocol`

Gets the accrued reward amounts of the protocol creator.

```solidity
function rewardOfProtocol() external view returns (
    uint256 inverseTokenReward, 
    uint256 reserveReward
) 
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Parameter          | Type    | Description                                       |
| ------------------ | ------- | ------------------------------------------------- |
| inverseTokenReward | uint256 | Accrued ibAsset rewards to protocol creator       |
| reserveReward      | uint256 | Accrued reserve asset rewards to protocol creator |
| {% endtab %}       |         |                                                   |
| {% endtabs %}      |         |                                                   |

### `totalStaked`

Gets the total staked ibAsset amount.

```solidity
function totalStaked() external view returns (uint256)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                     |
| ------------- | ------------------------------- |
| uint256       | Total amount of staked ibAssets |
| {% endtab %}  |                                 |
| {% endtabs %} |                                 |

### `rewardEMAPerSecond`

Gets the EMA-adjusted per-token per-second reward amounts for the specified reward type.

```solidity
function blockRewardEMA(RewardType rewardType) external view returns (
    uint256 inverseTokenReward, 
    uint256 reserveReward
)
```

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

| Parameter  | Type       | Description                |
| ---------- | ---------- | -------------------------- |
| rewardType | RewardType | Type of rewards to specify |

#### rewardType

```solidity
enum RewardType {
    LP, // 0
    STAKING, // 1
    PROTOCOL // 2
}
```

| Parameter    | Description                             |
| ------------ | --------------------------------------- |
| LP           | Reward type is LP rewards               |
| STAKING      | Reward type is ibAsset staking rewards  |
| PROTOCOL     | Reward type is protocol creator rewards |
| {% endtab %} |                                         |

{% tab title="Return Values" %}

| Parameter          | Type    | Description                                                                                |
| ------------------ | ------- | ------------------------------------------------------------------------------------------ |
| inverseTokenReward | uint256 | Per-second amount of ibAsset rewards accrued per-token for the specified reward type       |
| reserveReward      | uint256 | Per-second amount of reserve asset rewards accrued per-token for the specified reward type |
| {% endtab %}       |         |                                                                                            |
| {% endtabs %}      |         |                                                                                            |

### `rewardState`

Gets the total reward information for the entire protocol.

```solidity
function rewardState() external view returns (
    uint256[MAX_FEE_TYPE_COUNT][MAX_FEE_STATE_COUNT] memory totalReward,
    uint256[MAX_FEE_TYPE_COUNT][MAX_FEE_STATE_COUNT] memory totalPendingReward
)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Parameter          | Type                                                     | Description                                        |
| ------------------ | -------------------------------------------------------- | -------------------------------------------------- |
| totalReward        | uint256\[MAX\_FEE\_TYPE\_COUNT]\[MAX\_FEE\_STATE\_COUNT] | Total reward amount accrued                        |
| totalPendingReward | uint256\[MAX\_FEE\_TYPE\_COUNT]\[MAX\_FEE\_STATE\_COUNT] | Total reward amount accrued, but yet to be claimed |
| {% endtab %}       |                                                          |                                                    |
| {% endtabs %}      |                                                          |                                                    |


# IBC Factory

The IBC Factory contract acts as the deployer for new Inverse Bonding Curve contracts. Users can make a request to this contract to make new deployments of IBCs.

The IBC Factory maintains the full list of all deployed IBCs (`curves`), made queryable by users.

## Events

### `CurveCreated`

Emitted at IBC contract creation for the specified reserve asset.

```solidity
event CurveCreated(
    address curveContract, 
    address tokenContract, 
    address proxyContract, 
    uint256 initialReserve
);
```

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

| Parameter      | Type    | Description                                |
| -------------- | ------- | ------------------------------------------ |
| curveContract  | address | Contract address of IBC implementation     |
| tokenContract  | address | Contract address of ibAsset token contract |
| proxyContract  | address | Contract address of IBC proxy contract     |
| initialReserve | uint256 | Initial reserve amount of curve            |
| {% endtab %}   |         |                                            |
| {% endtabs %}  |         |                                            |

## State-Changing Functions

### `CreateCurve`

Deploys a new IBC implementation, its proxy contract, and the relevant ibAsset token contract for the specified reserve asset.

```solidity
function createCurve(
    uint256 initialReserves, 
    address reserveTokenAddress, 
    address recipient
) external payable
```

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

| Parameter           | Type    | Description                                          |
| ------------------- | ------- | ---------------------------------------------------- |
| initialReserves     | uint256 | Amount of initial reserves to supply to curve        |
| reserveTokenAddress | address | Contract address of the reserve asset token contract |
| recipient           | address | Address to receive initial LP position               |
| {% endtab %}        |         |                                                      |
| {% endtabs %}       |         |                                                      |

## Read-Only Functions

### `getCurve`

Gets the contract address of the specified reserve asset's IBC implementation.

```solidity
function getCurve(address reserveToken) public view returns (address)
```

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

| Parameter    | Type    | Description                       |
| ------------ | ------- | --------------------------------- |
| reserveToken | address | Contract address of reserve asset |
| {% endtab %} |         |                                   |

{% tab title="Return Values" %}

| Type          | Description                                                         |
| ------------- | ------------------------------------------------------------------- |
| address       | Contract address of the specified reserve asset's IBC implemenation |
| {% endtab %}  |                                                                     |
| {% endtabs %} |                                                                     |

### `allCurvesLength`

Gets the total number of IBC curves created through the IBC factory so far.

```solidity
function allCurvesLength() public view returns (uint256)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                                   |
| ------------- | --------------------------------------------- |
| uint256       | Total number of IBC curves created by Factory |
| {% endtab %}  |                                               |
| {% endtabs %} |                                               |


# IBC Router

The IBC Router contract is the point of interaction for most users of IBCs. This contract routes IBC interactions to contracts of the relevant reserve asset and ibAsset.

## State-Changing Functions

### `Execute`

```solidity
function execute(
    address recipient, 
    address curve, 
    bool useNative, 
    CommandType command, 
    bytes memory data
) external payable
```

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

| Parameter | Type        | Description                                                   |
| --------- | ----------- | ------------------------------------------------------------- |
| recipient | address     | Address to receive resulting tokens                           |
| curve     | address     | Contract address of the curve contract to be interacting with |
| useNative | bool        | Whether the interaction uses native ETH                       |
| command   | CommandType | Command type                                                  |
| data      | bytes       | Calldata of function call                                     |

#### CommandType

```solidity
enum CommandType {
    BUY_TOKEN,
    SELL_TOKEN,
    ADD_LIQUIDITY,
    REMOVE_LIQUIDITY,
    CLAIM_REWARD, 
    STAKE, 
    UNSTAKE
}
```

| Parameter         | Description                                      |
| ----------------- | ------------------------------------------------ |
| BUY\_TOKEN        | Command is to mint ibAssets                      |
| SELL\_TOKEN       | Command is to burn ibAssets                      |
| ADD\_LIQUIDITY    | Command is to add liquidity to the IBC           |
| REMOVE\_LIQUIDITY | Command is to remove liquidity from the IBC      |
| CLAIM\_REWARD     | Command is to claim LP & ibAsset staking rewards |
| STAKE             | Command is to stake ibAssets                     |
| UNSTAKE           | Command is to unstake ibAssets                   |
| {% endtab %}      |                                                  |
| {% endtabs %}     |                                                  |


# IBC Admin

The IBC Admin contract is where protocol configuration changes are made. Fee configuration updates as well as contract upgrades and pauses are managed through this contract.

## Events

### `FeeConfigChanged`

Emitted when fee configurations have been changed by the contract owner.

```solidity
event FeeConfigChanged(
    ActionType actionType, 
    uint256 lpFee, 
    uint256 stakingFee, 
    uint256 protocolFee
); 
```

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

| Parameter   | Type       | Description                            |
| ----------- | ---------- | -------------------------------------- |
| actionType  | ActionType | Type of user action                    |
| lpFee       | uint256    | Rate of fees given to LPs              |
| stakingFee  | uint256    | Rate of fees given to ibAsset stakers  |
| protocolFee | uint256    | Rate of fees given to protocol creator |

#### ActionType

```solidity
enum ActionType {
    BUY_TOKEN,
    SELL_TOKEN,
    ADD_LIQUIDITY,
    REMOVE_LIQUIDITY
}
```

| Parameter         | Description                                      |
| ----------------- | ------------------------------------------------ |
| BUY\_TOKEN        | Action is the minting of ibAssets                |
| SELL\_TOKEN       | Action is the burning of ibAssets                |
| ADD\_LIQUIDITY    | Action is the adding of liquidity to the IBC     |
| REMOVE\_LIQUIDITY | Action is the removing of liquidity from the IBC |
| {% endtab %}      |                                                  |
| {% endtabs %}     |                                                  |

### `FeeOwnerChanged`

Emitted when the protocol creator fee receival address is changed.

```solidity
event FeeOwnerChanged(address feeOwner); 
```

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

| Parameter     | Type    | Description                                 |
| ------------- | ------- | ------------------------------------------- |
| feeOwner      | address | New address receiving protocol creator fees |
| {% endtab %}  |         |                                             |
| {% endtabs %} |         |                                             |

### `RouterChanged`

Emitted when the IBC Router contract is changed.

```solidity
event RouterChanged(address router); 
```

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

| Parameter     | Type    | Description                        |
| ------------- | ------- | ---------------------------------- |
| router        | address | Address of new IBC Router contract |
| {% endtab %}  |         |                                    |
| {% endtabs %} |         |                                    |

### `CurveImplementationChanged`

Emitted when the IBC contract implementation is changed.

```solidity
event CurveImplementationChanged(address implementation); 
```

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

| Parameter      | Type    | Description                                |
| -------------- | ------- | ------------------------------------------ |
| implementation | address | Address of new IBC contract implementation |
| {% endtab %}   |         |                                            |
| {% endtabs %}  |         |                                            |

## Read-Only Functions

### `feeConfig`

Gets the fee configurations of inverse bonding curve interactions for the specified action type.

```solidity
function feeConfig(ActionType actionType) external view returns (
    uint256 lpFee, 
    uint256 stakingFee, 
    uint256 protocolFee
)
```

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

| Parameter  | Type       | Description         |
| ---------- | ---------- | ------------------- |
| actionType | ActionType | Type of user action |

#### ActionType

```solidity
enum ActionType {
    BUY_TOKEN,
    SELL_TOKEN,
    ADD_LIQUIDITY,
    REMOVE_LIQUIDITY
}
```

| Parameter         | Description                                      |
| ----------------- | ------------------------------------------------ |
| BUY\_TOKEN        | Action is the minting of ibAssets                |
| SELL\_TOKEN       | Action is the burning of ibAssets                |
| ADD\_LIQUIDITY    | Action is the adding of liquidity to the IBC     |
| REMOVE\_LIQUIDITY | Action is the removing of liquidity from the IBC |
| {% endtab %}      |                                                  |

{% tab title="Return Values" %}

| Parameter     | Type    | Description                                             |
| ------------- | ------- | ------------------------------------------------------- |
| lpFee         | uint256 | Fee rate given to LPs for user action type              |
| stakingFee    | uint256 | Fee rate given to ibAsset stakers for user action type  |
| protocolFee   | uint256 | Fee rate given to protocol creator for user action type |
| {% endtab %}  |         |                                                         |
| {% endtabs %} |         |                                                         |

### `factoryAddress`

Gets the contract address of the IBC Factory contract.

```solidity
function factoryAddress() external view returns (address)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                                  |
| ------------- | -------------------------------------------- |
| address       | Contract address of the IBC Factory contract |
| {% endtab %}  |                                              |
| {% endtabs %} |                                              |

### `feeOwner`

Gets the address receiving protocol creator fees.

```solidity
function feeOwner() external view returns (address)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                             |
| ------------- | --------------------------------------- |
| address       | Address receiving protocol creator fees |
| {% endtab %}  |                                         |
| {% endtabs %} |                                         |

### `weth`

Gets the contract address of the WETH token contract.

```solidity
function weth() external view returns (address)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                                 |
| ------------- | ------------------------------------------- |
| address       | Contract address of the WETH token contract |
| {% endtab %}  |                                             |
| {% endtabs %} |                                             |

### `router`

Gets the contract address of the IBC Router contract.

```solidity
function router() external view returns (address)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                                 |
| ------------- | ------------------------------------------- |
| address       | Contract address of the IBC Router contract |
| {% endtab %}  |                                             |
| {% endtabs %} |                                             |

### `curveImplementation`

Gets the contract address of the IBC implementation contract.

```solidity
function curveImplementation() external view returns (address)
```

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

| Parameter    | Type | Description |
| ------------ | ---- | ----------- |
|              |      |             |
| {% endtab %} |      |             |

{% tab title="Return Values" %}

| Type          | Description                       |
| ------------- | --------------------------------- |
| address       | Address of the IBC implementation |
| {% endtab %}  |                                   |
| {% endtabs %} |                                   |


