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

⚗️ How to realize same chain trades on Ethereum #665

Closed
bonomat opened this Issue Jan 16, 2019 · 19 comments

Comments

Projects
None yet
4 participants
@bonomat
Copy link
Member

bonomat commented Jan 16, 2019

DoD

  • Present a lightly documented protocol
  • Create issue to write the RFC

Child of #663

@LLFourn

This comment has been minimized.

Copy link
Contributor

LLFourn commented Jan 31, 2019

Design

Since we are doing a same chain trade, we don't need HTLCs and we can do non-interactive multi-party asset exchange:

This means that:

  1. When you do MakeOffer you make the offer to anyone.
  2. When someone does TakeOffer they are competing against other people. Only the first person to get their transaction in will be able to take the offer.
  3. You can do CancelOffer after MakeOffer to get your asset back and nullify any future TakeOffers.

Ether to ERC20

Alice wants to sell A Ether to anyone who will give her B of some ERC20.

Alice deploys a contract from her address alice_address. The contract code is parameterized by the following :

  1. alpha_asset: The asset Alice is selling. In this case A Ether. It should be included in the contract deployment.
  2. beta_asset_contract_address: The ERC20 contract address
  3. beta_asset_quantity: The quantity (B) of ERC20

The contract can be called in two ways:

By any address other than Alice's (TakeOffer)

If not called by Alice we call the caller address bob_address. And do the following:

  1. Call TransferFrom(bob_address, alice_address, beta_asset_quantity) on beta_asset_contract_address where alice_address is the address that deployed the contract.
  2. If that call succeeds, selfdesctruct(bob_address)

Note that for this to work that Bob has to approve the beta_asset_quantity on the contract before he does the TakeOffer.

By Alice (CancelOffer)

If Alice makes a call to her own contract we interpret this as Alice wanting to cancel. We then:

  1. selfdestruct(alice_address)

ERC20 to ERC20

The contract is parameterized by the same as above but has alpha_asset_contract_address and alpha_asset_quantity.

The contract can be called in two ways:

By any address other than Alice's (TakeOffer)

If not called by Alice we call the caller address bob_address. And do the following:

  1. Does a TransferFrom(bob_address, alice_address, beta_asset_quantity) on beta_asset_contract_address.
  2. If that succeeds, call TransferFrom(alice_address, bob_address, alpha_asset_quantity) on alpha_asset_contract_address. If this fails REVERT.

Note that this will only work if both Alice AND Bob have called approved the contract for the correct amount.

By Alice (CancelOffer)

If Alice makes a call to her own contract we interpret this as Alice wanting to cancel. We then:

  1. selfdestruct(alice_address)
    Note we don't need to do anything else because the contract doesn't own the ERC20 it simply has been approved. When it destroys itself any approves it has can be disregarded.

Open Questions

  • Would doing this as a stateful contract require less transactions?
@bonomat

This comment has been minimized.

Copy link
Member Author

bonomat commented Jan 31, 2019

Note: there is one error in your description but I assume you meant the following:

  • Alice deploys the HTLC contract including ETH
  • Bob calls transfer(htlc_contract, amount) on the token contract to transfer the amount of tokens to the HTLC contract.
  • Alice redeems the Ether from the HTLC contract (transfer(alice_address, amount) is called) by sending the secret to it

(same same but different for the otherway around :D )

Two thoughts on that:

  1. Alternatively, in order to not loose tokens by mistake, Bob could call approve(thlc_contract, amount) on the token contract so that the HTLC contract can call transfer_from(bob_address, alice_address, amount).

  2. I don't think we can get rid of having at least 3 transactions (same applies in two directions). Bob (or Alice) will always need at least 2 transactions to transfer (or allow a transfer) the tokens to the HTLC contract the redemption of the HTLC + 1 transaction for the deployment/funding

Afaik, even if we have a stateful contract, we will need these 3 transactions, however, we can get rid of the costly HTLC deployment transaction.

@D4nte D4nte added this to the Sprint 8 👬🥚 milestone Jan 31, 2019

@LLFourn

This comment has been minimized.

Copy link
Contributor

LLFourn commented Jan 31, 2019

@bonomat The goal of the protocol is for it to be non-interactive. So Alice puts up the contract and lets anyone in the world take the trade without interacting with her (Bob is just the name of the guy who was fastest to take the offer). There is no need for HTLCs because we're not sharing state across blockchains. I'll add more details making this clearer and add the approve step I forgot.

It does seem like we'll always need three transactions, which is lame because Bitcoin only takes one to do the same thing.

@D4nte

This comment has been minimized.

Copy link
Member

D4nte commented Feb 1, 2019

Ether to ERC20

Yes I was going to say, how come the contract can transfer Bob's ERC20? I guess Bob needs to give it the right to transfer them, right?
Also, shouldn't there be a refund path for alice to withdraw her offer?
Have you checked what current Ethereum Dex do? No need to re-invent the wheel I believe.

