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:
where is the oracle price at time , is the base discount percent of the market, is the decay speed, and is the capacity ratio.
We calculate on market creation as:
where is the duration of the market, is the deposit interval, and is the target discount over a deposit interval.
We calculate the capacity ratio as:
where is the initial capacity of the market, is the remaining capacity at time , and is the expected capacity at time .
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.
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 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.
Parameters to create a new OSDA market. Encoded as bytes and provided as input to createMarket
.
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 contains the token, callback, capacity, owner, and purchased/sold amount data for a Oracle Fixed Discount Market.
BondTerms contains the oracle, pricing, and time parameters of an Oracle Fixed Discount Market.
Whether or not the auctioneer allows new markets to be created
Changing to false will sunset the auctioneer after all active markets end
Roles authority contract for the bond system which managed access-control to permissioned functions.
Whether or not the market creator is authorized to use a callback address
creator_
address
Market creator address.
Returns current capacity of a market
Parameters
id_
uint256
Market ID
Returns the Aggregator that services the Auctioneer
Provides information for the Teller to execute purchases on a Market
Parameters
id_
uint256
Market ID
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
Returns the Teller that services the Auctioneer
Does market send payout immediately
Parameters
id_
uint256
Market ID
Is a given market accepting deposits
Parameters
id_
uint256
Market ID
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.oracleConversion factor. marketPrice
and marketScale
can be used to convert between amounts of quote tokens and payout tokens at the current price.
Parameters
id_
uint256
Market ID
Scale value to use when converting between quote token and payout token amounts with marketPrice()
Parameters
id_
uint256
Market ID
Returns the token, callback, capacity, owner, and purchased/sold amount data for a market. See BondMarket.
Parameters
id_
uint256
Market ID
Returns maximum amount of quote token accepted by the market
Parameters
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.
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
id_
uint256
Market ID
Minimum deposit interval for a market
Minimum market duration in seconds
New address to designate as market owner. They must accept ownership to transfer permissions.
Parameters
id_
uint256
Market ID
Returns the address of the market owner
Parameters
id_
uint256
Market ID
Payout due for amount of quote tokens at current market price
Parameters
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.
Information pertaining to oracle, pricing, and time parameters. See BondTerms.
Parameters
id_
uint256
Market ID
Disable existing bond market. Must be market owner
Parameters
id_
uint256
Market ID
Creates a new bond market
See MarketParams for the required formatting for the abi-encoded input params.
Parameters
params_
bytes
Configuration data needed for market creation, encoded in a bytes array
id_
uint256
Market ID
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
Exchange quote tokens for a bond in a specified market. Must be teller. End users interact with the Teller contract to purchase.
Parameters
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
payout
uint256
Amount of payout token to be received from the bond
Designate a new owner of a marketMust be market owner
Doesn't change permissions until newOwner calls pullOwnership
Parameters
id_
uint256
Market ID
newOwner_
address
New address to give ownership to
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
status_
bool
Allow market creation (true) : Disallow market creation (false)
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
creator_
address
Address of market creator
status_
bool
Allow callback (true) : Disallow callback (false)
Set the minimum deposit interval. Access controlled
Parameters
depositInterval_
uint48
Minimum deposit interval in seconds
Set the minimum market duration. Access controlled
Parameters
duration_
uint48
Minimum market duration in seconds
Parameters
id indexed
uint256
Market ID
Parameters
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
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).