# Sequential Dutch Auctioneer (SDA)

The [Base SDA contract](https://github.com/Bond-Protocol/bond-contracts/blob/master/src/bases/BondBaseSDA.sol) 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.&#x20;

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`.

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

<table><thead><tr><th>Field</th><th width="165">Type</th><th>Description</th></tr></thead><tbody><tr><td>payoutToken</td><td>ERC20 (address)</td><td>Payout Token (token paid out by market and provided by creator)</td></tr><tr><td>quoteToken</td><td>ERC20 (address)</td><td>Quote Token (token to be received by the market and provided by purchaser)</td></tr><tr><td>callbackAddr</td><td>address</td><td>Callback contract address, should conform to <code>IBondCallback</code>. If 0x00, tokens will be transferred from market owner. Using a callback requires whitelisting by the protocol</td></tr><tr><td>capacityInQuote</td><td>bool</td><td>Is Capacity in Quote Token?</td></tr><tr><td>capacity</td><td>uint256</td><td>Capacity (amount in quote token decimals or amount in payout token decimals). Set <code>capacityInQuote</code> flag appropriately</td></tr><tr><td>formattedInitialPrice</td><td>uint256</td><td>Initial price of the market as a ratio of quote tokens per payout token, see note below on formatting</td></tr><tr><td>formattedMinimumPrice</td><td>uint256</td><td>Minimum price of the market as a ratio of quote tokens per payout token, see note below on formatting</td></tr><tr><td>debtBuffer</td><td>uint32</td><td>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</td></tr><tr><td>vesting</td><td>uint48</td><td>Is fixed term ? Vesting length (seconds) : Vesting expiry (timestamp). A 'vesting' param longer than 50 years is considered a timestamp for fixed expiry</td></tr><tr><td>conclusion</td><td>uint48</td><td>Timestamp that the market will conclude on. Must be at least 1 day (86400 seconds) after creation</td></tr><tr><td>depositInterval</td><td>uint32</td><td>Target deposit interval for purchases (in seconds). Determines the <code>maxPayout</code> of the market. Minimum is 1 hour (3600 seconds)</td></tr><tr><td>scaleAdjustment</td><td>int8</td><td>Market scaling adjustment factor, ranges from -24 to +24. See note below on how to calculate</td></tr></tbody></table>

#### 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 $$\Phi\_p$$ is the price of the payout token and $$\Phi\_q$$  is the price of quote token in the common unit, it can expressed in base 10 (or scientific) notation as:

$$
\Phi\_p = \phi\_p \times 10^{d\_{\phi p}}
$$

$$
\Phi\_q = \phi\_q \times 10^{d\_{\phi q}}
$$

where:

* $$\phi\_p$$ is the coefficient of the payout token price and ​$$d\_{\phi p}$$​ is the number of price decimals for the payout token (aka the significand of the price).
* $$\phi\_q$$​ is the coefficient of the quote token price and $$d\_{\phi q}$$​ 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 $$1.5 \times 10^3$$​. Therefore $$\phi = 1.5$$ and $$d\_{\phi} = 3$$.

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

$$
s = d\_p - d\_q - \left\lfloor\frac{d\_{\phi p} - d\_{\phi q}}{2}\right\rfloor
$$

where:

* $$d\_p$$ is the configured payout token decimals (e.g. WETH has 18 configured decimals)
* $$d\_q$$ is the configured quote token decimals.
* $$d\_{\phi p}$$ and $$d\_{\phi q}$$ are as defined above.

Example:&#x20;

* 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 -> $$1.5 \times 10^3$$and the market price of OHM is $10 -> $$1 \times 10^1$$.​
* Then, the scale adjustment is $$s = 9 - 18 - \left\lfloor\frac{1-3}{2}\right\rfloor = -9 + 1 = -8$$​

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).

$$
\Phi\_0 = \frac{\phi\_p}{\phi\_q} \times 10^{36 + s + d\_q - d\_p +d\_{\phi p} - d\_{\phi q}}
$$

Example: Continuing with the WETH and OHM example from above, we format the initial price as:

$$
\Phi\_0 = \frac{1}{1.5} \times 10^{36+(-8)+18-9+1-3} = 0.666.. \times 10^{35} = 0.00666.. \times 10^{37}
$$

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: $$\Phi\_{min} = 0.005 \times 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.

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

<table><thead><tr><th width="200">Field</th><th width="185">Type</th><th width="364">Description</th></tr></thead><tbody><tr><td>owner</td><td>address </td><td>Market owner. Sends payout tokens, receives quote tokens (defaults to creator)</td></tr><tr><td>payoutToken</td><td>ERC20 (address)</td><td>Payout Token (token paid out by market and provided by creator)</td></tr><tr><td>quoteToken</td><td>ERC20 (address)</td><td>Quote Token (token to be received by the market and provided by purchaser)</td></tr><tr><td>callbackAddr</td><td>address</td><td>Address to call for any operations on bond purchase. Must inherit to <code>IBondCallback</code></td></tr><tr><td>capacityInQuote</td><td>bool</td><td>Capacity limit is in payment token (true) or in payout (false, default)</td></tr><tr><td>capacity</td><td>uint256</td><td>Capacity remaining</td></tr><tr><td>totalDebt</td><td>uint256</td><td>Total payout token debt from market</td></tr><tr><td>minPrice</td><td>uint256</td><td>Minimum price (debt will stop decaying to maintain this)</td></tr><tr><td>maxPayout</td><td>uint256</td><td>Max payout tokens out in one order</td></tr><tr><td>sold</td><td>uint256</td><td>Payout tokens out</td></tr><tr><td>purchased</td><td>uint256</td><td>Quote tokens in</td></tr><tr><td>scale</td><td>uint256</td><td>Scaling factor for the market (see <a href="#marketparams">MarketParams</a> struct)</td></tr></tbody></table>

### BondTerms

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

<table><thead><tr><th width="198">Field</th><th width="132">Type</th><th>Description</th></tr></thead><tbody><tr><td>controlVariable</td><td>uint256</td><td>Scaling variable for price</td></tr><tr><td>maxDebt</td><td>uint256</td><td>Max payout token debt accrued</td></tr><tr><td>vesting</td><td>uint48</td><td>Length of time from deposit to expiry if fixed-term, vesting timestamp if fixed-expiry</td></tr><tr><td>conclusion</td><td>uint48</td><td>Timestamp when market no longer offered</td></tr></tbody></table>

### BondMetadata

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

<table><thead><tr><th width="239">Field</th><th width="123">Type</th><th>Description</th></tr></thead><tbody><tr><td>lastTune</td><td>uint48</td><td>Last timestamp when control variable was tuned</td></tr><tr><td>lastDecay</td><td>uint48</td><td>Last timestamp when market was created and debt was decayed</td></tr><tr><td>length</td><td>uint32</td><td>Time from creation to conclusion</td></tr><tr><td>depositInterval</td><td>uint32</td><td>Target frequency of deposits</td></tr><tr><td>tuneInterval</td><td>uint32</td><td>Frequency of tuning</td></tr><tr><td>tuneAdjustmentDelay</td><td>uint32</td><td>Time to implement downward tuning adjustments</td></tr><tr><td>debtDecayInterval</td><td>uint32</td><td>Interval over which debt should decay completely</td></tr><tr><td>tuneIntervalCapacity</td><td>uint256</td><td>Capacity expected to be used during a tuning interval</td></tr><tr><td>tuneBelowCapacity</td><td>uint256</td><td>Capacity that the next tuning will occur at</td></tr><tr><td>lastTuneDebt</td><td>uint256</td><td>Target debt calculated at last tuning</td></tr></tbody></table>

## Methods

### closeMarket

```solidity
function closeMarket(uint256 id_) external nonpayable
```

Disable existing bond marketMust be market owner

#### Parameters

| Name | Type    | Description           |
| ---- | ------- | --------------------- |
| id\_ | uint256 | ID of market to close |

### createMarket

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

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

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

Returns current capacity of a market

#### Parameters

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | undefined   |

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | uint256 | undefined   |

### currentControlVariable

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

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

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

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

```solidity
function getAggregator() external view returns (contract IBondAggregator)
```

Returns the Aggregator that services the Auctioneer

#### Returns

| Name | Type                     | Description |
| ---- | ------------------------ | ----------- |
| \_0  | contract IBondAggregator | undefined   |

### getMarketInfoForPurchase

```solidity
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

| 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

```solidity
function getTeller() external view returns (contract IBondTeller)
```

Returns the Teller that services the Auctioneer

#### Returns

| Name   | Type                 | Description                                             |
| ------ | -------------------- | ------------------------------------------------------- |
| teller | contract IBondTeller | Address of the Teller contract servicing the Auctioneer |

### isInstantSwap

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

Does market send payout immediately

#### Parameters

| Name | Type    | Description             |
| ---- | ------- | ----------------------- |
| id\_ | uint256 | Market ID to search for |

#### Returns

| Name | Type | Description |
| ---- | ---- | ----------- |
| \_0  | bool | undefined   |

### isLive

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

Is a given market accepting deposits

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type | Description |
| ---- | ---- | ----------- |
| \_0  | bool | undefined   |

### marketPrice

```solidity
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

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type    | Description                                                |
| ---- | ------- | ---------------------------------------------------------- |
| \_0  | uint256 | Price for market in configured decimals (see MarketParams) |

### marketScale

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

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

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

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

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

Returns the address of the market owner

#### Parameters

| Name | Type    | Description  |
| ---- | ------- | ------------ |
| id\_ | uint256 | ID of market |

#### Returns

| Name | Type    | Description |
| ---- | ------- | ----------- |
| \_0  | address | undefined   |

### payoutFor

```solidity
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

| 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

```solidity
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

| Name | Type    | Description |
| ---- | ------- | ----------- |
| id\_ | uint256 | Market ID   |

### purchaseBond

```solidity
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

| 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

```solidity
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

| Name       | Type    | Description                      |
| ---------- | ------- | -------------------------------- |
| id\_       | uint256 | Market ID                        |
| newOwner\_ | address | New address to give ownership to |

### setAllowNewMarkets

```solidity
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

| Name     | Type | Description                                                     |
| -------- | ---- | --------------------------------------------------------------- |
| status\_ | bool | Allow market creation (true) : Disallow market creation (false) |

### setCallbackAuthStatus

```solidity
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

| Name      | Type    | Description                                       |
| --------- | ------- | ------------------------------------------------- |
| creator\_ | address | Address of market creator                         |
| status\_  | bool    | Allow callback (true) : Disallow callback (false) |

### setDefaults

```solidity
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

| 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

```solidity
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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.bondprotocol.finance/smart-contracts/bond-system/auctioneer/sequential-dutch-auctioneer-sda.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
