--- title: PEPA Bond Market --- ###### tags: `Bond Market` `Fuel Network` `Sway Language` <font size="8"> PEPA Bond Market </font> Design & Spec === > Copyright © 2023 by PEPA Market. All rights reserved. > Feb 16, 2023 > by **PEPA Market** <!-- <span style="position:fixed; top:200px; right:400px; opacity:0.5; font-size: 20px; z-index:99;">watermark</span> --> <!-- inser new picture here --> ![PEPA-Market-Cover](https://i.imgur.com/Z6DNdg1.png) This report presents our PEPA dev team's engineering design & spec for the PEPA Bond Market. --- ## Table of Content [TOC] --- ## Project Summary We design this bond market as a financial market in which decentralized bonds are traded and issued. It allows for the automation of bond issuance, trading, and settlement processes through the use of decentralized applications (dApps) built on the PEPA platform. As a decentralized bond market, PEPA Bond offers several potential benefits compared to traditional bond markets, including increased transparency, reduced counterparty risk, and reduced settlement times. Our design also allows for greater access to bond markets for a wider range of investors, as well as more efficient and cost-effective issuance and trading of bonds. --- ## Protocol Overview ### Business Logic PEPA Bond Market is a decentralized bond platform that allows investors to buy and sell bonds directly without the need for intermediaries. Here are some of the key features of PEPA Bond Market: + **Decentralized bond issuance**: The PEPA Bond Market enables any qualified entities to issue bonds directly on the platform without the need for traditional financial intermediaries like banks or underwriters. + **Automated smart contract execution**: The PEPA Bond Market uses smart contracts to automate the bond issuance process, including bond purchase and payout claim. This ensures that transactions are executed automatically and transparently, reducing the risk of fraud. + **Tokenization of bonds**: The bonds issued on the PEPA Bond Market are tokenized, meaning that they are represented by digital tokens. This makes them easily tradable and divisible. ![Buying a Bond](https://i.imgur.com/ggN45UI.png) ### Core Elements PEPA Bond Market is a Fuel-based contract suite that enables the on-chain creation and trading of bonds backed by Fuel. Bond prices will be adjusted based on market activity and do not require regular maintenance. Bond issuers create bond markets that pay out a Payout Token in exchange for Quote Tokens deposited. Users may acquire future-dated Payout Tokens with Quote Tokens at the current market price and receive Bond Tokens indicating their position. After the bond becomes matured, user can redeem their payout token share. Currently, we build on the design of [BondProtocol](https://www.bondprotocol.finance/), a leading platform that provides Bonds-as-a-Service to meet the needs of DeFi with innovative ideas. Customization and optimization specifically for Fuel Network and the Sway language is coming along. #### Vendor Contract The Vendor contract allows users to create and manage bond markets. All bond pricing logic and market data is stored in the Vendor. A Vendor is dependent on a Seller to serve external users and an Floor to register new markets. This implementation of the Vendor uses a Sequential Dutch Auction pricing system to buy a target amount of quote tokens or sell a target amount of payout tokens over the duration of a market. #### Floor Contract The Floor contract keeps a unique set of market IDs across multiple Sellers and Vendors. Additionally, it aggregates market data from multiple Vendors in convenient view functions for front-end interfaces. The Floor contract should be deployed first since Sellers, Vendors, and Callbacks all require it in their constructors. #### Seller Contract The Seller 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, Investors can redeem their Bond Tokens for the underlying Payout Token. A Seller requires one or more Vendor contracts to be deployed to provide markets for users to purchase bonds from. #### Callback Contract The Callback contract is an optional feature of the Bond system. 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 Floor contract for the Vendor 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 Seller serving that market for the amount of Payout Tokens equivalent to the capacity of a market when created. --- ## PEPA Bond Market Architecture <!-- todo: add an system level overview / graph to explain each component --> <!-- ![Architecture](https://i.imgur.com/VlyqHdd.png) --> ![Pepa Bond Architecture](https://i.imgur.com/vXGqfiq.png) ### Floor Contract #### initialize - storage(read,write) Initilize a Floor. #### register_vendor - storage(read, write) Register a vendor with the floor. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | vendor_id | b256 | `Address` of Vendor | #### register_market - storage(read, write) Register a new market with the floor. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | payout_token | b256 | `ContractID` of payout token | | Input - 2 | quote_token | b256 | `ContractID` of quote token | | Output - 1 | market_id | b256 | `ContractID` of the market being created | #### get_vendor - storage(read) Get the vendor for the provided market ID. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | vendor_id | b256 | `Address` of the vendor for the provided market | #### market_price - storage(read) Calculate current market price of payout token in quote tokens. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | price | u256 | Price for market | #### market_scale - storage(read) Scale value to use when converting between quote token and payout token amounts with market_price(). | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | scale | u256 |Scaling factor for market in configured decimals | #### payout_for - storage(read, write) Payout due for amount of quote tokens. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Input - 2 | amount | u256 | Amount of quote tokens to spend | | Output - 1 | referrer | Address | Address of referrer | #### max_amount_accepted - storage(read) Returns maximum amount of quote token accepted by the market. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Input - 2 | referrer | Address | Address of referrer | | Output - 1 | | u256 | Maximum amount of quote token accepted by the market | #### is_instant_swap - storage(read) Does market send payout immediately. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | bool | whether market send payout immediately | #### is_live - storage(read) Is a given market accepting deposits. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | bool | whether market accepting deposits | #### live_markets_between - storage(read) Returns array of active market IDs within a range. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | first_id | b256 | `ContractID` of of the first market | | Input - 2 | last_id | b256 | `ContractID` of of the last market | | Output - 1 | | Vec<u256> | active market IDs | #### live_markets_for - storage(read) Returns an array of all active market IDs for a given quote token. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | first_id | b256 | `ContractID` of token to query by | | Input - 2 | is_payout | bool | If true, search by payout token, else search for quote token | | Output - 1 | | Vec<u256> | active market IDs | #### live_markets_by - storage(read) Returns an array of all active market IDs for a given owner. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | b256 | Address | Address of owner to query by | | Input - 2 | first_id | b256 | Market ID to start at | | Input - 3 | last_id | b256 | Market ID to end at (non-inclusive) | | Output - 1 | | Vec<u256> | active market IDs | #### markets_for - storage(read) Returns an array of all active market IDs for a given payout and quote token. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | payout | b256 | Address of payout token | | Input - 2 | quote | b256 | Address of quote token | | Output - 1 | | Vec<u256> | active market IDs | #### find_market_for - storage(read) Returns the market ID with the highest current payoutToken payout for depositing quoteToken. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | b256 | payout | Address of payout token | | Input - 2 | b256 | quote | Address of quote token | | Input - 3 | amount_in | u256 | Amount of quote tokens to deposit | | Input - 4 | min_amount_out | u256 | Minimum amount of payout tokens to receive as payout | | Input - 5 | max_expiry | u256 | Latest acceptable vesting timestamp for bond | | Output - 1 | id | u256 | the market ID found | #### get_seller - storage(read) Returns the Seller that services the market ID. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | b256 | address of the seller | #### current_capacity - storage(read) Returns current capacity of a market. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | u256 | current capacity of the market | ### Vendor Contract #### initialize - storage(read,write) Initialize a vendor. #### create_market - storage(read, write) Creates a new bond market. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | params | | Configuration data needed for market creation | | Output - 1 | | b256 | ID of new bond market | #### close_market - storage(read, write) Disable existing bond market. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | #### purchase_bond - storage(read, write) Exchange quote tokens for a bond in a specified market. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Input - 2 | amount | u256 | Amount to deposit in exchange for bond | | Input - 3 | min_amount | u256 | Minimum acceptable amount of bond to receive. | | Output - 2 | payout | u256 | Amount of payout token to be received from the bond | #### set_intervals - storage(read, write) Set market intervals to different values than the defaults. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Input - 2 | intervals | u32[3] | Array of intervals (3) | | Input - 3 | intervals[0] | u32 | Tune interval - Frequency of tuning | | Input - 4 | intervals[1] | u32 | Tune adjustment delay - Time to implement downward tuning adjustments | | Input - 5 | intervals[2] | u32 | Debt decay interval - Interval over which debt should decay completely | #### push_ownership - storage(read, write) Designate a new owner of a market. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Input - 2 | owner | Address | New address to give ownership to | #### pull_ownership - storage(read, write) Accept ownership of a market. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | #### set_defaults - storage(read, write) Set the vendor defaults. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | defaults | u32[6] | Array of default values | | Input - 2 | defaults[0] | u32 | Tune interval - amount of time between tuning adjustments | | Input - 3 | defaults[1]| u32 | Tune adjustment delay - amount of time to apply downward tuning adjustments | | Input - 4 | defaults[2] | u32 | Minimum debt decay interval - minimum amount of time to let debt decay to zero | | Input - 5 | defaults[3] | u32 | Minimum deposit interval - minimum amount of time to wait between deposits | | Input - 6 | defaults[4] | u32 | Minimum market duration - minimum amount of time a market can be created for| | Input - 7 | defaults[5] | u32 |Minimum debt buffer - the minimum amount of debt over the initial debt to trigger a market shutdown | <!--- #### set_callback_auth_status ---> #### get_market_info_for_purchase - storage(read) Provides information for the Seller to execute purchases on a market. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | info | struct | | | Output - 2 | info.address | Address | Address of the market owner | | Output - 3 | info.callback_addr | struct | | | Output - 4 | info.payout_token | b256 | Payout Token | | Output - 5 | info.quote_token | b256 | Quote Token | | Output - 6 | info.vesting | u64 | Timestamp or duration for vesting, implementation-dependent| | Output - 7 | info.max_payout | u256 | Maximum amount of payout tokens you can purchase in one transaction| #### market_price - storage(read) Calculate current market price of payout token in quote tokens. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | price | u256 | Price for market | #### market_scale - storage(read) Scale value to use when converting between quote token and payout token amounts with market_price(). | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | scale | u256 |Scaling factor for market in configured decimals | #### payout_for - storage(read, write) Payout due for amount of quote tokens. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Input - 2 | amount | u256 | Amount of quote tokens to spend | | Output - 1 | referrer | Address | Address of referrer | #### max_amount_accepted - storage(read) Returns maximum amount of quote token accepted by the market. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Input - 2 | referrer | Address | Address of referrer | | Output - 1 | | u256 | Maximum amount of quote token accepted by the market | #### is_instant_swap - storage(read) Does market send payout immediately. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | bool | whether market send payout immediately | #### is_live - storage(read) Is a given market accepting deposits | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | bool | whether market accepting deposits | #### get_seller - storage(read) Returns the Seller that services the market ID. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | b256 | address of the seller | #### current_capacity - storage(read) Returns current capacity of a market. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | u256 | current capacity of the market | #### owner_of - storage(read) Returns the address of the market owner | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | market_id | b256 | `ContractID` of of the market | | Output - 1 | | Address | address of the market owner | #### get_floor - storage(read) Returns the Floor that services the Vendor. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Output - 1 | | b256 | Contract id of the Floor | ### Seller Contract #### claim_fee - storage(read) Claim fees accrued for input tokens and sends to protocol. Caller must be administrator. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | tokens | Vec<b256> | List of tokens to claim fees for | | Input - 2 | to | b256 | Fee collector address | #### create_fee_discount - storage(read,write) '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. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | discount | u64 | Discount from base protocol purchase fee when creating bond tokens for external use | #### get_fee - storage(read) Get current fee charged by the seller based on the combined protocol and referrer fee. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | referrer | b256 | address of referrer | | Output - 1 | fee | u64 | Fee in basis points (3 decimal places) | #### protocol_fee - storage(read) Get current fee charged by the seller based on the combined protocol and referrer fee. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Output - 1 | protocol_fee | u64 | fee paid to protocol (subject to configuration) | #### purchase - storage(read, write) Exchange quote tokens for a bond in a specified market. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | recipient | b256 | Address of recipient of bond. | | Input - 2 | referrer | b256 | Address of referrer who will receive referral fee. For frontends to fill. Direct calls can use the zero address for no referrer fee. | | Input - 3 | id | b256 | ID of the Market the bond is being purchased from | | Input - 4 | amount | u64 | Amount to deposit in exchange for bond| | Input - 5 | min_amount_out | u64 | Minimum acceptable amount of bond to receive. Prevents frontrunning | | Output - 1 | payout | u64 | Timestamp at which the bond token can be redeemed for the underlying token | | Output - 2 | expiry | u64 |Timestamp at which the bond token can be redeemed for the underlying token| #### referrer_fee - storage(read) <!--- Set by the referrer, must be less than or equal to $5e4$. ----> Fee paid to a front end operator. There are some situations where the fees may round down to zero (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. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | referrer | b256 | | | Output - 1 | fee | u64 | | #### rewards - storage(read) Fees earned by an address, by token. | | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | referrer | b256 | | | Input - 2 | token | b256 | | | Output - 1 | fee_balance | u64 | | #### set_protocol_fee - storage(read, write) Set protocol feeMust be guardian. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | fee | u64 | Protocol fee in basis points (3 decimal places) | #### set_referrer_fee - storage(read, write) Set your fee as a referrer to the protocolFee is set for sending address. | <font color='white'>test</font> &nbsp; &nbsp; &nbsp; &nbsp; | Veriable Name | Type | Description | | --------- | ---------------- | -----| -------- | | Input - 1 | fee | u64 | Protocol fee in basis points (3 decimal places) | --- ## License | Safety Notice | Disclaimer <!-- todo: Express current engineering and testing is still undergoing and contract has not been security review yet --> **DISCLAIMER:** This software is provided "as is" and without any express or implied warranties, including, without limitation, the implied warranties of merchantability and fitness for a particular purpose. The author(s) will not be held liable for any damages arising from the use of this software. This code is provided for educational and informational purposes only. It should not be used for any purpose that may be deemed commercial, without prior written consent from the author(s). The author(s) make no representations or warranties with respect to the accuracy or completeness of the contents of this code and specifically disclaim any implied warranties of merchantability or fitness for a particular purpose. The user assumes all responsibility and risk for the use of this code. Feel free to modify and customize the disclaimer as needed, depending on the specific details of your code and the intended use of the software.