wyvernprotocol / wyvern-v3

Wyvern Protocol v3.1, Ethereum implementation
https://wyvernprotocol.com
MIT License
298 stars 121 forks source link

Examples? #51

Closed coopermaruyama closed 3 years ago

coopermaruyama commented 3 years ago

I can't find any example code in the docs. Would be nice to at least see an example implementation somewhere. Really hard to determine what I'm supposed to pass into atomicMatch by just looking at the code.

MarvinJanssen commented 3 years ago

The test files are pretty comprehensive and show different ways to construct orders.

https://github.com/wyvernprotocol/wyvern-v3/blob/e4396ab753e4963f5e38b238c4b12a015be7c46b/test/5-wyvern-exchange-matching.js#L1

coopermaruyama commented 3 years ago

Okay, maybe you can let me know if my understanding is correct here or correct me if I'm wrong.

As far as I can tell, general idea of Wyvern is rather than trading 2 tokens maker/taker style like with 0x or something, we're trading arbitrary function calls, which is awesome and what got me interested in this project. So much potential.

I'm most interested in the protocol's ability to match on signatures, as this I think makes possible the UX that is really missing in a lot of other protocols so I'm thinking in this context.

The signature-based txs raises my first question with regards to one side being simply ETH. If a maker or taker approves the proxy to transfer their ERC20 tokens it makes sense but with ETH it would it only be able to go from taker -> maker (since it would rely on msg.value)?

And then my questions w/r/t the tests:

it('matches with signatures',async () => {
  let {exchange, registry, statici} = await withContracts()
  // My understanding here is `any(...)` is some arbitrary function I can write 
  // into a smart contract, which is what is referred to as the "registry" and 
  // implements my "predicate". All it needs to do is return true/false (or 
  // revert) to either accept/reject the exchange. Is that correct?
  // Also, I noticed in the tests these all have the same arguments `(bytes, 
  // address[7],uint256[6],...)` - where can I find out about what these 
  // arguments actually describe and how to use them? Does each index in the 
  // array of 7 address refer to a specific thing, or is it just coincidental 
  // that they all have the same args?
  const selector = web3.eth.abi.encodeFunctionSignature('any(bytes,address[7],uint8[2],uint256[6],bytes,bytes)');

  const one = {
    registry: registry.address, 
    maker: accounts[6], 
    staticTarget: statici.address, 
    staticSelector: selector, 
    staticExtradata: '0x', 
    maximumFill: '1', listingTime: '0', expirationTime: '100000000000', salt: 2344
  }
  const two = {registry: registry.address, maker: accounts[6], staticTarget: statici.address, staticSelector: selector, staticExtradata: '0x', maximumFill: '1', listingTime: '0', expirationTime: '100000000000', salt: 2345}

  let [oneSig,twoSig] = await Promise.all(
    [
      // I would have expected to see one call signed by maker, and one by 
      // taker, but here they are both by maker, so I think I'm misunderstanding
      // a basic part of the protocol here...
      exchange.sign(one, accounts[6]),
      exchange.sign(two, accounts[6])
    ]
  );

  // Am I correct in my observation that here, both parties are trading calls 
  // to `test()`?
  const call = {target: statici.address, howToCall: 0, data: web3.eth.abi.encodeFunctionSignature('test()')}

  // Am I correct in my assumption that this tx can theoretically be called
  // by a third party who is neither maker or taker, given that they include
  // both signatures?
  assert.isOk(await exchange.atomicMatch(one, oneSig, call, two, twoSig, call, ZERO_BYTES32))
}))

Thanks in advance

MarvinJanssen commented 3 years ago

As far as I can tell, general idea of Wyvern is rather than trading 2 tokens maker/taker style like with 0x or something, we're trading arbitrary function calls, which is awesome and what got me interested in this project. So much potential.

Correct.

The signature-based txs raises my first question with regards to one side being simply ETH. If a maker or taker approves the proxy to transfer their ERC20 tokens it makes sense but with ETH it would it only be able to go from taker -> maker (since it would rely on msg.value)?

Correct:

https://github.com/wyvernprotocol/wyvern-v3/blob/e4396ab753e4963f5e38b238c4b12a015be7c46b/contracts/exchange/ExchangeCore.sol#L338-L342

--

// My understanding here is any(...) is some arbitrary function I can write // into a smart contract, which is what is referred to as the "registry" and // implements my "predicate". All it needs to do is return true/false (or // revert) to either accept/reject the exchange. Is that correct?

Not the registry, that one hold the proxies. But yes, you write a static call smart contract with your "predicate". It should either revert or return the new order fill amount, which can be 1 if the order type does not allow for partial fills.

// Also, I noticed in the tests these all have the same arguments (bytes, // address[7],uint256[6],...) - where can I find out about what these // arguments actually describe and how to use them? Does each index in the // array of 7 address refer to a specific thing, or is it just coincidental // that they all have the same args?

Not a coincidence. Here you can see how the parameters are encoded:

https://github.com/wyvernprotocol/wyvern-v3/blob/e4396ab753e4963f5e38b238c4b12a015be7c46b/contracts/exchange/ExchangeCore.sol#L209-L227

And here a static call contract with predicates similar to what you can do with 0xProtocol:

https://github.com/wyvernprotocol/wyvern-v3/blob/e4396ab753e4963f5e38b238c4b12a015be7c46b/contracts/StaticMarket.sol#L16

--

// I would have expected to see one call signed by maker, and one by // taker, but here they are both by maker, so I think I'm misunderstanding // a basic part of the protocol here...

The maker and the taker appear to be the same principal in that test. You will see that other tests have different principals.

// Am I correct in my observation that here, both parties are trading calls // to test()?

Correct.

// Am I correct in my assumption that this tx can theoretically be called // by a third party who is neither maker or taker, given that they include // both signatures?

Correct. There are some tests that do that. The principal that sends the matching transaction needs not sign its part of the order.

coopermaruyama commented 3 years ago

@MarvinJanssen Appreciate the response can't thank you enough! Closing this now