# Takers

### Market Orders

A market order is the simplest way for a taker to buy or sell assets on Mangrove.  Each order is executed against a specific [offer list](https://docs.mangrove.exchange/dev/protocol/technical-references/the-order-book), which defines the outbound and inbound tokens of the trade.&#x20;

The takes specifies:

* how much the want to trade (either in terms of the token they want to receive or the one they are willing to spend), and
* the maximum price (or tick) they ware willing to accept.

This ensures that trades are execute only within a controller price range.&#x20;

### Market Orders in Mangrove vs. TradFi

In traditional finance, a market order executes immediately at the best available price. However, on-chain trading is exposed to MEV ([front-running](https://www.investopedia.com/terms/f/frontrunning.asp) and [sandwich attacks](https://coinmarketcap.com/alexandria/article/what-are-sandwich-attacks-in-defi-and-how-can-you-avoid-them)), making such unconstrained market orders unsafe.

For this reason, Mangrove's "market order" corresponds to a TradFi [**limit order**](https://www.investopedia.com/terms/l/limitorder.asp):

> It executes immediately, but only at prices equal to or better than the user's specified limit.

This "safe market order" model ensures that users never pay beyond their defined limit price.

### Execution Flow

When a market order is submitted, Mangrove's matching engine processes offers in sequence:

1. It scans offers from the best tick upward (asks) or lowest tick downward (bids).
2. Offers are consumed one by one, in FIFO order for the same tick.
3. Matching continues until:
   1. all offers within the taker's `maxTick` are processed,
   2. the offer list ends, or
   3. the taker's desired volume is fully filled.

For each matched offer:

1. Mangrove computes the trade amounts:

$$
inboundAmount = outboundAmount \times 1,0001^{tick}
$$

2. The inbound token is sent to the offer maker.
3. The offer logic (`makerExecute`) is called.
4. If successful, the outbound tokens are sent to the taker.
5. If the call fails, the trade is reverted and the taker receives a bounty for the gas spent.

### Function Overview <a href="#market-order-execution" id="market-order-execution"></a>

Mangrove provides two entry points for market orders:

```
function marketOrderByTick(
  OLKey memory olKey,
  Tick maxTick,
  uint fillVolume,
  bool fillWants,
) external returns (uint takerGot, uint takerGave, uint bounty, uint feePaid);

function marketOrderByVolume(
    OLKey memory olKey,
    uint takerWants,
    uint takerGives,
    bool fillWants
) external returns (uint takerGot, uint takerGave, uint bounty, uint feePaid);
```

Both return:

* `takerGot,` amount of `outbound_tkn` the taker received. Includes any partial fills and reflects fees already applied (if the offer list charges one).
* `takerGave,` amount of `inbound_tkn` the taker spent to execute the order.
* `bounty,` amount of native tokens (in wei) the taker earned as compensation for executing failing offers. Bounties are deducted from the failing maker’s provision.
* `feePaid,` amount of `outbound_tkn` transferred to Mangrove’s vault as payment for any configured offer list fee.

The `*ByVolume` variant is a wrapper around `*ByTick`, converting the volume ratio to the corresponding tick, rounding down to the nearest tick allowed on the offer list, such that the taker does not pay more than specified.

**Inputs**

`marketOrderByTick(olKey, maxTick, fillVolume, fillWants)`

**olKey**\
Identifies the offer list:

* `outbound_tkn` — token to buy (received by taker)
* `inbound_tkn` — token to pay (spent by taker)
* `tickSpacing` — allowed tick spacing

**maxTick**\
Maximum tick that can be matched with this order.

**fillVolume & fillWants**\
Specify how much the taker wants to trade and when the order stops:

* If `fillWants = true` → `fillVolume` is in `outbound_tkn` (the taker specifies how much they want to receive).
* If `fillWants = false` → `fillVolume` is in `inbound_tkn` (the taker specifies how much they want to spend).\
  The order ends when the specified volume is reached or no more eligible offers remain.

***

**`marketOrderByVolume(olKey, takerWants, takerGives, fillWants)`**

**olKey**\
Identifies the offer list (same structure as above).

**takerWants & takerGives**\
Define the desired trade amounts:

* `takerWants` — amount of `outbound_tkn` the taker wants to receive.
* `takerGives` — amount of `inbound_tkn` the taker is willing to spend.

$$
\text{max ratio} = \frac{\text{takerGives}}{\text{takerWants}}
$$

This ratio is converted into a corresponding `maxTick` (rounded down).

**fillWants**\
Controls when the order stops:

* If `true`, the order ends when the taker has received `takerWants`.
* If `false`, the order ends when the taker has spent `takerGives`.

#### Example: DAI/WETH Market[​](https://old.docs.mangrove.exchange/developers/protocol/technical-references/market-order/#example) <a href="#example" id="example"></a>

| Tick   | Ratio (WETH/DAI) | Offer ID | Gives (DAI) |
| ------ | ---------------- | -------- | ----------- |
| -75103 | 0.0005476        | 77       | 925.26      |
| -75103 | 0.0005476        | 177      | 916.47      |
| -75041 | 0.0005510        | 42       | 871.76      |

**Buying DAI**

A taker calls `marketOrderByTick` on the DAI/WETH offer list with:

* `maxTick` = -75000 -> corresponds to a max ratio of 0.0005539
* `fillVolume` = $$2,500 \times 10^{18}$$
* `fillWants` = `true`

Since `fillWants = true`, we have:

* `fillVolume` is in `olKey.outbound_tkn` and corresponds to 2,500 DAI
* the market order will be considered filled once 2,500 DAI has been received.

In other words, this is a buy order for 2,500 DAI, where the taker is willing to pay up to\
$$2,500 × 0.0005539 = 1.3832$$ WETH.

The market order will execute as follows:

1. Get 925.26 DAI for `925.26 * 0.0005476 = 0.5067` WETH from offer #77
2. Get 916.47 DAI for `916.47 * 0.0005476 = 0.5019` WETH from offer #177
3. Get the remaining `2500 - 925.26 - 916.47 = 658.27` DAI for `658.27 * 0.0005510 = 0.3627` WETH from offer #42.

In total, the taker gets 2,500 DAI and sends `0.5067 + 0.5019 + 0.3627 = 1.3713` WETH.

**Selling WETH**

A taker calls `marketOrderByTick` on the offer list with:

* `maxTick` = -75000 -> corresponds to a max ratio of 0.0005539
* `fillVolume` = $$1.2 \times 10^{18}$$
* `fillWants` = `false`

Because `fillWants = false`, the taker specifies how much they want to spend:

* `fillVolume` refers to 1.2 WETH (the `inbound_tkn`).
* The market order will end once 1.2 WETH has been sent.

This corresponds to a **sell order** of 1.2 WETH. At the maximum allowed ratio, the taker expects to receive at least:\
$$1.2 ÷ 0.0005539 = 2,168.84$$ DAI.

Execution proceeds as follows:

1. Sell `925.26 * 0.0005476 = 0.5067` WETH for 925.26 DAI to offer #77
2. Sell `916.47 * 0.0005476 = 0.5019` WETH for 916.47 DAI to offer #177
3. Sell the remaining `1.2 - 0.5067 - 0.5019 = 0.1914` WETH for `0.1914 / 0.0005510 = 347.37` DAI to offer #42.

In total, the taker gets `925.26 + 916.47 + 347.37 = 2,189.10` DAI and sends 1.2 WETH.

#### Market Order Behavior[​](https://old.docs.mangrove.exchange/developers/protocol/technical-references/market-order/#more-on-market-order-behaviour) <a href="#more-on-market-order-behaviour" id="more-on-market-order-behaviour"></a>

Suppose you want to trade a **base token (B)** against a **quote token (Q)**, on a market with tick spacing **T**.

* **Market buy:**

  Buy `x` units of `B` using `Q`.\
  → Call `marketOrderByTick` on `(B, Q, T)` with:\
  `fillWants = true`, `fillVolume = x`, and

  `maxTick = log₁.₀₀₀₁(priceLimit)`.
* **Market sell:**&#x20;

  Sell `x` units of `B` for `Q`.\
  → Call `marketOrderByTick` on `(Q, B, T)` with:\
  `fillWants = false`, `fillVolume = x`, and\
  `maxTick = −log₁.₀₀₀₁(priceLimit)`.

#### Order Residuals

Unlike traditional exchanges, any unfilled portion of a market order (the *residual*) is **not posted** to the order book.\
The order simply ends **partially filled** once the price limit is reached.

If you want [GTC](https://www.investopedia.com/terms/g/gtc.asp)-style (“Good Till Cancelled”) behavior, this can be implemented using a **maker contract**.\
The `MangroveOrder` contract in the Strat Library provides GTC and other advanced order types.

#### Bounties for Failing Offers

If an offer fails to deliver the promised liquidity, the taker receives a [bounty](https://docs.mangrove.exchange/dev/quick-links/glossary#bounty) in native tokens to compensate for gas costs. This bounty is deducted from the maker’s [provision](https://docs.mangrove.exchange/dev/quick-links/glossary#provision), the deposit they supplied when posting the offer.\
See [Offer provisions](https://docs.mangrove.exchange/dev/protocol/technical-references/makers/offer-provisions) for details.

#### Token Allowances <a href="#bounties-for-taking-failing-offers" id="bounties-for-taking-failing-offers"></a>

Mangrove transfers tokens using `transferFrom`. If the taker’s allowance for Mangrove (on the inbound token) is too low, the transaction will revert.

#### Active Offer Lists

Each [offer list](https://docs.mangrove.exchange/dev/protocol/technical-references/the-order-book) in Mangrove can be [active or inactive](https://docs.mangrove.exchange/dev/protocol/governance-parameters/local-variables#de-activating-an-offer-list), and the Mangrove contract itself can be [alive or dead](https://docs.mangrove.exchange/dev/protocol/governance-parameters/global-variables#other-governance-controlled-setters). Orders can only be executed when both Mangrove and the selected offer list are **active**.
