# Market administration

Everything on this page is called by a **market owner** (or someone stepping into the role). A market is created by `createMarket` — whoever calls it becomes the owner of the resulting pair and can later transfer that role, update the LP whitelist, or permanently stop new swaps.

Source: `SwapCore.sol`

## Market lifecycle

```
createMarket ──► (market is live) ──► transferMarketOwnership ──► acceptMarketOwnership
                       │                                               │
                       │                                               ▼
                       │                                       (new owner active)
                       │
                       └──► setMarketLpWhitelist (if lpWhitelistEnabled)
                       │
                       └──► terminateMarket ──► (no new swaps; existing swaps still settle)
```

Note that **every call to `createMarket` produces two market IDs** — one BUY\_FIXED and one BUY\_FLOATING — that share the same oracles, collateral token, term, and config. The two sides are independent markets from an ownership and accounting standpoint, but `transferMarketOwnership` / `terminateMarket` / `setMarketLpWhitelist` each operate on a single `marketId`, so if you want to change both sides you call each function twice.

***

## createMarket

```solidity
function createMarket(
    address referenceRateOracle,
    address baseSwapRateOracle,
    address swapToken,
    uint64  leverageMultiplier,
    uint32  swapTerm,
    uint256 utilFeeSlopeWad,
    uint256 kinkUtilization,
    uint256 maxKinkFeeWad,
    bool    earlyExitAllowed,
    uint256 earlyExitFee,
    uint256 liquidationIncentive,
    uint32  numBuckets,
    uint32  bucketInterval,
    address fixedRiskPremiumOracle,
    address floatingRiskPremiumOracle,
    bool    lpWhitelistEnabled,
    uint88  minCollateral,
    Types.RateConvention rateConvention
) external payable nonReentrant returns (bytes32 fixedMarketId, bytes32 floatingMarketId);
```

**Who calls:** anyone. No prior permission required — but if the protocol has a market creation fee configured in `Admin`, `msg.sender` has to pay it (ETH or ERC20, depending on `CREATE_MARKET_FEE_TOKEN`).

**What it does:** atomically creates a BUY\_FIXED / BUY\_FLOATING market pair. For each side, it validates oracles, checks parameter bounds, generates a unique market ID (hashing the params with `creator`, `timestamp`, and a nonce), initializes the pool and rate index, and emits `MarketCreated` + `MarketConfigured`. The caller is recorded as `marketOwner` on both sides.

**Parameters:**

| Parameter                   | Meaning                                                                                                                    |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `referenceRateOracle`       | Oracle that provides the floating rate used by the swap's floating leg. Shared between the two sides of the pair.          |
| `baseSwapRateOracle`        | Oracle that provides the tenor-dependent base rate used in swap pricing and collateral sizing. Shared between sides.       |
| `swapToken`                 | ERC20 used for collateral and settlement. Must be a standard ERC20 (no rebasing, no fee-on-transfer).                      |
| `leverageMultiplier`        | WAD-scaled leverage multiplier. `1e18` = 1x, `2e18` = 2x. Capped at `18e18`.                                               |
| `swapTerm`                  | Duration of each swap in seconds. Must be `> 0`.                                                                           |
| `utilFeeSlopeWad`           | Slope (WAD) of the linear region of the utilization fee curve. Capped at `10e18`.                                          |
| `kinkUtilization`           | Utilization at which the quadratic region kicks in (WAD, must be `< 1e18`).                                                |
| `maxKinkFeeWad`             | Maximum additional fee from the quadratic region (WAD, capped at `10e18`).                                                 |
| `earlyExitAllowed`          | Whether buyers can close a swap before expiry via `exitSwapEarly`.                                                         |
| `earlyExitFee`              | WAD early-exit fee. Capped at `1e18` (100%).                                                                               |
| `liquidationIncentive`      | WAD fraction paid to a liquidator from the liquidated party's collateral. Must be `< 1e18`.                                |
| `numBuckets`                | Number of time buckets. Must be in `[1, 365]`.                                                                             |
| `bucketInterval`            | Seconds per bucket. Must be `≥ 3600` and `≤ swapTerm`. `numBuckets × bucketInterval` must `≥ swapTerm`.                    |
| `fixedRiskPremiumOracle`    | Optional risk premium oracle for the BUY\_FIXED side. Pass `address(0)` to disable.                                        |
| `floatingRiskPremiumOracle` | Optional risk premium oracle for the BUY\_FLOATING side.                                                                   |
| `lpWhitelistEnabled`        | If true, only addresses on `marketLpWhitelist[marketId]` can `supplyCollateral`. The caller is auto-whitelisted.           |
| `minCollateral`             | Minimum per-swap collateral (both buyer and LP). Denominated in `swapToken` decimals. Must be `> 0`.                       |
| `rateConvention`            | How the reference rate oracle provides data. See `Types.RateConvention` (`Cumulative`, `SpotRate`, or `SpotCompoundRate`). |

