Skip to content
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

Allow generation of multiple orders with a single signature #9

Closed
abandeali1 opened this issue Sep 18, 2017 · 1 comment
Closed

Allow generation of multiple orders with a single signature #9

abandeali1 opened this issue Sep 18, 2017 · 1 comment

Comments

@abandeali1
Copy link
Member

abandeali1 commented Sep 18, 2017

Summary

This describes 2 different proposals that would allow multiple orders to be created with only a single signature.

Motivation

Currently, a single order requires a single signature. This creates usability issues and also adds an element of trust to certain relayer strategies.

For example, assume that relayer Alice is using the matching model. Trader Bob wants to buy 3000 ZRX and sees 3 orders on the Alice's orderbook:

  • orderA: 1000 ZRX for 1 WETH
  • orderB: 1000 ZRX for 2 WETH
  • orderC: 1000 ZRX for 3 WETH

Bob is perfectly fine with buying 3000 ZRX for 6 WETH. However, if Bob submits such an order to Alice, there is no guarantee that Alice will match the order against all 3 opposing orders. If Alice only matches Bob's order with orderB, Bob will get a worse rate for 1000 ZRX than if he simply submitted a smaller order to be matched with orderA.

Bob could instead submit 3 opposing orders to Alice:

  • orderA': 1 WETH for 1000 ZRX
  • orderB': 2 WETH for 1000 ZRX
  • orderC': 3 WETH for 1000 ZRX

Since Alice has no obligation to match any of the orders, Bob could end up getting a worse than market rate if Alice only matches orderC with orderC'.

Specification

Option 1

makerTokenAmount and takerTokenAmount in the order message format can be changed to be of type uint[]. When filling an order, the amounts would be filled sequentially. In this example, Bob would create an order with makerTokenAmounts equal to [1, 2, 3] and takerTokenAmounts equal to [1000, 1000, 1000]. Note that both arrays must be the same length. Bob will never get a worse than desired rate, since amounts must be filled sequentially.

Option 2

Rather than signing a single order's hash, we can sign the keccak256 hash of all of the order hashes we want included with the signature.

The following modifications need to be made to fillOrder:

  • It would take an extra parameter of type bytes32[], orderHashes, that is a sequential list of the order hashes needed to verify the signature.
  • The keccak256 hash of the order being filled must be included in orderHashes.
  • All orders referenced in orderHashes before the index of the current order's hash must be completely filled, or else the current fill will fail.
  • isValidSignature verifies that the keccak256 hash of the orderHashes array has been signed

In this example, Bob would create unsigned 3 unsigned orders: orderA', orderB', and orderC'. Bob would then sign keccak256(orderHashA', orderHashB', orderHashC'), creating signatureA'B'C'. The orders must be filled sequentially, so Bob will never get a worse than market rate.

Rationale

Option 1

Pros

  • This proposal uses less on-chain storage, since the combined orders still map to a single orderHash.

Cons

  • This requires modifying the order message format.
  • This makes race conditions more dangerous, since a trader can actually get a worse price if the order is executed out of the expected order.
  • This limits signing multiple orders at once to a single token pair and side of the market.

Option 2

Pros

  • This allows conditional orders to be created, which can be very powerful (e.g. orderA can only be filled if orderB has been completely filled).
  • This allows signing multiple orders at once regardless of token pair or side of market.

Cons

  • The additional on-chain verification could be expensive.
  • Each order maps to a separate orderHash, which requires more on-chain storage than option 1.
  • All associated order hashes must be known, or none of the orders are fillable.

Notes

Option 2 requires a change in how filled/cancelled amounts of an order are stored. There is currently no way to to tell if an order has been completely filled or cancelled on-chain with only the orderHash.

@danielvitorino
Copy link

IMO, based on one of the basic 0x value propositions (repeated and spread over and over by W.W.):

lower overall cost by low on-chain storage,

I would invest efforts on the first approach. Later, it would be better to improve a lean solution that is already adherent to your values, than try to make some other solution fit in these values.
That being said, from the 3 cons you listed for option 1:

  1. I’m not yet fully aware of the implications here (development wise) but, option 2 requires other not-so-simple development as well. Thus, this can be taken out of the equation.
  2. This is the only real con here.
  3. This too could be resolved by turning token address into an array (not sure if I’m missing something very obvious here that would make it not feasible)

Also, I would like to add a fourth concern on op1:

  1. Handling unbalanced match orders if a maker order was partially filled due to some other previous one, may cause the operation to result in a never filled taker order. Of course, this scenario depends on how a relayer/exchange would handle their matches.

At the end of the day, I believe that what 0x community expects is that you stay in tune with your original value propositions (me at least), and that should guide both your biz and your technical choices. Simple as that.

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

No branches or pull requests

2 participants