ERC20 to ERC20

Approval are missing, right? I guess Alice in this case can cancel the offer by just cancelling the approval. Is that possible using ERC20 API?

@bonomat

This comment has been minimized.

Copy link
Member Author

bonomat commented Feb 1, 2019

@bonomat The goal of the protocol is for it to be non-interactive. So Alice puts up the contract and lets anyone in the world take the trade without interacting with her (Bob is just the name of the guy who was fastest to take the offer). There is no need for HTLCs because we're not sharing state across blockchains. I'll add more details making this clearer and add the approve step I forgot.

It does seem like we'll always need three transactions, which is lame because Bitcoin only takes one to do the same thing.

True, an actual HTLC is not needed. Just replace HTLC in my description with contract.
However, if we want to allow multi-hops across blockchain then we would need an HTLC. And I think we should consider this right from the very beginning on.

@D4nte: refund path: Yes, this is indeed needed and there are multiple ways of how to handle this as well.

@LLFourn

This comment has been minimized.

Copy link
Contributor

LLFourn commented Feb 1, 2019

@bonomat @D4nte I rewrote the original to include missing pieces and motivation.

However, if we want to allow multi-hops across blockchain then we would need an HTLC. And I think we should consider this right from the very beginning on.

To condition a same chain trade on a cross chain trade? Yes in this case you would need a HTLC. You could use a single HTLC that holds two assets to do this (I think). This would definitely be a different RFC/contract.

@thomaseizinger

This comment has been minimized.

Copy link
Member

thomaseizinger commented Feb 1, 2019

I like the idea of non-interactive trades. Good stuff.

We should investigate whether msg.sender is Bob or the contract if Bob directly invokes the contract. If not, Bob will have to approve the token transfer first.

Gas considerations

In order to make things really atomic, we will have to look into:

  1. How to revert state changes while calling other contracts
  2. Make sure we have enough gas at the beginning to do all the stuff we need

RFC considerations

I think there should be 1 RFC that specifies same chain trades on Ethereum between Ether and ERC20.
Seems like a reasonable scope.

BAM considerations

Since it is non-interactive, this will neither use the SWAP message, nor need a new message type. Cool!

HTTP API considerations

Very likely a new sub-resource under /swaps with the given RFC number. Since we don't need communication and it is a new resource, we can leave out the peer address here.

@bonomat

This comment has been minimized.

Copy link
Member Author

bonomat commented Feb 1, 2019

Before we jump into non-interactive trades on Ethereum and write a RFC, please have a look at all the decentralized exchanges out there. To name a few: 0x, etherdelta , kyber network , idex, waves, ethfinex , radar...

Most of them are completely open source and provide a proper protocol to use.

We might need to clarify the goal of this ticket but if it's just Ethereum same chain trades, than we can really just use a solution which is out there already and skip the RFC.

I think the fun part starts when the protocol enables multi-hop trades on the same chain or in combination with cross-chain, partially execution of trades.

@luckysori luckysori changed the title ⚗️How to realize same chain trades on Ethereum ⚗️ How to realize same chain trades on Ethereum Feb 1, 2019

@LLFourn

This comment has been minimized.

Copy link
Contributor

LLFourn commented Feb 1, 2019

I like the idea of non-interactive trades. Good stuff.

Yes. Same chain trades are far better because the blockchain itself is the decentralised exchange. The COMIT node can still play a role in verifying and interpreting the blockchain I think.

We should investigate whether msg.sender is Bob or the contract if Bob directly invokes the contract. If not, Bob will have to approve the token transfer first.

I looked into this and unfortunately it looks like Bob has to do an approve first.

Gas considerations

In order to make things really atomic, we will have to look into:

  1. How to revert state changes while calling other contracts

There's a REVERT instruction in EVM which seems to do the trick.

  1. Make sure we have enough gas at the beginning to do all the stuff we need

If we run out of gas it should REVERT everything.

HTTP API considerations

Very likely a new sub-resource under /swaps with the given RFC number. Since we don't need communication and it is a new resource, we can leave out the peer address here.

Yes I guess you just have a system that whenever if finds a possible same chain trade on ethereum it posts it to the COMIT node which verifies it and produces the actions to "approve" and then poke the contract actions.

@thomaseizinger

This comment has been minimized.

Copy link
Member

thomaseizinger commented Feb 1, 2019

@LLFourn

Yes I guess you just have a system that whenever if finds a possible same chain trade on ethereum it posts it to the COMIT node which verifies it and produces the actions to "approve" and then poke the contract actions.

Very interesting point. I didn't even think that far :)

@thomaseizinger

This comment has been minimized.

Copy link
Member

thomaseizinger commented Feb 1, 2019

@bonomat

Before we jump into non-interactive trades on Ethereum and write a RFC, please have a look at all the decentralized exchanges out there. To name a few: 0x, etherdelta , kyber network , idex, waves, ethfinex , radar...