**Returns:** `(fixedMarketId, floatingMarketId)`. These are also published in `MarketCreated` events.

**Payable:** if `Admin.CREATE_MARKET_FEE_AMOUNT() > 0` and `CREATE_MARKET_FEE_TOKEN() == address(0)`, send the fee as `msg.value`. Excess ETH is refunded to `msg.sender` at the end of the call. If the fee token is an ERC20, approve `SwapCore` for the fee amount before calling — no `msg.value` is required.

**State changes / events:**

* `markets[fixedMarketId]` and `markets[floatingMarketId]` populated, both marked `exists = true`, `marketOwner = msg.sender`.
* Both IDs appended to `allMarketIds`.
* Global `rateIndex` initialized for the reference rate oracle if it wasn't already.
* If `lpWhitelistEnabled`, `marketLpWhitelist[<each>][msg.sender] = true` (creator is auto-whitelisted so they can seed liquidity).
* Emits `MarketCreated` (×2) and `MarketConfigured` (×2), plus `MarketCreationFeeCollected` if a fee was charged.

**Reverts:**

| Code            | Reason                                                                    |
| --------------- | ------------------------------------------------------------------------- |
| `E150`          | ETH fee required but `msg.value < feeAmount`.                             |
| `E151`          | ETH send to multisig or refund to caller failed.                          |
| `E301`          | Market ID collision (should not happen in practice — nonces are unique).  |
| `E600` / `E603` | Base rate oracle call reverted or returned `isValid = false`.             |
| `E602` / `E605` | Risk premium oracle (if set) call reverted or returned `isValid = false`. |
| `E606`          | Reference rate oracle is unhealthy during `rateIndex.initialize`.         |
| `E710`          | `referenceRateOracle == address(0)`.                                      |
| `E711`          | `baseSwapRateOracle == address(0)`.                                       |
| `E712`          | `swapToken == address(0)`.                                                |
| `E713`          | `leverageMultiplier == 0` or `> 18e18`.                                   |
| `E714`          | `liquidationIncentive >= 1e18`.                                           |
| `E715`          | `swapTerm == 0`.                                                          |
| `E716`          | `kinkUtilization >= 1e18`.                                                |
| `E717`          | `earlyExitFee > 1e18`.                                                    |
| `E718`          | `utilFeeSlopeWad > 10e18`.                                                |
| `E719`          | `maxKinkFeeWad > 10e18`.                                                  |
| `E703`          | `numBuckets == 0` or `> 365`.                                             |
| `E704`          | `bucketInterval < 3600` or `> swapTerm`.                                  |
| `E705`          | `numBuckets × bucketInterval < swapTerm`.                                 |
| `E720`          | Invalid `rateType` (unreachable from the enum but guarded).               |
| `E721`          | `minCollateral == 0`.                                                     |

