# Developer Docs

Bond Protocol launched on October 3rd, 2022 with a mission to empower sustainable treasury growth for crypto projects. Currently, our product suite consists of two flagship products — [Permissionless Bonds](https://docs.bondprotocol.finance/products/permissionless-bond-marketplace) (live on Ethereum, Arbitrum, and Optimism) and [Options Liquidity Mining](https://docs.bondprotocol.finance/products/options-liquidity-mining) (live on Ethereum and Arbitrum)**.**

There are two primary inefficiencies within the crypto industry that we are solving:

* Projects that aim to diversify their treasury, acquire new assets, and extend their runway have limited options and are forced to operate on open markets. This is troublesome due to slippage and price impact, especially when it involves selling native token(s).&#x20;
* Projects set aside a large portion of their token supply to incentivize participation, and current distribution mechanisms lead to significant sell pressure, goal misalignment, and a decreased treasury size.

<figure><img src="/files/kzdR7yDMUXG4jFUf1kf4" alt=""><figcaption><p>Architecture Overview</p></figcaption></figure>


# Bond System

Overview of Bond Protocol's smart contract architecture

Bond Protocol is a system to create OTC markets for any ERC20 token pair with optional vesting of the payout. The markets do not require maintenance and will manage bond prices per the methodology defined in the specific auctioneer contract. Bond issuers create markets that pay out a Payout Token in exchange for deposited Quote Tokens. If payouts are instant, users can purchase Payout Tokens with Quote Tokens at the current market price and receive the Payout tokens immediately on purchase. Otherwise, they receive Bond Tokens to represent their position while their bond vests. Once the Bond Tokens vest, they can redeem it for the Quote Tokens. The type of Bond Token received depends on the vesting type of the market: Fixed Expiry (all purchases vest at a set time in the future) -> ERC20, Fixed Term (each purchaser waits a specific amount of time from their purchase) -> ERC1155.

Bond Protocol is comprised of 3 main types of contracts:

* [Auctioneers](/smart-contracts/bond-system/auctioneer) - Store market data, implement pricing logic, and allow creators to create/close markets
* [Tellers](/smart-contracts/bond-system/teller) - Handle user purchases and issuing/redeeming of bond tokens
* [Aggregator](/smart-contracts/bond-system/aggregator) - Maintains unique count of markets across system and provides convenient view functions for querying data across multiple Auctioneers or Tellers

<figure><img src="/files/kzdR7yDMUXG4jFUf1kf4" alt=""><figcaption><p>Architecture Diagram</p></figcaption></figure>


# Auctioneer

The Auctioneer contract allows users to create and manage bond markets. All bond pricing logic and market data is stored in the Auctioneer.  An Auctioneer is dependent on a Teller to serve external users and an Aggregator to register new markets.

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


# Auctioneer Interfaces

The [Auctioneer Interface](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/interfaces/IBondAuctioneer.sol) defines the external functions that all Auctioneer contracts must implement. Specifically, each Auctioneer should have the following functions:

```solidity
createMarket
closeMarket
purchaseBond // Only Teller
getMarketInfoForPurchase
marketPrice
payoutFor
maxAmountAccepted
isInstantSwap
isLive
getTeller
getAggregator
currentCapacity
```

#### Sequential Dutch Auction (SDA) Interface

The [SDA Interface](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/interfaces/IBondSDA.sol) extends the Auctioneer interface and adds two functions specific to Olympus' implementation:

```solidity
currentDebt
currentControlVariable
```

Additionally, it defines five structs that are used in the SDA implementation:

```solidity
MarketParams
BondMarket
BondTerms
BondMetaData
Adjustment
```

#### Fixed Price Auctioneer (FPA) Interface

The FPA Interface extends the Auctioneer interface and adds a couple functions specific to global FPA parameters. These functions are in lieu of the existing `setDefaults` and `setIntervals` functions, which, in hindsight, were too specific to the SDA case to be in the general Auctioneer Interface.

```
setMinMarketDuration
setMinDepositInterval
```

Additionally, it defines three structs specific to the FPA implementation:

```
MarketParams
BondMarket
BondTerms
```


# Sequential Dutch Auctioneer (SDA)

The [Base SDA contract](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/bases/BondBaseSDA.sol) is an implementation of the Auctioneer Interface that uses a Sequential Dutch Auction pricing system to buy a target amount of quote tokens or sell a target amount of base tokens over the duration of a market.&#x20;

The contract is abstract since it leaves final implementation of the `createMarket` function to a contract that inherits it.

## Data Structures (Structs)

### MarketParams

Parameters to create a new SDA market. Encoded as bytes and provided as input to `createMarket`.

```solidity
struct MarketParams {
    ERC20 payoutToken;
    ERC20 quoteToken;
    address callbackAddr;
    bool capacityInQuote;
    uint256 capacity;
    uint256 formattedInitialPrice;
    uint256 formattedMinimumPrice;
    uint32 debtBuffer;
    uint48 vesting;
    uint48 conclusion;
    uint32 depositInterval;
    int8 scaleAdjustment;
}
```

<table><thead><tr><th>Field</th><th width="165">Type</th><th>Description</th></tr></thead><tbody><tr><td>payoutToken</td><td>ERC20 (address)</td><td>Payout Token (token paid out by market and provided by creator)</td></tr><tr><td>quoteToken</td><td>ERC20 (address)</td><td>Quote Token (token to be received by the market and provided by purchaser)</td></tr><tr><td>callbackAddr</td><td>address</td><td>Callback contract address, should conform to <code>IBondCallback</code>. If 0x00, tokens will be transferred from market owner. Using a callback requires whitelisting by the protocol</td></tr><tr><td>capacityInQuote</td><td>bool</td><td>Is Capacity in Quote Token?</td></tr><tr><td>capacity</td><td>uint256</td><td>Capacity (amount in quote token decimals or amount in payout token decimals). Set <code>capacityInQuote</code> flag appropriately</td></tr><tr><td>formattedInitialPrice</td><td>uint256</td><td>Initial price of the market as a ratio of quote tokens per payout token, see note below on formatting</td></tr><tr><td>formattedMinimumPrice</td><td>uint256</td><td>Minimum price of the market as a ratio of quote tokens per payout token, see note below on formatting</td></tr><tr><td>debtBuffer</td><td>uint32</td><td>Debt buffer. Percent with 3 decimals. Percentage over the initial debt to allow the market to accumulate at anyone time. Works as a circuit breaker for the market in case external conditions incentivize massive buying (e.g. stablecoin depeg). Minimum is the greater of 10% or initial max payout as a percentage of capacity</td></tr><tr><td>vesting</td><td>uint48</td><td>Is fixed term ? Vesting length (seconds) : Vesting expiry (timestamp). A 'vesting' param longer than 50 years is considered a timestamp for fixed expiry</td></tr><tr><td>conclusion</td><td>uint48</td><td>Timestamp that the market will conclude on. Must be at least 1 day (86400 seconds) after creation</td></tr><tr><td>depositInterval</td><td>uint32</td><td>Target deposit interval for purchases (in seconds). Determines the <code>maxPayout</code> of the market. Minimum is 1 hour (3600 seconds)</td></tr><tr><td>scaleAdjustment</td><td>int8</td><td>Market scaling adjustment factor, ranges from -24 to +24. See note below on how to calculate</td></tr></tbody></table>

#### Calculating Formatted Price and Scale Adjustment

In order to support a broad range of tokens, with different decimal configurations and prices, we calculate an optimal scaling factor for each market. Specifically, the scale adjustment allows the SDA to support tokens with 6 to 18 configured decimals and with prices that differ by up to 24 decimal places (if the tokens have the configured decimals, less if not). To implement this, the market creator must provide a scale adjustment factor and format the price correctly.

First, you need the price of each token in a common unit, e.g. dollars or ether.

Then, if $$\Phi\_p$$ is the price of the payout token and $$\Phi\_q$$  is the price of quote token in the common unit, it can expressed in base 10 (or scientific) notation as:

$$
\Phi\_p = \phi\_p \times 10^{d\_{\phi p}}
$$

$$
\Phi\_q = \phi\_q \times 10^{d\_{\phi q}}
$$

where:

* $$\phi\_p$$ is the coefficient of the payout token price and ​$$d\_{\phi p}$$​ is the number of price decimals for the payout token (aka the significand of the price).
* $$\phi\_q$$​ is the coefficient of the quote token price and $$d\_{\phi q}$$​ is the number of price decimals for the quote token.

Example: If the price of WETH is $1,500, then we would deconstruct it as $$1.5 \times 10^3$$​. Therefore $$\phi = 1.5$$ and $$d\_{\phi} = 3$$.

Now, using the price values and the configured number of decimals for each token, we can calculate the scale adjustment.

$$
s = d\_p - d\_q - \left\lfloor\frac{d\_{\phi p} - d\_{\phi q}}{2}\right\rfloor
$$

where:

* $$d\_p$$ is the configured payout token decimals (e.g. WETH has 18 configured decimals)
* $$d\_q$$ is the configured quote token decimals.
* $$d\_{\phi p}$$ and $$d\_{\phi q}$$ are as defined above.

Example:&#x20;

* Let WETH be the quote token and OHM be the payout token. WETH has 18 configured decimals   and OHM has 9 configured decimals. Assume the market price of WETH is $1,500 -> $$1.5 \times 10^3$$and the market price of OHM is $10 -> $$1 \times 10^1$$.​
* Then, the scale adjustment is $$s = 9 - 18 - \left\lfloor\frac{1-3}{2}\right\rfloor = -9 + 1 = -8$$​

Once we have the scale adjustment, we can format the initial price using the variables defined above. We're starting the market at the current market price by using the token prices at the time of creation. This is optimal in most situations, but there may be circumstances where it makes sense to choose a different starting price (e.g. you want delayed activity or activity only if the price increases in the short-term).

$$
\Phi\_0 = \frac{\phi\_p}{\phi\_q} \times 10^{36 + s + d\_q - d\_p +d\_{\phi p} - d\_{\phi q}}
$$

Example: Continuing with the WETH and OHM example from above, we format the initial price as:

$$
\Phi\_0 = \frac{1}{1.5} \times 10^{36+(-8)+18-9+1-3} = 0.666.. \times 10^{35} = 0.00666.. \times 10^{37}
$$

The difference between the scale and the full decimal difference can result in the price ratio shifting some decimal places. However, we can find the appropriate price factor by considering what we expect the ratio to be from the initial prices. 10 / 1500 = 0.00666.., so we can see the proper price factor is 10^37.

The minimum formatted price can then be extrapolated from the initial price. The above initial price example can be interpreted as 0.00666.. WETH per OHM. Therefore, if you want to receive a minimum of 0.005 WETH per OHM, you would set minimum price as: $$\Phi\_{min} = 0.005 \times 10^{37}$$.

Any alternative way to confirm your minimum price is correct is to redo the same calculation as used to determine initial price, with an updated minimum price for the payout token. Using the 0.005 WETH per OHM value, that would be an OHM price of $7.5 ($1500 x 0.005 = $7.5).

### BondMarket

The BondMarket struct contains the core data about a bond market.

```solidity
struct BondMarket {
    address owner; 
    ERC20 payoutToken;
    ERC20 quoteToken; 
    address callbackAddr; 
    bool capacityInQuote; 
    uint256 capacity;
    uint256 totalDebt;
    uint256 minPrice; 
    uint256 maxPayout; 
    uint256 sold; 
    uint256 purchased; 
    uint256 scale; 
}
```

<table><thead><tr><th width="200">Field</th><th width="185">Type</th><th width="364">Description</th></tr></thead><tbody><tr><td>owner</td><td>address </td><td>Market owner. Sends payout tokens, receives quote tokens (defaults to creator)</td></tr><tr><td>payoutToken</td><td>ERC20 (address)</td><td>Payout Token (token paid out by market and provided by creator)</td></tr><tr><td>quoteToken</td><td>ERC20 (address)</td><td>Quote Token (token to be received by the market and provided by purchaser)</td></tr><tr><td>callbackAddr</td><td>address</td><td>Address to call for any operations on bond purchase. Must inherit to <code>IBondCallback</code></td></tr><tr><td>capacityInQuote</td><td>bool</td><td>Capacity limit is in payment token (true) or in payout (false, default)</td></tr><tr><td>capacity</td><td>uint256</td><td>Capacity remaining</td></tr><tr><td>totalDebt</td><td>uint256</td><td>Total payout token debt from market</td></tr><tr><td>minPrice</td><td>uint256</td><td>Minimum price (debt will stop decaying to maintain this)</td></tr><tr><td>maxPayout</td><td>uint256</td><td>Max payout tokens out in one order</td></tr><tr><td>sold</td><td>uint256</td><td>Payout tokens out</td></tr><tr><td>purchased</td><td>uint256</td><td>Quote tokens in</td></tr><tr><td>scale</td><td>uint256</td><td>Scaling factor for the market (see <a href="#marketparams">MarketParams</a> struct)</td></tr></tbody></table>

### BondTerms

```solidity
struct BondTerms {
    uint256 controlVariable; 
    uint256 maxDebt; 
    uint48 vesting; 
    uint48 conclusion; 
}
```

<table><thead><tr><th width="198">Field</th><th width="132">Type</th><th>Description</th></tr></thead><tbody><tr><td>controlVariable</td><td>uint256</td><td>Scaling variable for price</td></tr><tr><td>maxDebt</td><td>uint256</td><td>Max payout token debt accrued</td></tr><tr><td>vesting</td><td>uint48</td><td>Length of time from deposit to expiry if fixed-term, vesting timestamp if fixed-expiry</td></tr><tr><td>conclusion</td><td>uint48</td><td>Timestamp when market no longer offered</td></tr></tbody></table>

### BondMetadata

```solidity
struct BondMetadata {
    uint48 lastTune; 
    uint48 lastDecay; 
    uint32 length; 
    uint32 depositInterval; 
    uint32 tuneInterval; 
    uint32 tuneAdjustmentDelay; 
    uint32 debtDecayInterval; 
    uint256 tuneIntervalCapacity; 
    uint256 tuneBelowCapacity; 
    uint256 lastTuneDebt; 
}
```

<table><thead><tr><th width="239">Field</th><th width="123">Type</th><th>Description</th></tr></thead><tbody><tr><td>lastTune</td><td>uint48</td><td>Last timestamp when control variable was tuned</td></tr><tr><td>lastDecay</td><td>uint48</td><td>Last timestamp when market was created and debt was decayed</td></tr><tr><td>length</td><td>uint32</td><td>Time from creation to conclusion</td></tr><tr><td>depositInterval</td><td>uint32</td><td>Target frequency of deposits</td></tr><tr><td>tuneInterval</td><td>uint32</td><td>Frequency of tuning</td></tr><tr><td>tuneAdjustmentDelay</td><td>uint32</td><td>Time to implement downward tuning adjustments</td></tr><tr><td>debtDecayInterval</td><td>uint32</td><td>Interval over which debt should decay completely</td></tr><tr><td>tuneIntervalCapacity</td><td>uint256</td><td>Capacity expected to be used during a tuning interval</td></tr><tr><td>tuneBelowCapacity</td><td>uint256</td><td>Capacity that the next tuning will occur at</td></tr><tr><td>lastTuneDebt</td><td>uint256</td><td>Target debt calculated at last tuning</td></tr></tbody></table>

## Methods

### closeMarket

```solidity
function closeMarket(uint256 id_) external nonpayable
```

Disable existing bond marketMust be market owner

#### Parameters

| Name | Type    | Description           |
| ---- | ------- | --------------------- |
| id\_ | uint256 | ID of market to close |

### createMarket

```solidity
function createMarket(bytes params_) external nonpayable returns (uint256)
```

Creates a new bond market

*See specific auctioneer implementations for details on encoding the parameters.*

#### Parameters

| Name     | Type  | Description                                                             |
| -------- | ----- | ----------------------------------------------------------------------- |
| params\_ | bytes | Configuration data needed for market creation, encoded in a bytes array |

#### Returns

| Name | Type    | Description           |
| ---- | ------- | --------------------- |
| id   | uint256 | ID of new bond market |

### currentCapacity

```solidity
function currentCapacity(uint256 id_) external view returns (uint256)
```

Returns current capacity of a market

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | undefined   |

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | uint256 | undefined   |

### currentControlVariable

```solidity
function currentControlVariable(uint256 id_) external view returns (uint256)
```

Up to date control variable

*Accounts for control variable adjustment*

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type    | Description                                          |
| ---- | ------- | ---------------------------------------------------- |
| \_0  | uint256 | Control variable for market in payout token decimals |

### currentDebt

```solidity
function currentDebt(uint256 id_) external view returns (uint256)
```

Calculate debt factoring in decay

*Accounts for debt decay since last deposit*

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type    | Description                                      |
| ---- | ------- | ------------------------------------------------ |
| \_0  | uint256 | Current debt for market in payout token decimals |

### getAggregator

```solidity
function getAggregator() external view returns (contract IBondAggregator)
```

Returns the Aggregator that services the Auctioneer

#### Returns

| Name | Type                     | Description |
| ---- | ------------------------ | ----------- |
| \_0  | contract IBondAggregator | undefined   |

### getMarketInfoForPurchase

```solidity
function getMarketInfoForPurchase(uint256 id_) external view returns (address owner, address callbackAddr, contract ERC20 payoutToken, contract ERC20 quoteToken, uint48 vesting, uint256 maxPayout)
```

Provides information for the Teller to execute purchases on a Market

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

#### Returns

| Name         | Type           | Description                                                                       |
| ------------ | -------------- | --------------------------------------------------------------------------------- |
| owner        | address        | Address of the market owner (tokens transferred from this address if no callback) |
| callbackAddr | address        | Address of the callback contract to get tokens for payouts                        |
| payoutToken  | contract ERC20 | Payout Token (token paid out) for the Market                                      |
| quoteToken   | contract ERC20 | Quote Token (token received) for the Market                                       |
| vesting      | uint48         | Timestamp or duration for vesting, implementation-dependent                       |
| maxPayout    | uint256        | Maximum amount of payout tokens you can purchase in one transaction               |

### getTeller

```solidity
function getTeller() external view returns (contract IBondTeller)
```

Returns the Teller that services the Auctioneer

#### Returns

| Name   | Type                 | Description                                             |
| ------ | -------------------- | ------------------------------------------------------- |
| teller | contract IBondTeller | Address of the Teller contract servicing the Auctioneer |

### isInstantSwap

```solidity
function isInstantSwap(uint256 id_) external view returns (bool)
```

Does market send payout immediately

#### Parameters

| Name | Type    | Description             |
| ---- | ------- | ----------------------- |
| id\_ | uint256 | Market ID to search for |

#### Returns

| Name | Type | Description |
| ---- | ---- | ----------- |
| \_0  | bool | undefined   |

### isLive

```solidity
function isLive(uint256 id_) external view returns (bool)
```

Is a given market accepting deposits

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type | Description |
| ---- | ---- | ----------- |
| \_0  | bool | undefined   |

### marketPrice

```solidity
function marketPrice(uint256 id_) external view returns (uint256)
```

Calculate current market price of payout token in quote tokens

*Accounts for debt and control variable decay since last deposit (vs \_marketPrice())*

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type    | Description                                                |
| ---- | ------- | ---------------------------------------------------------- |
| \_0  | uint256 | Price for market in configured decimals (see MarketParams) |

### marketScale

```solidity
function marketScale(uint256 id_) external view returns (uint256)
```

Scale value to use when converting between quote token and payout token amounts with marketPrice()

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type    | Description                                      |
| ---- | ------- | ------------------------------------------------ |
| \_0  | uint256 | Scaling factor for market in configured decimals |

### maxAmountAccepted

```solidity
function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256)
```

Returns maximum amount of quote token accepted by the market

#### Parameters

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| id\_       | uint256 | ID of market                                                                                                                                        |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | uint256 | undefined   |

### ownerOf

```solidity
function ownerOf(uint256 id_) external view returns (address)
```

Returns the address of the market owner

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | address | undefined   |

### payoutFor

```solidity
function payoutFor(uint256 amount_, uint256 id_, address referrer_) external view returns (uint256)
```

Payout due for amount of quote tokens

*Accounts for debt and control variable decay so it is up to date*

#### Parameters

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| amount\_   | uint256 | Amount of quote tokens to spend                                                                                                                     |
| id\_       | uint256 | ID of market                                                                                                                                        |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

#### Returns

| Name | Type    | Description                        |
| ---- | ------- | ---------------------------------- |
| \_0  | uint256 | amount of payout tokens to be paid |

### pullOwnership

```solidity
function pullOwnership(uint256 id_) external nonpayable
```

Accept ownership of a marketMust be market newOwner

*The existing owner must call pushOwnership prior to the newOwner calling this function*

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### purchaseBond

```solidity
function purchaseBond(uint256 id_, uint256 amount_, uint256 minAmountOut_) external nonpayable returns (uint256 payout)
```

Exchange quote tokens for a bond in a specified marketMust be teller

#### Parameters

| Name           | Type    | Description                                                          |
| -------------- | ------- | -------------------------------------------------------------------- |
| id\_           | uint256 | ID of the Market the bond is being purchased from                    |
| amount\_       | uint256 | Amount to deposit in exchange for bond (after fee has been deducted) |
| minAmountOut\_ | uint256 | Minimum acceptable amount of bond to receive. Prevents frontrunning  |

#### Returns

| Name   | Type    | Description                                         |
| ------ | ------- | --------------------------------------------------- |
| payout | uint256 | Amount of payout token to be received from the bond |

### pushOwnership

```solidity
function pushOwnership(uint256 id_, address newOwner_) external nonpayable
```

Designate a new owner of a market. Must be existing market owner to call.

*Doesn't change permissions until newOwner calls pullOwnership*

#### Parameters

| Name       | Type    | Description                      |
| ---------- | ------- | -------------------------------- |
| id\_       | uint256 | Market ID                        |
| newOwner\_ | address | New address to give ownership to |

### setAllowNewMarkets

```solidity
function setAllowNewMarkets(bool status_) external nonpayable
```

Change the status of the auctioneer to allow creation of new markets

*Setting to false and allowing active markets to end will sunset the auctioneer*

#### Parameters

| Name     | Type | Description                                                     |
| -------- | ---- | --------------------------------------------------------------- |
| status\_ | bool | Allow market creation (true) : Disallow market creation (false) |

### setCallbackAuthStatus

```solidity
function setCallbackAuthStatus(address creator_, bool status_) external nonpayable
```

Change whether a market creator is allowed to use a callback address in their markets or notMust be guardian

*Callback is believed to be safe, but a whitelist is implemented to prevent abuse*

#### Parameters

| Name      | Type    | Description                                       |
| --------- | ------- | ------------------------------------------------- |
| creator\_ | address | Address of market creator                         |
| status\_  | bool    | Allow callback (true) : Disallow callback (false) |

### setDefaults

```solidity
function setDefaults(uint32[6] defaults_) external nonpayable
```

Set the auctioneer defaultsMust be policy

*The defaults set here are important to avoid edge cases in market behavior, e.g. a very short market reacts doesn't tune wellOnly applies to new markets that are created after the change*

#### Parameters

| Name       | Type       | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ---------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| defaults\_ | uint32\[6] | Array of default values 1. Tune interval - amount of time between tuning adjustments 2. Tune adjustment delay - amount of time to apply downward tuning adjustments 3. Minimum debt decay interval - minimum amount of time to let debt decay to zero 4. Minimum deposit interval - minimum amount of time to wait between deposits 5. Minimum market duration - minimum amount of time a market can be created for 6. Minimum debt buffer - the minimum amount of debt over the initial debt to trigger a market shutdown |

### setIntervals

```solidity
function setIntervals(uint256 id_, uint32[3] intervals_) external nonpayable
```

Set market intervals to different values than the defaultsMust be market owner

*Changing the intervals could cause markets to behave in unexpected way tuneInterval should be greater than tuneAdjustmentDelay*

#### Parameters

| Name        | Type       | Description                                                                                                                                                                                                      |
| ----------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id\_        | uint256    | Market ID                                                                                                                                                                                                        |
| intervals\_ | uint32\[3] | Array of intervals (3) 1. Tune interval - Frequency of tuning 2. Tune adjustment delay - Time to implement downward tuning adjustments 3. Debt decay interval - Interval over which debt should decay completely |


# Auction Pricing

Bond Protocol utilizes the Sequential Dutch Auction for its bond pricing mechanism. This mechanism is specified in detail in the [SDAM paper](https://github.com/Bond-Protocol/research/blob/master/papers/Sequential_Dutch_Auction_Markets.pdf) released by Bond Protocol.

### Auction Type

In a Dutch Auction, a high initial price is set for an item (*in this case the exchange rate between two tokens*). Once the auction starts, the price decreases (decays) as time passes until it is purchased (*or hits a configured minimum price that it cannot go below*).&#x20;

In a Sequential Dutch Auction, once a purchase is made, the price increases from the purchase and starts to decay again until another purchase is made. One can also view this as immediately starting a new auction on the next token after a purchase is made. The bounds for the auction are the duration it is expected to last for and the capacity of tokens to sell.

### Payout to Deposit ratio

Bond pricing is not the price of one of the tokens but the ratio of payout to deposit. As bond price falls, the same payout can be acquired with a decreasing deposit. This allows for the auction to function without the need for an oracle.

### Contract Initialization

Markets are initialized with an amount of debt equal to the total amount either to sell or acquire depending on configuration and this debt is grouped into a discrete amount of time, the decay interval, over which that debt should decay.&#x20;

### Vesting

The amount of time is 5 times the deposit interval or user-configured as long as it is a minimum of 3 days. The 3 day minimum ensures the price will not suddenly drop to 0. Using a multiple of the deposit interval ensures that debt will not decay significantly in between deposits.

### Debt decay

Debt is expected to decay linearly from 1 to 0 during the decay interval and it does so by tracking debt and a reference point in time.&#x20;

Market initialization and tuning both store the amount of debt is expected to decrease over a decay interval and both calculate the control variable based on that amount and time frame.&#x20;

When a deposit is made, debt increases by the amount sold or acquired depending on configuration. The reference point in time moves forward through the decay interval proportional to the change in debt relative to the expected decrease over the decay interval. This decays the debt linearly through time even as new debt is added.

### Bond Price

The Sequential Dutch Auctioneer Contract uses the following equation to calculate the price of a particular market:

$$
Price = Decayed Debt \* Control Variable
$$

### ​Control Variable

Control Variable is an independent variable that controls the relationship between Price and Debt.&#x20;

During market initialization, the price is provided either directly or through an oracle and the debt is the total amount either to sell or acquire over a deposit interval.&#x20;

During tuning, the price is the price of the deposit that triggered the tuning and debt is the remaining amount either to sell or acquire over a deposit interval. By adjusting the control variable based on what remains to be sold, the market is able to scale prices up or down relative to debt so that the target capacity is reached by the market conclusion.&#x20;

Control variable updates are called Tuning. The tuning frequency is set by the `tuneInterval` and is triggered by purchases.


# Fixed-Term SDA

### Fixed-Term SDA Contract

The Fixed-Term SDA is an implementation of the [Base SDA](/smart-contracts/bond-system/auctioneer/sequential-dutch-auctioneer-sda) contract specific to creating fixed-term bond markets.&#x20;

There are no additional actions required on market creation since the ERC1155 tokens get created by the Teller on the first purchase of each day.&#x20;

As such, this can be thought of as a non-abstract implementation of the Base SDA Auctioneer.


# Fixed-Expiry SDA

### Fixed-Expiry SDA Contract

The Fixed-Expiry SDA is an implementation of the [Base SDA](/smart-contracts/bond-system/auctioneer/sequential-dutch-auctioneer-sda) contract specific to creating fixed-expiry bond markets and deploying an ERC20 bond position token for the market on creation.


# Fixed Price Auctioneer (FPA)

Fixed Price Auctioneer is the simplest auction variant. It allows creators to buy/sell a set capacity of token at the quoted price for a certain amount of time. Because of this, it is similar to a limit order in an order book exchange. The goal of this auction variant is to sell as many tokens as possible at the set price. Unlike the SDA auction variants, it will not adjust price to sell out the capacity over the duration.

The Base FPA contract has the following data structures, variables, and methods.

## Data Structures (Structs)

### MarketParams

Parameters to create a new FPA market. Encoded as bytes and provided as input to `createMarket`.

```solidity
struct MarketParams {
    ERC20 payoutToken;
    ERC20 quoteToken;
    address callbackAddr;
    bool capacityInQuote;
    uint256 capacity;
    uint256 formattedPrice;
    uint48 depositInterval;
    uint48 vesting;
    uint48 start;
    uint48 duration;
    int8 scaleAdjustment;
}
```

| Field           | Type            | Description                                                                                                                                                                                             |
| --------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| payoutToken     | ERC20 (address) | Payout Token (token paid out by market and provided by creator)                                                                                                                                         |
| quoteToken      | ERC20 (address) | Quote Token (token to be received by the market and provided by purchaser)                                                                                                                              |
| callbackAddr    | address         | Callback contract address, should conform to `IBondCallback`. If 0x00, tokens will be transferred from market owner. Using a callback requires whitelisting by the protocol                             |
| capacityInQuote | bool            | Is Capacity in Quote Token?                                                                                                                                                                             |
| capacity        | uint256         | Capacity (amount in quote token decimals or amount in payout token decimals). Set `capacityInQuote` flag appropriately                                                                                  |
| formattedPrice  | uint256         | Initial price of the market as a ratio of quote tokens per payout token, see note below on formatting                                                                                                   |
| depositInterval | uint48          | Target deposit interval for purchases (in seconds). Determines the `maxPayout` of the market. Minimum is 1 hour (3600 seconds)                                                                          |
| vesting         | uint48          | Is fixed term ? Vesting length (seconds) : Vesting expiry (timestamp). A 'vesting' param longer than 50 years is considered a timestamp for fixed expiry                                                |
| start           | uint48          | Start time of the market as a timestamp. Allows starting a market in the future. If provided, the transaction must be sent prior to the start time. If not provided, the market will start immediately. |
| duration        | uint48          | Duration of the market in seconds.                                                                                                                                                                      |
| scaleAdjustment | int8            | Market scaling adjustment factor, ranges from -24 to +24. See note below on how to calculate                                                                                                            |

#### Calculating Formatted Price and Scale Adjustment

In order to support a broad range of tokens, with different decimal configurations and prices, we calculate an optimal scaling factor for each market. Specifically, the scale adjustment allows the FPA to support tokens with 6 to 18 configured decimals and with prices that differ by up to 24 decimal places (if the tokens have the configured decimals, less if not). To implement this, the market creator must provide a scale adjustment factor and format the price correctly.

First, you need the price of each token in a common unit, e.g. dollars or ether.

Then, if $$\Phi\_p$$ is the price of the payout token and $$\Phi\_q$$  is the price of quote token in the common unit, it can expressed in base 10 (or scientific) notation as:

$$
\Phi\_p = \phi\_p \times 10^{d\_{\phi p}}
$$

$$
\Phi\_q = \phi\_q \times 10^{d\_{\phi q}}
$$

where:

* $$\phi\_p$$ is the coefficient of the payout token price and ​$$d\_{\phi p}$$​ is the number of price decimals for the payout token (aka the significand of the price).
* $$\phi\_q$$​ is the coefficient of the quote token price and $$d\_{\phi q}$$​ is the number of price decimals for the quote token.

Example: If the price of WETH is $1,500, then we would deconstruct it as $$1.5 \times 10^3$$​. Therefore $$\phi = 1.5$$ and $$d\_{\phi} = 3$$.

Now, using the price values and the configured number of decimals for each token, we can calculate the scale adjustment.

$$
s = d\_p - d\_q - \left\lfloor\frac{d\_{\phi p} - d\_{\phi q}}{2}\right\rfloor
$$

where:

* $$d\_p$$ is the configured payout token decimals (e.g. WETH has 18 configured decimals)
* $$d\_q$$ is the configured quote token decimals.
* $$d\_{\phi p}$$ and $$d\_{\phi q}$$ are as defined above.

Example:&#x20;

* Let WETH be the quote token and OHM be the payout token. WETH has 18 configured decimals   and OHM has 9 configured decimals. Assume the market price of WETH is $1,500 -> $$1.5 \times 10^3$$and the market price of OHM is $10 -> $$1 \times 10^1$$.​
* Then, the scale adjustment is $$s = 9 - 18 - \left\lfloor\frac{1-3}{2}\right\rfloor = -9 + 1 = -8$$​

Once we have the scale adjustment, we can format the price using the variables defined above. Here we assume the auction will use the current market price. If selling vesting tokens, a discount to the current market price may be appropriate.

$$
\Phi\_0 = \frac{\phi\_p}{\phi\_q} \times 10^{36 + s + d\_q - d\_p +d\_{\phi p} - d\_{\phi q}}
$$

Example: Continuing with the WETH and OHM example from above, we format the price as:

$$
\Phi\_0 = \frac{1}{1.5} \times 10^{36+(-8)+18-9+1-3} = 0.666.. \times 10^{35} = 0.0666.. \times 10^{36}
$$

The above price example can be interpreted as 0.0666.. WETH per OHM.

### BondMarket

BondMarket contains the core data, such as tokens, capacity, owner, price, etc., for a Fixed Price Market.

```solidity
struct BondMarket {
    address owner; // market owner. sends payout tokens, receives quote tokens (defaults to creator)
    ERC20 payoutToken; // token to pay depositors with
    ERC20 quoteToken; // token to accept as payment
    address callbackAddr; // address to call for any operations on bond purchase. Must inherit to IBondCallback.
    bool capacityInQuote; // capacity limit is in payment token (true) or in payout (false, default)
    uint256 capacity; // capacity remaining
    uint256 maxPayout; // max payout tokens out in one order
    uint256 price; // fixed price of the market (see MarketParams struct)
    uint256 scale; // scaling factor for the market (see MarketParams struct)
    uint256 sold; // payout tokens out
    uint256 purchased; // quote tokens in
}
```

### BondTerms

BondTerms contains the time parameters of a Fixed Price Market.

<pre class="language-solidity"><code class="lang-solidity">struct BondTerms {
<strong>    uint48 start; // timestamp when market starts
</strong>    uint48 conclusion; // timestamp when market no longer offered
    uint48 vesting; // length of time from deposit to expiry if fixed-term, vesting timestamp if fixed-expiry
}
</code></pre>

## Public Variables and View Methods

### allowNewMarkets

```solidity
function allowNewMarkets() external view returns (bool)
```

Whether or not the auctioneer allows new markets to be created

*Changing to false will sunset the auctioneer after all active markets end*

### authority

```solidity
function authority() external view returns (contract Authority)
```

### callbackAuthorized

```solidity
function callbackAuthorized(address) external view returns (bool)
```

Whether or not the market creator is authorized to use a callback address

### currentCapacity

```solidity
function currentCapacity(uint256 id_) external view returns (uint256)
```

Returns current capacity of a market

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### getAggregator

```solidity
function getAggregator() external view returns (contract IBondAggregator)
```

Returns the Aggregator that services the Auctioneer

### getMarketInfoForPurchase

```solidity
function getMarketInfoForPurchase(uint256 id_) external view returns (address owner, address callbackAddr, contract ERC20 payoutToken, contract ERC20 quoteToken, uint48 vesting, uint256 maxPayout_)
```

Provides information for the Teller to execute purchases on a Market

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name         | Type           | Description                                                                       |
| ------------ | -------------- | --------------------------------------------------------------------------------- |
| owner        | address        | Address of the market owner (tokens transferred from this address if no callback) |
| callbackAddr | address        | Address of the callback contract to get tokens for payouts                        |
| payoutToken  | contract ERC20 | Payout Token (token paid out) for the Market                                      |
| quoteToken   | contract ERC20 | Quote Token (token received) for the Market                                       |
| vesting      | uint48         | Timestamp or duration for vesting, implementation-dependent                       |
| maxPayout\_  | uint256        | Maximum amount of payout tokens you can purchase in one transaction               |

### getTeller

```solidity
function getTeller() external view returns (contract IBondTeller)
```

Returns the Teller that services the Auctioneer

### isInstantSwap

```solidity
function isInstantSwap(uint256 id_) external view returns (bool)
```

Returns whether the market sends payout immediately (true = no vesting) or not (false = vesting)

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### isLive

```solidity
function isLive(uint256 id_) external view returns (bool)
```

Returns whether the market is currently accepting deposits (true) or not (false)

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### marketPrice

```solidity
function marketPrice(uint256 id_) external view returns (uint256)
```

Calculates current market price, value returned is the number of quote tokens per payout token, scaled according to the logic described in [#calculating-formatted-price-and-scale-adjustment](#calculating-formatted-price-and-scale-adjustment "mention")

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### marketScale

```solidity
function marketScale(uint256 id_) external view returns (uint256)
```

Scale value to use when converting between quote token and payout token amounts with marketPrice()

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### markets

```solidity
function markets(uint256) external view returns (address owner, contract ERC20 payoutToken, contract ERC20 quoteToken, address callbackAddr, bool capacityInQuote, uint256 capacity, uint256 maxPayout, uint256 price, uint256 scale, uint256 sold, uint256 purchased)
```

Returns the core information pertaining to a bond market, see [#bondmarket](#bondmarket "mention")

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### maxAmountAccepted

```solidity
function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256)
```

Returns maximum amount of quote token accepted by the market

#### Parameters

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| id\_       | uint256 | ID of market                                                                                                                                        |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

### maxPayout

```solidity
function maxPayout(uint256 id_) external view returns (uint256)
```

Calculate max payout of the market in payout tokens

*Returns a dynamically calculated payout or the maximum set by the creator, whichever is less. If the remaining capacity is less than the max payout, then that amount will be returned.*

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### minDepositInterval

```solidity
function minDepositInterval() external view returns (uint48)
```

Minimum deposit interval for a market

### minMarketDuration

```solidity
function minMarketDuration() external view returns (uint48)
```

Minimum market duration in seconds

### newOwners

```solidity
function newOwners(uint256) external view returns (address)
```

New address to designate as market owner. They must accept ownership to transfer permissions.

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### ownerOf

```solidity
function ownerOf(uint256 id_) external view returns (address)
```

Returns the address of the market owner

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

### payoutFor

```solidity
function payoutFor(uint256 amount_, uint256 id_, address referrer_) external view returns (uint256)
```

Payout due for amount of quote tokens

#### Parameters

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| amount\_   | uint256 | Amount of quote tokens to spend                                                                                                                     |
| id\_       | uint256 | ID of market                                                                                                                                        |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

### terms

```solidity
function terms(uint256) external view returns (uint48 start, uint48 conclusion, uint48 vesting)
```

Information pertaining to market time parameters, see [#bondterms](#bondterms "mention")

#### Parameters

| Name | Type    | Description      |
| ---- | ------- | ---------------- |
| id\_ | uint256 | ID of the market |

## State-Mutating Methods

### closeMarket

```solidity
function closeMarket(uint256 id_) external nonpayable
```

Disable existing bond marketMust be market owner

#### Parameters

| Name | Type    | Description           |
| ---- | ------- | --------------------- |
| id\_ | uint256 | ID of market to close |

### createMarket

```solidity
function createMarket(bytes params_) external nonpayable returns (uint256)
```

Creates a new bond market

*See* [#marketparams](#marketparams "mention") for the required formatting for the abi-encoded input params.

#### Parameters

| Name     | Type  | Description                                                             |
| -------- | ----- | ----------------------------------------------------------------------- |
| params\_ | bytes | Configuration data needed for market creation, encoded in a bytes array |

#### Returns

|    |         |                           |
| -- | ------- | ------------------------- |
| id | uint256 | ID of the new bond market |

### pullOwnership

```solidity
function pullOwnership(uint256 id_) external nonpayable
```

Accept ownership of a marketMust be market newOwner

*The existing owner must call pushOwnership prior to the newOwner calling this function*

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### purchaseBond

```solidity
function purchaseBond(uint256 id_, uint256 amount_, uint256 minAmountOut_) external nonpayable returns (uint256 payout)
```

Execute a purchase on the auctioneer. Only callable by the configured [Teller](/smart-contracts/bond-system/teller). Users must interact with the Teller to make purchases.

#### Parameters

| Name           | Type    | Description                                                          |
| -------------- | ------- | -------------------------------------------------------------------- |
| id\_           | uint256 | ID of the Market the bond is being purchased from                    |
| amount\_       | uint256 | Amount to deposit in exchange for bond (after fee has been deducted) |
| minAmountOut\_ | uint256 | Minimum acceptable amount of bond to receive. Prevents front-running |

#### Returns

| Name   | Type    | Description                                         |
| ------ | ------- | --------------------------------------------------- |
| payout | uint256 | Amount of payout token to be received from the bond |

### pushOwnership

```solidity
function pushOwnership(uint256 id_, address newOwner_) external nonpayable
```

Designate a new owner of a marketMust be market owner

*Doesn't change permissions until newOwner calls pullOwnership*

#### Parameters

| Name       | Type    | Description                      |
| ---------- | ------- | -------------------------------- |
| id\_       | uint256 | Market ID                        |
| newOwner\_ | address | New address to give ownership to |

### setAllowNewMarkets

```solidity
function setAllowNewMarkets(bool status_) external nonpayable
```

Change the status of the auctioneer to allow creation of new markets

*Setting to false and allowing active markets to end will sunset the auctioneer*

#### Parameters

| Name     | Type | Description                                                     |
| -------- | ---- | --------------------------------------------------------------- |
| status\_ | bool | Allow market creation (true) : Disallow market creation (false) |

### setCallbackAuthStatus

```solidity
function setCallbackAuthStatus(address creator_, bool status_) external nonpayable
```

Change whether a market creator is allowed to use a callback address in their markets or notMust be guardian

*Callback is believed to be safe, but a whitelist is implemented to prevent abuse*

#### Parameters

| Name      | Type    | Description                                       |
| --------- | ------- | ------------------------------------------------- |
| creator\_ | address | Address of market creator                         |
| status\_  | bool    | Allow callback (true) : Disallow callback (false) |

### setMinDepositInterval

```solidity
function setMinDepositInterval(uint48 depositInterval_) external nonpayable
```

Set the minimum deposit intervalAccess controlled

#### Parameters

| Name              | Type   | Description                         |
| ----------------- | ------ | ----------------------------------- |
| depositInterval\_ | uint48 | Minimum deposit interval in seconds |

### setMinMarketDuration

```solidity
function setMinMarketDuration(uint48 duration_) external nonpayable
```

Set the minimum market durationAccess controlled

#### Parameters

| Name       | Type   | Description                        |
| ---------- | ------ | ---------------------------------- |
| duration\_ | uint48 | Minimum market duration in seconds |

## Events

### MarketClosed

```solidity
event MarketClosed(uint256 indexed id)
```

#### Parameters

| Name         | Type    | Description      |
| ------------ | ------- | ---------------- |
| id `indexed` | uint256 | ID of the market |

### MarketCreated

```solidity
event MarketCreated(uint256 indexed id, address indexed payoutToken, address indexed quoteToken, uint48 vesting, uint256 fixedPrice)
```

#### Parameters

| Name                  | Type    | Description                   |
| --------------------- | ------- | ----------------------------- |
| id `indexed`          | uint256 | ID of the market              |
| payoutToken `indexed` | address | Address of the payout token   |
| quoteToken `indexed`  | address | Address of the quote token    |
| vesting               | uint48  | Vesting duration or timestamp |
| fixedPrice            | uint256 | Fixed price of the market     |

## Errors

### Auctioneer\_AmountLessThanMinimum

```solidity
error Auctioneer_AmountLessThanMinimum()
```

### Auctioneer\_BadExpiry

```solidity
error Auctioneer_BadExpiry()
```

### Auctioneer\_InvalidCallback

```solidity
error Auctioneer_InvalidCallback()
```

### Auctioneer\_InvalidParams

```solidity
error Auctioneer_InvalidParams()
```

### Auctioneer\_MarketNotActive

```solidity
error Auctioneer_MarketNotActive()
```

### Auctioneer\_MaxPayoutExceeded

```solidity
error Auctioneer_MaxPayoutExceeded()
```

### Auctioneer\_NewMarketsNotAllowed

```solidity
error Auctioneer_NewMarketsNotAllowed()
```

### Auctioneer\_NotAuthorized

```solidity
error Auctioneer_NotAuthorized()
```

### Auctioneer\_NotEnoughCapacity

```solidity
error Auctioneer_NotEnoughCapacity()
```

### Auctioneer\_OnlyMarketOwner

```solidity
error Auctioneer_OnlyMarketOwner()
```


# Fixed-Term FPA

### Fixed-Term FPA Contract

The Fixed-Term FPA is an implementation of the [Base FPA](broken://pages/gLPqj1T9h90FWgqoFlFi) contract specific to creating fixed-term bond markets.&#x20;

There are no additional actions required on market creation since the ERC1155 tokens get created by the Teller on the first purchase of each day.&#x20;

As such, this can be thought of as a non-abstract implementation of the Base FPA Auctioneer.


# Fixed-Expiry FPA

### Fixed-Expiry FPA Contract

The Fixed-Expiry FPA is an implementation of the [Base FPA](broken://pages/gLPqj1T9h90FWgqoFlFi) contract specific to creating fixed-expiry bond markets and deploying an ERC20 bond position token for the market on creation.


# Oracle-based Auctioneers

The Oracle-based Auctioneer contracts allow market creators to create bond markets that use external price feeds to stay in line with market prices. There are two variants of Oracle-based Auctioneers:

* Oracle Fixed Discount Auctioneer (OFDA)
* Oracle Sequential Dutch Auctioneer (OSDA)

The IBondOracle interface is required to be implemented for a contract that will serve as an oracle. Bond protocol has created a Base Oracle abstract and implemented a sample oracle contract for Chainlink price feeds that can be used by market issuers. With the sample contract, each issuer deploys their own oracle contract so they have control over the configuration.

## IBondOracle

### Methods

#### currentPrice

```solidity
function currentPrice(uint256 id_) external view returns (uint256)
```

Returns the price as a ratio of quote tokens to base tokens for the provided market ID scaled by `10^decimals(id_)`.

*Market ID is not known prior to market creation. This version is used by the Bond system after market creation.*

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

**Returns**

| Name  | Type    | Description  |
| ----- | ------- | ------------ |
| price | uint256 | Oracle price |

#### currentPrice

```solidity
function currentPrice(contract ERC20 quoteToken_, contract ERC20 payoutToken_) external view returns (uint256)
```

Returns the price as a ratio of quote tokens to base tokens for the provided token pair scaled by `10^decimals(quoteToken_, payoutToken_)`

*Not used directly by the bond system, but useful for checking whether the oracle parameters are setup correctly before deploying a bond market.*

**Parameters**

| Name          | Type           | Description                                                              |
| ------------- | -------------- | ------------------------------------------------------------------------ |
| quoteToken\_  | contract ERC20 | Token that purchasers provide to the market and creators receive.        |
| payoutToken\_ | contract ERC20 | Token that creators provide and purchasers will receive from the market. |

**Returns**

| Name  | Type    | Description  |
| ----- | ------- | ------------ |
| price | uint256 | Oracle price |

#### decimals

```solidity
function decimals(uint256 id_) external view returns (uint8)
```

Returns the number of configured decimals of the price value for the provided market ID

*Market ID is not known prior to market creation. This version is used by the Bond system after market creation.*

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

**Returns**

| Name     | Type  | Description                                      |
| -------- | ----- | ------------------------------------------------ |
| decimals | uint8 | Number of decimals to assume for Market ID price |

#### decimals

```solidity
function decimals(contract ERC20 quoteToken_, contract ERC20 payoutToken_) external view returns (uint8)
```

Returns the number of configured decimals of the price value for the provided token pair

**Parameters**

| Name          | Type           | Description                                                              |
| ------------- | -------------- | ------------------------------------------------------------------------ |
| quoteToken\_  | contract ERC20 | Token that purchasers provide to the market and creators receive.        |
| payoutToken\_ | contract ERC20 | Token that creators provide and purchasers will receive from the market. |

**Returns**

| Name     | Type  | Description                                       |
| -------- | ----- | ------------------------------------------------- |
| decimals | uint8 | Number of decimals to assume for token pair price |

#### registerMarket

```solidity
function registerMarket(uint256 id_, contract ERC20 quoteToken_, contract ERC20 payoutToken_) external nonpayable
```

Register a new bond market on the oracle

*Used by the bond system to register the market ID and token pair. Must permission the auctioneer to use this function.*

**Parameters**

| Name          | Type           | Description                                                              |
| ------------- | -------------- | ------------------------------------------------------------------------ |
| id\_          | uint256        | Market ID                                                                |
| quoteToken\_  | contract ERC20 | Token that purchasers provide to the market and creators receive.        |
| payoutToken\_ | contract ERC20 | Token that creators provide and purchasers will receive from the market. |


# Oracle Interface

## IBondOracle

### Methods

#### currentPrice

```solidity
function currentPrice(uint256 id_) external view returns (uint256)
```

Returns the price as a ratio of quote tokens to base tokens for the provided market id scaled by 10^decimals

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | undefined   |

**Returns**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | uint256 | undefined   |

#### currentPrice

```solidity
function currentPrice(contract ERC20 quoteToken_, contract ERC20 payoutToken_) external view returns (uint256)
```

Returns the price as a ratio of quote tokens to base tokens for the provided token pair scaled by 10^decimals

**Parameters**

| Name          | Type           | Description |
| ------------- | -------------- | ----------- |
| quoteToken\_  | contract ERC20 | undefined   |
| payoutToken\_ | contract ERC20 | undefined   |

**Returns**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | uint256 | undefined   |

#### decimals

```solidity
function decimals(uint256 id_) external view returns (uint8)
```

Returns the number of configured decimals of the price value for the provided market id

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | undefined   |

**Returns**

| Name | Type  | Description |
| ---- | ----- | ----------- |
| \_0  | uint8 | undefined   |

#### decimals

```solidity
function decimals(contract ERC20 quoteToken_, contract ERC20 payoutToken_) external view returns (uint8)
```

Returns the number of configured decimals of the price value for the provided token pair

**Parameters**

| Name          | Type           | Description |
| ------------- | -------------- | ----------- |
| quoteToken\_  | contract ERC20 | undefined   |
| payoutToken\_ | contract ERC20 | undefined   |

**Returns**

| Name | Type  | Description |
| ---- | ----- | ----------- |
| \_0  | uint8 | undefined   |

#### registerMarket

```solidity
function registerMarket(uint256 id_, contract ERC20 quoteToken_, contract ERC20 payoutToken_) external nonpayable
```

Register a new bond market on the oracle

**Parameters**

| Name          | Type           | Description |
| ------------- | -------------- | ----------- |
| id\_          | uint256        | undefined   |
| quoteToken\_  | contract ERC20 | undefined   |
| payoutToken\_ | contract ERC20 | undefined   |


# Oracle Fixed Discount Auctioneer (OFDA)

&#x20;Oracle Fixed Discount Auctioneer allows market creators to sell tokens at a discount to a price provided by an oracle, likely in exchange for vesting the tokens over a certain amount of time. Typically, longer duration vesting will require a larger discount. Additionally, larger discounts may be required for smaller cap tokens or when market demand is low. Unlike the SDA auction variants, it will not adjust price to sell out the capacity over the duration.

Market creators can also set a minimum total discount from the starting price, which creates a hard floor for the market price.

The below chart shows a notional example of how price might evolve over an OFDA market.

<figure><img src="/files/ObjVHC2wqjx506l3geAc" alt=""><figcaption><p>Notional Price of OFDA Market over Time</p></figcaption></figure>

The Base OFDA contract has the following data structures, variables, and methods.

## Data Structures (Structs)

### MarketParams

Parameters to create a new OFDA market. Encoded as bytes and provided as input to `createMarket`.

```solidity
struct MarketParams {
    ERC20 payoutToken;
    ERC20 quoteToken;
    address callbackAddr;
    IBondOracle oracle;
    uint48 fixedDiscount;
    uint48 maxDiscountFromCurrent;
    bool capacityInQuote;
    uint256 capacity;
    uint48 depositInterval;
    uint48 vesting;
    uint48 start;
    uint48 duration;
}
```

| Field                  | Type                  | Description                                                                                                                                                                                             |
| ---------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| payoutToken            | ERC20 (address)       | Payout Token (token paid out by market and provided by creator)                                                                                                                                         |
| quoteToken             | ERC20 (address)       | Quote Token (token to be received by the market and provided by purchaser)                                                                                                                              |
| callbackAddr           | address               | Callback contract address, should conform to `IBondCallback`. If 0x00, tokens will be transferred from market owner. Using a callback requires whitelisting by the protocol                             |
| oracle                 | IBondOracle (address) | Oracle contract address, must conform to `IBondOracle`. Provides current price data for the quote/payout token pair.                                                                                    |
| fixedDiscount          | uint48                | Fixed discount (%) of the market from the oracle price. Units are a percent with 3 decimals of precision (e.g. `10_000` = 10%)                                                                          |
| maxDiscountFromCurrent | uint48                | Max Discount (%) from the oracle price when the time the market is created. Sets a minimum price for the market. Units are a percent with 3 decimals of precision (e.g. `10_000` = 10%).                |
| capacityInQuote        | bool                  | Is Capacity in Quote Token?                                                                                                                                                                             |
| capacity               | uint256               | Capacity (amount in quote token decimals or amount in payout token decimals). Set `capacityInQuote` flag appropriately.                                                                                 |
| depositInterval        | uint48                | Target deposit interval for purchases (in seconds). Determines the `maxPayout` of the market. Minimum is 1 hour (3600 seconds)                                                                          |
| vesting                | uint48                | Is fixed term ? Vesting length (seconds) : Vesting expiry (timestamp). A 'vesting' param longer than 50 years is considered a timestamp for fixed expiry                                                |
| start                  | uint48                | Start time of the market as a timestamp. Allows starting a market in the future. If provided, the transaction must be sent prior to the start time. If not provided, the market will start immediately. |
| duration               | uint48                | Duration of the market in seconds.                                                                                                                                                                      |

### BondMarket

BondMarket contains the token, callback, capacity, owner, and purchased/sold amount data for a Oracle Fixed Discount Market.

```solidity
struct BondMarket {
    address owner; // market owner. sends payout tokens, receives quote tokens (defaults to creator)
    ERC20 payoutToken; // token to pay depositors with
    ERC20 quoteToken; // token to accept as payment
    address callbackAddr; // address to call for any operations on bond purchase. Must inherit to IBondCallback.
    bool capacityInQuote; // capacity limit is in payment token (true) or in payout (false, default)
    uint256 capacity; // capacity remaining
    uint256 maxPayout; // max payout tokens out in one order
    uint256 sold; // payout tokens out
    uint256 purchased; // quote tokens in
}
```

### BondTerms

BondTerms contains the oracle, pricing, and time parameters of an Oracle Fixed Discount Market.

```solidity
struct BondTerms {
    IBondOracle oracle; // address to call for reference price. Must implement IBondOracle.
    uint48 start; // timestamp when market starts
    uint48 conclusion; // timestamp when market no longer offered
    uint48 vesting; // length of time from deposit to expiry if fixed-term, vesting timestamp if fixed-expiry
    uint48 fixedDiscount; // fixed discount percent for the market
    uint256 minPrice; // minimum price (hard floor for the market)
    uint256 scale; // scaling factor for the market (see MarketParams struct)
    uint256 oracleConversion; // conversion factor for oracle -> market price
}
```

## Public Variables and View Methods

### allowNewMarkets

```solidity
function allowNewMarkets() external view returns (bool)
```

Whether or not the auctioneer allows new markets to be created

*Changing to false will sunset the auctioneer after all active markets end*

### authority

```solidity
function authority() external view returns (contract Authority)
```

Roles authority contract for the bond system which managed access-control to permissioned functions.

### callbackAuthorized

```solidity
function callbackAuthorized(address) external view returns (bool)
```

Whether or not the market creator is authorized to use a callback address

#### Parameters

| Name      | Type    | Description             |
| --------- | ------- | ----------------------- |
| creator\_ | address | Market creator address. |

### currentCapacity

```solidity
function currentCapacity(uint256 id_) external view returns (uint256)
```

Returns current capacity of a market

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### getAggregator

```solidity
function getAggregator() external view returns (contract IBondAggregator)
```

Returns the Aggregator that services the Auctioneer

### getMarketInfoForPurchase

```solidity
function getMarketInfoForPurchase(uint256 id_) external view returns (address owner, address callbackAddr, contract ERC20 payoutToken, contract ERC20 quoteToken, uint48 vesting, uint256 maxPayout_)
```

Provides information for the Teller to execute purchases on a Market

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

**Returns**

| Name         | Type           | Description                                                                       |
| ------------ | -------------- | --------------------------------------------------------------------------------- |
| owner        | address        | Address of the market owner (tokens transferred from this address if no callback) |
| callbackAddr | address        | Address of the callback contract to get tokens for payouts                        |
| payoutToken  | contract ERC20 | Payout Token (token paid out) for the Market                                      |
| quoteToken   | contract ERC20 | Quote Token (token received) for the Market                                       |
| vesting      | uint48         | Timestamp or duration for vesting, implementation-dependent                       |
| maxPayout\_  | uint256        | Maximum amount of payout tokens you can purchase in one transaction               |

### getTeller

```solidity
function getTeller() external view returns (contract IBondTeller)
```

Returns the Teller that services the Auctioneer

### isInstantSwap

```solidity
function isInstantSwap(uint256 id_) external view returns (bool)
```

Does market send payout immediately

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### isLive

```solidity
function isLive(uint256 id_) external view returns (bool)
```

Is a given market accepting deposits

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### marketPrice

```solidity
function marketPrice(uint256 id_) external view returns (uint256)
```

Calculate current market price. Value returned is the number of quote tokens per payout token. The value is the oracle price scaled by the [#bondterms](#bondterms "mention").oracleConversion factor. `marketPrice` and `marketScale` can be used to convert between amounts of quote tokens and payout tokens at the current price.

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### marketScale

```solidity
function marketScale(uint256 id_) external view returns (uint256)
```

Scale value to use when converting between quote token and payout token amounts with marketPrice()

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### markets

```solidity
function markets(uint256) external view returns (address owner, contract ERC20 payoutToken, contract ERC20 quoteToken, address callbackAddr, bool capacityInQuote, uint256 capacity, uint256 maxPayout, uint256 sold, uint256 purchased)
```

Returns the token, callback, capacity, owner, and purchased/sold amount data for a market. See [#bondmarket](#bondmarket "mention").

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### maxAmountAccepted

```solidity
function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256)
```

Returns maximum amount of quote token accepted by the market

**Parameters**

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| id\_       | uint256 | Market ID                                                                                                                                           |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

### maxPayout

```solidity
function maxPayout(uint256 id_) external view returns (uint256)
```

Calculate max payout of the market in payout tokens

*Returns a dynamically calculated payout or the maximum set by the creator, whichever is less. If the remaining capacity is less than the max payout, then that amount will be returned.*

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### minDepositInterval

```solidity
function minDepositInterval() external view returns (uint48)
```

Minimum deposit interval for a market

### minMarketDuration

```solidity
function minMarketDuration() external view returns (uint48)
```

Minimum market duration in seconds

### newOwners

```solidity
function newOwners(uint256) external view returns (address)
```

New address to designate as market owner. They must accept ownership to transfer permissions.

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### ownerOf

```solidity
function ownerOf(uint256 id_) external view returns (address)
```

Returns the address of the market owner

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### payoutFor

```solidity
function payoutFor(uint256 amount_, uint256 id_, address referrer_) external view returns (uint256)
```

Payout due for amount of quote tokens at current market price

**Parameters**

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| amount\_   | uint256 | Amount of quote tokens to spend                                                                                                                     |
| id\_       | uint256 | Market ID                                                                                                                                           |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

### terms

```solidity
function terms(uint256) external view returns (contract IBondOracle oracle, uint48 start, uint48 conclusion, uint48 vesting, uint48 fixedDiscount, uint256 minPrice, uint256 scale, uint256 oracleConversion)
```

Information pertaining to oracle, pricing, and time parameters. See [#bondterms](#bondterms "mention").

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

## State-Mutating Methods

### closeMarket

```solidity
function closeMarket(uint256 id_) external nonpayable
```

Disable existing bond market. Must be market owner

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### createMarket

```solidity
function createMarket(bytes params_) external nonpayable returns (uint256)
```

Creates a new bond market

*See* [#marketparams](#marketparams "mention") for the required formatting for the abi-encoded input params.

**Parameters**

| Name     | Type  | Description                                                             |
| -------- | ----- | ----------------------------------------------------------------------- |
| params\_ | bytes | Configuration data needed for market creation, encoded in a bytes array |

#### Returns

|      |         |           |
| ---- | ------- | --------- |
| id\_ | uint256 | Market ID |

### pullOwnership

```solidity
function pullOwnership(uint256 id_) external nonpayable
```

Accept ownership of a marketMust be market newOwner

*The existing owner must call pushOwnership prior to the newOwner calling this function*

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### purchaseBond

```solidity
function purchaseBond(uint256 id_, uint256 amount_, uint256 minAmountOut_) external nonpayable returns (uint256 payout)
```

Exchange quote tokens for a bond in a specified market. Must be teller. End users interact with the Teller contract to purchase.

**Parameters**

| Name           | Type    | Description                                                          |
| -------------- | ------- | -------------------------------------------------------------------- |
| id\_           | uint256 | Market ID                                                            |
| amount\_       | uint256 | Amount to deposit in exchange for bond (after fee has been deducted) |
| minAmountOut\_ | uint256 | Minimum acceptable amount of bond to receive. Prevents front-running |

**Returns**

| Name   | Type    | Description                                         |
| ------ | ------- | --------------------------------------------------- |
| payout | uint256 | Amount of payout token to be received from the bond |

### pushOwnership

```solidity
function pushOwnership(uint256 id_, address newOwner_) external nonpayable
```

Designate a new owner of a marketMust be market owner

*Doesn't change permissions until newOwner calls pullOwnership*

**Parameters**

| Name       | Type    | Description                      |
| ---------- | ------- | -------------------------------- |
| id\_       | uint256 | Market ID                        |
| newOwner\_ | address | New address to give ownership to |

### setAllowNewMarkets

```solidity
function setAllowNewMarkets(bool status_) external nonpayable
```

Change the status of the auctioneer to allow creation of new markets

*Setting to false and allowing active markets to end will sunset the auctioneer*

**Parameters**

| Name     | Type | Description                                                     |
| -------- | ---- | --------------------------------------------------------------- |
| status\_ | bool | Allow market creation (true) : Disallow market creation (false) |

### setCallbackAuthStatus

```solidity
function setCallbackAuthStatus(address creator_, bool status_) external nonpayable
```

Change whether a market creator is allowed to use a callback address in their markets or not. Must be guardian

*Callback is believed to be safe, but a whitelist is implemented to prevent abuse*

**Parameters**

| Name      | Type    | Description                                       |
| --------- | ------- | ------------------------------------------------- |
| creator\_ | address | Address of market creator                         |
| status\_  | bool    | Allow callback (true) : Disallow callback (false) |

### setMinDepositInterval

```solidity
function setMinDepositInterval(uint48 depositInterval_) external nonpayable
```

Set the minimum deposit interval. Access controlled

**Parameters**

| Name              | Type   | Description                         |
| ----------------- | ------ | ----------------------------------- |
| depositInterval\_ | uint48 | Minimum deposit interval in seconds |

### setMinMarketDuration

```solidity
function setMinMarketDuration(uint48 duration_) external nonpayable
```

Set the minimum market duration. Access controlled

**Parameters**

| Name       | Type   | Description                        |
| ---------- | ------ | ---------------------------------- |
| duration\_ | uint48 | Minimum market duration in seconds |

## Events

### MarketClosed

```solidity
event MarketClosed(uint256 indexed id)
```

**Parameters**

| Name         | Type    | Description |
| ------------ | ------- | ----------- |
| id `indexed` | uint256 | Market ID   |

### MarketCreated

```solidity
event MarketCreated(uint256 indexed id, address indexed payoutToken, address indexed quoteToken, uint48 vesting)
```

**Parameters**

| Name                  | Type    | Description                   |
| --------------------- | ------- | ----------------------------- |
| id `indexed`          | uint256 | Market ID                     |
| payoutToken `indexed` | address | Address of the payout token   |
| quoteToken `indexed`  | address | Address of the quote token    |
| vesting               | uint48  | Vesting duration or timestamp |

## Errors

The following custom errors are used in the OFDA contract to denote specific revert conditions. The errors are prefixed with "Auctioneer" to denote that it is within this contract when multi-contract actions are performed (such as buying a bond).

```solidity
error Auctioneer_OnlyMarketOwner();
error Auctioneer_MarketNotActive();
error Auctioneer_MaxPayoutExceeded();
error Auctioneer_AmountLessThanMinimum();
error Auctioneer_NotEnoughCapacity();
error Auctioneer_InvalidCallback();
error Auctioneer_BadExpiry();
error Auctioneer_InvalidParams();
error Auctioneer_NotAuthorized();
error Auctioneer_NewMarketsNotAllowed();
error Auctioneer_OraclePriceZero();
```


# Fixed-Term OFDA

### Fixed-Term OFDA Contract

The Fixed-Term OFDA is an implementation of the [Base OFDA](/smart-contracts/bond-system/auctioneer/oracle-fixed-discount-auctioneer-ofda) contract specific to creating fixed-term bond markets.&#x20;

There are no additional actions required on market creation since the ERC1155 tokens get created by the Teller on the first purchase of each day.&#x20;

As such, this can be thought of as a non-abstract implementation of the Base OFDA.


# Fixed-Expiry OFDA

### Fixed-Expiry OFDA Contract

The Fixed-Expiry OFDA is an implementation of the [Base OFDA](/smart-contracts/bond-system/auctioneer/oracle-fixed-discount-auctioneer-ofda) contract specific to creating fixed-expiry bond markets and deploying an ERC20 bond position token for the market on creation.


# Oracle Sequential Dutch Auctioneer (OSDA)

The Oracle Sequential Dutch Auctioneer implements a simplified sequential dutch auction pricing methodology which seeks to sell out the capacity of the market linearly over the duration. We do so by implementing a linear decay of price based on the percent difference in expected capacity vs. actual capacity (relative to the initial capacity) at any given point in time. The OSDA allows specifying a base discount from the oracle price and calculates a decay speed based on a target deposit interval and target discount over that interval. More specifically, we define the price as:

$$P(t) = O(t) \times (1 - b) \times (1 + k \times r(t))$$

where $$O(t)$$ is the oracle price at time $$t$$, $$b$$ is the base discount percent of the market, $$k$$ is the decay speed, and $$r(t)$$ is the capacity ratio.

We calculate $$k$$ on market creation as:

$$k = \frac{L}{I\_d} \times d$$

where $$L$$ is the duration of the market, $$I\_d$$ is the deposit interval, and $$d$$ is the target discount over a deposit interval.

We calculate the capacity ratio as:

$$r(t) = \frac{\chi(t) - C(t)}{C\_0}$$

where $$C\_0$$ is the initial capacity of the market, $$C(t)$$ is the remaining capacity at time $$t$$, and $$\chi(t) = C\_0 \times \frac{L - t}{L}$$ is the expected capacity at time $$t$$.

Market creators can also set a minimum total discount from the starting price, which creates a hard floor for the market price.

The below chart shows a notional example of how price might evolve over an OSDA market.

<figure><img src="/files/7p9clNdTH9kAxYXlmZQS" alt=""><figcaption><p>Notional Price of an OSDA Market over Time</p></figcaption></figure>

If you're familiar with other dutch auction mechanism designs, this version of the SDA is similar to [Paradigm's Continuous Gradual Dutch Auction (GDA) model](https://www.paradigm.xyz/2022/04/gda#continuous-gda) with linear decay, but there is no price slippage based on the purchase amount. Note the version described in the link above uses exponential decay vs. linear decay, but it's possible to derive a linear decay version as well.

Configuring appropriate base discount and target interval discounts is a function of the market demand for the token and the vesting period of the payouts. Typically, longer vesting periods require a larger base discount. Target interval discounts may need to be higher for smaller cap tokens or where demand is soft. However, various combinations can be used depending on desired market characteristics. For example, a high base discount and low target interval discount will give a consistently good deal with low volatility in the market price. The opposite configuration, low base discount and high target interval discount, will be more volatile, but may result in lower overall discounts depending on demand.

## Data Structures (Structs)

### MarketParams

Parameters to create a new OSDA market. Encoded as bytes and provided as input to `createMarket`.

```solidity
struct MarketParams {
    ERC20 payoutToken;
    ERC20 quoteToken;
    address callbackAddr;
    IBondOracle oracle;
    uint48 baseDiscount;
    uint48 maxDiscountFromCurrent;
    uint48 targetIntervalDiscount;
    bool capacityInQuote;
    uint256 capacity;
    uint48 depositInterval;
    uint48 vesting;
    uint48 start;
    uint48 duration;
}
```

| Field                  | Type                  | Description                                                                                                                                                                                                                                                    |
| ---------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| payoutToken            | ERC20 (address)       | Payout Token (token paid out by market and provided by creator)                                                                                                                                                                                                |
| quoteToken             | ERC20 (address)       | Quote Token (token to be received by the market and provided by purchaser)                                                                                                                                                                                     |
| callbackAddr           | address               | Callback contract address, should conform to `IBondCallback`. If 0x00, tokens will be transferred from market owner. Using a callback requires whitelisting by the protocol                                                                                    |
| oracle                 | IBondOracle (address) | Oracle contract address, must conform to `IBondOracle`. Provides current price data for the quote/payout token pair.                                                                                                                                           |
| baseDiscount           | uint48                | Base discount from oracle price before time-related decay is applied. Units are a percent with 3 decimals of precision (e.g. `10_000` = 10%)                                                                                                                   |
| maxDiscountFromCurrent | uint48                | Max Discount (%) from the oracle price when the time the market is created. Sets a minimum price for the market. Units are a percent with 3 decimals of precision (e.g. `10_000` = 10%).                                                                       |
| targetIntervalDiscount | uint48                | The discount from zero to be achieved over a depositInterval if no purchases are made during that time. Controls the decay speed of the market price. Applied after the base  discount. Units are a percent with 3 decimals of precision (e.g. `10_000` = 10%) |
| capacityInQuote        | bool                  | Is Capacity in Quote Token?                                                                                                                                                                                                                                    |
| capacity               | uint256               | Capacity (amount in quote token decimals or amount in payout token decimals). Set `capacityInQuote` flag appropriately.                                                                                                                                        |
| depositInterval        | uint48                | Target deposit interval for purchases (in seconds). Determines the `maxPayout` of the market. Minimum is 1 hour (3600 seconds)                                                                                                                                 |
| vesting                | uint48                | Is fixed term ? Vesting length (seconds) : Vesting expiry (timestamp). A 'vesting' param longer than 50 years is considered a timestamp for fixed expiry                                                                                                       |
| start                  | uint48                | Start time of the market as a timestamp. Allows starting a market in the future. If provided, the transaction must be sent prior to the start time. If not provided, the market will start immediately.                                                        |
| duration               | uint48                | Duration of the market in seconds.                                                                                                                                                                                                                             |

### BondMarket

BondMarket contains the token, callback, capacity, owner, and purchased/sold amount data for a Oracle Fixed Discount Market.

```solidity
struct BondMarket {
    address owner; // market owner. sends payout tokens, receives quote tokens (defaults to creator)
    ERC20 payoutToken; // token to pay depositors with
    ERC20 quoteToken; // token to accept as payment
    address callbackAddr; // address to call for any operations on bond purchase. Must inherit to IBondCallback.
    bool capacityInQuote; // capacity limit is in payment token (true) or in payout (false, default)
    uint256 capacity; // capacity remaining
    uint256 maxPayout; // max payout tokens out in one order
    uint256 sold; // payout tokens out
    uint256 purchased; // quote tokens in
}
```

### BondTerms

BondTerms contains the oracle, pricing, and time parameters of an Oracle Fixed Discount Market.

```solidity
struct BondTerms {
    IBondOracle oracle; // address to call for reference price. Must implement IBondOracle.
    uint48 start; // timestamp when market starts
    uint48 conclusion; // timestamp when market no longer offered
    uint48 vesting; // length of time from deposit to expiry if fixed-term, vesting timestamp if fixed-expiry
    uint48 baseDiscount; // base discount from oracle price, with 3 decimals of precision. E.g. 10_000 = 10%
    uint48 decaySpeed; // market price decay speed (discount achieved over a target deposit interval)
    uint256 minPrice; // minimum price (hard floor for the market)
    uint256 scale; // scaling factor for the market (see MarketParams struct)
    uint256 oracleConversion; // conversion factor for oracle -> market price
}
```

## Public Variables and View Methods

### allowNewMarkets

```solidity
function allowNewMarkets() external view returns (bool)
```

Whether or not the auctioneer allows new markets to be created

*Changing to false will sunset the auctioneer after all active markets end*

### authority

```solidity
function authority() external view returns (contract Authority)
```

Roles authority contract for the bond system which managed access-control to permissioned functions.

### callbackAuthorized

```solidity
function callbackAuthorized(address) external view returns (bool)
```

Whether or not the market creator is authorized to use a callback address

#### Parameters

| Name      | Type    | Description             |
| --------- | ------- | ----------------------- |
| creator\_ | address | Market creator address. |

### currentCapacity

```solidity
function currentCapacity(uint256 id_) external view returns (uint256)
```

Returns current capacity of a market

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### getAggregator

```solidity
function getAggregator() external view returns (contract IBondAggregator)
```

Returns the Aggregator that services the Auctioneer

### getMarketInfoForPurchase

```solidity
function getMarketInfoForPurchase(uint256 id_) external view returns (address owner, address callbackAddr, contract ERC20 payoutToken, contract ERC20 quoteToken, uint48 vesting, uint256 maxPayout_)
```

Provides information for the Teller to execute purchases on a Market

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

#### Returns

| Name         | Type           | Description                                                                       |
| ------------ | -------------- | --------------------------------------------------------------------------------- |
| owner        | address        | Address of the market owner (tokens transferred from this address if no callback) |
| callbackAddr | address        | Address of the callback contract to get tokens for payouts                        |
| payoutToken  | contract ERC20 | Payout Token (token paid out) for the Market                                      |
| quoteToken   | contract ERC20 | Quote Token (token received) for the Market                                       |
| vesting      | uint48         | Timestamp or duration for vesting, implementation-dependent                       |
| maxPayout\_  | uint256        | Maximum amount of payout tokens you can purchase in one transaction               |

### getTeller

```solidity
function getTeller() external view returns (contract IBondTeller)
```

Returns the Teller that services the Auctioneer

### isInstantSwap

```solidity
function isInstantSwap(uint256 id_) external view returns (bool)
```

Does market send payout immediately

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### isLive

```solidity
function isLive(uint256 id_) external view returns (bool)
```

Is a given market accepting deposits

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### marketPrice

```solidity
function marketPrice(uint256 id_) external view returns (uint256)
```

Calculate current market price. Value returned is the number of quote tokens per payout token. The value is the oracle price scaled by the [#bondterms](#bondterms "mention").oracleConversion factor. `marketPrice` and `marketScale` can be used to convert between amounts of quote tokens and payout tokens at the current price.

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### marketScale

```solidity
function marketScale(uint256 id_) external view returns (uint256)
```

Scale value to use when converting between quote token and payout token amounts with marketPrice()

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### markets

```solidity
function markets(uint256) external view returns (address owner, contract ERC20 payoutToken, contract ERC20 quoteToken, address callbackAddr, bool capacityInQuote, uint256 capacity, uint256 maxPayout, uint256 sold, uint256 purchased)
```

Returns the token, callback, capacity, owner, and purchased/sold amount data for a market. See [#bondmarket](#bondmarket "mention").

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### maxAmountAccepted

```solidity
function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256)
```

Returns maximum amount of quote token accepted by the market

**Parameters**

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| id\_       | uint256 | Market ID                                                                                                                                           |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

### maxPayout

```solidity
function maxPayout(uint256 id_) external view returns (uint256)
```

Calculate max payout of the market in payout tokens

*Returns a dynamically calculated payout or the maximum set by the creator, whichever is less. If the remaining capacity is less than the max payout, then that amount will be returned.*

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### minDepositInterval

```solidity
function minDepositInterval() external view returns (uint48)
```

Minimum deposit interval for a market

### minMarketDuration

```solidity
function minMarketDuration() external view returns (uint48)
```

Minimum market duration in seconds

### newOwners

```solidity
function newOwners(uint256) external view returns (address)
```

New address to designate as market owner. They must accept ownership to transfer permissions.

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### ownerOf

```solidity
function ownerOf(uint256 id_) external view returns (address)
```

Returns the address of the market owner

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### payoutFor

```solidity
function payoutFor(uint256 amount_, uint256 id_, address referrer_) external view returns (uint256)
```

Payout due for amount of quote tokens at current market price

**Parameters**

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| amount\_   | uint256 | Amount of quote tokens to spend                                                                                                                     |
| id\_       | uint256 | Market ID                                                                                                                                           |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

### terms

```solidity
function terms(uint256) external view returns (contract IBondOracle oracle, uint48 start, uint48 conclusion, uint48 vesting, uint48 fixedDiscount, uint256 minPrice, uint256 scale, uint256 oracleConversion)
```

Information pertaining to oracle, pricing, and time parameters. See [#bondterms](#bondterms "mention").

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

## State-Mutating Methods

### closeMarket

```solidity
function closeMarket(uint256 id_) external nonpayable
```

Disable existing bond market. Must be market owner

**Parameters**

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### createMarket

```solidity
function createMarket(bytes params_) external nonpayable returns (uint256)
```

Creates a new bond market

*See* [#marketparams](#marketparams "mention") for the required formatting for the abi-encoded input params.

**Parameters**

| Name     | Type  | Description                                                             |
| -------- | ----- | ----------------------------------------------------------------------- |
| params\_ | bytes | Configuration data needed for market creation, encoded in a bytes array |

#### Returns

|      |         |           |
| ---- | ------- | --------- |
| id\_ | uint256 | Market ID |

### pullOwnership

```solidity
function pullOwnership(uint256 id_) external nonpayable
```

Accept ownership of a marketMust be market newOwner

*The existing owner must call pushOwnership prior to the newOwner calling this function*

**Parameters**

|      |         |           |
| ---- | ------- | --------- |
| id\_ | uint256 | Market ID |

### purchaseBond

```solidity
function purchaseBond(uint256 id_, uint256 amount_, uint256 minAmountOut_) external nonpayable returns (uint256 payout)
```

Exchange quote tokens for a bond in a specified market. Must be teller. End users interact with the Teller contract to purchase.

**Parameters**

| Name           | Type    | Description                                                          |
| -------------- | ------- | -------------------------------------------------------------------- |
| id\_           | uint256 | Market ID                                                            |
| amount\_       | uint256 | Amount to deposit in exchange for bond (after fee has been deducted) |
| minAmountOut\_ | uint256 | Minimum acceptable amount of bond to receive. Prevents front-running |

#### Returns

| Name   | Type    | Description                                         |
| ------ | ------- | --------------------------------------------------- |
| payout | uint256 | Amount of payout token to be received from the bond |

### pushOwnership

```solidity
function pushOwnership(uint256 id_, address newOwner_) external nonpayable
```

Designate a new owner of a marketMust be market owner

*Doesn't change permissions until newOwner calls pullOwnership*

**Parameters**

| Name       | Type    | Description                      |
| ---------- | ------- | -------------------------------- |
| id\_       | uint256 | Market ID                        |
| newOwner\_ | address | New address to give ownership to |

### setAllowNewMarkets

```solidity
function setAllowNewMarkets(bool status_) external nonpayable
```

Change the status of the auctioneer to allow creation of new markets

*Setting to false and allowing active markets to end will sunset the auctioneer*

**Parameters**

| Name     | Type | Description                                                     |
| -------- | ---- | --------------------------------------------------------------- |
| status\_ | bool | Allow market creation (true) : Disallow market creation (false) |

### setCallbackAuthStatus

```solidity
function setCallbackAuthStatus(address creator_, bool status_) external nonpayable
```

Change whether a market creator is allowed to use a callback address in their markets or not. Must be guardian

*Callback is believed to be safe, but a whitelist is implemented to prevent abuse*

**Parameters**

| Name      | Type    | Description                                       |
| --------- | ------- | ------------------------------------------------- |
| creator\_ | address | Address of market creator                         |
| status\_  | bool    | Allow callback (true) : Disallow callback (false) |

### setMinDepositInterval

```solidity
function setMinDepositInterval(uint48 depositInterval_) external nonpayable
```

Set the minimum deposit interval. Access controlled

**Parameters**

| Name              | Type   | Description                         |
| ----------------- | ------ | ----------------------------------- |
| depositInterval\_ | uint48 | Minimum deposit interval in seconds |

### setMinMarketDuration

```solidity
function setMinMarketDuration(uint48 duration_) external nonpayable
```

Set the minimum market duration. Access controlled

**Parameters**

| Name       | Type   | Description                        |
| ---------- | ------ | ---------------------------------- |
| duration\_ | uint48 | Minimum market duration in seconds |

## Events

### MarketClosed

```solidity
event MarketClosed(uint256 indexed id)
```

**Parameters**

| Name         | Type    | Description |
| ------------ | ------- | ----------- |
| id `indexed` | uint256 | Market ID   |

### MarketCreated

```solidity
event MarketCreated(uint256 indexed id, address indexed payoutToken, address indexed quoteToken, uint48 vesting)
```

**Parameters**

| Name                  | Type    | Description                   |
| --------------------- | ------- | ----------------------------- |
| id `indexed`          | uint256 | Market ID                     |
| payoutToken `indexed` | address | Address of the payout token   |
| quoteToken `indexed`  | address | Address of the quote token    |
| vesting               | uint48  | Vesting duration or timestamp |

## Errors

The following custom errors are used in the OSDA contract to denote specific revert conditions. The errors are prefixed with "Auctioneer" to denote that it is within this contract when multi-contract actions are performed (such as buying a bond).

```solidity
error Auctioneer_OnlyMarketOwner();
error Auctioneer_InitialPriceLessThanMin();
error Auctioneer_MarketNotActive();
error Auctioneer_MaxPayoutExceeded();
error Auctioneer_AmountLessThanMinimum();
error Auctioneer_NotEnoughCapacity();
error Auctioneer_InvalidCallback();
error Auctioneer_BadExpiry();
error Auctioneer_InvalidParams();
error Auctioneer_NotAuthorized();
error Auctioneer_NewMarketsNotAllowed();
error Auctioneer_OraclePriceZero();
```


# Fixed-Term OSDA

### Fixed-Term OSDA Contract

The Fixed-Term OSDA is an implementation of the [Base OSDA](/smart-contracts/bond-system/auctioneer/oracle-sequential-dutch-auctioneer-osda) contract specific to creating fixed-term bond markets.&#x20;

There are no additional actions required on market creation since the ERC1155 tokens get created by the Teller on the first purchase of each day.&#x20;

As such, this can be thought of as a non-abstract implementation of the Base OSDA.


# Fixed-Expiry OSDA

### Fixed-Expiry OSDA Contract

The Fixed-Expiry OSDA is an implementation of the [Base OSDA](/smart-contracts/bond-system/auctioneer/oracle-sequential-dutch-auctioneer-osda) contract specific to creating fixed-expiry bond markets and deploying an ERC20 bond position token for the market on creation.


# Teller

The Teller contract handles all interactions with end users and manages tokens issued to represent bond positions.&#x20;

Users purchase bonds by depositing Quote Tokens and receive a Bond Token (token type is implementation-specific) that represents their payout and the designated maturity.&#x20;

Once a bond vests, users can redeem their Bond Tokens for the underlying Payout Token.&#x20;

A Teller requires one or more Auctioneer contracts to be deployed to provide markets for users to purchase bonds from.&#x20;

A Teller depends on an Aggregator contract to get market information to complete purchases.

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


# Teller Interfaces

The Teller contract handles all interactions with end users and manages tokens issued to represent bond positions. Users purchase bonds by depositing Quote Tokens and receive a Bond Token (token type is implementation-specific) that represents their payout and the designated expiry. Once a bond vests, users can redeem their Bond Tokens for the underlying Payout Token. A Teller requires one or more Auctioneer contracts to be deployed to provide markets for users to purchase bonds from.

### Teller Interface

The [Teller Interface](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/interfaces/IBondTeller.sol) defines the functions that all Teller contracts should implement.&#x20;

Significant functionality is left to specific implementations.&#x20;

The two Tellers implemented here both tokenize the bond positions, but this is not required. The functions Tellers must implement are:

```solidity
purchase
getFee
setProtocolFee // onlyGuardian
setReferrerFee
claimFees
```

### Fixed-Term Teller Interface

The [Fixed-Term Teller Interface](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/interfaces/IBondFixedTermTeller.sol) defines the functions that should be implemented to tokenize and redeem fixed-term bond positions using ERC1155 tokens.&#x20;

The required functions are:

```solidity
deploy
create
redeem
batchRedeem
getTokenId
getTokenNameAndSymbol
```

### Fixed-Expiry Teller Interface

The [Fixed-Expiry Teller Interface](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/interfaces/IBondFixedExpiryTeller.sol) defines the functions that should be implemented to tokenize and redeem fixed-maturity bond positions using ERC20 tokens. The required functions are:

```solidity
deploy
create
redeem
getBondTokenForMarket
```

The `deploy, create` and `redeem` functions are similar across each Teller that tokenizes bond positions but they differ in the arguments required and the type of token they return.


# Base Teller

The Base Teller implements standard functionality shared by both types of Bond Tellers, including the core purchase logic, fee handling, and helper functions for generating token names for bond positions.&#x20;

Logic for handling payouts and tokenizing bond positions is left to contract implementations.

## Methods

### claimFees

```solidity
function claimFees(contract ERC20[] tokens_, address to_) external nonpayable
```

Claim fees accrued for input tokens and sends to protocolMust be guardian

#### Parameters

| Name     | Type              | Description                       |
| -------- | ----------------- | --------------------------------- |
| tokens\_ | contract ERC20\[] | Array of tokens to claim fees for |
| to\_     | address           | Address to send fees to           |

### createFeeDiscount

```solidity
function createFeeDiscount() external view returns (uint48)
```

'Create' function fee discount. Amount standard fee is reduced by for partners who just want to use the 'create' function to issue bond tokens. Configurable by policy.

#### Returns

| Name        | Type   | Description                                                                          |
| ----------- | ------ | ------------------------------------------------------------------------------------ |
| feeDiscount | uint48 | Discount from base protocol purchase fee  when creating bond tokens for external use |

### getFee

```solidity
function getFee(address referrer_) external view returns (uint48)
```

Get current fee charged by the teller based on the combined protocol and referrer fee

#### Parameters

| Name       | Type    | Description             |
| ---------- | ------- | ----------------------- |
| referrer\_ | address | Address of the referrer |

#### Returns

| Name | Type   | Description                            |
| ---- | ------ | -------------------------------------- |
| fee  | uint48 | Fee in basis points (3 decimal places) |

### protocolFee

```solidity
function protocolFee() external view returns (uint48)
```

Fee paid to protocol. Configurable by policy, must be greater than 30 bps.

#### Returns

| Name        | Type   | Description |
| ----------- | ------ | ----------- |
| protocolFee | uint48 | undefined   |

### purchase

```solidity
function purchase(address recipient_, address referrer_, uint256 id_, uint256 amount_, uint256 minAmountOut_) external nonpayable returns (uint256, uint48)
```

Exchange quote tokens for a bond in a specified market

#### Parameters

| Name           | Type    | Description                                                                                                                          |
| -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| recipient\_    | address | Address of recipient of bond. Allows deposits for other addresses                                                                    |
| referrer\_     | address | Address of referrer who will receive referral fee. For frontends to fill. Direct calls can use the zero address for no referrer fee. |
| id\_           | uint256 | ID of the Market the bond is being purchased from                                                                                    |
| amount\_       | uint256 | Amount to deposit in exchange for bond                                                                                               |
| minAmountOut\_ | uint256 | Minimum acceptable amount of bond to receive. Prevents frontrunning                                                                  |

#### Returns

| Name   | Type    | Description                                                                |
| ------ | ------- | -------------------------------------------------------------------------- |
| payout | uint256 | Amount of payout token to be received from the bond                        |
| expiry | uint48  | Timestamp at which the bond token can be redeemed for the underlying token |

### referrerFees

```solidity
function referrerFees(address) external view returns (uint48)
```

Fee paid to a front end operator. Set by the referrer, must be less than or equal to 5e4.

*There are some situations where the fees may round down to zero if quantity of baseToken is < 1e5 wei (can happen with big price differences on small decimal tokens). This is purely a theoretical edge case, as the bond amount would not be practical.*

#### Parameters

| Name     | Type    | Description |
| -------- | ------- | ----------- |
| referrer | address | undefined   |

#### Returns

| Name | Type   | Description |
| ---- | ------ | ----------- |
| fee  | uint48 | undefined   |

### rewards

```solidity
function rewards(address, contract ERC20) external view returns (uint256)
```

Fees earned by an address, by token

#### Parameters

| Name     | Type           | Description |
| -------- | -------------- | ----------- |
| referrer | address        | undefined   |
| token    | contract ERC20 | undefined   |

#### Returns

| Name       | Type    | Description |
| ---------- | ------- | ----------- |
| feeBalance | uint256 | undefined   |

### setProtocolFee

```solidity
function setProtocolFee(uint48 fee_) external nonpayable
```

Set protocol feeMust be guardian

#### Parameters

| Name  | Type   | Description                                     |
| ----- | ------ | ----------------------------------------------- |
| fee\_ | uint48 | Protocol fee in basis points (3 decimal places) |

### setReferrerFee

```solidity
function setReferrerFee(uint48 fee_) external nonpayable
```

Set your fee as a referrer to the protocolFee is set for sending address

#### Parameters

| Name  | Type   | Description                                     |
| ----- | ------ | ----------------------------------------------- |
| fee\_ | uint48 | Referrer fee in basis points (3 decimal places) |

## Events

### Bonded

```solidity
event Bonded(uint256 indexed id, address indexed referrer, uint256 amount, uint256 payout)
```

#### Parameters

| Name               | Type    | Description                 |
| ------------------ | ------- | --------------------------- |
| id `indexed`       | uint256 | Market ID                   |
| referrer `indexed` | address | Referrer address            |
| amount             | uint256 | Amount of quote tokens in   |
| payout             | uint256 | Amount of payout tokens out |

## Errors

### Teller\_InvalidCallback

```solidity
error Teller_InvalidCallback()
```

### Teller\_InvalidParams

```solidity
error Teller_InvalidParams()
```

### Teller\_NotAuthorized

```solidity
error Teller_NotAuthorized()
```

### Teller\_TokenDoesNotExist

```solidity
error Teller_TokenDoesNotExist(contract ERC20 underlying, uint48 expiry)
```

#### Parameters

| Name       | Type           | Description |
| ---------- | -------------- | ----------- |
| underlying | contract ERC20 | undefined   |
| expiry     | uint48         | undefined   |

### Teller\_TokenNotMatured

```solidity
error Teller_TokenNotMatured(uint48 maturesOn)
```

#### Parameters

| Name      | Type   | Description |
| --------- | ------ | ----------- |
| maturesOn | uint48 | undefined   |

### Teller\_UnsupportedToken

```solidity
error Teller_UnsupportedToken()
```


# Fixed-Expiry Teller

The [Fixed Expiry Teller](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/BondFixedExpiryTeller.sol) is an implementation of the [Base Teller](/smart-contracts/bond-system/teller/base-teller) contract specific to handling user bond transactions and tokenizing bond markets where all purchases vest at the same timestamp as ERC20 tokens. It implements the functions required by the [Fixed-Expiry Teller Interface](/smart-contracts/bond-system/teller/teller-interfaces#fixed-expiry-teller-interface).&#x20;

Specifically, it implements the `_handlePayout` function to mint ERC20 tokens to the user to represent their bond position during a purchase.&#x20;

Additionally, it implements the `deploy` (deploys new ERC20 token contract if one does not exist for a combination of underlying token and the maturity date), `create` (allows anyone to mint Bond Tokens for a combination of an underlying token and maturity date by paying a fee to the protocol), and `redeem` (redeems ERC20 Bond Tokens that have vested for the underlying token).&#x20;

By design, the tokenization of the Teller is not permissioned. This allows other participants to use the same ERC20 Bond Tokens that Bond Protocol is issuing to create a standard in the market and drive additional liquidity.

## Methods

This section only includes methods not inherited from [Base Teller](/smart-contracts/bond-system/teller/base-teller).

### bondTokenImplementation

```solidity
function bondTokenImplementation() external view returns (contract ERC20BondToken)
```

ERC20BondToken reference implementation (deployed on creation to clone from)

#### Returns

| Name      | Type                    | Description                                                                          |
| --------- | ----------------------- | ------------------------------------------------------------------------------------ |
| reference | contract ERC20BondToken | reference address that each ERC20 bond token proxies to (using a Clone architecture) |

### bondTokens

```solidity
function bondTokens(contract ERC20, uint48) external view returns (contract ERC20BondToken)
```

ERC20 bond tokens (unique to a underlying and expiry)

#### Parameters

| Name       | Type           | Description                           |
| ---------- | -------------- | ------------------------------------- |
| underlying | contract ERC20 | Address of the underlying ERC20 token |
| expiry     | uint48         | Expiry of the bond token              |

#### Returns

| Name      | Type                    | Description                     |
| --------- | ----------------------- | ------------------------------- |
| bondToken | contract ERC20BondToken | Address of the ERC20 bond token |

### create

```solidity
function create(contract ERC20 underlying_, uint48 expiry_, uint256 amount_) external nonpayable returns (contract ERC20BondToken, uint256)
```

Deposit an ERC20 token and mint a future-dated ERC20 bond token

#### Parameters

| Name         | Type           | Description                                                                |
| ------------ | -------------- | -------------------------------------------------------------------------- |
| underlying\_ | contract ERC20 | ERC20 token redeemable when the bond token vests                           |
| expiry\_     | uint48         | Timestamp at which the bond token can be redeemed for the underlying token |
| amount\_     | uint256        | Amount of underlying tokens to deposit                                     |

#### Returns

| Name      | Type                    | Description                              |
| --------- | ----------------------- | ---------------------------------------- |
| bondToken | contract ERC20BondToken | Address of the ERC20 bond token received |
| amountOut | uint256                 | Amount of the ERC20 bond token received  |

### deploy

```solidity
function deploy(contract ERC20 underlying_, uint48 expiry_) external nonpayable returns (contract ERC20BondToken)
```

Deploy a new ERC20 bond token for an (underlying, expiry) pair and return its address

*ERC20 used for fixed-expiryIf a bond token exists for the (underlying, expiry) pair, it returns that address*

#### Parameters

| Name         | Type           | Description                                                                |
| ------------ | -------------- | -------------------------------------------------------------------------- |
| underlying\_ | contract ERC20 | ERC20 token redeemable when the bond token vests                           |
| expiry\_     | uint48         | Timestamp at which the bond token can be redeemed for the underlying token |

#### Returns

| Name      | Type                    | Description                                   |
| --------- | ----------------------- | --------------------------------------------- |
| bondToken | contract ERC20BondToken | Address of the ERC20 bond token being created |

### getBondTokenForMarket

```solidity
function getBondTokenForMarket(uint256 id_) external view returns (contract ERC20BondToken)
```

Get the OlympusERC20BondToken contract corresponding to a market

#### Parameters

| Name | Type    | Description      |
| ---- | ------- | ---------------- |
| id\_ | uint256 | ID of the market |

#### Returns

| Name      | Type                    | Description                     |
| --------- | ----------------------- | ------------------------------- |
| bondToken | contract ERC20BondToken | ERC20BondToken contract address |

### redeem

```solidity
function redeem(contract ERC20BondToken token_, uint256 amount_) external nonpayable
```

Redeem a fixed-expiry bond token for the underlying token (bond token must have matured)

#### Parameters

| Name     | Type                    | Description      |
| -------- | ----------------------- | ---------------- |
| token\_  | contract ERC20BondToken | Token to redeem  |
| amount\_ | uint256                 | Amount to redeem |

## Events

### ERC20BondTokenCreated

```solidity
event ERC20BondTokenCreated(contract ERC20BondToken bondToken, contract ERC20 indexed underlying, uint48 indexed expiry)
```

#### Parameters

| Name                 | Type                    | Description                                                            |
| -------------------- | ----------------------- | ---------------------------------------------------------------------- |
| bondToken            | contract ERC20BondToken | Address of the bond token                                              |
| underlying `indexed` | contract ERC20          | Address of the underlying ERC20 token                                  |
| expiry `indexed`     | uint48                  | Timestamp when the bond token can be redeemed for the underlying token |


# Fixed-Term Teller

The  Fixed Term Teller is an implementation of the Bond Base Teller contract specific to handling user bond transactions and tokenizing bond markets where purchases vest in a fixed amount of time (rounded to the day) as ERC1155 tokens.It implements the functions required by the [Fixed-Term Teller Interface](/smart-contracts/bond-system/teller/teller-interfaces#fixed-term-teller-interface) and the [Base Teller](/smart-contracts/bond-system/teller/base-teller) Abstract Contract.&#x20;

It also inherits the ERC1155 standard and is itself the contract which provides information on the Bond Tokens it issues.&#x20;

Specifically, it implements the `_handlePayout` function to mint ERC1155 tokens to the user to represent their bond position during a purchase.&#x20;

Additionally, it implements the `deploy` (*i.e. stores the metadata for a new ERC1155 token if one does not exist for a combination of underlying token and the maturity date*), `create` (*allows anyone to mint ERC1155 Bond Tokens for a combination of an underlying token and maturity date by paying a fee to the protocol*), and `redeem` (*redeems ERC1155 Bond Tokens that have vested for the underlying token*).&#x20;

By design, the tokenization of the Teller is not permissioned. This allows other market participants  to use the same Bond Tokens that Bond Protocol is issuing to create a standard in the market and drive additional liquidity (*less likely for ERC1155, but it is an option*).

## Methods

This section only includes methods not inherited from [Base Teller](/smart-contracts/bond-system/teller/base-teller) or [ERC1155](https://github.com/transmissions11/solmate/blob/bff24e835192470ed38bf15dbed6084c2d723ace/src/tokens/ERC1155.sol).

### batchRedeem

```solidity
function batchRedeem(uint256[] tokenIds_, uint256[] amounts_) external nonpayable
```

Redeem multiple fixed-term bond tokens for the underlying tokens (bond tokens must have matured)

#### Parameters

| Name       | Type       | Description                               |
| ---------- | ---------- | ----------------------------------------- |
| tokenIds\_ | uint256\[] | Array of bond token ids                   |
| amounts\_  | uint256\[] | Array of amounts of bond tokens to redeem |

### create

```solidity
function create(contract ERC20 underlying_, uint48 expiry_, uint256 amount_) external nonpayable returns (uint256, uint256)
```

Deposit an ERC20 token and mint a future-dated ERC1155 bond token

#### Parameters

| Name         | Type           | Description                                                                |
| ------------ | -------------- | -------------------------------------------------------------------------- |
| underlying\_ | contract ERC20 | ERC20 token redeemable when the bond token vests                           |
| expiry\_     | uint48         | Timestamp at which the bond token can be redeemed for the underlying token |
| amount\_     | uint256        | Amount of underlying tokens to deposit                                     |

#### Returns

| Name      | Type    | Description                               |
| --------- | ------- | ----------------------------------------- |
| tokenId   | uint256 | ID of the ERC1155 bond token received     |
| amountOut | uint256 | Amount of the ERC1155 bond token received |

### createFeeDiscount

```solidity
function createFeeDiscount() external view returns (uint48)
```

'Create' function fee discount. Amount standard fee is reduced by for partners who just want to use the 'create' function to issue bond tokens. Configurable by policy.

#### Returns

| Name        | Type   | Description |
| ----------- | ------ | ----------- |
| feeDiscount | uint48 | undefined   |

### deploy

```solidity
function deploy(contract ERC20 underlying_, uint48 expiry_) external nonpayable returns (uint256)
```

"Deploy" a new ERC1155 bond token for an (underlying, expiry) pair and return its ID.

#### Parameters

| Name         | Type           | Description                                                                |
| ------------ | -------------- | -------------------------------------------------------------------------- |
| underlying\_ | contract ERC20 | ERC20 token redeemable when the bond token vests                           |
| expiry\_     | uint48         | Timestamp at which the bond token can be redeemed for the underlying token |

#### Returns

| Name    | Type    | Description                                |
| ------- | ------- | ------------------------------------------ |
| tokenId | uint256 | ID of the ERC1155 bond token being created |

### getTokenId

```solidity
function getTokenId(contract ERC20 underlying_, uint48 expiry_) external pure returns (uint256)
```

Get token ID from token and expiry

#### Parameters

| Name         | Type           | Description                     |
| ------------ | -------------- | ------------------------------- |
| underlying\_ | contract ERC20 | Address of the underlying token |
| expiry\_     | uint48         | Expiry of the bond              |

#### Returns

| Name    | Type    | Description          |
| ------- | ------- | -------------------- |
| tokenId | uint256 | ID of the bond token |

### getTokenNameAndSymbol

```solidity
function getTokenNameAndSymbol(uint256 tokenId_) external view returns (string, string)
```

Get the token name and symbol for a bond token

#### Parameters

| Name      | Type    | Description          |
| --------- | ------- | -------------------- |
| tokenId\_ | uint256 | ID of the bond token |

#### Returns

| Name   | Type   | Description       |
| ------ | ------ | ----------------- |
| name   | string | Bond token name   |
| symbol | string | Bond token symbol |

### redeem

```solidity
function redeem(uint256 tokenId_, uint256 amount_) external nonpayable
```

Redeem a fixed-term bond token for the underlying token (bond token must have matured)

#### Parameters

| Name      | Type    | Description                    |
| --------- | ------- | ------------------------------ |
| tokenId\_ | uint256 | ID of the bond token to redeem |
| amount\_  | uint256 | Amount of bond token to redeem |

### tokenMetadata

```solidity
function tokenMetadata(uint256) external view returns (bool active, contract ERC20 payoutToken, uint48 expiry, uint256 supply)
```

#### Parameters

| Name      | Type    | Description          |
| --------- | ------- | -------------------- |
| tokenId\_ | uint256 | ID of the bond token |

#### Returns

| Name        | Type           | Description                                                             |
| ----------- | -------------- | ----------------------------------------------------------------------- |
| active      | bool           | Whether the bond token has been created                                 |
| payoutToken | contract ERC20 | Address of the underlying token                                         |
| expiry      | uint48         | Timestamp when the bond token can be exchanged for the underlying token |
| supply      | uint256        | Total supply of the bond token                                          |

## Events

### ERC1155BondTokenCreated

```solidity
event ERC1155BondTokenCreated(uint256 tokenId, contract ERC20 indexed payoutToken, uint48 indexed expiry)
```

#### Parameters

| Name                  | Type           | Description                                                            |
| --------------------- | -------------- | ---------------------------------------------------------------------- |
| tokenId               | uint256        | ID of the ERC1155 bond token                                           |
| payoutToken `indexed` | contract ERC20 | Address of the underlying token                                        |
| expiry `indexed`      | uint48         | Timestamp when the bond token can be redeemed for the underlying token |


# Callback

The Callback contract is an optional feature of the Bond system.&#x20;

Callbacks allow issuers (market creators) to apply custom logic on receipt and payout of tokens. The Callback must be created prior to market creation and the address passed in as an argument. The Callback depends on the Aggregator contract for the Auctioneer that the market is created with to get market data.

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


# Callback Interface

The Callback Interface defines the functions that all Callback contracts should implement. These have been kept to a minimum to the functions necessary to ensure functionality and security. Each Callback contract should implement:

```solidity
callback
amountsForMarket
whitelist
deposit
withdraw
```


# Base Callback

The [Base Callback](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/bases/BondBaseCallback.sol) contract is an optional feature of the Bond system. Callbacks allow issuers (market creators) to apply custom logic on receipt and payout of tokens.&#x20;

In addition to the [Callback Interface](/smart-contracts/bond-system/callback/callback-interface), the Base Callback is also implemented to provide a secure starting point for creating a Callback contract.&#x20;

The base handles permissioning of Tellers (*and specific markets served by the Teller*) to avoid unauthorized contracts from accessing the callback function.&#x20;

Additionally, the setup and data storage for getting data from an Aggregator.&#x20;

Finally, the external callback function is implemented to ensure the Teller is providing the stated amount of Quote Tokens prior to disbursing Payout Tokens. Issuer-specific logic can be implemented in the `_callback` internal function which is called by the external one.

The Callback must be created prior to market creation and the address passed in as an argument. The Callback depends on the Aggregator contract for the Auctioneer that the market is created to get market data. Without a Callback contract, payout tokens are transferred directly from the market owner on each bond purchase (market owners must approve the Teller serving that market for the amount of Payout Tokens equivalent to the capacity of a market when created.

## Methods

### amountsForMarket

```solidity
function amountsForMarket(uint256 id_) external view returns (uint256 in_, uint256 out_)
```

Returns the number of quote tokens received and payout tokens paid out for a market

#### Parameters

| Name | Type    | Description      |
| ---- | ------- | ---------------- |
| id\_ | uint256 | ID of the market |

#### Returns

| Name  | Type    | Description                                    |
| ----- | ------- | ---------------------------------------------- |
| in\_  | uint256 | Amount of quote tokens bonded to the market    |
| out\_ | uint256 | Amount of payout tokens paid out to the market |

### approvedMarkets

```solidity
function approvedMarkets(address, uint256) external view returns (bool)
```

#### Parameters

| Name     | Type    | Description                    |
| -------- | ------- | ------------------------------ |
| teller\_ | address | Address of the Teller contract |
| id\_     | uint256 | ID of the market               |

#### Returns

| Name     | Type | Description                                                               |
| -------- | ---- | ------------------------------------------------------------------------- |
| approved | bool | Whether the Teller and Market ID combination are approved on the callback |

### callback

```solidity
function callback(uint256 id_, uint256 inputAmount_, uint256 outputAmount_) external nonpayable
```

Send payout tokens to Teller while allowing market owners to perform custom logic on received or paid out tokensMarket ID on Teller must be whitelisted

*Must transfer the output amount of payout tokens back to the TellerShould check that the quote tokens have been transferred to the contract in the \_callback function*

#### Parameters

| Name           | Type    | Description                                          |
| -------------- | ------- | ---------------------------------------------------- |
| id\_           | uint256 | ID of the market                                     |
| inputAmount\_  | uint256 | Amount of quote tokens bonded to the market          |
| outputAmount\_ | uint256 | Amount of payout tokens to be paid out to the market |

### deposit

```solidity
function deposit(contract ERC20 token_, uint256 amount_) external nonpayable
```

Deposit tokens to the callback and update balancesOnly callback owner

#### Parameters

| Name     | Type           | Description                     |
| -------- | -------------- | ------------------------------- |
| token\_  | contract ERC20 | Address of the token to deposit |
| amount\_ | uint256        | Amount of tokens to deposit     |

### owner

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

*Returns the address of the current owner.*

#### Returns

| Name  | Type    | Description                                 |
| ----- | ------- | ------------------------------------------- |
| owner | address | Owner of the callback with admin privileges |

### renounceOwnership

```solidity
function renounceOwnership() external nonpayable
```

*Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.*

### transferOwnership

```solidity
function transferOwnership(address newOwner) external nonpayable
```

*Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.*

#### Parameters

| Name     | Type    | Description                      |
| -------- | ------- | -------------------------------- |
| newOwner | address | Address to transfer ownership to |

### whitelist

```solidity
function whitelist(address teller_, uint256 id_) external nonpayable
```

Whitelist a teller and market ID combinationMust be callback owner

#### Parameters

| Name     | Type    | Description                                            |
| -------- | ------- | ------------------------------------------------------ |
| teller\_ | address | Address of the Teller contract which serves the market |
| id\_     | uint256 | ID of the market                                       |

### withdraw

```solidity
function withdraw(address to_, contract ERC20 token_, uint256 amount_) external nonpayable
```

Withdraw tokens from the callback and update balancesOnly callback owner

#### Parameters

| Name     | Type           | Description                      |
| -------- | -------------- | -------------------------------- |
| to\_     | address        | Address of the recipient         |
| token\_  | contract ERC20 | Address of the token to withdraw |
| amount\_ | uint256        | Amount of tokens to withdraw     |

## Events

### OwnershipTransferred

```solidity
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
```

#### Parameters

| Name                    | Type    | Description               |
| ----------------------- | ------- | ------------------------- |
| previousOwner `indexed` | address | Address of previous owner |
| newOwner `indexed`      | address | Address of new owner      |

## Errors

### Callback\_MarketNotSupported

```solidity
error Callback_MarketNotSupported(uint256 id)
```

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id   | uint256 | ID of market |

### Callback\_TokensNotReceived

```solidity
error Callback_TokensNotReceived()
```


# Sample Callback Contract

For issuers that do not have custom logic to implement in the callback function, but would like to receive Quote Tokens and pay out Payout Tokens from a standalone contract vs. a multi-sig or EOA, the [Sample Callback Contract](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/BondSampleCallback.sol) has been implemented to facilitate this.&#x20;

This contract inherits the Base Callback and transfers the requested Payout Tokens to the Teller after confirming that the correct number of Quote Tokens have been transferred in.&#x20;

This contract relies on a good data trust assumption from the Teller.


# Aggregator

The Aggregator keeps a unique set of market IDs across multiple Tellers and Auctioneers.&#x20;

Additionally, it aggregates market data from multiple Auctioneers in convenient view functions. The main idea is that the Aggregator is a single point for information within the system about available markets.&#x20;

This contract can therefore be used by users, front-ends, and other contracts to find and obtain information about any market. &#x20;

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


# Aggregator Interface

The Aggregator Interface defines the functions that the Aggregator Contract should implement. Some of the functions are specific to the operations of the Aggregator, while others just route view functions to the correct Auctioneer to return data.&#x20;

The Aggregator functions are:

* **Permissions**

```solidity
registerAuctioneer // only Olympus Guardian
registerMarket // only whitelisted Auctioneers
```

* **View**

```solidity
getAuctioneer
marketPrice
payoutFor
maxAmountAccepted
isInstantSwap
isLive
liveMarketsBetween
liveMarketsFor
marketsFor
findMarketFor
getTellerForMarket
currentCapacity
```


# Aggregator Contract

The Aggregator Contract implements the functions required in the [Aggregator Interface](/smart-contracts/bond-system/aggregator/aggregator-interface).&#x20;

Additionally, it implements state variables for the management of markets across multiple Auctioneers, tracking whitelisted Auctioneers.

The Aggregator contract keeps a unique set of market IDs across multiple Tellers and Auctioneers. Additionally, it aggregates market data from multiple Auctioneers in convenient view functions for front-end interfaces.

## Methods

### currentCapacity

```solidity
function currentCapacity(uint256 id_) external view returns (uint256)
```

Returns current capacity of a market

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

#### Returns

| Name     | Type    | Description                    |
| -------- | ------- | ------------------------------ |
| capacity | uint256 | Current capacity of the market |

### findMarketFor

```solidity
function findMarketFor(address payout_, address quote_, uint256 amountIn_, uint256 minAmountOut_, uint256 maxExpiry_) external view returns (uint256)
```

Returns the market ID with the highest current payoutToken payout for depositing quoteToken

#### Parameters

| Name           | Type    | Description                                                                                                           |
| -------------- | ------- | --------------------------------------------------------------------------------------------------------------------- |
| payout\_       | address | Address of payout token                                                                                               |
| quote\_        | address | Address of quote token                                                                                                |
| amountIn\_     | uint256 | Amount of quote tokens to deposit                                                                                     |
| minAmountOut\_ | uint256 | Minimum amount of payout tokens to receive as payout                                                                  |
| maxExpiry\_    | uint256 | Latest acceptable vesting timestamp for bond Inputting the zero address will take into account just the protocol fee. |

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### getAuctioneer

```solidity
function getAuctioneer(uint256 id_) external view returns (contract IBondAuctioneer)
```

Get the auctioneer for the provided market ID

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

#### Returns

| Name       | Type                     | Description                                        |
| ---------- | ------------------------ | -------------------------------------------------- |
| auctioneer | contract IBondAuctioneer | Address of the auctioneer that provides the market |

### getTeller

```solidity
function getTeller(uint256 id_) external view returns (contract IBondTeller)
```

Returns the Teller that services the market ID

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

#### Returns

| Name   | Type                 | Description                                    |
| ------ | -------------------- | ---------------------------------------------- |
| teller | contract IBondTeller | Address of the teller that services the market |

### isInstantSwap

```solidity
function isInstantSwap(uint256 id_) external view returns (bool)
```

Does market send payout immediately

#### Parameters

| Name | Type    | Description             |
| ---- | ------- | ----------------------- |
| id\_ | uint256 | Market ID to search for |

#### Returns

| Name      | Type | Description                                                                    |
| --------- | ---- | ------------------------------------------------------------------------------ |
| isInstant | bool | Whether the market is instant swap (true) or has vesting of the payout (false) |

### isLive

```solidity
function isLive(uint256 id_) external view returns (bool)
```

Is a given market accepting purchases

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name   | Type | Description                               |
| ------ | ---- | ----------------------------------------- |
| isLive | bool | Whether the market is accepting purchases |

### liveMarketsBetween

```solidity
function liveMarketsBetween(uint256 firstIndex_, uint256 lastIndex_) external view returns (uint256[])
```

Returns array of active market IDs within a range

*Should be used if length exceeds max to query entire array*

#### Parameters

| Name         | Type    | Description                 |
| ------------ | ------- | --------------------------- |
| firstIndex\_ | uint256 | Start index of market range |
| lastIndex\_  | uint256 | End index of market range   |

#### Returns

| Name | Type       | Description    |
| ---- | ---------- | -------------- |
| ids  | uint256\[] | IDs of markets |

### liveMarketsBy

```solidity
function liveMarketsBy(address owner_) external view returns (uint256[])
```

Returns an array of all active market IDs for a given owner

#### Parameters

| Name    | Type    | Description                  |
| ------- | ------- | ---------------------------- |
| owner\_ | address | Address of owner to query by |

#### Returns

| Name | Type       | Description    |
| ---- | ---------- | -------------- |
| ids  | uint256\[] | IDs of markets |

### liveMarketsFor

```solidity
function liveMarketsFor(address token_, bool isPayout_) external view returns (uint256[])
```

Returns an array of all active market IDs for a given quote token

#### Parameters

| Name       | Type    | Description                                                  |
| ---------- | ------- | ------------------------------------------------------------ |
| token\_    | address | Address of token to query by                                 |
| isPayout\_ | bool    | If true, search by payout token, else search for quote token |

#### Returns

| Name | Type       | Description    |
| ---- | ---------- | -------------- |
| ids  | uint256\[] | IDs of markets |

### marketCounter

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

Counter for bond markets on approved auctioneers

#### Returns

| Name   | Type    | Description                   |
| ------ | ------- | ----------------------------- |
| nextId | uint256 | Next market ID to be assigned |

### marketPrice

```solidity
function marketPrice(uint256 id_) external view returns (uint256)
```

Calculate current market price of payout token in quote tokens

*Accounts for debt and control variable decay since last deposit (vs \_marketPrice())*

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name  | Type    | Description                                              |
| ----- | ------- | -------------------------------------------------------- |
| price | uint256 | Price for market (see the specific auctioneer for units) |

### marketScale

```solidity
function marketScale(uint256 id_) external view returns (uint256)
```

Scale value to use when converting between quote token and payout token amounts with marketPrice()

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name  | Type    | Description                                                                 |
| ----- | ------- | --------------------------------------------------------------------------- |
| scale | uint256 | Scaling factor for market in configured decimals (see auctioneer for units) |

### marketsFor

```solidity
function marketsFor(address payout_, address quote_) external view returns (uint256[])
```

Returns an array of all active market IDs for a given payout and quote token

#### Parameters

| Name     | Type    | Description             |
| -------- | ------- | ----------------------- |
| payout\_ | address | Address of payout token |
| quote\_  | address | Address of quote token  |

#### Returns

| Name | Type       | Description    |
| ---- | ---------- | -------------- |
| ids  | uint256\[] | IDs of markets |

### marketsForPayout

```solidity
function marketsForPayout(address, uint256) external view returns (uint256)
```

Market IDs for payout token

#### Parameters

| Name          | Type    | Description             |
| ------------- | ------- | ----------------------- |
| payoutToken\_ | address | Address of payout token |

#### Returns

| Name | Type    | Description    |
| ---- | ------- | -------------- |
| ids  | uint256 | IDs of markets |

### marketsForQuote

```solidity
function marketsForQuote(address) external view returns (uint256)
```

Market IDs for quote token

#### Parameters

| Name         | Type    | Description            |
| ------------ | ------- | ---------------------- |
| quoteToken\_ | address | Address of quote token |

#### Returns

| Name | Type    | Description    |
| ---- | ------- | -------------- |
| ids  | uint256 | IDs of markets |

### marketsToAuctioneers

```solidity
function marketsToAuctioneers(uint256) external view returns (contract IBondAuctioneer)
```

Auctioneer for Market ID

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name       | Type                     | Description                     |
| ---------- | ------------------------ | ------------------------------- |
| auctioneer | contract IBondAuctioneer | Auctioneer that provides market |

### maxAmountAccepted

```solidity
function maxAmountAccepted(uint256 id_, address referrer_) external view returns (uint256)
```

Returns maximum amount of quote token accepted by the market

#### Parameters

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| id\_       | uint256 | ID of market                                                                                                                                        |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

#### Returns

| Name     | Type    | Description                                                               |
| -------- | ------- | ------------------------------------------------------------------------- |
| amountIn | uint256 | Max amount of quote token that can currently be exchanged with the market |

### payoutFor

```solidity
function payoutFor(uint256 amount_, uint256 id_, address referrer_) external view returns (uint256)
```

Payout due for amount of quote tokens

*Accounts for debt and control variable decay so it is up to date*

#### Parameters

| Name       | Type    | Description                                                                                                                                         |
| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| amount\_   | uint256 | Amount of quote tokens to spend                                                                                                                     |
| id\_       | uint256 | ID of market                                                                                                                                        |
| referrer\_ | address | Address of referrer, used to get fees to calculate accurate payout amount. Inputting the zero address will take into account just the protocol fee. |

#### Returns

| Name   | Type    | Description                        |
| ------ | ------- | ---------------------------------- |
| payout | uint256 | amount of payout tokens to be paid |

### registerAuctioneer

```solidity
function registerAuctioneer(contract IBondAuctioneer auctioneer_) external nonpayable
```

Register a auctioneer with the aggregatorOnly Guardian

*A auctioneer must be registered with an aggregator to create markets*

#### Parameters

| Name         | Type                     | Description                           |
| ------------ | ------------------------ | ------------------------------------- |
| auctioneer\_ | contract IBondAuctioneer | Address of the Auctioneer to register |

### registerMarket

```solidity
function registerMarket(contract ERC20 payoutToken_, contract ERC20 quoteToken_) external nonpayable returns (uint256 marketId)
```

Register a new market with the aggregatorOnly registered depositories

#### Parameters

| Name          | Type           | Description                        |
| ------------- | -------------- | ---------------------------------- |
| payoutToken\_ | contract ERC20 | Token to be paid out by the market |
| quoteToken\_  | contract ERC20 | Token to be accepted by the market |

#### Returns

| Name     | Type    | Description  |
| -------- | ------- | ------------ |
| marketId | uint256 | ID of market |

## Errors

### Aggregator\_OnlyAuctioneer

```solidity
error Aggregator_OnlyAuctioneer()
```


# Intended User Actions

Describes intended user actions with the smart contracts

### Issuer

Issuers primarily interface with Auctioneers to create markets. If they choose to use a Callback contract, it must be deployed before creating a market. After the market is created, it will need to be whitelisted on the Callback. The same Callback can be used for multiple markets across multiple Auctioneers.&#x20;

Issuers can end markets at any time on the Auctioneer and set certain variables for a market after creation, such as `tuneInterval`, `tuneAdjustmentDelay`, and `debtDecayInterval`.&#x20;

However it is not recommended to change these unless the Issuer is experienced and knowledgeable about how it will impact the market operation. <mark style="color:red;">If in doubt, please reach out to Bond Protocol team.</mark>

<figure><img src="/files/1Ena4LU2baNkVSBaUAnE" alt=""><figcaption></figcaption></figure>

### End user

End users primarily interact with the Aggregator to get market information and the Teller to purchase and redeem bonds.&#x20;

The following diagram shows the main actions expected from end users:

<figure><img src="/files/23G62xhDl0xlU9oZpM0f" alt=""><figcaption></figcaption></figure>


# Limit Orders

The `LimitOrders.sol` contract is a settlement contract for executing orders from our off-chain limit order service. Users approve the contract to spend their tokens and provide signatures of their `Order` to an off-chain API. An order execution bot monitors markets and executes them against this contract when allowed. Orders are executed on the contract by providing the Order parameters and an EIP712 Typed Data Signature of the Order, using the contracts domain information, to the `executeOrder` function.  The functions to execute orders on the contract are permissioned in the initial version as a security precaution.

## Data Structures

```solidity
struct Order {
    uint256 marketId;
    address recipient;
    address referrer;
    uint256 amount;
    uint256 minAmountOut;
    uint256 maxFee;
    uint256 submitted;
    uint256 deadline;
    address user;
}
```

| Field        | Type    | Description                                                                                                                                                                                                            |
| ------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| marketId     | uint256 | ID of the market that the order is for                                                                                                                                                                                 |
| recipient    | address | Address that will receive the payout of the order                                                                                                                                                                      |
| referrer     | address | Referrer address for the order. May receive a fee if set on the Teller contract for the market.                                                                                                                        |
| amount       | uint256 | Amount of quote tokens to spend on the order, in quote token decimals                                                                                                                                                  |
| minAmountOut | uint256 | Minimum amount of payout tokens to receive from the order, in payout token decimals                                                                                                                                    |
| maxFee       | uint256 | Maximum fee in the quote token that the user is willing to process the order, in quote token decimals                                                                                                                  |
| submitted    | uint256 | Timestamp that the order was submitted at. Used by the off-chain service to give priority to equivalent orders. API will not accept an order where the submitted date is a certain amount older than the current time. |
| deadline     | uint256 | Timestamp that the order is valid until. The order will not be executable after this time.                                                                                                                             |
| user         | address | Address that the order proceeds will come from and that is required to sign the order.                                                                                                                                 |

```solidity
enum Status {
    Open,
    Executed,
    Cancelled
}
```

## Public Variables and View Methods

#### DOMAIN\_SEPARATOR

```solidity
function DOMAIN_SEPARATOR() external view returns (bytes32)
```

The current domain separator hashed used to verify EIP712 signatures.

#### aggregator

```solidity
function aggregator() external view returns (contract IBondAggregator)
```

The Bond Aggregator contract (i.e. top-level contract of the bond system) that this settlement contract supports.

#### authority

```solidity
function authority() external view returns (contract Authority)
```

The Authority contract that determine access to permissioned functions on the contract.

#### chainId

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

Currently cached value for the chain ID.

#### getDigest

```solidity
function getDigest(LimitOrders.Order order_) external view returns (bytes32)
```

Returns the hash digest of the provided order. Used to calculate a unique order identifier and verify EIP712 signatures of Orders.

#### orderStatus

```solidity
function orderStatus(bytes32) external view returns (enum LimitOrders.Status)turns
```

Returns the `Status` of an order (identified by its hash digest).

## State-Mutating Methods

#### cancelOrder

```solidity
function cancelOrder(LimitOrders.Order order_) external nonpayable
```

Cancels an order on the settlement contract. A cancelled order cannot be executed, even by a permissioned executor.

**Parameters**

| Name    | Type              | Description                                                       |
| ------- | ----------------- | ----------------------------------------------------------------- |
| order\_ | LimitOrders.Order | Order parameters. Specified in the Data Structures section above. |

#### executeOrder

```solidity
function executeOrder(LimitOrders.Order order_, bytes signature_, uint256 fee_) external nonpayable
```

Execute a single order. Permissioned.

**Parameters**

| Name        | Type              | Description                                                                                                                                                                               |
| ----------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| order\_     | LimitOrders.Order | Order parameters. Specified in the Data Structures section above.                                                                                                                         |
| signature\_ | bytes             | ECDSA signature of the EIP712 hash digest of the `order_` by `order_.user`                                                                                                                |
| fee\_       | uint256           | Amount of quote tokens to charge as a fee. Must be less than or equal to `order_.maxFee`. Determined by the executor based on network gas fees and token prices at the time of execution. |

#### executeOrders

```solidity
function executeOrders(LimitOrders.Order[] orders_, bytes[] signatures_, uint256[] fees_) external nonpayable
```

Execute multiple orders in one transaction. Permissioned.

**Parameters**

| Name         | Type                 | Description                                                                                                                                                                                                                   |
| ------------ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| orders\_     | LimitOrders.Order\[] | Array of Order parameters. Specified in the Data Structures section above.                                                                                                                                                    |
| signatures\_ | bytes\[]             | Array of ECDSA signatures of the EIP712 hash digest of the corresponding `order_` by `order_.user`                                                                                                                            |
| fees\_       | uint256\[]           | Array of quote token amounts to charge as a fee on the corresponding `order_`. Must be less than or equal to `order_.maxFee`. Determined by the executor based on network gas fees and token prices at the time of execution. |

#### reinstateOrder

```solidity
function reinstateOrder(LimitOrders.Order order_) external nonpayable
```

Reinstates a previously cancelled order.

**Parameters**

| Name    | Type              | Description |
| ------- | ----------------- | ----------- |
| order\_ | LimitOrders.Order | undefined   |

#### updateDomainSeparator

```solidity
function updateDomainSeparator() external nonpayable
```

Updates the cached domain separator in the event that the chainId changes. Saves gas on future digest computations.

## Events

#### AuthorityUpdated

```solidity
event AuthorityUpdated(address indexed user, contract Authority indexed newAuthority)
```

**Parameters**

| Name                   | Type               | Description |
| ---------------------- | ------------------ | ----------- |
| user `indexed`         | address            | undefined   |
| newAuthority `indexed` | contract Authority | undefined   |

#### OrderCancelled

```solidity
event OrderCancelled(bytes32 digest)
```

**Parameters**

| Name   | Type    | Description |
| ------ | ------- | ----------- |
| digest | bytes32 | undefined   |

#### OrderExecuted

```solidity
event OrderExecuted(bytes32 digest)
```

**Parameters**

| Name   | Type    | Description |
| ------ | ------- | ----------- |
| digest | bytes32 | undefined   |

#### OrderReinstated

```solidity
event OrderReinstated(bytes32 digest)
```

**Parameters**

| Name   | Type    | Description |
| ------ | ------- | ----------- |
| digest | bytes32 | undefined   |

#### OwnerUpdated

```solidity
event OwnerUpdated(address indexed user, address indexed newOwner)
```

**Parameters**

| Name               | Type    | Description |
| ------------------ | ------- | ----------- |
| user `indexed`     | address | undefined   |
| newOwner `indexed` | address | undefined   |

## Errors

#### LimitOrders\_AlreadyExecuted

```solidity
error LimitOrders_AlreadyExecuted(bytes32 digest)
```

**Parameters**

| Name   | Type    | Description |
| ------ | ------- | ----------- |
| digest | bytes32 | undefined   |

#### LimitOrders\_InvalidFee

```solidity
error LimitOrders_InvalidFee(uint256 fee, uint256 maxFee)
```

**Parameters**

| Name   | Type    | Description |
| ------ | ------- | ----------- |
| fee    | uint256 | undefined   |
| maxFee | uint256 | undefined   |

#### LimitOrders\_InvalidParams

```solidity
error LimitOrders_InvalidParams()
```

#### LimitOrders\_InvalidSignature

```solidity
error LimitOrders_InvalidSignature(bytes signature)
```

**Parameters**

| Name      | Type  | Description |
| --------- | ----- | ----------- |
| signature | bytes | undefined   |

#### LimitOrders\_InvalidUpdate

```solidity
error LimitOrders_InvalidUpdate()
```

#### LimitOrders\_InvalidUser

```solidity
error LimitOrders_InvalidUser()
```

#### LimitOrders\_MarketClosed

```solidity
error LimitOrders_MarketClosed(uint256 marketId)
```

**Parameters**

| Name     | Type    | Description |
| -------- | ------- | ----------- |
| marketId | uint256 | undefined   |

#### LimitOrders\_NotAuthorized

```solidity
error LimitOrders_NotAuthorized()
```

#### LimitOrders\_OrderCancelled

```solidity
error LimitOrders_OrderCancelled(bytes32 digest)
```

**Parameters**

| Name   | Type    | Description |
| ------ | ------- | ----------- |
| digest | bytes32 | undefined   |

#### LimitOrders\_OrderExpired

```solidity
error LimitOrders_OrderExpired(uint256 deadline)
```

**Parameters**

| Name     | Type    | Description |
| -------- | ------- | ----------- |
| deadline | uint256 | undefined   |


# Option System

Overview of the Bond Protocol Option system contracts

Smart contracts for Option Tokens (oTokens) and Options Liquidity Mining (OLM).

### Background

Our mission [began as a paradigm shift](https://medium.com/@Bond_Protocol/introducing-bond-protocol-8476881f84e4) in the way protocols utilize emissions to acquire assets, own liquidity, and diversify their treasuries. Liquidity mining incentives are still, for better or worse, widely utilized in crypto to incentivize early network participants providing a valuable service - liquidity.

But incentives naturally attract short-term participants and [mercenary capital](https://www.nansen.ai/research/all-hail-masterchef-analysing-yield-farming-activity). Liquidity is also inherently temporary, a good mental model is that LM incentives "rent" liquidity.

**Re-contextualizing liquidity mining incentives as call options unlocks the ability for protocols to capture value and own their liquidity.**

This implementation draws inspiration from a number of sources including:

* Andre Cronje - [Liquidity Mining Rewards v2](https://andrecronje.medium.com/liquidity-mining-rewards-v2-50896e44f259)
* TapiocaDAO - [R.I.P Liquidity Mining](https://mirror.xyz/tapiocada0.eth/CYZVxI_zyislBjylOBXdE2nS-aP-ZxxE8SRgj_YLLZ0)
* Timeless Finance - [Bunni oLIT](https://docs.bunni.pro/docs/tokenomics/olit)

### Overview

Bond Protocol's Option System is a flexible system for unlocking the power of Option Liquidity Mining (OLM) for projects of all sizes. We incorporated insights gained from bonding, notably designing a system that can be used with or without a price oracle.

#### [Fixed Strike oTokens](/smart-contracts/option-system/fixed-strike-otokens)

ERC20 implementation of a Fixed-Strike Option Token (oToken). When the token is created, strike price is set to a fixed exchange rate between two ERC20 tokens - the Payout and Quote tokens. oTokens inherit the units of the Payout token, and they are created 1:1. The Strike Price is provided in Quote token units and is formatted as the number of Quote tokens per Payout token. Timestamps are used to determine when the option is Eligible to be exercised and its Expiry, beyond which it cannot be exercised. The interplay between Eligible and Expiry times gives rise to the entire design space between American-style and European-style options.

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

#### [Fixed Strike Option Teller](/smart-contracts/option-system/fixed-strike-option-teller)

The Teller contract handles token accounting and manages interactions with end users exercising options. oTokens can be permissionlessly deployed and created by depositing the appropriate quantity of tokens as collateral. oTokens can be used as incentives via the OLM contracts, used within an existing ERC20 reward contract, or sold via a bond market (likely in an instant swap). Users can exercise their options by providing the appropriate quantity of tokens as payment alongside Eligible (but not Expired) option tokens. Exercised oTokens are burned after being provided to the Teller. After Expiry, the Receiver can reclaim collateral from unexercised options. Receivers can unwrap oTokens they possess at any time via the exercise function.

#### [Options Liquidity Mining (OLM)](/smart-contracts/option-system/options-liquidity-mining-olm)

Liquidity mining implementation that issues oToken rewards to stakers via an epoch-based system. OLM instances are deployed with immutable Staked Token (ex: LP token), Payout Token, and Option Teller addresses. Owners manage parameters used to create oTokens for a given epoch, as well as that epoch's duration and reward rate. Strike price can be set for the next epoch via a Manual implementation (only Owner) or based on a set discount from Oracle price. Owners manage rewards payouts in the OLM contract by directing sending (or withdrawing) Payout Tokens to the contract.

Users can stake and un-stake tokens at any time. An emergency un-stake function is provided for edge cases, but users will forfeit all rewards if stake is withdrawn using this function. Rewards can be claimed for each eligible epoch. Option tokens which have already expired are not claimed in order to save on gas costs.

New epochs can be triggered manually by the Owner, or they can be started when users call a function that tries to start a new epoch. If a user starts a new epoch, they are sent Option Tokens as the Epoch Transition Reward in order to compensate for increased gas cost paid.

Setting up an OLM requires three steps.

1. Deploy an OLM contract from a [factory](/smart-contracts/option-system/olm-factories).
2. Fund the OLM contract with `payoutTokens` to pay rewards with (via a simple ERC20 transfer). Owners must monitor the balance of `payoutTokens` in the contract to ensure that users can claim their rewards.&#x20;
3. [Initialize](#initialize) the OLM contract, including inputting the remaining options and staking parameters.

#### [OLM Factory](/smart-contracts/option-system/olm-factories)

Factory contracts deploy instances of OLM contracts. The MOLMFactory deploys ManualStrikeOLM contracts, and the OOLMFactory deploys OracleStrikeOLM contracts. The sender of a deploy transaction is made the owner of the OLM contract. OLM contracts are not active when deployed. Owners must deposit rewards to the contract and then to call `initialize` to provide additional inputs and allow deposits.

### Design Decisions

In designing this system, we made a few opinionated decisions that differentiate it from other option protocols:

1. Our oTokens are Physically Settled, meaning that the underlying assets are actually exchanged when the option is exercised. This is in contrast to some systems which use Cash Settlement, where the difference in value from the strike price and the market price is exchanged in a separate unit of account asset when exercised. Traditional options markets often work on a cash settlement basis, but for protocols issuing options as rewards, physical settlement is superior since they often have large amounts of their native token and little "reserves".
2. Our initial oToken implementations use a fixed strike price determined when it is deployed instead of an oracle to track market price over time. Oracles are a challenging problem and are expensive to maintain. This means that many projects, especially new ones, do not have reliable oracles for their tokens. Liquidity mining is more common in early stage projects so it makes sense to build a system that is usable without an oracle. However, we recognize the convenience of reliable oracles and did make a version of the OLM contract which uses an oracle to set the fixed strike price at the beginning of each epoch. Our token + teller design can easily be extended to a true oracle-strike version in the future.
3. We sacrificed some fungibility of our oTokens by having each be unique to a `receiver` address in order to route proceeds from oToken exercises directly to the issuer (while providing them some flexibility on where these funds go). Our primary use case is not creating an exchange for options, and, therefore fungibility of the tokens was not the top priority. A future version may alter this part of the design to be more fungible.
4. Our oTokens have configurable `eligible` and `expiry` dates which allow for the creation of European options (only exercisable at the expiry), American options (exercisable any time from issuance up to expiry), or somewhere in between. Other options do not have expiries or implement one specific flavor.

### Audits

The smart contracts in this repository were audited by Sherlock. The comprehensive audit report can be found in the `audit/` directory of the GitHub repository.

### License

The source code of this project is licensed under the AGPL 3.0 license.

### Deployments

#### Testnets

| Contract                | Address                                    | Goerli                                                                                             | Arbitrum Goerli                                                                                  |
| ----------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| FixedStrikeOptionTeller | 0xF507733f260a42bB2c8108dE87B7B0Ce5826A9cD | [Goerli Etherscan](https://goerli.etherscan.io/address/0xF507733f260a42bB2c8108dE87B7B0Ce5826A9cD) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0xF507733f260a42bB2c8108dE87B7B0Ce5826A9cD) |
| MOLMFactory             | 0x301378372314F1976d054f159FC9A5CDCA040FC0 | [Goerli Etherscan](https://goerli.etherscan.io/address/0x301378372314F1976d054f159FC9A5CDCA040FC0) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0x301378372314F1976d054f159FC9A5CDCA040FC0) |
| OOLMFactory             | 0x0013d3a7aF301f235eecc1a85F9fdaA72038A75b | [Goerli Etherscan](https://goerli.etherscan.io/address/0x0013d3a7aF301f235eecc1a85F9fdaA72038A75b) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0x0013d3a7aF301f235eecc1a85F9fdaA72038A75b) |

#### Production

| Contract                | Address                                    | Mainnet                                                                              | Arbitrum                                                                           |
| ----------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- |
| FixedStrikeOptionTeller | 0xF507733f260a42bB2c8108dE87B7B0Ce5826A9cD | [Etherscan](https://etherscan.io/address/0xF507733f260a42bB2c8108dE87B7B0Ce5826A9cD) | [Arbiscan](https://arbiscan.io/address/0xF507733f260a42bB2c8108dE87B7B0Ce5826A9cD) |
| MOLMFactory             | 0x301378372314F1976d054f159FC9A5CDCA040FC0 | [Etherscan](https://etherscan.io/address/0x301378372314F1976d054f159FC9A5CDCA040FC0) | [Arbiscan](https://arbiscan.io/address/0x301378372314F1976d054f159FC9A5CDCA040FC0) |


# Fixed Strike oTokens

ERC20-compatible option token implementation with fixed strike prices

### Overview

Option Tokens (oTokens) are issued by a Option Teller to represent American-style options on the underlying token. Call option tokens can be exercised for the underlying token 1:1 by paying the amount \* strike price in the quote token at any time between the eligible and expiry timestamps. Put option tokens can be exercised for the underlying token 1:1 by paying the amount of the underlying token to receive the amount \* strike price in the quote token at any time between the eligible and expiry timestamps.

The Fixed Strike Option Token contract is a specific implementation of oTokens where the strike price is specified and fixed on creation.

oTokens are unique to the combination of parameters that they are deployed with. Eligible and expiry timestamps are rounded down to the nearest day (using UTC) to reduce the possible number of tokens.

This contract uses [Clones With Immutable Args](https://github.com/wighawag/clones-with-immutable-args) to save gas on deployment and is based on [VestedERC20](https://github.com/ZeframLou/vested-erc20).

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

## FixedStrikeOptionToken Contract

[Git Source](https://github.com/Bond-Protocol/option-contracts/blob/master/src/fixed-strike/FixedStrikeOptionToken.sol)

### Immutable Args

#### payout

The token that the option is on

```solidity
function payout() public pure returns (ERC20 _payout);
```

#### quote

The token that the option is quoted in

```solidity
function quote() public pure returns (ERC20 _quote);
```

#### eligible

Timestamp at which the Option token can first be exercised

```solidity
function eligible() public pure returns (uint48 _eligible);
```

#### expiry

Timestamp at which the Option token cannot be exercised after

```solidity
function expiry() public pure returns (uint48 _expiry);
```

#### receiver

Address that will receive the proceeds when option tokens are exercised. Also, the only address that can reclaim collateral from expired oTokens.

```solidity
function receiver() public pure returns (address _receiver);
```

#### call

Whether the option is a call (true) or a put (false)

```solidity
function call() public pure returns (bool _call);
```

#### teller

Address of the Teller that created the token

```solidity
function teller() public pure returns (address _teller);
```

#### strike

The strike price of the option (in quote token units)

```solidity
function strike() public pure returns (uint256 _strike);
```

### Functions

#### mint

Mint option tokens

Only callable by the Teller that created the token

```solidity
function mint(address to, uint256 amount) external;
```

**Parameters**

| Name     | Type      | Description            |
| -------- | --------- | ---------------------- |
| `to`     | `address` | The address to mint to |
| `amount` | `uint256` | The amount to mint     |

#### burn

Burn option tokens

Only callable by the Teller that created the token

```solidity
function burn(address from, uint256 amount) external;
```

**Parameters**

| Name     | Type      | Description              |
| -------- | --------- | ------------------------ |
| `from`   | `address` | The address to burn from |
| `amount` | `uint256` | The amount to burtn      |

#### getOptionParameters

Get collection of option parameters in a single call

```solidity
function getOptionParameters()
    external
    pure
    returns (
        uint8 decimals_,
        ERC20 payout_,
        ERC20 quote_,
        uint48 eligible_,
        uint48 expiry_,
        address receiver_,
        bool call_,
        uint256 strike_
    );
```

**Returns**

| Name        | Type      | Description                                                                          |
| ----------- | --------- | ------------------------------------------------------------------------------------ |
| `decimals_` | `uint8`   | The number of decimals for the option token (same as payout token)                   |
| `payout_`   | `ERC20`   | The address of the payout token                                                      |
| `quote_`    | `ERC20`   | The address of the quote token                                                       |
| `eligible_` | `uint48`  | The option exercise eligibility timestamp                                            |
| `expiry_`   | `uint48`  | The option exercise expiry timestamp                                                 |
| `receiver_` | `address` | The address of the receiver                                                          |
| `call_`     | `bool`    | Whether the option is a call (true) or a put (false)                                 |
| `strike_`   | `uint256` | The option strike price specified in the amount of quote tokens per underlying token |

### Errors

#### OptionToken\_OnlyTeller

```solidity
error OptionToken_OnlyTeller();
```


# Fixed Strike Option Teller

Contract that creates and manages the lifecycle of oTokens with a fixed strike price

### Overview

Option Teller contracts handle the deployment, creation, and exercise of option tokens. oTokens are ERC20 tokens that represent the right to buy (call) or sell (put) a fixed amount of an asset (payout token) for an amount of another asset (quote token) between two timestamps (eligible and expiry). oTokens are denominated in units of the payout token and are created at a 1:1 ratio for the amount of payout tokens to buy or sell. The amount of quote tokens required to exercise (call) or collateralize (put) an oToken is called the strike price. Strike prices are denominated in units of the quote token.&#x20;

The Fixed Strike Option Teller implementation creates option tokens that have a fixed strike price that is set at the time of creation.&#x20;

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

### Deploy and Creating oTokens

In order to create oTokens, an issuer must [deploy](#deploy) the specific token configuration on the teller, and then provide collateral to the teller to [create](#create) option tokens. The collateral is required to guarantee that the oTokens can be exercised. The collateral required depends on the option type.

* For call options, the collateral required is an amount of payout tokens equivalent to the amount of option tokens being minted.
* For put options, the collateral required is an amount of quote tokens equivalent to the amount of option tokens being minted multiplied by the strike price.&#x20;

As the name "option" suggests, the holder of an option token has the right, but not the obligation, to exercise the oToken within the eligible time window. If the oToken is not exercised, the designated "receiver" of the oToken exercise proceeds can reclaim the collateral after the expiry timestamp. If an oToken is exercised, the holder receives the collateral and the receiver receives the exercise proceeds.

## FixedStrikeOptionTeller

[Git Source](https://github.com/Bond-Protocol/option-contracts/blob/master/src/fixed-strike/FixedStrikeOptionTeller.sol)

## State Variables

### protocolFee

Fee paid to protocol when options are exercised in basis points (3 decimal places).

```solidity
uint48 public protocolFee;
```

### FEE\_DECIMALS

Base value used to scale fees. 1e5 = 100%

```solidity
uint48 public constant FEE_DECIMALS = 1e5;
```

### optionTokenImplementation

FixedStrikeOptionToken reference implementation (deployed on creation to clone from)

```solidity
FixedStrikeOptionToken public immutable optionTokenImplementation;
```

### minOptionDuration

Minimum duration an option must be eligible to exercise (in seconds)

```solidity
uint48 public minOptionDuration;
```

### fees

Fees earned by protocol, by token

```solidity
mapping(ERC20 => uint256) public fees;
```

### optionTokens

Fixed strike option tokens (hash of parameters to address)

```solidity
mapping(bytes32 => FixedStrikeOptionToken) public optionTokens;
```

### collateralClaimed

Whether the receiver of an option token has reclaimed the collateral

```solidity
mapping(FixedStrikeOptionToken => bool) public collateralClaimed;
```

## User Functions

### deploy

Deploy a new ERC20 fixed strike option token and return its address

*If an option token already exists for the parameters, it returns that address*

```solidity
function deploy(
    ERC20 payoutToken_,
    ERC20 quoteToken_,
    uint48 eligible_,
    uint48 expiry_,
    address receiver_,
    bool call_,
    uint256 strikePrice_
) external override nonReentrant returns (FixedStrikeOptionToken);
```

**Parameters**

| Name           | Type      | Description                                                                                                                                   |
| -------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `payoutToken_` | `ERC20`   | ERC20 token that the purchaser will receive on execution                                                                                      |
| `quoteToken_`  | `ERC20`   | ERC20 token used that the purchaser will need to provide on execution                                                                         |
| `eligible_`    | `uint48`  | Timestamp at which the option token can first be executed (gets rounded down to nearest day)                                                  |
| `expiry_`      | `uint48`  | Timestamp at which the option token can no longer be executed (gets rounded down to nearest day)                                              |
| `receiver_`    | `address` | Address that will receive the proceeds when option tokens are exercised. Also the address that can claim collateral from unexercised options. |
| `call_`        | `bool`    | Whether the option token is a call (true) or a put (false)                                                                                    |
| `strikePrice_` | `uint256` | Strike price of the option token (in units of quoteToken per payoutToken)                                                                     |

**Returns**

| Name     | Type                     | Description                                                  |
| -------- | ------------------------ | ------------------------------------------------------------ |
| `oToken` | `FixedStrikeOptionToken` | Address of the ERC20 fixed strike option token being created |

### create

Deposit an ERC20 token and mint an ERC20 fixed strike option token

```solidity
function create(FixedStrikeOptionToken optionToken_, uint256 amount_) external override nonReentrant;
```

**Parameters**

| Name           | Type                     | Description                                                                                 |
| -------------- | ------------------------ | ------------------------------------------------------------------------------------------- |
| `optionToken_` | `FixedStrikeOptionToken` | Fixed strike option token to mint                                                           |
| `amount_`      | `uint256`                | Amount of option tokens to mint (also the number of payout tokens required to be deposited) |

### exercise

Exercise an ERC20 fixed strike option token. Provide required quote tokens and receive amount of payout tokens.

*Amount of quote tokens required to exercise is return from the exerciseCost() function*

```solidity
function exercise(FixedStrikeOptionToken optionToken_, uint256 amount_) external override nonReentrant;
```

**Parameters**

| Name           | Type                     | Description                                                                       |
| -------------- | ------------------------ | --------------------------------------------------------------------------------- |
| `optionToken_` | `FixedStrikeOptionToken` | Fixed strike option token to exercise                                             |
| `amount_`      | `uint256`                | Amount of option tokens to exercise (also the number of payout tokens to receive) |

### reclaim

Reclaim collateral from expired option tokens

```solidity
function reclaim(FixedStrikeOptionToken optionToken_) external override nonReentrant;
```

**Parameters**

| Name           | Type                     | Description                                          |
| -------------- | ------------------------ | ---------------------------------------------------- |
| `optionToken_` | `FixedStrikeOptionToken` | Fixed strike option token to reclaim collateral from |

## View Functions

### exerciseCost

Get the cost to exercise an amount of fixed strike option tokens

```solidity
function exerciseCost(FixedStrikeOptionToken optionToken_, uint256 amount_) external view returns (ERC20, uint256);
```

**Parameters**

| Name           | Type                     | Description                           |
| -------------- | ------------------------ | ------------------------------------- |
| `optionToken_` | `FixedStrikeOptionToken` | Fixed strike option token to exercise |
| `amount_`      | `uint256`                | Amount of option tokens to exercise   |

**Returns**

| Name     | Type      | Description                                                           |
| -------- | --------- | --------------------------------------------------------------------- |
| `token_` | `ERC20`   | Token required to exercise (quoteToken for call, payoutToken for put) |
| `cost_`  | `uint256` | Amount of `token_` required to exercise                               |

### getOptionToken

Get the FixedStrikeOptionToken contract corresponding to the params, reverts if no token exists

```solidity
function getOptionToken(
    ERC20 payoutToken_,
    ERC20 quoteToken_,
    uint48 eligible_,
    uint48 expiry_,
    address receiver_,
    bool call_,
    uint256 strikePrice_
) public view returns (FixedStrikeOptionToken);
```

**Parameters**

| Name           | Type      | Description                                                                                                                                   |
| -------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `payoutToken_` | `ERC20`   | ERC20 token that the purchaser will receive on execution                                                                                      |
| `quoteToken_`  | `ERC20`   | ERC20 token used that the purchaser will need to provide on execution                                                                         |
| `eligible_`    | `uint48`  | Timestamp at which the option token can first be executed (gets rounded to nearest day)                                                       |
| `expiry_`      | `uint48`  | Timestamp at which the option token can no longer be executed (gets rounded to nearest day)                                                   |
| `receiver_`    | `address` | Address that will receive the proceeds when option tokens are exercised. Also the address that can claim collateral from unexercised options. |
| `call_`        | `bool`    | Whether the option token is a call (true) or a put (false)                                                                                    |
| `strikePrice_` | `uint256` | Strike price of the option token (in units of quoteToken per payoutToken)                                                                     |

**Returns**

| Name            | Type                     | Description                             |
| --------------- | ------------------------ | --------------------------------------- |
| \`optionToken\` | `FixedStrikeOptionToken` | FixedStrikeOptionToken contract address |

### getOptionTokenHash

Get the hash ID of the fixed strike option token with these parameters

```solidity
function getOptionTokenHash(
    ERC20 payoutToken_,
    ERC20 quoteToken_,
    uint48 eligible_,
    uint48 expiry_,
    address receiver_,
    bool call_,
    uint256 strikePrice_
) external pure returns (bytes32);
```

**Parameters**

| Name           | Type      | Description                                                                                                                                   |
| -------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `payoutToken_` | `ERC20`   | ERC20 token that the purchaser will receive on execution                                                                                      |
| `quoteToken_`  | `ERC20`   | ERC20 token used that the purchaser will need to provide on execution                                                                         |
| `eligible_`    | `uint48`  | Timestamp at which the option token can first be executed (gets rounded to nearest day)                                                       |
| `expiry_`      | `uint48`  | Timestamp at which the option token can no longer be executed (gets rounded to nearest day)                                                   |
| `receiver_`    | `address` | Address that will receive the proceeds when option tokens are exercised. Also the address that can claim collateral from unexercised options. |
| `call_`        | `bool`    | Whether the option token is a call (true) or a put (false)                                                                                    |
| `strikePrice_` | `uint256` | Strike price of the option token (in units of quoteToken per payoutToken)                                                                     |

**Returns**

| Name         | Type      | Description                                                    |
| ------------ | --------- | -------------------------------------------------------------- |
| `optionHash` | `bytes32` | Hash ID of the fixed strike option token with these parameters |

## Admin Functions

### setMinOptionDuration

Set minimum duration to exercise option

*Absolute minimum is 1 day (86400 seconds) due to timestamp rounding of eligible and expiry parameters*

```solidity
function setMinOptionDuration(uint48 duration_) external override requiresAuth;
```

**Parameters**

| Name        | Type     | Description                 |
| ----------- | -------- | --------------------------- |
| `duration_` | `uint48` | Minimum duration in seconds |

### setProtocolFee

Set protocol fee

```solidity
function setProtocolFee(uint48 fee_) external override requiresAuth;
```

**Parameters**

| Name   | Type     | Description                                     |
| ------ | -------- | ----------------------------------------------- |
| `fee_` | `uint48` | Protocol fee in basis points (3 decimal places) |

### claimFees

Claim fees accrued by protocol in the input tokens and sends them to the provided address

```solidity
function claimFees(ERC20[] memory tokens_, address to_) external override nonReentrant requiresAuth;
```

**Parameters**

| Name      | Type      | Description                       |
| --------- | --------- | --------------------------------- |
| `tokens_` | `ERC20[]` | Array of tokens to claim fees for |
| `to_`     | `address` | Address to send fees to           |

## Events

### WroteOption

```solidity
event WroteOption(uint256 indexed id, address indexed referrer, uint256 amount, uint256 payout);
```

### OptionTokenCreated

```solidity
event OptionTokenCreated(
    FixedStrikeOptionToken optionToken,
    ERC20 indexed payoutToken,
    ERC20 quoteToken,
    uint48 eligible,
    uint48 indexed expiry,
    address indexed receiver,
    bool call,
    uint256 strikePrice
);
```

## Errors

### Teller\_NotAuthorized

```solidity
error Teller_NotAuthorized();
```

### Teller\_TokenDoesNotExist

```solidity
error Teller_TokenDoesNotExist(bytes32 optionHash);
```

### Teller\_UnsupportedToken

```solidity
error Teller_UnsupportedToken(address token);
```

### Teller\_InvalidParams

```solidity
error Teller_InvalidParams(uint256 index, bytes value);
```

### Teller\_OptionExpired

```solidity
error Teller_OptionExpired(uint48 expiry);
```

### Teller\_NotEligible

```solidity
error Teller_NotEligible(uint48 eligible);
```

### Teller\_NotExpired

```solidity
error Teller_NotExpired(uint48 expiry);
```

### Teller\_AlreadyReclaimed

```solidity
error Teller_AlreadyReclaimed(FixedStrikeOptionToken optionToken);
```

### Teller\_PriceOutOfBounds

```solidity
error Teller_PriceOutOfBounds();
```

### Teller\_InvalidAmount

```solidity
error Teller_InvalidAmount();
```


# Options Liquidity Mining (OLM)

Contract that implements an epoch-based liquidity mining reward system using oTokens

### Introduction

Options Liquidity Mining allows the protocol to re-capture some of the value from liquidity mining rewards when LPs realize profit. Additionally, it can cap the amount of sell pressure on a protocols token in a down market by limiting the profitability of exercising option tokens to above the strike price.&#x20;

The OLM contract implements a version of this using fixed strike call options. Protocols can deploy an OLM contract with their specific configuration of staked token and option parameters. The contract implements epoch-based staking rewards to issue new option tokens at fixed time intervals and at a new strike price based on the configuration when an epoch transitions. The `stakedToken` and option `payoutToken` are fixed when the OLM contract is deployed. The owner of the contract can update the other staking and option token parameters over time to adjust their rewards program.  The owner can also optionally designate an Allowlist contract to limit which users can can stake in the contract. The allowlist should conform to the `IAllowlist` interface.

Protocols can choose between two implementations of the OLM contract: [Manual Strike](/smart-contracts/option-system/options-liquidity-mining-olm/manual-strike-olm) or [Oracle Strike](/smart-contracts/option-system/options-liquidity-mining-olm/oracle-strike-olm).

* Manual Strike: Owners must manually update the strike price to change it over time.
* Oracle Strike: Strike price is automatically updated based on an oracle and discount. A minimum strike price can be set on the Oracle Strike version to prevent it from going too low.&#x20;

Users can deposit the configured `stakedToken` into the contract to earn rewards. Rewards are continuously accrued based on the configured reward rate and the total balance of staked tokens in the contract. Any user action updates the reward calculations. Additionally, user actions can trigger a new epoch start, which will earn them additional option tokens in the form of the epoch transition reward for paying the extra gas. Users can claim their outstanding rewards from all epochs or from the next unclaimed epoch. If the option token for a specific epoch has expired, the user will not receive any rewards for that period since they are now worthless.

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

### Deployment

Setting up an OLM requires three steps.

1. Deploy an OLM contract from a [factory](/smart-contracts/option-system/olm-factories).
2. Fund the OLM contract with `payoutTokens` to pay rewards with (via a simple ERC20 transfer). Owners must monitor the balance of `payoutTokens` in the contract to ensure that users can claim their rewards.&#x20;
3. [Initialize](#initialize) the OLM contract, including inputting the remaining options and staking parameters.

Step three of this process is accomplished by calling `initialize` on this contract.

## OLM Contract (abstract)

[Git Source](https://github.com/Bond-Protocol/option-contracts/blob/master/src/fixed-strike/liquidity-mining/OLM.sol)

### State Variables

#### stakedToken

Token that is staked in the OLM contract

```solidity
ERC20 public immutable stakedToken;
```

#### depositsEnabled

Whether users can deposit staking tokens into the OLM contract at the current time

```solidity
bool public depositsEnabled;
```

#### initialized

Whether the OLM contract has been initialized

*No settings can be changed or tokens deposited before the OLM contract is initialized*

```solidity
bool public initialized;
```

#### allowlist

(Optional) Address of the allowlist contract which determines which addresses are allowed to interact with the OLM contract

```solidity
IAllowlist public allowlist;
```

#### optionTeller

Option Teller contract that is used to deploy and create option tokens

```solidity
IFixedStrikeOptionTeller public immutable optionTeller;
```

#### payoutToken

Token that stakers receive call options for

```solidity
ERC20 public immutable payoutToken;
```

#### quoteToken

Token that stakers must pay to exercise the call options they receive

```solidity
ERC20 public quoteToken;
```

#### timeUntilEligible

Amount of time (in seconds) from option token deployment to when it can be exercised

```solidity
uint48 public timeUntilEligible;
```

#### eligibleDuration

Amount of time (in seconds) from when the option token is eligible to when it expires

```solidity
uint48 public eligibleDuration;
```

#### receiver

Address that will receive the quote tokens when an option is exercised.&#x20;

**IMPORTANT:** This address is the only one that can reclaim the payoutToken collateral for expired option tokens. Make sure this address can call `reclaim` on the FixedStrikeOptionTeller contract for any option token address.&#x20;

```solidity
address public receiver;
```

#### epoch

Current staking epoch

```solidity
uint48 public epoch;
```

#### epochDuration

Staking epoch duration

```solidity
uint48 public epochDuration;
```

#### epochStart

Timestamp of the start of the current staking epoch

```solidity
uint48 public epochStart;
```

#### REWARD\_PERIOD

Amount of time (in seconds) that the reward rate is distributed over

```solidity
uint48 public constant REWARD_PERIOD = uint48(1 days);
```

#### lastRewardUpdate

Timestamp when the stored rewards per token was last updated

```solidity
uint48 public lastRewardUpdate;
```

#### rewardRate

Amount of option tokens rewarded per reward period

```solidity
uint256 public rewardRate;
```

#### rewardsPerTokenStored

Global reward distribution variable, used to calculate user rewards

```solidity
uint256 public rewardsPerTokenStored;
```

#### epochTransitionReward

Amount of option tokens that are rewarded for starting a new epoch

```solidity
uint256 public epochTransitionReward;
```

#### epochRewardsPerTokenStart

Rewards Per Token value at the start of each epoch

```solidity
mapping(uint48 => uint256) public epochRewardsPerTokenStart;
```

#### totalBalance

Total amount of staked tokens currently in the contract

```solidity
uint256 public totalBalance;
```

#### stakeBalance

Mapping of staker address to their staked balance

```solidity
mapping(address => uint256) public stakeBalance;
```

#### rewardsPerTokenClaimed

Mapping of staker address to the rewards per token they have claimed

```solidity
mapping(address => uint256) public rewardsPerTokenClaimed;
```

#### lastEpochClaimed

Mapping of staker address to the last epoch they claimed rewards for

```solidity
mapping(address => uint48) public lastEpochClaimed;
```

#### epochOptionTokens

Mapping of epochs to the option tokens that was rewarded for that epoch

```solidity
mapping(uint48 => FixedStrikeOptionToken) public epochOptionTokens;
```

### Modifiers

#### updateRewards

Modifier that updates the stored rewards per token before a function is executed

*This modifier should be placed on any function where rewards are claimed or staked tokens are deposited/withdrawn.*

*Additionally, it should be placed on any functions that modify the reward parameters of the OLM contract.*

```solidity
modifier updateRewards();
```

#### tryNewEpoch

Modifier that tries to start a new epoch before a function is executed and rewards the caller for doing so

```solidity
modifier tryNewEpoch();
```

#### requireInitialized

Modifier that requires the OLM contract to be initialized before a function is executed

```solidity
modifier requireInitialized();
```

### User Functions

#### stake

Deposit staking tokens into the contract to earn rewards

Only callable if deposits are enabled

Only callable if the user is allowed to stake per the allowlist

May receive reward if calling triggers new epoch

```solidity
function stake(uint256 amount_, bytes calldata proof_)
    external
    nonReentrant
    requireInitialized
    updateRewards
    tryNewEpoch;
```

**Parameters**

| Name      | Type      | Description                                                |
| --------- | --------- | ---------------------------------------------------------- |
| `amount_` | `uint256` | Amount of staking tokens to deposit                        |
| `proof_`  | `bytes`   | Optional proof data for specific allowlist implementations |

#### unstake

Withdraw staking tokens from the contract

May receive reward if calling triggers new epoch

```solidity
function unstake(uint256 amount_) external nonReentrant updateRewards tryNewEpoch;
```

**Parameters**

| Name      | Type      | Description                          |
| --------- | --------- | ------------------------------------ |
| `amount_` | `uint256` | Amount of staking tokens to withdraw |

#### unstakeAll

Withdraw entire balance of staking tokens from the contract

May receive reward if calling triggers new epoch

```solidity
function unstakeAll() external nonReentrant updateRewards tryNewEpoch;
```

#### emergencyUnstakeAll

Withdraw entire balance of staking tokens without updating or claiming outstanding rewards.

Rewards will be lost if stake is withdrawn using this function. Only for emergency use.

```solidity
function emergencyUnstakeAll() external nonReentrant;
```

#### claimRewards

Claim all outstanding rewards for the user across epochs

May receive reward if calling triggers new epoch

```solidity
function claimRewards() external nonReentrant updateRewards tryNewEpoch returns (uint256);
```

#### claimNextEpochRewards

Claim all outstanding rewards for the user for the next unclaimed epoch (and any remaining rewards from the previously claimed epoch)

May receive reward if calling triggers new epoch

```solidity
function claimNextEpochRewards() external nonReentrant updateRewards tryNewEpoch returns (uint256);
```

### View Functions

#### currentRewardsPerToken

Returns the current rewards per token value updated to the second

```solidity
function currentRewardsPerToken() public view returns (uint256);
```

#### nextStrikePrice

Returns the strike price that would be used if a new epoch started right now

```solidity
function nextStrikePrice() public view virtual returns (uint256);
```

### Owner Functions

#### initialize

Initializes the OLM contract

Only owner

*This function can only be called once.*

*When the function completes, the contract is live. Users can start staking and claiming rewards.*

```solidity
function initialize(
    ERC20 quoteToken_,
    uint48 timeUntilEligible_,
    uint48 eligibleDuration_,
    address receiver_,
    uint48 epochDuration_,
    uint256 epochTransitionReward_,
    uint256 rewardRate_,
    IAllowlist allowlist_,
    bytes calldata allowlistParams_,
    bytes calldata other_
) external onlyOwner;
```

#### Parameters

| Name                     | Type         | Description                                                                                                                                                                                                                                                                                                                                                       |
| ------------------------ | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `quoteToken_`            | `ERC20`      | Token that stakers must pay to exercise the call options they receive                                                                                                                                                                                                                                                                                             |
| `timeUntilEligible_`     | `uint48`     | Amount of time (in seconds) from option token deployment to when it can be exercised                                                                                                                                                                                                                                                                              |
| `eligibleDuration_`      | `uint48`     | Amount of time (in seconds) from when the option token is eligible to when it expires                                                                                                                                                                                                                                                                             |
| `receiver_`              | `address`    | Address that will receive the quote tokens when an option is exercised **IMPORTANT: receiver is the only address that can retrieve payout token collateral from expired options. It must be able to call the `reclaim` function on the Option Teller contract.**                                                                                                  |
| `epochDuration_`         | `uint48`     | Staking epoch duration (in seconds)                                                                                                                                                                                                                                                                                                                               |
| `epochTransitionReward_` | `uint256`    | Amount of option tokens that are rewarded for starting a new epoch                                                                                                                                                                                                                                                                                                |
| `rewardRate_`            | `uint256`    | Amount of option tokens rewarded per reward period (1 day)                                                                                                                                                                                                                                                                                                        |
| `allowlist_`             | `IAllowlist` | Address of the allowlist contract that can be used to restrict who can stake in the OLM contract. If the zero address, then no allow list is used.                                                                                                                                                                                                                |
| `allowlistParams_`       | `bytes`      | Parameters that are passed to the allowlist contract when this contract registers with it                                                                                                                                                                                                                                                                         |
| `other_`                 | `bytes`      | Additional parameters that are required by specific implementations of the OLM contract. Must be abi-encoded. See [Manual Strike OLM](/smart-contracts/option-system/options-liquidity-mining-olm/manual-strike-olm) or [Oracle Strike OLM](/smart-contracts/option-system/options-liquidity-mining-olm/oracle-strike-olm) for details on what each expects here. |

#### setDepositsEnabled

Toggle whether deposits are enabled

Only owner

```solidity
function setDepositsEnabled(bool depositsEnabled_) external onlyOwner requireInitialized;
```

**Parameters**

| Name               | Type   | Description                        |
| ------------------ | ------ | ---------------------------------- |
| `depositsEnabled_` | `bool` | Whether deposits should be enabled |

#### triggerNextEpoch

Manually start a new epoch

Only owner

```solidity
function triggerNextEpoch() external onlyOwner requireInitialized updateRewards;
```

#### withdrawPayoutTokens

Withdraw payout tokens that were deposited to the contract for rewards

Only owner

```solidity
function withdrawPayoutTokens(address to_, uint256 amount_) external onlyOwner;
```

**Parameters**

| Name      | Type      | Description                |
| --------- | --------- | -------------------------- |
| `to_`     | `address` | The address to withdraw to |
| `amount_` | `uint256` | The amount to withdraw     |

#### setRewardRate

Set the staking reward rate

Only owner

```solidity
function setRewardRate(uint256 rewardRate_) external onlyOwner requireInitialized updateRewards;
```

**Parameters**

| Name          | Type      | Description                                                |
| ------------- | --------- | ---------------------------------------------------------- |
| `rewardRate_` | `uint256` | Amount of option tokens rewarded per reward period (1 day) |

#### setEpochDuration

Set the epoch duration

Only owner

```solidity
function setEpochDuration(uint48 epochDuration_) external onlyOwner requireInitialized;
```

**Parameters**

| Name             | Type     | Description                         |
| ---------------- | -------- | ----------------------------------- |
| `epochDuration_` | `uint48` | Staking epoch duration (in seconds) |

#### setEpochTransitionReward

Set the epoch transition reward

Only owner

```solidity
function setEpochTransitionReward(uint256 amount_) external onlyOwner requireInitialized;
```

**Parameters**

| Name      | Type      | Description                                                        |
| --------- | --------- | ------------------------------------------------------------------ |
| `amount_` | `uint256` | Amount of option tokens that are rewarded for starting a new epoch |

#### setOptionReceiver

Set the option receiver

Only owner

```solidity
function setOptionReceiver(address receiver_) external onlyOwner requireInitialized;
```

**Parameters**

| Name        | Type      | Description                                                                                                                                                                                                                                                  |
| ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `receiver_` | `address` | Address that will receive the quote tokens when an option is exercised IMPORTANT: receiver is the only address that can retrieve payout token collateral from expired options. It must be able to call the `reclaim` function on the Option Teller contract. |

#### setOptionDuration

Set the option duration

Only owner

```solidity
function setOptionDuration(uint48 timeUntilEligible_, uint48 eligibleDuration_) external onlyOwner requireInitialized;
```

**Parameters**

| Name                 | Type     | Description                                                                          |
| -------------------- | -------- | ------------------------------------------------------------------------------------ |
| `timeUntilEligible_` | `uint48` | Amount of time (in seconds) from option token deployment to when it can be exercised |
| `eligibleDuration_`  | `uint48` | Amount of time (in seconds) from when the option token is eligible to when it expire |

#### setQuoteToken

Set the quote token that is used for the option tokens

Only owner

```solidity
function setQuoteToken(ERC20 quoteToken_) external virtual onlyOwner requireInitialized;
```

**Parameters**

| Name          | Type    | Description                                                           |
| ------------- | ------- | --------------------------------------------------------------------- |
| `quoteToken_` | `ERC20` | Token that stakers must pay to exercise the call options they receive |

#### setAllowlist

```solidity
function setAllowlist(IAllowlist allowlist_, bytes calldata allowlistParams_) external onlyOwner requireInitialized;
```

### Events

#### NewEpoch

```solidity
event NewEpoch(uint48 indexed epoch_, FixedStrikeOptionToken optionToken_);
```

### Errors

#### OLM\_InvalidParams

```solidity
error OLM_InvalidParams();
```

#### OLM\_InvalidAmount

```solidity
error OLM_InvalidAmount();
```

#### OLM\_InvalidEpoch

```solidity
error OLM_InvalidEpoch();
```

#### OLM\_ZeroBalance

```solidity
error OLM_ZeroBalance();
```

#### OLM\_PreviousUnclaimedEpoch

```solidity
error OLM_PreviousUnclaimedEpoch();
```

#### OLM\_AlreadyInitialized

```solidity
error OLM_AlreadyInitialized();
```

#### OLM\_NotInitialized

```solidity
error OLM_NotInitialized();
```

#### OLM\_DepositsDisabled

```solidity
error OLM_DepositsDisabled();
```

#### OLM\_NotAllowed

```solidity
error OLM_NotAllowed();
```


# Manual Strike OLM

[Git Source](https://github.com/Bond-Protocol/option-contracts/blob/master/src/fixed-strike/liquidity-mining/OLM.sol)

**Inherits:** [OLM](/smart-contracts/option-system/options-liquidity-mining-olm)

*The Manual Strike OLM contract allows the owner to manually set the strike price that new option tokens are created with on epoch transition.*

### State Variables

#### strikePrice

Strike price to be used for new option tokens

```solidity
uint256 public strikePrice;
```

### Functions

#### \_initialize

Internal function, not callable directly. Called within `initialize` to implement Manual Strike OLM specific initialization logic.

```solidity
function _initialize(bytes calldata params_) internal override;
```

**Parameters**

| Name          | Type      | Description                                                                            |
| ------------- | --------- | -------------------------------------------------------------------------------------- |
| strikePrice\_ | `uint256` | The initial strike price for the  Manual Strike OLM, in quote tokens per payout token. |

**The parameters for this function are ABI-encoded into a** `bytes` **object and passed as the** `other_`**variable into the top-level OLM** `initialize` **function. For example:**

```solidity
bytes memory other = abi.encode(strikePrice);
```

#### nextStrikePrice

Returns the strike price that would be used if a new epoch started right now

```solidity
function nextStrikePrice() public view override returns (uint256);
```

#### setStrikePrice

Set the strike price to be used for future option tokens

Only owner

```solidity
function setStrikePrice(uint256 strikePrice_) external onlyOwner requireInitialized;
```

**Parameters**

| Name           | Type      | Description                                                                                          |
| -------------- | --------- | ---------------------------------------------------------------------------------------------------- |
| `strikePrice_` | `uint256` | Strike price for the option tokens formatted as the number of quote tokens required per payout token |


# Oracle Strike OLM

[Git Source](https://github.com/Bond-Protocol/option-contracts/blob/master/src/fixed-strike/liquidity-mining/OLM.sol)

**Inherits:** [OLM](/smart-contracts/option-system/options-liquidity-mining-olm)

*The Oracle Strike OLM contract uses an oracle to determine the fixed strike price when a new option token is created on epoch transition. This should not be confused with Oracle Strike Option Tokens, whose strike price changes dynamically based on the oracle price.*

### State Variables

#### oracle

Oracle contract used to get a current strike price when creating a new option token

```solidity
IBondOracle public oracle;
```

#### oracleDiscount

Discount to the oracle price used to set the strike price when creating a new option token

```solidity
uint48 public oracleDiscount;
```

#### ONE\_HUNDRED\_PERCENT

```solidity
uint48 internal constant ONE_HUNDRED_PERCENT = 1e5;
```

#### minStrikePrice

Minimum strike price that can be set when creating a new option token, in number of quote tokens per payout token

```solidity
uint256 public minStrikePrice;
```

### Functions

#### \_initialize

Internal function, not callable directly. Called within `initialize` to implement Oracle Strike OLM specific initialization logic.

```solidity
function _initialize(bytes calldata params_) internal override;
```

**Parameters**

| Name              | Type          | Description                                                                                                                   |
| ----------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `oracle_`         | `IBondOracle` | ABI-encoded bytes containing the oracle, oracle discount, and minimum strike price                                            |
| `oracleDiscount_` | `uint48`      | Percent discount from oracle price to use for strike price, with 3 decimal places. i.e. `1e3 = 1000 = 1%`                     |
| `minStrikePrice_` | `uint256`     | Minimum strike price allowed to be used by the OLM. Provides a floor price in case of large market declines or oracle issues. |

**The parameters for this function are ABI-encoded into a** `bytes` **object and passed as the** `other_`**variable into the top-level OLM** `initialize` **function. For example:**

```solidity
bytes memory other = abi.encode(oracle, oracleDiscount, minStrikePrice);
```

#### nextStrikePrice

Returns the strike price that would be used if a new epoch started right now

```solidity
function nextStrikePrice() public view override returns (uint256);
```

#### setOracle

Set the oracle contract

Only owner

```solidity
function setOracle(IBondOracle oracle_) external onlyOwner requireInitialized;
```

**Parameters**

| Name      | Type          | Description                                                                         |
| --------- | ------------- | ----------------------------------------------------------------------------------- |
| `oracle_` | `IBondOracle` | Oracle contract used to get a current strike price when creating a new option token |

#### setOracleDiscount

Set the oracle discount

Only owner

```solidity
function setOracleDiscount(uint48 oracleDiscount_) external onlyOwner requireInitialized;
```

**Parameters**

| Name              | Type     | Description                                                                                |
| ----------------- | -------- | ------------------------------------------------------------------------------------------ |
| `oracleDiscount_` | `uint48` | Discount to the oracle price used to set the strike price when creating a new option token |

#### setMinStrikePrice

Set the minimum strike price

Only owner

```solidity
function setMinStrikePrice(uint256 minStrikePrice_) external onlyOwner requireInitialized;
```

**Parameters**

| Name              | Type      | Description                                                                                                       |
| ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
| `minStrikePrice_` | `uint256` | Minimum strike price that can be set when creating a new option token, in number of quote tokens per payout token |

#### setQuoteToken

Set the quote token that is used for the option tokens

```solidity
function setQuoteToken(ERC20 quoteToken_) external override onlyOwner requireInitialized;
```

**Parameters**

| Name          | Type    | Description                                                           |
| ------------- | ------- | --------------------------------------------------------------------- |
| `quoteToken_` | `ERC20` | Token that stakers must pay to exercise the call options they receive |


# OLM Factories

Factory contracts for easy deployment of OLM contracts

### Introduction

The OLM Factory contracts allows anyone to deploy new[ OLM ](/smart-contracts/option-system/options-liquidity-mining-olm)contracts without compiling and deploying them manually. When deployed, the owner of the OLM is set to the caller.&#x20;

There are two factories for the two OLM implementations: Manual Strike ([MOLMFactory](#molmfactory)) and Oracle Strike ([OOLMFactory](#oolmfactory)).

* Manual Strike: Owners must manually update the strike price to change it over time.
* Oracle Strike: Strike price is automatically updated based on an oracle and discount. A minimum strike price can be set on the Oracle Strike version to prevent it from going too low.&#x20;

### Deployment

Setting up an OLM requires three steps.

1. Deploy an OLM contract from a factory.
2. Fund the OLM contract with `payoutTokens` to pay rewards with (via a simple ERC20 transfer). Owners must monitor the balance of `payoutTokens` in the contract to ensure that users can claim their rewards.&#x20;
3. [Initialize](/smart-contracts/option-system/options-liquidity-mining-olm) the OLM contract, including inputting the remaining options and staking parameters.

Step one of this process is accomplished by interacting with one of these factory contracts.

## MOLMFactory

[Git Source](https://github.com/Bond-Protocol/option-contracts/blob/master/src/fixed-strike/liquidity-mining/OLMFactory.sol)

Factory for deploying Manual Strike OLM contracts

### State Variables

#### optionTeller

Option Teller to be used by OLM contracts

```solidity
IFixedStrikeOptionTeller public immutable optionTeller;
```

### Functions

#### deploy

Deploy a new Manual Strike OLM contract with the caller as the owner

```solidity
function deploy(ERC20 stakedToken_, ERC20 payoutToken_) external returns (ManualStrikeOLM);
```

**Parameters**

| Name           | Type    | Description                                            |
| -------------- | ------- | ------------------------------------------------------ |
| `stakedToken_` | `ERC20` | ERC20 token that will be staked to earn rewards        |
| `payoutToken_` | `ERC20` | ERC20 token that stakers will receive call options for |

**Returns**

| Name   | Type              | Description                     |
| ------ | ----------------- | ------------------------------- |
| `molm` | `ManualStrikeOLM` | Address of the new OLM contract |

## OOLMFactory

[Git Source](https://github.com/Bond-Protocol/option-contracts/blob/master/src/fixed-strike/liquidity-mining/OLMFactory.sol)

Factory for deploying Oracle Strike OLM contracts

### State Variables

#### optionTeller

Option Teller to be used by OLM contracts

```solidity
IFixedStrikeOptionTeller public immutable optionTeller;
```

### Functions

#### deploy

Deploy a new Oracle Strike OLM contract with the caller as the owner

```solidity
function deploy(ERC20 stakedToken_, ERC20 payoutToken_) external returns (OracleStrikeOLM);
```

**Parameters**

| Name           | Type    | Description                                            |
| -------------- | ------- | ------------------------------------------------------ |
| `stakedToken_` | `ERC20` | ERC20 token that will be staked to earn rewards        |
| `payoutToken_` | `ERC20` | ERC20 token that stakers will receive call options for |

**Returns**

| Name   | Type              | Description                     |
| ------ | ----------------- | ------------------------------- |
| `oolm` | `OracleStrikeOLM` | Address of the new OLM contract |


# Subgraph

View data related to markets, tokens and bond purchases

We have subgraphs available for all supported chains, mainnet and testnet. Our Ethereum Mainnet runs on Graph Protocol's decentralized network, all others are on their hosted service.

Documentation is available for all entities and their fields, to access it, follow one of the links at the bottom of this page, then in GraphiQL:

<figure><img src="/files/DwtUqTDC72F1TBiN3yOW" alt=""><figcaption><p>Click the <code>Query</code> link in the Document Explorer</p></figcaption></figure>

<figure><img src="/files/H6OAgPtUUdIwXGFGi7k7" alt=""><figcaption><p>Click the link for the entity you are interested in</p></figcaption></figure>

<figure><img src="/files/lMO7mDtANGiWOlACDXPZ" alt=""><figcaption><p>A description of the entity and each field will be available</p></figcaption></figure>

{% hint style="warning" %}
The documentation is usually identical across all subgraphs, so it does not matter which one you use.

However, if changes are being made, the updates may appear on testnet or backup subgraphs before they appear in production.
{% endhint %}

#### Mainnet Subgraphs

* <https://gateway.thegraph.com/api/{API\\_KEY}/subgraphs/id/9F8K4UDnrQEzXsVmHoJxs5qBVDJB5jEKtU9EVsXNTzZZ[> ]\(<https://gateway.thegraph.com/api/17f8839a7d9c7f990a93cb221bf4248b/subgraphs/id/9F8K4UDnrQEzXsVmHoJxs5qBVDJB5jEKtU9EVsXNTzZZ)(Mainnet> Production - paid, requires API key)
* <https://api.studio.thegraph.com/query/41517/bond-protocol-ethereum-mainnet/v1.0.6> (Mainnet Development - version number at the end of the URL may change)
* <https://api.thegraph.com/subgraphs/name/bond-protocol/bond-protocol-arbitrum-mainnet> (Arbitrum Production)
* <https://thegraph.com/hosted-service/subgraph/bond-protocol/bond-protocol-mainnet> (Mainnet Backup)

#### Testnet Subgraphs

* <https://api.thegraph.com/subgraphs/name/bond-protocol/bond-protocol-goerli>
* <https://api.thegraph.com/subgraphs/name/bond-protocol/bond-protocol-goerli-arbitrum>
* <https://api.thegraph.com/subgraphs/name/bond-protocol/bond-protocol-optimism-goerli>
* <https://api.thegraph.com/subgraphs/name/bond-protocol/bond-protocol-polygon-mumbai>
* <https://api.thegraph.com/subgraphs/name/bond-protocol/bond-protocol-avalanche-fuji>

#### Example Queries

{% hint style="warning" %}
NOTES

* Each subgraph only returns data for the chain it is indexing. You cannot filter by fields such as "network" or "chainId", they have only been added to allow the dApp to do so, once the results from multiple subgraphs have been merged.
* String searches are case sensitive, unless you add `_nocase` for example `owner_contains_nocase` as seen in the vesting token balance example.
* The `hasClosed` field on the `Market` entity is not fully trustworthy, markets can sometimes close without triggering an event which updates this. We use it to filter out the majority which do trigger an event, then on the dApp, filter the rest manually.
* By default, a request returns a maximum of 100 results. You can request up to 1000 using `first: 1000`, for example: `ownerTokenTbvs(first: 1000)`. If more than 1000 results are required, you will have to use pagination (<https://thegraph.com/docs/en/querying/graphql-api/#pagination>).
  {% endhint %}

List markets, including all data loaded by dApp on initial load:

```
{
    markets(where: { hasClosed: false }) {
      id
      name
      network
      auctioneer
      teller
      marketId
      owner
      callbackAddress
      capacity
      capacityInQuote
      chainId
      minPrice
      scale
      start
      conclusion
      payoutToken {
        id
        address
        symbol
        decimals
        name
      }
      quoteToken {
        id
        address
        symbol
        decimals
        name
        lpPair {
          token0 {
            id
            address
            symbol
            decimals
            name
            typeName
          }
          token1 {
            id
            address
            symbol
            decimals
            name
            typeName
          }
        }
        balancerWeightedPool {
          id
          vaultAddress
          poolId
          constituentTokens {
            id
            address
            symbol
            decimals
            name
            typeName
          }
        }
      }
      vesting
      vestingType
      isInstantSwap
      hasClosed
      totalBondedAmount
      totalPayoutAmount
      creationBlockTimestamp
    }
  }
```

List all tokens:

```
{
    tokens {
      id
      network
      chainId
      address
      decimals
      symbol
      name
      lpPair {
        token0 {
          id
        }
        token1 {
          id
        }
      }
      balancerWeightedPool {
        constituentTokens {
          id
        }
      }
    }
  }
```

Show vesting token balances for a given user:

```
{
    ownerBalances(where: { owner_contains_nocase: OWNER_ADDRESS, balance_gt: 0 }) {
      id
      tokenId
      owner
      balance
      network
      chainId
      bondToken {
        id
        symbol
        decimals
        expiry
        network
        chainId
        type
        teller
        underlying {
          id
          symbol
          decimals
        }
      }
    }
  }
```

TBV per owner/token combination:

```
{
    ownerTokenTbvs(first: 1000) {
      owner
      token
      tbv
      network
      chainId
    }
  }
```

Bond purchases per market:

```
{
    bondPurchases(
      first: 1000
      where: { marketId: MARKET_ID }
      orderBy: timestamp
    ) {
      id
      recipient
      payout
      amount
      timestamp
      purchasePrice
      postPurchasePrice
      quoteToken {
        id
        name
        symbol
        address
      }
      payoutToken {
        id
        name
        symbol
        address
      }
    }
  }
```


# Market Calculations

How to calculate pricing, discount, vesting etc for markets

### Pricing & Discount

First, assuming you wish to display USD pricing, you will need to obtain USD prices for your quote and payout tokens. How you do this is up to you, and can vary depending on the token. For example, if both tokens have accurate pricing available on Coingecko or a similar service, you can simply pull the price from their API. In other cases, you may wish to use an oracle or calculate from an LP pair. If your quote token is something like an LP pair or a Balancer Weighted Pool, you will have to manually calculate the value of the token to get accurate market pricing.

You will also need the number of decimals for your payout/quote tokens - if you are simply displaying your markets with a known set of tokens, it makes sense to hardcode these values.

This is a UI issue - the underlying contracts work on the quote/payout ratio, not USD price, so nothing here will affect the actual price at which users can bond, just the usability of your UI. Accordingly, if you wanted to display pricing in EUR, BTC or anything else, you could substitute USD prices for those.

Once you have your pricing information, we recommend the following contract requests:

```
const [
  currentCapacity,
  marketPrice,
  marketScale,
  maxAmountAccepted,
  marketInfo,
  isLive,
  markets,
  ownerPayoutBalance,
  ownerPayoutAllowance,
] = await Promise.all([
  auctioneerContract.currentCapacity(marketId),
  auctioneerContract.marketPrice(marketId),
  auctioneerContract.marketScale(marketId),
  auctioneerContract.maxAmountAccepted(
    marketId,
    referrerAddress,
  ),
  auctioneerContract.getMarketInfoForPurchase(marketId),
  auctioneerContract.isLive(marketId),
  auctioneerContract.markets(marketId),
  payoutTokenContract.balanceOf(owner),
  payoutTokenContract.allowance(
    ownerAddress,
    tellerAddress,
  ),
]);
```

The next step is to adjust for market scale and get the discounted price:

{% hint style="info" %}
The price decimal scaling for a market is split between the price value and the scale value in order to be able to support a broader range of inputs. Specifically, half of it is in the scale and half in the price. To normalize the price value for display, we can add the half that is in the scale factor back to it.
{% endhint %}

```
const baseScale = BigNumber.from('10').pow(
  BigNumber.from('36')
    .add(payoutToken.decimals)
    .sub(quoteToken.decimals),
);

const shift = Number(baseScale) / Number(marketScale);
const price = Number(marketPrice) * shift;
const quoteTokensPerPayoutToken = price / Math.pow(10, 36);
const discountedPrice = quoteTokensPerPayoutToken * quoteToken.price;
```

Here, `quoteTokensPerPayoutToken` is the exchange rate between the two tokens used by the contract to determine the current bond price. Multiplying this by the quote token's USD price gives us the USD price at which a user can purchase from the market.

Next we can calculate the discount:

```
let discount = (discountedPrice - payoutToken.price) / payoutToken.price;
discount *= 100;
```

{% hint style="warning" %}
The 'discount' can also be negative - i.e. purchasing from BondProtocol is currently more expensive than purchasing at market rates. Once the daily capacity has been hit, the discount will be negative until it gradually ticks back to a positive discount.

It is strongly recommended to make this clear in your UI (different colors, warning message etc) to avoid complaints from users who accidentally bonded at a large premium.
{% endhint %}

### Vesting

There are a few options for displaying vesting. First, if you are running an instant swap market, you can just display it as such in the front end. The auctioneer contract has an `isInstantSwap(marketId)` function, if you are unsure.

In most cases, your market will either have a fixed vesting date, or a fixed vesting term (e.g. 14 days). You can get the `vesting` period value from the auctioneer contract's `terms(marketId)` function, which returns 4 values, `vesting` (`uint48`) being the 3rd. Since this doesn't change after market creation, you could hardcode it.

If you have a fixed expiration market, `vesting` will be a timestamp. We use this to create a new JS `Date` object for the expiration date, which you can then format as desired, for example:

```
new Date(calculatedMarket.vesting * 1000, 'yyyy-MM-dd');
```

If you have a fixed term market, `vesting` will be a duration in seconds. We use the following function to create a human-readable value:

```
export function longVestingPeriod(seconds: number): string {
  const d = Math.floor(seconds / (3600 * 24));
  const h = Math.floor((seconds % (3600 * 24)) / 3600);
  const m = Math.floor((seconds % 3600) / 60);

  const dDisplay = d > 0 ? d + (d == 1 ? ' day, ' : ' days, ') : '';
  const hDisplay = h > 0 ? h + (h == 1 ? ' hr, ' : ' hrs, ') : '';
  const mDisplay = m > 0 ? m + (m == 1 ? ' min' : ' mins') : '';

  let result = dDisplay + hDisplay + mDisplay;
  if (mDisplay === '') {
    result = result.slice(0, result.length - 2);
  }

  return result;
}
```

### Capacity, Payout & Allowances

To display the current capacity of your market in a human-readable way, you need to adjust the `currentCapacity` value by your capacity token's decimals - the capacity can be in either quote or payout token depending on how you set up the market, this could be hardcoded if you know the decimal value will be the same across all markets you are displaying:

```
const decimals = capacityInQuote ? quoteToken.decimals : payoutToken.decimals;
currentCapacity = Number(currentCapacity) / Math.pow(10, decimals);
```

To calculate the max payout for a market:

```
const maxPayout = Number(marketInfo.maxPayout) / Math.pow(10, payoutToken.decimals);
const maxPayoutUsd = maxPayout * payoutToken.price;
```

To calculate the max amount of quote tokens accepted for a single purchase:

```
const maxAccepted =
  (Number(maxAmountAccepted) - Number(maxAmountAccepted) * 0.005) / 
  Math.pow(10, quoteToken.decimals);
```

{% hint style="warning" %}
We multiply the result of `Number(maxAmountAccepted) - Number(maxAmountAccepted)` by 0.005 in order to reduce `maxAmountAccepted` by 0.5%.

This is due to the fee being slightly underestimated in the contract function.

See comment on <https://github.com/Bond-Protocol/bond-contracts/blob/master/src/bases/BondBaseSDA.sol> line 764 for more detail.
{% endhint %}

Since payout tokens are not held by BondProtocol, it is possible that the maximum payout could be limited by either the payout token balance of your owner address, or the spending allowance. We check these, and if one is insufficient, display an error message showing the exact issue. Should you wish to do the same, it is straightforward:

```
const ownerBalance = Number(ownerPayoutBalance) / Math.pow(10, payoutToken.decimals);
const ownerAllowance = Number(ownerPayoutAllowance) / Math.pow(10, payoutToken.decimals);
```

Finally, you can optionally use `isLive` to check the status of your market and hide it from your UI when closed.


# Purchases & Redemptions

How to enable users to purchase and redeem bonds

### Purchases

Our Teller contract's `purchase` function takes the following parameters:

* `recipient` - the address which will receive the vesting tokens (i.e. the purchaser)
* `referrer` - the address to which frontend referral fees (currently disabled) will be sent if enabled (or `0x0000000000000000000000000000000000000000` if not providing an address)
* `id` - the id of the market from which the bond is being purchased
* `amount` - the amount being purchased
* `minAmountOut` - the minimum number of payout tokens the user will receive. This protects the user against excessive slippage
* `overrides` - standard override parameters, `gasLimit`, `gasPrice` etc

The values for `amount` and `minAmountOut` should be formatted taking into account their decimals:

```
amount = ethers.utils.parseUnits(amount.toString(), quoteDecimals)
        .toString();
        
minAmountOut = ethers.utils.parseUnits(minAmountOut.toString(), payoutDecimals)
        .toString()
```

So an example call would be:

```
tellerContract.purchase(
      recipientAddress,
      referrer,
      id,
      amount,
      minAmountOut,
      overrides
);
```

### Redemptions

Our Teller's `redeem` function takes the following parameters:

* `token` - the address of the vesting token
* `amount` - the amount to redeem
* `overrides` - standard override parameters, `gasLimit`, `gasPrice` etc

For `amount` we recommend using the user's full balance by default.

So an example call would be:

<pre><code>tellerContract.redeem(
<strong>    tokenAddress, 
</strong>    amount, 
    overrides
);
</code></pre>


# User Balances

How to load user vesting token balances

When a user purchases a bond from BondProtocol, they receive a vesting token. The underlying payout token is held by the Teller contract. Users can redeem their vesting tokens for the underlying payout token when the vesting period is complete.

The way our contracts work is to create a vesting token for each unique combination of underlying token + vesting date timestamp. All tokens vest at midnight UTC.

Our Fixed-Expiry markets create an `ERC-20` vesting token, while our Fixed-Term markets create an `ERC-1155` vesting token.

Our Teller contracts have functions which return the token address (in the case of an `ERC-20`) or token ID (in the case of an `ERC-1155`). In both cases, you must provide the address of the underlying payout token, and the vesting date timestamp.

For Fixed-Expiry markets, this is straightforward - there is only one expiry date, and as such, only one vesting token.

For Fixed-Term markets, there is a different vesting token for each day the market is open, with the vesting timestamp being the day of purchase plus the vesting term.

See below for more details.

### ERC-20 (Fixed-Expiry) Vesting Tokens

You can find the vesting token address by calling the `bondTokens(payoutTokenAddress, vestingTimestamp)` function on the `FixedExpiryTeller` contract.

As the vesting token is an `ERC-20` token, you can then call the vesting token's `balanceOf(holderAddress)` function to get the user's balance.

### ERC-1155 (Fixed-Term) Vesting Tokens

{% hint style="danger" %}
The easiest way to get the data required below is from our subgraph. However, as our Ethereum Mainnet subgraph is on [Graph Protocol's](https://thegraph.com) decentralized network, this would require you to pay query fees.

At the time of writing, other chains are available on the Graph Protocol hosted service without fees. Graph Protocol have not yet announced a timeline for migrating the other chains we support to their decentralized network.

As all tokens vest at midnight UTC, one manual alternative method of generating vesting date timestamps is, for each day your market will be open, to add the vesting term to a midnight UTC timestamp for that date.
{% endhint %}

You can find the vesting token ID by calling the `getTokenId(payoutTokenAddress, vestingTimestamp)` function on the `FixedTermTeller` contract.

As the vesting token is an `ERC-1155` token, you can then call the vesting token's `balanceOf(holderAddress, tokenId`) function to get the user's balance.


# Options Library

Frontend library for interacting with Option contracts

As we are not currently running a frontend for Option Tokens or Options Liquidity Mining, the Options Library is intended to allow protocols to easily integrate these into their own frontends.

[GitHub](https://github.com/Bond-Protocol/options-library)

[NPM](https://www.npmjs.com/package/@bond-protocol/options-library)

The main benefits of this library are as follows:

* Helper functions for common frontend tasks such as calculating prices, APRs, requesting commonly used data on Option Tokens etc
* Getter functions for contract addresses/ABIs on a per chain basis (initially, these will all be identical, and ideally will stay that way. However, past experience with our Bond contracts shows that there is a possibility they may diverge later).

The library uses [Viem](https://viem.sh), and some helper functions require a Viem [`PublicClient`](https://viem.sh/docs/clients/public.html) or [`WalletClient`](https://viem.sh/docs/clients/wallet.html) (the Viem equivalent of [Ethers](https://ethers.org/)' [`Provider`](https://docs.ethers.org/v6/api/providers/) and [`Signer`](https://docs.ethers.org/v6/api/providers/#Signer)) to be passed in - this is easiest for frontends using [wagmi](https://wagmi.sh) v1+, but we have included an example UI using the legacy Ethers based version of wagmi in order to demonstrate manual setup of a `PublicClient` and `WalletClient`.


# Helper Functions

Functions providing data commonly required by frontend displays.

See [helpers.ts](https://github.com/Bond-Protocol/options-library/blob/master/src/helpers.ts)

### getAddressesForChain

Gets the addresses of pre-deployed contracts for the Option system on the specified chain.

At launch, these should be identical across all chains, but this is included in case they diverge for some reason in the future.

Parameters:

* `chainId (number)` - the chain id to get addresses for.

Returns:

* A [`ChainAddresses`](/developers/options-library/types#chainaddresses) object, containing the addresses of contracts deployed on the specified chain.

### getAbisForChain

Gets the ABIs of Option system contracts on the specified chain.

At launch, these should be identical across all chains, but this is included in case they diverge for some reason in the future.

Parameters:

* `chainId (number)` - the chain id to get ABIs for.

Returns:

* A [`ChainAbis`](/developers/options-library/types#chainabis) object, containing the ABIs of contracts deployed on the specified chain.

### getOLMInitializeBytecode

Hex encodes the provided parameters in the correct format for the OLM's initialize function. This is compatible with both MOLM and OOLM contracts.

Parameters:

* `quoteTokenAddress (0x${string})` - Token that stakers must pay to exercise the call options they receive.
* `timeUntilEligible (number)` - Amount of time (in seconds) from option token deployment to when it can be exercised.
* `eligibleDuration (number)` - Amount of time (in seconds) from when the option token is eligible to when it expires.
* `receiver (0x${string})` - Address that will receive the quote tokens when an option is exercised. IMPORTANT: receiver is the only address that can retrieve payout token collateral from expired options. It must be able to call the `reclaim` function on the Option Teller contract.
* `epochDuration (number)` - Staking epoch duration (in seconds).
* `epochTransitionReward (number)` - Amount of option tokens that are rewarded for starting a new epoch.
* `rewardRate (string)` - Amount of option tokens rewarded per reward period (1 day).
* `allowlistAddress (0x${string})` - Address of the allowlist contract that can be used to restrict who can stake in the OLM contract. If the zero address, then no allow list is used.
* `allowlistParams (string)` - Parameters that are passed to the allowlist contract when this contract registers with it.
* `other (string)` - Additional parameters that are required by specific implementations of the OLM contract.
* `chainId (number)` - The chain id on which the transaction will be executed.

Returns:

* A `0x${string}` consisting of the hex-encoded bytecode for the OLM `initialize` function. This can be copied and executed manually.

### getOLMPricing

Calculates OLM pricing information which is commonly required for front end displays.

Parameters:

* `olmAddress (0x${string})` - Address of the OLM contract to get pricing for.
* `payoutPriceUSD (number)` - The current price of the Payout Token in USD.
* `quotePriceUSD (number)` - The current price of the Quote Token in USD.
* `stakedTokenPriceUSD (number)` - The current price of the Staked Token in USD.
* `publicClient (PublicClient)` - A Viem `PublicClient`.

Returns:

* > `Promise<`[`OLMPricing`](/developers/options-library/types#olmpricing)`>` containing pricing data for the specified OLM.

### getOLMTokenList

Returns a list of addresses for Option Tokens created by an OLM, in order of epoch.

Parameters:

* `olmAddress (0x${string})` - Address of the OLM contract to get a token list for.
* `publicClient (PublicClient)` - A Viem `PublicClient`.

Returns:

* `Promise<string[]>` containing a list of addresses for Option Tokens created by the specified OLM, in order of epoch.

### getOTokenData

Gathers Option Token data commonly required by front end displays.

Parameters:

* `oTokenAddress (0x${string})` - Address of the Option Token to get data for.
* `publicClient (PublicClient)` - A Viem `PublicClient`.
* `userAddress (0x${string}) [OPTIONAL]` - The address of a user to check Option Token balances for. If not provided, a balance of 0 will be returned for all Option Tokens.

Returns:

* `Promise<`[`OTokenData`](/developers/options-library/types#otokendata)`>` containing data commonly required by frontend displays.


# Types

Custom types used by options-library

## ChainAddresses

Contains the addresses of the pre-deployed contracts used by the Option system.

```
type ChainAddresses = {
  FixedStrikeOptionTeller: `0x${string}`;
  MOLMFactory: `0x${string}`;
  OOLMFactory: `0x${string}`;
};
```

## ChainAbis

Contains the ABIs of the contracts used by the Option system.

```
type ChainAbis = {
  ERC20: typeof IERC20;
  FixedStrikeOptionTeller: typeof fixedStrikeOptionTeller;
  MOLMFactory: typeof MOLMFactory;
  OOLMFactory: typeof OOLMFactory;
  Allowlist: typeof allowlist;
  FixedStrikeOptionToken: typeof fixedStrikeOptionToken;
  OLM: typeof OLM;
  MOLM: typeof manualStrikeOLM;
  OOLM: typeof oracleStrikeOLM;
  OptionToken: typeof optionToken;
};
```

## OLMPricing

Contains pricing data for an OLM.

```
type OLMPricing = {
  strikePriceUSD: number;
  impliedValue: number;
  stakedTokenBalance: string;
  rewardRate: string;
  epochRoi: number;
  epochDuration: number;
  epochsPerYear: number;
  apr: number;
};
```

## Token

Contains the basic data for an ERC-20 token.

```
type Token = {
  address: `0x${string}`;
  name: string;
  symbol: string;
  decimals: number;
};
```

## OTokenData

Contains data for an Option Token which is commonly required by frontend displays.

```
type OTokenData = {
  optionToken: Token;
  payoutToken: Token;
  quoteToken: Token;
  strikePrice: bigint;
  decimalAdjustedStrike: string;
  eligibleTime: number;
  expiryTime: number;
  call: boolean;
  balance: bigint;
  decimalAdjustedBalance: string;
};
```


# Technical Resources

#### Smart Contracts (Ethereum, Arbitrum, Optimism)

| Contract                                        | Address                                    | Ethereum                                                                             | Arbitrum                                                                           |
| ----------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- |
| Roles Authority                                 | 0x007A0F48A4e3d74Ab4234adf9eA9EB32f87b4b14 | [Etherscan](https://etherscan.io/address/0x007A0F48A4e3d74Ab4234adf9eA9EB32f87b4b14) | [Arbiscan](https://arbiscan.io/address/0x007A0F48A4e3d74Ab4234adf9eA9EB32f87b4b14) |
| Aggregator                                      | 0x007A66A2a13415DB3613C1a4dd1C942A285902d1 | [Etherscan](https://etherscan.io/address/0x007A66A2a13415DB3613C1a4dd1C942A285902d1) | [Arbiscan](https://arbiscan.io/address/0x007A66A2a13415DB3613C1a4dd1C942A285902d1) |
| Fixed-Expiration Teller                         | 0x007FE70dc9797C4198528aE43d8195ffF82Bdc95 | [Etherscan](https://etherscan.io/address/0x007FE70dc9797C4198528aE43d8195ffF82Bdc95) | [Arbiscan](https://arbiscan.io/address/0x007FE70dc9797C4198528aE43d8195ffF82Bdc95) |
| Fixed-Expiration SDA                            | 0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD | [Etherscan](https://etherscan.io/address/0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD) | [Arbiscan](https://arbiscan.io/address/0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD) |
| ERC20 Bond Token Reference (clones proxy to it) | 0xD525c81912E242D0E86BC6A05e97A7c9AD747c48 | [Etherscan](https://etherscan.io/address/0xD525c81912E242D0E86BC6A05e97A7c9AD747c48) | [Arbiscan](https://arbiscan.io/address/0xD525c81912E242D0E86BC6A05e97A7c9AD747c48) |
| Fixed-Term Teller                               | 0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6 | [Etherscan](https://etherscan.io/address/0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6) | [Arbiscan](https://arbiscan.io/address/0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6) |
| Fixed-Term SDA                                  | 0x007F7A1cb838A872515c8ebd16bE4b14Ef43a222 | [Etherscan](https://etherscan.io/address/0x007F7A1cb838A872515c8ebd16bE4b14Ef43a222) | [Arbiscan](https://arbiscan.io/address/0x007F7A1cb838A872515c8ebd16bE4b14Ef43a222) |
| Fixed-Term FPA                                  | 0xF7F9Ae2415F8Cb89BEebf9662A19f2393e7065e0 | [Etherscan](https://etherscan.io/address/0xF7F9Ae2415F8Cb89BEebf9662A19f2393e7065e0) | [Arbiscan](https://arbiscan.io/address/0xF7F9Ae2415F8Cb89BEebf9662A19f2393e7065e0) |
| Fixed-Expiration FPA                            | 0xFEF9A527ac84836DC9939Ad75eb8ce325bBE0E54 | [Etherscan](https://etherscan.io/address/0xFEF9A527ac84836DC9939Ad75eb8ce325bBE0E54) | [Arbiscan](https://arbiscan.io/address/0xFEF9A527ac84836DC9939Ad75eb8ce325bBE0E54) |

**Testnet Smart Contracts**

| Contract                                        | Address                                    | Goerli                                                                                             | Arbitrum Goerli                                                                                   |
| ----------------------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Roles Authority                                 | 0x007A0F48A4e3d74Ab4234adf9eA9EB32f87b4b14 | [Goerli Etherscan](https://goerli.etherscan.io/address/0x007A0F48A4e3d74Ab4234adf9eA9EB32f87b4b14) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0x007A0F48A4e3d74Ab4234adf9eA9EB32f87b4b14)  |
| Aggregator                                      | 0x007A66A2a13415DB3613C1a4dd1C942A285902d1 | [Goerli Etherscan](https://goerli.etherscan.io/address/0x007A66A2a13415DB3613C1a4dd1C942A285902d1) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0x007A66A2a13415DB3613C1a4dd1C942A285902d1)  |
| Fixed-Expiration Teller                         | 0x007FE70dc9797C4198528aE43d8195ffF82Bdc95 | [Goerli Etherscan](https://goerli.etherscan.io/address/0x007FE70dc9797C4198528aE43d8195ffF82Bdc95) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0x007FE70dc9797C4198528aE43d8195ffF82Bdc95)  |
| Fixed-Expiration SDA                            | 0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD | [Goerli Etherscan](https://goerli.etherscan.io/address/0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0x007FEA32545a39Ff558a1367BBbC1A22bc7ABEfD)  |
| ERC20 Bond Token Reference (clones proxy to it) | 0xD525c81912E242D0E86BC6A05e97A7c9AD747c48 | [Goerli Etherscan](https://goerli.etherscan.io/address/0xD525c81912E242D0E86BC6A05e97A7c9AD747c48) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0xD525c81912E242D0E86BC6A05e97A7c9AD747c48)  |
| Fixed-Term Teller                               | 0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6 | [Goerli Etherscan](https://goerli.etherscan.io/address/0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0x007F7735baF391e207E3aA380bb53c4Bd9a5Fed6)  |
| Fixed-Term SDA                                  | 0x007F7A1cb838A872515c8ebd16bE4b14Ef43a222 | [Goerli Etherscan](https://goerli.etherscan.io/address/0x007F7A1cb838A872515c8ebd16bE4b14Ef43a222) | [Goerli Arbiscan](https://goerli.arbiscan.io/address/0x007F7A1cb838A872515c8ebd16bE4b14Ef43a222)  |
| Fixed-Term FPA                                  | 0xF7F9Ae2415F8Cb89BEebf9662A19f2393e7065e0 | [Goerli Etherscan](https://goerli.etherscan.io/address/0xF7F9Ae2415F8Cb89BEebf9662A19f2393e7065e0) | [Goerli Arbiscan](https://testnet.arbiscan.io/address/0xF7F9Ae2415F8Cb89BEebf9662A19f2393e7065e0) |
| Fixed-Expiration FPA                            | 0xFEF9A527ac84836DC9939Ad75eb8ce325bBE0E54 | [Goerli Etherscan](https://goerli.etherscan.io/address/0xFEF9A527ac84836DC9939Ad75eb8ce325bBE0E54) | [Goerli Arbiscan](https://testnet.arbiscan.io/address/0xFEF9A527ac84836DC9939Ad75eb8ce325bBE0E54) |

The source code for the smart contracts can be found at:

<https://github.com/Bond-Protocol/bond-contracts>

### Bond library

Library containing off-chain details related to bonds, protocols, tokens, chains and etc:

<https://github.com/Bond-Protocol/bond-library>


# Audits

| Auditor  | Product                  | Link                                                                          |
| -------- | ------------------------ | ----------------------------------------------------------------------------- |
| Sherlock | Permissionless Bonds     | <https://github.com/Bond-Protocol/bond-contracts/tree/master/audits/Sherlock> |
| Zellic   | Permissionless Bonds     | <https://github.com/Bond-Protocol/bond-contracts/tree/master/audits/Zellic>   |
| yAcademy | Permissionless Bonds     | <https://github.com/Bond-Protocol/bond-contracts/tree/master/audits/yAcademy> |
| Sherlock | Options Liquidity Mining | <https://github.com/Bond-Protocol/option-contracts/tree/master/audit>         |


# Community Resources

### The Basics

* [A Comparison of Bonds and OLM](https://medium.com/@Bond_Protocol/a-comparison-of-bonds-and-olm-a416b11ee8fa)
* [Introducing Options Liquidity Mining](https://medium.com/@Bond_Protocol/introducing-options-liquidity-mining-9beee41e6fdf)
* [Introducing Permissionless Bond Market Deployment](https://medium.com/@Bond_Protocol/introducing-permissionless-bond-market-deployment-b6cfbcd13fad)
* [What the Dutch](https://medium.com/@Bond_Protocol/auctions-what-the-dutch-80e4bb3ee7ad)
* [An Updated Primer on Bonding](https://medium.com/@Bond_Protocol/an-updated-primer-on-bonding-ef75a284fcd8)
* [Introducing Bond Protocol](https://medium.com/@Bond_Protocol/introducing-bond-protocol-8476881f84e4)

### Case Studies

* [Acquiring Strategic Assets through Bond Issuance — JPEG'd](https://medium.com/@Bond_Protocol/acquiring-strategic-assets-through-bond-issuance-jpegd-c83c4856ca7a)
* [Funding Security Audits through Bond Issuance — Lodestar Finance](https://medium.com/@Bond_Protocol/funding-security-audits-through-bond-issuance-lodestar-finance-c75d1a1e27d2)
* [The Impact of Bond Protocol on the Arbitrum Ecosystem](https://medium.com/@Bond_Protocol/the-impact-of-bond-protocol-on-the-arbitrum-ecosystem-d8764149b002)
* [How Bond Market Issuers Handled the USDC Depeg](https://twitter.com/Bond_Protocol/status/1645854935186305025?s=20)

### Twitter Threads

* [How Fixed Price Bonds Provide Value to Projects](https://twitter.com/bfjoe1/status/1643365258780880896?s=20)
* [How Sequential Dutch Auctions Provide Value Throughout a Project's Lifecycle](https://twitter.com/Bond_Protocol/status/1656420879944007680?s=20)
* [Big Brain Bonding Strategies](https://twitter.com/Bond_Protocol/status/1559975553280638978?s=20\&t=QUV3mXSHw4Hw8wCxpe021w)
* [Auction Capacity](https://twitter.com/Bond_Protocol/status/1557843046468919296?s=20\&t=QUV3mXSHw4Hw8wCxpe021w)
* [Dysfunctional DeFi](https://twitter.com/Bond_Protocol/status/1549822684019703816?s=20)


# Brand Assets

### Logos and Icons

Various logos and icons are available for download [<mark style="color:blue;">here</mark>](https://drive.google.com/drive/folders/1oVTz3pweG98vgs2hfB33ixKfZ8zwNFN2)&#x20;

### Colors

* Core [<mark style="color:blue;">colors</mark>](https://colorpeek.com/#f2a94a,40749b,12172b)
* Secondary [<mark style="color:blue;">colors</mark>](https://colorpeek.com/#f0dec4,9cc1c7)


# Contact Us

* [Request Form](https://gkk12lnayco.typeform.com/to/VVyP9rqt)
* [Discord](https://discord.gg/EjAm9m6jFy)


