-
Notifications
You must be signed in to change notification settings - Fork 24
CHIP-0052: Partial Offers #174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
The CI of the 'partial' repo has a step that outputs costs for all the test cases: Note: I'm editing this post to keep costs up-to-date with the
|
There is also this summary available regarding some design choices made for this standard. |
This is really important functionality! Thanks for getting it out there @Yakuhito and CNI team! And also shout out to |
This CHIP is now a |
This is incredible and I'm a huge fan of bringing this to CHIA. I think it will make DEX and offer experiences much easier to use. A few questions / notes:
|
Hey Jude, thank you a lot for the quesitons/notes. Much appreciated!
Right now, wallets would need to use the Replace-by-Fee mechanism to allow multiple people to fill the same partial offer in the same block. When A spends the partial coin to partially fill the offer, the coin creates a new partial coin with the remainder amount - B would need to spend the newly-created coin, meaning that B needs to include A's bundle in the new mempool item to fill the offer (or wait until the mempool item is confirmed). In the end, a farmer will only include valid bundles in a block. The 'simple' scenario is that A broadcasts a bundle, then B broadcasts a new mempool item that is a superset of A's, and C comes along and uses RBF on the [A, B] mempool item. The farmer may then include [A, B, C] in the next block. If D submits their bundle around the same time as B, the options become [A, B, C] and [A, D] - some farmers will consider [A, D] valid and that [A, B, C] is conflicting, while others will consider [A, B, C] valid (due to mempool propagation). Retries & how to handle those cases would be left up to individual wallets.
Partial offers are 'compatible' with normal offers. If you use a normal offer, which I assume would be the default for wallets, you get 'fill-or-kill'. As you noted, you may also create a 'matching' partial offer to accept partial fills.
Usually, offer IDs were either the hash of the 'offer1...' string (current Dexie behavior) or the hash of the spend bundle you get when you decode them (reference wallet behavior). Both change with every partial offer fill, but it's easy to follow the partial offer on-chain as a partial fill transaction leads to a new coin being created, up until the offer is cancelled/expires/is fully filled.
Interesting point - everyone I talked to until now assumed the prefix would be |
Arguably these are dynamic offers. |
Yak will present the details of this CHIP over a Zoom call on Monday, September 29. See the CHIPs channel of our Discord for more details. |
What would you estimate the scope would be to support multiple assets (still restricted to xch, cat, and rcat) on either side of the offer? I'm thinking about the case of liquidity pool tokens ala TibetSwap. It seems like one could have a partial offer which understands the arithmetic of the ratios between the assets ( 1 TIBET-DBX-XCH -> [0.00593 XCH, 0.84 DBX]) It's a little more complicated (perhaps uncomfortably so) to allow [multi-asset] -> [multi-asset], but having it permitting multiple assets on one (but not both) sides of the offer might be a nice addition. |
How do partial offers handle arithmetic underflow errors? test cases:
Do partial offers guard against accepting them with values greater than what's expected?
[edit: correct stated precision of DBX] |
The current partial puzzle is just 438 bytes long - it's specialized, which allows it to be tiny. Adding one-for-many (i.e., taker has to pay more than one asset to fill the partial offer) would remove a lot of the optimizations in the puzzle - for example, you'd need a recursive function that creates announcement asserts for each asset, which would also make the environment harder to access (it'd have several arguments). I'd expect the puzzle to at least double in size, which is a bad trade-off given that most usage will involve one asset being traded for another. The smaller the puzzle, the more partial offer spends we can fit in a block, and the more efficient the market is overall. To offer multiple assets, the complexity would also grow a lot (not just the puzzle size) - I'd design it so the partial offers would be spent in a ring, with the lead coin asserting that the other side paid the fair amount. Each CAT/rCAT needs to be its own coin, so the coins would need to coordinate with each other (or at least assert the same nonce without being vulnerable to nonce replay between two separate partial offers). Alternatively, you could have a singleton owning all assets. In both cases, supporting multiple assets leads to the 'one asset for one asset' case being more expensive because the puzzle has to include the logic for supporting multiple assets (even if it's not used). I think that the right approach is to keep this optimized puzzle for partial offers, and make another one for multi-asset support should the need arise in the future. To borrow an idea from @Rigidity, wallets adding multi-asset support will have to make a lot of updates anyway, so using a different puzzle shouldn't make a difference in adoption.
I don't think this is a use case - when you add assets to TibetSwap, you add 50% of value in XCH and 50% in the CAT at the pool's current price. It doesn't matter how much liquidity you add - the ratio ('price') is the same. I don't see value in using partial offers there because successfully adding some liquidity means you would've been able to add 100% of the liquidity as well. |
The logic is here. Precision is left flexible, but usually the values are in mojos. The rounding is always done in the partial coin's favor (so the taker can lower their bid up until the 'discrepancy' is 0). The amount the partial coin will give the taker is based to what the taker gives ( To clarify, in the example below,
1 XCH - 10^18 mojos ; 1 DBX = 1000 mojos
If you give the partial offer coin the whole value, it will happily swallow the change:
The drivers catch that - or the maker has 20 extra mojos. The main idea is that the taker can arrive at the minimum amount they need to offer to get n DBX.
Driver/wallet would limit the amount to 1 XCH. But, just for fun, let's assume they won't. Then the partial coin will send the following amount to the taker: |
@Yakuhito Thank you for your thoughtful and thorough answers! |
In case you missed it, here is Yak's discussion of this CHIP: |
So if I understand correctly, the initial offer is off-chain but subsequent partial offers are on-chain. It sounds to me like there's an opportunity here to more properly define an on-chain offer standard even for the initial offer or normal offers in general. The major benefit would be on-chain discovery and being able to replace the current "counter offer" functionality that's sharing off-chain data (plus a minor side benefit of a shorter offer string). The obvious downside is the inefficient use of blockspace but do you think it's worth explicitly defining that standard anyhow? To build on Rigidity's question in the call, a nice property of partial offers would be easy discoverability by wallets (without needing to do offer backups) so that expired partial offers could just be displayed and spent alongside other "regular" coins without a need to explicitly cancel them by spending them to wallet controlled puzzle hash. I understand this is possible now but it sounds like it requires the wallet to at least know about the initial offer first. I also think it's worth considering different terms here as to not overload "partial offers":
|
Hey stl, thank you for your comment.
I would bring up the "x% orders remain unfulfilled in traditional markets." argument - having to post offers of any kind on-chain without knowing if they'll be filled at all seems like a very big barrier, especially under fee pressure conditions. We can always come and change this in the future (it doesn't change the Chialisp itself; it's just a matter of consensus/ecosystem support - and could pass as a separate CHIP), but, for now, I think supporting on-chain creation requires a lot of effort for something that feels like a step backwards. One of the main advantages of both types of offers is that they don't require transactions until a counterparty is found - if that weren't the case, I think the best method to swap two assets is to deposit concentrated liquidity in a v3 AMM and withdraw your LP after the price has moved over your position (assuming such an AMM would exist on Chia).
This is a very good point, and I agree. I had a call with @Rigidity this morning and we think it's worth it to hint the initial partial offer coin to the wallet. It would add ~100 bytes to the initial transaction, but would allow the wallet to discover all the partial offers that have been accepted at least once by solely looking at the blockchain (no partial offer exports needed). I'll add this to the CHIP shortly.
Naming in the context of this standard is something I should've thought about sooner. I've certainly changed the terms quite a bit since I first started talking about this standard. Here's how I would call each term now: |
To those following, I would like to propose changing the puzzle of partial offers from Chialisp to Rue. A lot of effort has gone into optimizing the partial offer Chialisp puzzle - however, the Rue-produced CLVM output is ~96% of the Chialisp-produced one (17 less bytes; ~200k cost saved in benchmarks) while being functionally equivalent. This is thanks to Rue's additional optimization methods - some of which cannot be replicated in Chialisp (read more). |
I agree on-chain initial offers make little sense in most circumstances but I do think there's value in standardizing it (in case anybody does want to do it -- e.g. counter offers) but also agree that should be a separate CHIP.
Nice! I think the added bytes is definitely a worthwhile trade off to add hinting.
Amazing, shoutout @Rigidity! |
Yak has answered all questions so far, and he has updated the CHIP to include a Rue version of the puzzle. |
No description provided.