---
# System prepended metadata

title: Introduction

---

# Introduction

Flat curves have shown to perform very well for assets that are supposed to have a fixed target price, i.e. uusd vs kusd. Especially in growing ecosystems with little liquidity coming up with solutions to leverage the liquidity more effectively is key to success and speeds up said growth. The flat curves allow the liquidity to be concentrated at the target price, effectively enabling a larger volume compared to a naive constant product market maker.

This brainstorming aims at finding a way to use flat curves with target price set by an external observation (aka oracle). 

If we choose a naive approach and use all of the same formulas and logic from the flat curve, but adapt the target price at an interval we can achieve the effect we are looking for, but are introducing a couple of issues that need to be mitigated:

- Pool front-running: If we have an observation every i.e. 15 minutes short before the next observation an arbitrageur can swap at the "old" price from the pool knowing the new target allows them to make a profit.
- Stale price: The external observation can fail for many reasons (API down, bug in the oracle software, protocol updates, congestion on protocol level, etc...). What should be done if the set target on-chain deviates too much from the off-chain observation? 

# Solutions

## Swap pre-commit

We introduce to the flat curve additional state:

- `intent_counter` nat: an incremental counter that keeps track of the order of the intents
- `executed_intent_counter` nat: an incremental counter that keeps track of the order of the intents
- `intents` big-map: a big map storing intentions
- `epoch_counter` nat: an incremental counter that keeps track of the observation count.

We introduce a new entry point:

- `execute_intent(intent_id: nat)`

An "intent" can be the users' intent to:

- `add_liquidity`
- `remove_liquidity`
- `token_to_cash` 
- `cash_to_token`

The intents don't differ from the current implementations, only the flow is different. Instead of executing the intent immediately the intent is only stored and allowed to be executed iff:
- it is the next intent in line `executed_intent_counter+1 == intent_id`
- the new target of a future epoch is set

This two-stepped approach mitigates the risks above at the cost of a delay in the trade.

# Appendix

## Setting the target

Setting a target different than 1:1 on the flat curves requires only small adaptions of the current code:

```
let tokensBought (cashPool : nat) (cashMultiplier : nat) (tokenPool : nat) (tokenMultiplier : nat) (cashSold : nat) : nat =
    let x = cashPool * cashMultiplier in
    let y = tokenPool * tokenMultiplier in
    (* 4 round is enough for most cases and underestimates the true payoff, so the user
        can always break up a trade for better terms *)
    let u, _ = util x y in
    (newton {x = x; y = y ; dx = cashSold * cashMultiplier ; dy = 0n ; u = u ; n = 5}) / tokenMultiplier 

let cashBought (cashPool : nat) (cashMultiplier : nat) (tokenPool : nat) (tokenMultiplier : nat) (tokenSold : nat) : nat =
    let x = tokenPool * tokenMultiplier  in
    let y = cashPool * cashMultiplier in
    let u, _ = util x y in
    (newton {x = x; y = y ; dx = tokenSold * tokenMultiplier ; dy = 0n ; u = u ; n = 5}) / cashMultiplier
```
