Skip to content

Instantly share code, notes, and snippets.

@richardkiss
Last active November 5, 2023 09:40
Show Gist options
  • Save richardkiss/0e165ce111ee50e66eb27d2f45f3cc5e to your computer and use it in GitHub Desktop.
Save richardkiss/0e165ce111ee50e66eb27d2f45f3cc5e to your computer and use it in GitHub Desktop.
Ideas about Offers on Chia

We introduce a new puzzle, "settlement_payments", which pays out coins and make an announcement for each new coin created.

settlement_payments.cl:

(mod (coins_paid)
  ;; `coins_paid` is a list of notarized coin payments
  ;; a notarized coin payment is `(nonce puzzle_hash amount ...)`
  ;; Each notarized coin payment creates a `(CREATE_COIN puzzle_hash amount)` payment
  ;; and a `(CREATE_PUZZLE_ANNOUNCEMENT (sha256tree notarized_coin_payment))` announcement
  ;; The idea is the other side of this trade requires observing the announcement from a
  ;; `settlement_payments` puzzle hash as a condition of one or more coin spends.

  (include condition_codes.clvm)

  (defun sha256tree (TREE)
     (if (l TREE)
         (sha256 2 (sha256tree (f TREE)) (sha256tree (r TREE)))
         (sha256 1 TREE)
     )
  )

  (defun-inline create_coin_for_payment (notarized_coin_payment)
    (c CREATE_COIN (r notarized_coin_payment))
  )

  (defun-inline create_announcement_for_payment (notarized_coin_payment)
      (list CREATE_PUZZLE_ANNOUNCEMENT
            (sha256tree notarized_coin_payment))
  )

  (defun-inline augment_condition_list (notarized_coin_payment so_far)
      (c (create_coin_for_payment notarized_coin_payment)
         (c (create_announcement_for_payment notarized_coin_payment) so_far))
  )

  (defun construct_create_coin_list (coins_paid)
    (if coins_paid
        (augment_condition_list (f coins_paid) (construct_create_coin_list (r coins_paid)))
        0
    )
  )

  (construct_create_coin_list coins_paid)
)

This puzzle can be an inner puzzle inside a CAT (and many other condition-mutating type of puzzles).

The idea is that an offer maker can create a CoinSpend that requires an announcement from a settlement_payments puzzle hash of a given form. That announcement guarantees that the corresponding payment has also been made. So the offer maker can simply supply excess mojos of a specific type (XCH or CAT) knowing that the announcement ensures the corresponding counter-payment has been made (without even concerning itself as to the source of the funds).

Offer Files

Suppose a user who has asset type T0 value V0 and wants asset type T1 value V1 to destination puzzle hash D1 wants to create an offer. We give an example to show that an offer file can be serialized as a SpendBundle.

The user can encapsulate it in a SpendBundle by creating one (or more) real CoinSpend spending the coin (or coins) that they are selling, and one template CoinSpend that shows how the create the announcement they require by spending through a settlement payment.

The user chooses an arbitrary nonce N1 (a coin id that is being spent is recommended as this nonce). The notarized coin payment for the settlement payment is (N1 D1 V1). The settlement payment puzzle is wrapped in the appropriate outer puzzle for the asset T1 (for example, the CAT for T1, or no wrapper for XCH), yielding puzzle hash P0 with puzzle hash PH0.

The user creates a coin spend CS0 with placeholder coin (Z PH0 V1) where Z=000...00 (a placeholder parent coin) and PH0 and V1 are as above. The solution is the list with a single notarized payment ((N1 P1 V1)). This generates a puzzle announcement. Seeing this announcement is a guarantee that the user has been paid.

The user creates a coin spend CS1 (and possibly CS2, CS3, etc. if more coins are needed) that freely releases asset T0 with value V0, not assigning this value anywhere specific. The spends also must do (ASSERT_PUZZLE_ANNOUNCEMENT PHA0) where PHA0 is the one announced by the settlement payment in CS0.

Aggregation

A farmer or a mempool observer can look at a list of offers, and aggregate overlapping ones. This operation is known as a "market maker". A market maker can create a single settlement puzzle for each type of asset, and put aggregate all the notarized coin payments of that type in that puzzle.

A "taker" can be considered a combination offer creator and market maker. A taker finds an offer of interest, and constructs the other side of that offer, resolving the cross-asset payments through the settlement payment puzzle on each side.

So a maker might create coin spend CS0 and CS1 above. The taker creates a coin spend that looks just like CS0, and creates a coin spend to pay itself through a settlement payment. This means a minimum of four coin spends are required to complete the offer (including two ephemeral settlement payment coins, one for each asset type).

An independent and sophisticated market maker might aggregate multiple settlement payments into a single spend, which means it could join an arbitrary number of offers, paying through one settlement payment ephemeral coin for each asset type.

Bootstrap Coins

A user making an offer of XCH for a certain type T0 of CAT coin might have the problem of not being able to claim the coins since, generally speaking, only CAT coins can create spendable children using the CREATE_COIN condition. Leaving a slot for an optional additional payment

The following is intended to be used as an inner delegated puzzle in the standard p2_delegated_puzzle_or_hidden_puzzle.

p2_conditions_and_free_payment.cl

(mod (CONDITIONS OFFER_AMOUNT settlement_address)
    (include condition_codes.clvm)

    (if settlement_address
        (c (list CREATE_COIN settlement_address OFFER_AMOUNT) CONDITIONS)
        CONDITIONS
    )
)

This might seem alarming at first glace, as settlement_address is not signed or verified in any way, so it can be mutated by a farmer. However, recall that an offer ensures its getting paid using the notarized coin announcement – it doesn't care what happens to the extra valued coins. Using this construct allows the market maker to redirect the coins through a settlement payment coin even if the market maker has no bootstrap coin of the correct type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment