Sequential Dutch Auctioneer (SDA)
The Base SDA contract 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.
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
.
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
formattedInitialPrice
uint256
Initial price of the market as a ratio of quote tokens per payout token, see note below on formatting
formattedMinimumPrice
uint256
Minimum price of the market as a ratio of quote tokens per payout token, see note below on formatting
debtBuffer
uint32
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
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
conclusion
uint48
Timestamp that the market will conclude on. Must be at least 1 day (86400 seconds) after creation
depositInterval
uint32
Target deposit interval for purchases (in seconds). Determines the maxPayout
of the market. Minimum is 1 hour (3600 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 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 is the price of the payout token and is the price of quote token in the common unit, it can expressed in base 10 (or scientific) notation as:
where:
is the coefficient of the payout token price and is the number of price decimals for the payout token (aka the significand of the price).
is the coefficient of the quote token price and 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 . Therefore and .
Now, using the price values and the configured number of decimals for each token, we can calculate the scale adjustment.
where:
is the configured payout token decimals (e.g. WETH has 18 configured decimals)
is the configured quote token decimals.
and are as defined above.
Example:
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 -> and the market price of OHM is $10 -> .
Then, the scale adjustment is
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).
Example: Continuing with the WETH and OHM example from above, we format the initial price as:
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: .
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.
owner
address
Market owner. Sends payout tokens, receives quote tokens (defaults to creator)
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
Address to call for any operations on bond purchase. Must inherit to IBondCallback
capacityInQuote
bool
Capacity limit is in payment token (true) or in payout (false, default)
capacity
uint256
Capacity remaining
totalDebt
uint256
Total payout token debt from market
minPrice
uint256
Minimum price (debt will stop decaying to maintain this)
maxPayout
uint256
Max payout tokens out in one order
sold
uint256
Payout tokens out
purchased
uint256
Quote tokens in
BondTerms
controlVariable
uint256
Scaling variable for price
maxDebt
uint256
Max payout token debt accrued
vesting
uint48
Length of time from deposit to expiry if fixed-term, vesting timestamp if fixed-expiry
conclusion
uint48
Timestamp when market no longer offered
BondMetadata
lastTune
uint48
Last timestamp when control variable was tuned
lastDecay
uint48
Last timestamp when market was created and debt was decayed
length
uint32
Time from creation to conclusion
depositInterval
uint32
Target frequency of deposits
tuneInterval
uint32
Frequency of tuning
tuneAdjustmentDelay
uint32
Time to implement downward tuning adjustments
debtDecayInterval
uint32
Interval over which debt should decay completely
tuneIntervalCapacity
uint256
Capacity expected to be used during a tuning interval
tuneBelowCapacity
uint256
Capacity that the next tuning will occur at
lastTuneDebt
uint256
Target debt calculated at last tuning
Methods
closeMarket
Disable existing bond marketMust be market owner
Parameters
id_
uint256
ID of market to close
createMarket
Creates a new bond market
See specific auctioneer implementations for details on encoding the parameters.
Parameters
params_
bytes
Configuration data needed for market creation, encoded in a bytes array
Returns
id
uint256
ID of new bond market
currentCapacity
Returns current capacity of a market
Parameters
id_
uint256
undefined
Returns
_0
uint256
undefined
currentControlVariable
Up to date control variable
Accounts for control variable adjustment
Parameters
id_
uint256
ID of market
Returns
_0
uint256
Control variable for market in payout token decimals
currentDebt
Calculate debt factoring in decay
Accounts for debt decay since last deposit
Parameters
id_
uint256
ID of market
Returns
_0
uint256
Current debt for market in payout token decimals
getAggregator
Returns the Aggregator that services the Auctioneer
Returns
_0
contract IBondAggregator
undefined
getMarketInfoForPurchase
Provides information for the Teller to execute purchases on a Market
Parameters
id_
uint256
Market ID
Returns
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
Returns the Teller that services the Auctioneer
Returns
teller
contract IBondTeller
Address of the Teller contract servicing the Auctioneer
isInstantSwap
Does market send payout immediately
Parameters
id_
uint256
Market ID to search for
Returns
_0
bool
undefined
isLive
Is a given market accepting deposits
Parameters
id_
uint256
ID of market
Returns
_0
bool
undefined
marketPrice
Calculate current market price of payout token in quote tokens
Accounts for debt and control variable decay since last deposit (vs _marketPrice())
Parameters
id_
uint256
ID of market
Returns
_0
uint256
Price for market in configured decimals (see MarketParams)
marketScale
Scale value to use when converting between quote token and payout token amounts with marketPrice()
Parameters
id_
uint256
ID of market
Returns
_0
uint256
Scaling factor for market in configured decimals
maxAmountAccepted
Returns maximum amount of quote token accepted by the market
Parameters
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
_0
uint256
undefined
ownerOf
Returns the address of the market owner
Parameters
id_
uint256
ID of market
Returns
_0
address
undefined
payoutFor
Payout due for amount of quote tokens
Accounts for debt and control variable decay so it is up to date
Parameters
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
_0
uint256
amount of payout tokens to be paid
pullOwnership
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
Exchange quote tokens for a bond in a specified marketMust be teller
Parameters
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
payout
uint256
Amount of payout token to be received from the bond
pushOwnership
Designate a new owner of a market. Must be existing market owner to call.
Doesn't change permissions until newOwner calls pullOwnership
Parameters
id_
uint256
Market ID
newOwner_
address
New address to give ownership to
setAllowNewMarkets
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)
setCallbackAuthStatus
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
creator_
address
Address of market creator
status_
bool
Allow callback (true) : Disallow callback (false)
setDefaults
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
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
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
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
Last updated