**See also:** [`getAllMarketIds`](#getallmarketids), [`transferMarketOwnership`](#transfermarketownership), [`terminateMarket`](#terminatemarket).

***

## transferMarketOwnership

```solidity
function transferMarketOwnership(bytes32 marketId, address newOwner) external;
```

**Who calls:** the current `marketOwner` of `marketId`.

**What it does:** step one of a two-step ownership handoff. Sets `pendingMarketOwner[marketId] = newOwner`. No state on the market itself changes yet — the actual owner only flips when `newOwner` accepts.

Pass `newOwner = address(0)` to cancel an in-flight transfer. There is no `renounceOwnership` — a market always has an owner once created.

**Modifiers:** `marketOwner(marketId)` (reverts with `E202` if not the current owner, `E300` if the market does not exist).

**State changes / events:**

* `pendingMarketOwner[marketId] = newOwner`.
* Emits `MarketOwnershipTransferStarted(marketId, currentOwner, newOwner)`.

**Reverts:**

* `E300` — market doesn't exist.
* `E202` — caller is not the current market owner.

**See also:** [`acceptMarketOwnership`](#acceptmarketownership).

***

## acceptMarketOwnership

```solidity
function acceptMarketOwnership(bytes32 marketId) external;
```

**Who calls:** the address previously set as `pendingMarketOwner[marketId]`.

**What it does:** step two of the handoff. Flips `markets[marketId].marketOwner` to `msg.sender` and clears the pending slot. After this call, the new owner has full control over `terminateMarket` and `setMarketLpWhitelist`, and will receive the creator fee split on new swaps (if configured in `Admin`).

**State changes / events:**

* `markets[marketId].marketOwner = msg.sender`.
* `pendingMarketOwner[marketId] = address(0)`.
* Emits `MarketOwnerChanged(marketId, msg.sender)`.

**Reverts:**

* `E300` — market doesn't exist.
* `E202` — caller is not the pending owner.

***

## terminateMarket

```solidity
function terminateMarket(bytes32 marketId) external;
```

**Who calls:** the `marketOwner` of `marketId`.

**What it does:** permanently flips `markets[marketId].terminated = true`. From that block forward, `buySwap` reverts on this market (see `E304`). **Existing swaps are unaffected** — LPs can still withdraw, keepers can still `makePayment`, liquidators can still `liquidateSwap`, and buyers can still `exitSwapEarly` if it was enabled at market creation. This is a one-way switch; there is no `unterminate`.

Terminate when you want to wind a market down cleanly — new positions can't be opened, but open ones still settle.

**Modifiers:** `marketOwner(marketId)`.

**State changes / events:**

* `markets[marketId].terminated = true`.
* Emits `MarketAdminChange(marketId, "terminateMarket", true)`.

**Reverts:**

* `E300` — market doesn't exist.
* `E202` — not market owner.
* `E304` — market is already terminated.

***

## setMarketLpWhitelist

```solidity
function setMarketLpWhitelist(bytes32 marketId, address lp, bool status) external;
```

**Who calls:** the `marketOwner` of `marketId`.

**What it does:** toggles an address's presence in `marketLpWhitelist[marketId]`. Only meaningful if the market was created with `lpWhitelistEnabled = true` — otherwise the call reverts. `supplyCollateral` checks this mapping inline and reverts with `E201` if the target LP isn't listed. `withdrawCollateral` is **not** gated on the whitelist — an LP who is removed can still withdraw their existing shares.

The market creator is auto-whitelisted at `createMarket` time, so there's always at least one LP who can seed the pool.

**Modifiers:** `marketOwner(marketId)`.

**State changes / events:**

* `marketLpWhitelist[marketId][lp] = status`.
* Emits `MarketLpWhitelistUpdated(marketId, lp, status)`.

**Reverts:**

* `E300` — market doesn't exist.
* `E202` — not market owner.
* `E205` — `lpWhitelistEnabled == false` on this market (you can't toggle entries on a market that doesn't use a whitelist).

**See also:** [`supplyCollateral`](/protocol/liquidity.md#supplycollateral).

***

## getAllMarketIds

```solidity
function getAllMarketIds() external view returns (bytes32[] memory);
```

**Who calls:** anyone — frontends, indexers, scripts.

**What it does:** returns every market ID that has ever been created, in creation order. BUY\_FIXED and BUY\_FLOATING sides appear consecutively for each `createMarket` call. Use the returned IDs as keys into the public `markets(bytes32)` getter to read full configs.

There is no pagination — if you expect thousands of markets, read this via `staticCall` off-chain rather than from on-chain code that would run out of gas.

**See also:** [`markets` mapping getter](/protocol/views.md#markets).


---

# 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://docs.kairosswap.com/protocol/market-admin.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.
