Inspect offer transaction

I want to inspect offer transaction, but after taken the offer, I cannot find the transaction directly.

If I find the latest transaction id from wallet get_transactions and get detail via wallet get_transaction -v -tx command, I would see an empty spend_bundle. That’s weird.

Is there anyway to display spendbundles of offer transaction?

Right now we use a bit of a hack to push the transaction where we create a dummy transaction to a non existent wallet ID for the purposes of pushing the transaction. This is hacky and should probably be changed. chia-blockchain/ at 231ef6faf20fba7463831a5015edee649a1d5d49 · Chia-Network/chia-blockchain · GitHub

This does interestingly lead to the fact that you can search for records with wallet ID 0 to see your pushed taken offers but I wouldn’t rely on that because like I said, we shouldn’t be doing that probably.

However, if you look at trade records rather than transaction records, they all contain the compressed offer blob on them (as long as you specify file_contents: true on the RPC). You can use this compressed offer blob and some of the Offer driver code located here: chia-blockchain/ at main · Chia-Network/chia-blockchain · GitHub to inspect the spendbundle:

Offer.from_bech32(<bech32 blob>).to_valid_spend()

Keep in mind to_valid_spend() will only work if the offer is perfectly symmetrical (no arbitrage) and if the offer can be pushed to the network in the current state. If you’re looking at proposed offers, they are not yet valid spends so this method will throw an error on them. You can use the similarly named to_spend_bundle() method to see how we serialize offers as invalid spend bundles before we compress and encode them.


Your answer really pushed me further a lot. I’m able to use to_spend_bundle() to deserialize the offer file and find some interesting clues there.
However, I didn’t find a way to successfully execute to_valid_spend(), as I cannot fabricate the second offer file to make the offer perfectly symmetrical(didn’t find a way to mix them).

I tried to find the generated coin and their parents for clues, here is my understanding of Offer:

  1. One raise offer file by utilizing settlement_payments.clvm to send coin to one virtual address(which coin has no parent) and with conditions(like ASSERT_COIN_ANNOUNCEMENT and ASSERT_PUZZLE_ANNOUNCEMENT)
  2. The opponent could accept the offer by virtually providing another symmetrical offer.
  3. All above signed by their owner before distribute, as BLS support aggregate, simply bring together all these coins(conditions) and aggregate the signature.
  4. Send this final spendbundle to blockchain, all

A trivial question always puzzle me: how these coins (which send to virtual addresses) have been redirect to the receiver’s addresses?

You can execute to_valid_spend for an asymmetrical offer if you provide a puzzle hash for the arbitrage to go to. But it does need to be a fully valid offer (all parties are satisfied)

Your understanding is not quite correct, offers are actually based on a very simple premise. An offer is mostly just a signed transaction sending all of the coins you want to offer to settlement_payments.clvm. This puzzle allows anyone to spend the money to wherever they want BUT it is going to announce where it is sending the money. This may seem like a terrible transaction to sign if you only know that much because someone could just come and take all of your money and give you nothing. So how do we secure it?

We use a trick similar to what we do with singleton launchers, we assert an announcement as part of completing this transaction we have signed. The announcement we assert is from a hypothetical settlement_payments.clvm puzzle that pays us exactly what we are requesting. This is how we secure our offer. Anyone can spend our money wherever they want, but only if they pay us what we want.

This is the fundamental idea behind an offer. When you are looking at the spend bundle that the offer file decodes to, you’ll notice a spend or spends that look fake because they have a fake-looking parent ID. Those spends are really just an encoding of the coins we are requesting. The puzzle gives the information about the type of asset we are requesting, and the solution gives information about the payments we would like to receive. We could potentially just as easily encode some JSON in our offer file like so:

  "requesting": [
    "spacebucks": 100,
    "marmot": 5,

But we encode it as a coin spend so that our offer file remain a spend bundle and therefore can be passed through a lot of the functionality that works for spend bundles already.


Thanks for your detail answers, really helped a lot. However, I still have doubts.
As following, I constructed a sample, which XCH is exchanged with CAT.

The calculated assertation relationship as:

62-63: d625-db44
62-63: 0d47-acc4

60-61: 622b-0424
60-61: 462c-094b

I ignored 50/51 as they are standard parts we already familiar with.

I can easily understand the interlock mechanism for securing the transactions which required happen together.

My question is: How the amount be secured? (In my understanding, 62/63 assert the puzzle_hash which doesn’t contain amount information)

1 Like

They assert an announcement from the settlement payments puzhash. Remember I said that the settlement payments puzzle just creates coins and announces what coins it’s creating. When an offer is asserting that it is being paid, it asserts that the settlement payments puzzle announces the coins it wants including puzzle hash and amount.

A lot of this is hidden behind hashing, but that’s the basic idea.

1 Like