# Ticks, Ratios, and Prices

### Ticks

A tick on Mangrove represents a discrete point in the price space of a market. Rather than allowing continuous prices, Mangrove divides the space into fixed increments, each tick corresponds to a 0.01% (1 basis point) change in price.

This discrete representation allows for precise, gas-efficient price calculations and easy integration with on chain logic.

Formally:

$$
\text{ratio} = 1.0001^{\text{tick}}
$$

A higher tick value represents a higher price on the ask side and lower price on the bids side.

### Ratios

In Mangrove, every offer is defined not directly by a "price", but by a ratio. The relationship between the amount offered and the amount requested:

$$
\text{ratio} = \frac{\text{wants}}{\text{gives}}
$$

This ratio determines how much of a token is received for a given amount of another. It's the fundamental internal measure of price used throughout the protocol and codebase, ensuring consistency across all token pairs.

### The Relation Between Ticks and Ratios

Ticks and ratios are directly linked: each tick corresponds to one unique ratio, and each ratio can be expressed as a tick using a logarithmic function:

$$
\text{tick} = \log\_{1.0001}(\text{ratio})
$$

This relationship allows prices to be converted between human-readable form and the compact on-chain tick representation

The meaning of a ratio depends on whether the offer is on the asks or bids side of a market.&#x20;

* Asks side, selling the base token, receiving the quote tokens:

$$
\text{price} = \frac{\text{wants}}{\text{gives}} = \text{ratio} = 1.0001^{\text{tick}}
$$

* Bids side, buying the base token, giving the quote tokens:

$$
\text{price} = \frac{\text{gives}}{\text{wants}} = \frac{1}{\text{ratio}} = 1.0001^{\text{-tick}}
$$

This distinction ensures consistent logic across both side of the book, even though mathematical expressions are inverted.

**Example:**\
In a WETH/DAI market (prices expressed in DAI per WETH):

* On the **asks** side (selling WETH), price = wants/gives = 2,224 DAI/WETH.
* On the **bids** side (buying WETH), price = gives/wants = 0.0004496 WETH/DAI.

### Prices, Decimals, and Raw Values

All ERC-20 token amounts are stored on-chain as integers, often called **raw values**. Each token defines its own number of decimals, and Mangrove ignores these decimals internally for consistency.&#x20;

<table><thead><tr><th width="101.30859375">Token</th><th width="110.9609375">Decimals</th><th>Raw Amount</th><th>User Amount</th></tr></thead><tbody><tr><td>USDC</td><td>6</td><td><code>87654321</code></td><td>87.654321</td></tr><tr><td>DAI</td><td>18</td><td><code>876543210987654321</code></td><td>0.876543210987654321</td></tr><tr><td>WETH</td><td>18</td><td><code>109876543210987654321</code></td><td>109.876543210987654321</td></tr><tr><td>:::</td><td></td><td></td><td></td></tr></tbody></table>

To display human-readable prices, the SDK or UI must account for the difference in decimals between the base and quote tokens.

The conversions between raw ratios & prices and their user representations are:

$$
\def\arraystretch{1.5}
\begin{array}{rcl}
userRepresentation(raw\_ratio) & = & raw\_ratio \* 10^{(outbound\_decimals - inbound\_decimals)} \\
raw(user\_ratio) & = & user\_ratio / 10^{(outbound\_decimals - inbound\_decimals)} \\
userRepresentation(raw\_price) & = & raw\_price \* 10^{(base\_decimals - quote\_decimals)} \\
raw(user\_price) & = & user\_price / 10^{(base\_decimals - quote\_decimals)}
\end{array}
$$

This ensures correct display of "real-world" prices, even when token decimals differ.

**Example:**

| **Market**   | **Token Decimals**           | **Ask (quote/base)** | **Ask ratio (raw)**                                          | **Bid (base/quote)** | **Bid ratio (raw)**                                              |
| ------------ | ---------------------------- | -------------------- | ------------------------------------------------------------ | -------------------- | ---------------------------------------------------------------- |
| **DAI/USDC** | <p>DAI = 18<br>USDC = 6</p>  | $$1$$                | $$1 \times 10^{-12} \ = 10^{6}/10^{18}$$                     | $$1$$                | $$1 \times 10^{12} \ = 10^{18}/10^{6}$$                          |
| **WETH/DAI** | <p>WETH = 18<br>DAI = 18</p> | $$2{,}224$$          | $$2{,}224 \times 10^{0} \ = 2{,}224 \times 10^{18}/10^{18}$$ | $$0.0004410$$        | $$0.0004410 \times 10^{0} \ = 0.0004410 \times 10^{18}/10^{18}$$ |

> **Beware decimals!** As an important example of the implications, note that while the price space contains the *raw* price 1, it may not contain the user readable price 1. This is likely if base and quote have different numbers of decimals.

### Converting Prices and Ticks

Because the price space is discrete, not every price maps exactly to an integer tick. When converting a price to a tick:

$$
\text{tick} =\
\begin{cases}\
\log\_{1.0001}(\text{price}) & \text{for asks} \\\
-\log\_{1.0001}(\text{price}) & \text{for bids}\
\end{cases}
$$

The resulting tick is then rounded:

* Takers usually round down, ensuring they never pay more or receive less than expected.
* Makers usually round up, ensuring they never receive less or sell for too little.&#x20;

### Tick Spacing

Mangrove allows each market to define a `tickSpacing` parameter, controlling how dense the available price points are. Only ticks where:

$$
\text{tick} \bmod \text{tickSpacing} = 0
$$

are valid for offer in that market.

**Example:**

With `tickSpacing = 5` , valid ticks are `..., -15. -10, -5, 0, 5, 10, 15,...` The smallest price increment is then:

$$
1.0001^5 - 1= 0.0005001 (≈0.05%)
$$

### Ranges

Mangrove supports a wide range of ticks, allowing for extremely high or low prices:

| Value | Min                     | Max                   |
| ----- | ----------------------- | --------------------- |
| Tick  | -887,272                | 887,272               |
| Ratio | $$2.9\times10^{-39}$$   | $$3.4\times 10^{38}$$ |
| Price | $$2.9 \times 10^{-39}$$ | $$3.4\times 10^{38}$$ |

### The TickLib Library

Mangrove provides a Solidity library called  [`TickLib`](https://github.com/mangrovedao/mangrove-core/blob/2ae172805fd8b309c30b2dc877dba66245abbb3e/lib/core/TickLib.sol) which includes:

* Functions to convert between ticks, ratios, and prices.
* Utilities for rounding ticks appropriately for maker or taker use.
* Helpers for computing inbound/outbound volumes at specific tick levels.

### Comparison to Uniswap Ticks

Mangrove's ticks are inspired by Uniswap V3 ticks, but with the following notable differences:

* It operates directly on ratios (not √ratios), simplifying computation.
* Ratios are handled as floating-point numbers, improving precision.
