Closed bonomat closed 5 years ago
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:
MakeOffer
you make the offer to anyone.TakeOffer
they are competing against other people. Only the first person to get their transaction in will be able to take the offer.CancelOffer
after MakeOffer
to get your asset back and nullify any future TakeOffers
.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 :
alpha_asset
: The asset Alice is selling. In this case A Ether. It should be included in the contract deployment. beta_asset_contract_address
: The ERC20 contract addressbeta_asset_quantity
: The quantity (B) of ERC20 The contract can be called in two ways:
TakeOffer
)If not called by Alice we call the caller address bob_address
. And do the following:
TransferFrom(bob_address, alice_address, beta_asset_quantity)
on beta_asset_contract_address
where alice_address
is the address that deployed the contract.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
.
CancelOffer
)If Alice makes a call to her own contract we interpret this as Alice wanting to cancel. We then:
selfdestruct(alice_address)
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:
TakeOffer
)If not called by Alice we call the caller address bob_address
. And do the following:
TransferFrom(bob_address, alice_address, beta_asset_quantity)
on beta_asset_contract_address
.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.
CancelOffer
)If Alice makes a call to her own contract we interpret this as Alice wanting to cancel. We then:
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 approve
s it has can be disregarded. Note: there is one error in your description but I assume you meant the following:
transfer(htlc_contract, amount)
on the token contract to transfer the amount
of tokens to 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.
@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.
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.
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 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.
@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.
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.
In order to make things really atomic, we will have to look into:
I think there should be 1 RFC that specifies same chain trades on Ethereum between Ether and ERC20. Seems like a reasonable scope.
Since it is non-interactive, this will neither use the SWAP
message, nor need a new message type. Cool!
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.
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.
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
isBob
or thecontract
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:
- How to revert state changes while calling other contracts
There's a REVERT
instruction in EVM which seems to do the trick.
- 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.
@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 :)
@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?
@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:
We should investigate whether
msg.sender
isBob
or thecontract
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:
- How to revert state changes while calling other contracts
There's a
REVERT
instruction in EVM which seems to do the trick.
- 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).
@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):
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.
Talked with @bonomat and came to the following outcome for this ticket:
DoD:
Let's wait until everyone is in office.
Meeting invite sent for Monday.
Unblock, @LLFourn to write down decisions.
We left the discussion with the following resolutions:
DoD
Child of #663