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.

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;
}

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.

where:

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

where:

Example:

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.

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.

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; 
}

BondTerms

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

BondMetadata

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

Methods

closeMarket

function closeMarket(uint256 id_) external nonpayable

Disable existing bond marketMust be market owner

Parameters

createMarket

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

Creates a new bond market

See specific auctioneer implementations for details on encoding the parameters.

Parameters

Returns

currentCapacity

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

Returns current capacity of a market

Parameters

Returns

currentControlVariable

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

Up to date control variable

Accounts for control variable adjustment

Parameters

Returns

currentDebt

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

Calculate debt factoring in decay

Accounts for debt decay since last deposit

Parameters

Returns

getAggregator

function getAggregator() external view returns (contract IBondAggregator)

Returns the Aggregator that services the Auctioneer

Returns

getMarketInfoForPurchase

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

Returns

getTeller

function getTeller() external view returns (contract IBondTeller)

Returns the Teller that services the Auctioneer

Returns

isInstantSwap

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

Does market send payout immediately

Parameters

Returns

isLive

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

Is a given market accepting deposits

Parameters

Returns

marketPrice

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

Returns

marketScale

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

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

Parameters

Returns

maxAmountAccepted

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

Returns maximum amount of quote token accepted by the market

Parameters

Returns

ownerOf

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

Returns the address of the market owner

Parameters

Returns

payoutFor

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

Returns

pullOwnership

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

purchaseBond

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

Returns

pushOwnership

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

setAllowNewMarkets

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

setCallbackAuthStatus

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

setDefaults

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

setIntervals

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

Last updated