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
.
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 |
capacityInQuote | bool | Is Capacity in Quote Token? |
capacity | uint256 | Capacity (amount in quote token decimals or amount in payout token decimals). Set |
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 |
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.
Field | Type | Description |
---|---|---|
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 |
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 |
scale | uint256 | Scaling factor for the market (see MarketParams struct) |
BondTerms
Field | Type | Description |
---|---|---|
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
Field | Type | Description |
---|---|---|
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
Name | Type | Description |
---|---|---|
id_ | uint256 | ID of market to close |
createMarket
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
Returns current capacity of a market
Parameters
Name | Type | Description |
---|---|---|
id_ | uint256 | undefined |
Returns
Name | Type | Description |
---|---|---|
_0 | uint256 | undefined |
currentControlVariable
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
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
Returns the Aggregator that services the Auctioneer
Returns
Name | Type | Description |
---|---|---|
_0 | contract IBondAggregator | undefined |
getMarketInfoForPurchase
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
Returns the Teller that services the Auctioneer
Returns
Name | Type | Description |
---|---|---|
teller | contract IBondTeller | Address of the Teller contract servicing the Auctioneer |
isInstantSwap
Does market send payout immediately
Parameters
Name | Type | Description |
---|---|---|
id_ | uint256 | Market ID to search for |
Returns
Name | Type | Description |
---|---|---|
_0 | bool | undefined |
isLive
Is a given market accepting deposits
Parameters
Name | Type | Description |
---|---|---|
id_ | uint256 | ID of market |
Returns
Name | Type | Description |
---|---|---|
_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
Name | Type | Description |
---|---|---|
id_ | uint256 | ID of market |
Returns
Name | Type | Description |
---|---|---|
_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
Name | Type | Description |
---|---|---|
id_ | uint256 | ID of market |
Returns
Name | Type | Description |
---|---|---|
_0 | uint256 | Scaling factor for market in configured decimals |
maxAmountAccepted
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
Returns the address of the market owner
Parameters
Name | Type | Description |
---|---|---|
id_ | uint256 | ID of market |
Returns
Name | Type | Description |
---|---|---|
_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
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
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
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
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
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
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
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
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 |
Last updated