Are you saying we should copy the protocol or make the COMIT node compatible with any of those exchanges?

@bonomat

This comment has been minimized.

Copy link
Member Author

bonomat commented Feb 1, 2019

@thomaseizinger

Are you saying we should copy the protocol or make the COMIT node compatible with any of those exchanges?

Using one obviously :)

@LLFourn

I like the idea of non-interactive trades. Good stuff.

Yes. Same chain trades are far better because the blockchain itself is the decentralised exchange. The COMIT node can still play a role in verifying and interpreting the blockchain I think.

In this case we don't need the COMIT node at all:

  • a static website with web3 can monitor the blockchain and looks for offers
  • signing transactions is done with your ledger/metamask
    The result is Etherdelta :D

We should investigate whether msg.sender is Bob or the contract if Bob directly invokes the contract. If not, Bob will have to approve the token transfer first.

I looked into this and unfortunately it looks like Bob has to do an approve first.

Correct, we verified that in our last hackathon remember?
If Bob issues a transaction he is msg.sender. If a contract forwards the transaction (i.e. call is invoked) then msg.sender is the contract. The thing we were confused about last time was that during a contract deployment msg.sender is already the contract and not Bob who was the sender of that transaction.

Gas considerations

In order to make things really atomic, we will have to look into:

  1. How to revert state changes while calling other contracts

There's a REVERT instruction in EVM which seems to do the trick.

  1. Make sure we have enough gas at the beginning to do all the stuff we need

If we run out of gas it should REVERT everything.

Yes, this is correct. Unless a contract checks for gas and does not call REVERT but silently returns false (or ignores an action). I have the feeling we should not do any gas checks/assumptions in the contract given the latest problems with Ethereum (https://medium.com/chainsecurity/constantinople-enables-new-reentrancy-attack-ace4088297d9).

@bonomat

This comment has been minimized.

Copy link
Member Author

bonomat commented Feb 1, 2019

@LLFourn : one note on your cancel approach:

The one with the better connection to the Ethereum network has an advantage (or the one being able using the least amount of gas):

  • assuming Alice wants to cancel because the rate is not in her favor anymore (or just because it is) and sends a cancel transaction, Bob sees this transaction before it is confirmed and can front run her
  • same goes the other way around, Alice has a beautiful Option as she can wait with her offer until Bob tries to redeem it. If the rate evolves in her favor (or not), she can always front run Bob without losing her funds and only paying for the transaction fees.

-> I did this on etherdelta: I monitored the blockchain for fatfinger offers (too many zeroes, etc): immediately fired a transaction (1 block afterwards). If I saw another incoming transaction in the same block, I tried to front run it with a higher gas price. There was some good money to make from this :)

I think we should design the contract in a way that Bob can safely redeem without being afraid of being front run by a cancelation.

@LLFourn

This comment has been minimized.

Copy link
Contributor

LLFourn commented Feb 12, 2019

Talked with @bonomat and came to the following outcome for this ticket:

  1. Before implementing our own non-interactive same chain trades on Ethereum we should check out existing contracts and protocols that do this already.
  2. If we need to design interactive same chain Ethereum trades that can be conditioned on the outcome of the HTLC we should do the research into that when we come to that requirement.

@LLFourn LLFourn closed this Feb 12, 2019

@wafflebot wafflebot bot removed the review label Feb 12, 2019

@D4nte

This comment has been minimized.

Copy link
Member

D4nte commented Feb 13, 2019

DoD:

  • Team discussion needed to decide on how we want to proceed with same chain swaps

@D4nte D4nte reopened this Feb 13, 2019

@LLFourn LLFourn assigned D4nte and unassigned LLFourn Feb 15, 2019

@D4nte D4nte added the blocked label Feb 17, 2019

@D4nte

This comment has been minimized.

Copy link
Member

D4nte commented Feb 17, 2019

Let's wait until everyone is in office.

@D4nte

This comment has been minimized.

Copy link
Member

D4nte commented Feb 19, 2019

Meeting invite sent for Monday.

@D4nte D4nte assigned LLFourn and unassigned D4nte Feb 26, 2019

@D4nte D4nte removed the blocked label Feb 26, 2019

@D4nte

This comment has been minimized.

Copy link
Member

D4nte commented Feb 26, 2019

Unblock, @LLFourn to write down decisions.

@LLFourn

This comment has been minimized.

Copy link
Contributor

LLFourn commented Feb 26, 2019

We left the discussion with the following resolutions:

  1. Ethereum same chain swaps can be non-interactive (like the protocol I describe above and things like EtherDelta etc). Since these protocols don't require any inter-party communication they are not within the scope of COMIT.
  2. If we were to create an interactive same chain swap protocol (so you can do a swap with a particular person) that would be part of COMIT but we should wait until we have a proper motivation for this.

@LLFourn LLFourn closed this Feb 26, 2019

@wafflebot wafflebot bot removed the sprint-backlog label Feb 26, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.