Skip to content

Ordering of trades on Cauldron

Cauldron trades follow a directed acyclic graph (DAG) model, where every trade is directly linked to a previous transaction.

flowchart LR

    utxo2([
        UTXO:
        txid: ac..b2
        n: 0
        ])

    utxo3([
        UTXO:
        txid: 40..24
        n: 0
    ])

    utxob([
        UTXO:
        txid: 9f..32 n: 5
    ])

    trade2[
        Transaction A:
        1 token
        ↓
        99 sats
    ]

    trade3[
        Transaction B:
        199 sats
        ↓
        2 token
    ]

    unspent1([
        Unspent LP utxo
    ])

    unspent2([
        Unspent LP utxo
    ])



    utxo2 --> trade2 --> utxo3

    utxo3 --> trade3
    utxob --> trade3

    trade3 --> unspent1
    trade3 --> unspent2

Every liquidity pool has a local state that gets updated with every transaction that interracts with it.

Having trades ordered in a DAG with a local state has several benefits:

  • You know the exact price -- When performing the trade, you know the exact price you'll pay, including slippage. It is not effected by other interactions with a global state. There is no front-running.

  • You know the transaction will succeed or not happen at all -- If your transaction is accepted by a miner, your trade will happen. If it's not accepted, it is simply dropped and you don't pay a network fee.

  • No waiting on block confirmation -- You instantly know the result of a trade, and can continue to perform new actions based on the result. For example transfering them to a wallet. There is no waiting on a block confirmation.

A downside is that miners may choose to drop transactions, or select a conflicting transaction. In this case, also all transactions after a dropped transaction will also be dropped. See article about pending transactions.

Comparison to EVM

Contracts on EVM operate with a global state. The order the miners chooses to accept a transaction within a block matters.

Consider the following transaction order within Block A:


flowchart TB
    subgraph "Block A"
        trade1["TX A: Buy 10 token"]
        trade2["TX B: Sell 10 token"]
        trade3["TX C: Buy 1 token"]
    end

In this block, there is a 10 token buy before a sell. Miners could also choose to order the transactions like this:


flowchart TB
    subgraph "Block A (alternative)"
        trade2["TX B: Sell 10 token"]
        trade1["TX A: Buy 10 token"]
        trade3["TX C: Buy 1 token"]
    end

Because the transactions are not in a DAG, but operate on a global state, the sell order will not be as profitable for the seller if the miner chooses the second transaction order, than if first. This is because the buy order (TX A) now happens after the sell order (TX B).

The seller can mitigate this by setting a limitation on allowed slippage and cancel the sell. However, the transaction will still be accepted and mined and the seller will have to pay the network fee, regardless.