Introduction of direct ETH-xDai swap with the xDai bridge and Uniswap


#1

Uniswap is a protocol for automated token exchange on Ethereum.”. In fact it is a form of decentralized exchange implemented with Ethereum contracts. It provides an ability to exchange ETH on ERC20 tokens and vice versa. And if ETH is used as a common pair for for all tokens exchange so it provides the ability to trade an ERC20 token to another ERC20 token.

This document describes a proposal to modify the xDai Bridge as so it could use Uniswap for ETH-xDai bridging.

Since there are two direction for the bridge operations, consider both of them separately:

ETH-xDai

The Uniswap exchange contract responsible for ETH-DAI trades is 0x09cabec1ead1c0ba254b09efb3ee13841712be14.

In order to swap ETH to DAI and send them to the bridge contract it is necessary to call ethToTokenTransferOutput with the token bridge address as the parameter (recipient). This call will generate the Transfer event where from is the exchange contract and to is the bridge contract. It also generates TokenPurchase where the caller of ethToTokenTransferOutput is specified in the buyer field.

It means that the token bridge behavior can be changed as so:

  1. Every token bridge instance observes the Transfer event where the field to is the bridge contract address.
  2. It checks the from field of the event in order to understand that the transfer is from the ETH-DAI exchange. It triggers the special handling of the relay request: the buyer field for the TokenPurchase event is used to take the sender of the request rather than the field from of Transfer.
  3. Every instance confirmrs the request and the corresponding amount of xDai coins minted and sent to buyer address in the xDai chain.

xDai-ETH

The current implementation of the bridge assumes that the relay request is triggered as soon as xDai coins are sent to the fallback method of the bridge contract. So, there is no any possibility to specify the information if the receiver of tokens differs from the coins sender that’s why we cannot point out the Uniswap exchange as the receiver.

Since the swapping scenario assumes some special handling the following is suggested:

  1. A new method must be introduced in the bridge contract like requestToSwap. This method will be payable and require at least two parameters: min_eth and deadline that will be calculated by the Token Bridge UI by the same manner as Uniswap Send UI does.
  2. As soon as the user calls requestToSwap the bridge contract on the xDai chain recognizes special treatment of such relay request. This is reflected on the structure of the relay message. The parameters min_eth and deadline will be encoded as part of this message.
  3. The bridge contract on the ETH Mainnet side receives confirmation of the relay message signed by the bridge validators.
  4. Since the message differs from the ordinary relay request, the bridge contract calls:
    • approve in DAI token contract to confirm swapping
    • tokenToEthTransferInput in the ETH-DAI exchange contract, where recipient is the address of the relay request sender.
    • if tokenToEthTransferInput fails (e.g. the exchange rate was changed dramatically or the transaction was picked up by the network validators to late), the bridge contract claims the token transfer approval and send the DAI tokens to the recipient instead. It will allow the user to finish exchange later with more preferable rate.

Another option could be to handle the fail of tokenToEthTransferInput as so the tokens will remain locked on the token bridge contract and the user will need to claim/re-request swapping explicitly later. A con of this approach is absense of a notification to the end user that the relay requests failed.


#2

Great write-up Alexander! Is the intent for the ETH-xDai bridge instance to use the same xDai chain Validators, or will this be a new, stand-alone deployment with a unique (albeit perhaps identical) set of Validators? Keeping the instances separate reduces complexity and can increase adoption.

An exciting aspect is that with independent bridges, an identical POA<–>xDai bridge can be deployed enabling direct transition between the POA Core and xDai blockchains, empowering direct wealth transfer between chains. An instance of Uniswap can be deployed on POA Core Network, empowering any token deployed on the POA Core Network to add to overall economic liquidity. choosing the Uniswap instance deployed on POA Core will massively reduce transaction costs for distributed exchange users, and will have no negative affect on the Ethereum Uniswap instance.

Providing liquidity for the Uniswap exchange deployed on the POA Core Network could be an excellent use for POA Core Emissions. Validators can vote on how to utilize emissions once every three months. Annual Emissions are around 6.3M POA and the upcoming vote could direct 1.6M POA toward creating a market basket for the POA<–>xDai bridge. This solves the liquidity issue that is a significant barrier for most distributed exchanges (DEX’s).

The Buffidai wallet team is helping drive adoption of POA and xDai in the conventional economy, and Uniswap is an excellent, existing Open Source tool to increase market access. a POA<–>xDai bridge will be an excellent addition to the overall ecosystem. Thank you for your effort - looking forward to your response and more discussion!


First round of POA Core emission funds discussion, February 2019
#3

@akolotov

This is awesome. Its great to see you guys working on this! Overall looks good. This will work for ETH to xDAI swaps in a single tx however I have a proposal for extending it to any ERC20 to xDAI swaps in a single tx.

ERC20-xDAI

It triggers the special handling of the relay request: the buyer field for the TokenPurchase event is used to take the sender of the request rather than the field from of Transfer .

This will work for when ethToTokenTransferOutput and ethToTokenTransferInput is called on the DAI exchange, which is awesome. This will work for ETH to xDAI swaps which is exciting!

However there will be difficulties with ERC20 to xDAI swaps. In an ERC20 to ERC20 swap (ABC to XYZ), the buyer sends ABC to the ABC exchange where it is converted to ETH. That ETH is then sent to the XYZ exchange which converts it to XYZ and then forwards the funds to a recipient. What this means is that the ‘buyer’ in the EthPurchase event on the ABC exchange is the transaction sender, however the ‘buyer’ in the TokenPurchase event on the XYZ exchange becomes the ABC exchange.

To put it in xDAI terms, if someone were to execute an MKR to xDAI swap on Uniswap, the bridge would see it received DAI from Uniswap and check the buyer in the TokenPurchase event. However, this buyer would actually be the MKR exchange, not the real buyer. One option is to not support ERC20 to xDAI swaps in a single transaction, but potentially we can make it work :grinning:

One way to fix this would be to have a list of Uniswap exchange contract addresses, in addition to the DAI address. If a transfer event is seen from the DAI exchange, the buyer address is checked on the TokenPurchase event. So far, this is the same. However, if the buyer address is ANOTHER uniswap exchange (such as MKR exchange, ANT exchange, etc…) then the EthPurchase event needs to be checked and the buyer address from that event should be used. This would allow any ERC20 (as long as its exchange contract address was stored in the xDAI list) could be swapped for xDAI in a single tx.

Here is an example MKR to DAI transfer tx using the tokenToTokenTransferInput and tokenToTokenTransferOutput functions:

https://etherscan.io/tx/0x7b6e28f9d9965e4723e4eeba2088e01ae914bbd749a83ae2e5d8e0afe242444d

If you check the event logs you will see there are 4. The MKR transfer from the buyer to MKR exchange, the DAI transfer to the recipient (would be to xDAI bridge), the EthPurchase on the MKR exchange, and the DAI purchase on the DAI exchange.

xDAI-ERC20

Should basically be the same as xDAI-ETH but an additional function would need to be added such as requestSwapToToken. Instead of calling tokenToEthTransfer(buyer) it would call tokenToTokenTransfer(buyer, outputToken) along with min/max values, etc…


#4

This is great to see. Thank you @akolotov for getting this started and writing up your thoughts. Thank you 1proof for your comments. Thank you @haydenadams for being willing to discuss this idea and possible implementation.


#5

Thanks for sharing this.

have a list of Uniswap exchange contract addresses

Is there any Uniswap API to check if a contract address is the address of one of Uniswap exchange? If we have such functionality, the bridge instance could use the address from buyer to differentiate whether it is token swap or ether swap.


#6

Simplest way to check if a given address is a uniswap exchange is to call the getToken() function on the Uniswap factory. If it is an exchange it will return the address of the associated token. If it is not an exchange it will return 0x000000000…

https://docs.uniswap.io/frontend-integration/connect-to-uniswap#get-token-address

That said it might be useful to get the full list of Uniswap exchanges (and update the list regularly), by retrieving all NewExchange events from the factory contract.

This API endpoint will eventually contain the full list, but it is still in progress and only has a few exchanges right now
https://uniswap-analytics.appspot.com/api/v1/directory


#7

Just wanted to say this sounds awesome, we (althea.org) would have implemented something like this but with more steps since we obviously can’t modify the bridge contract. Any ideas when this will be live?


#8

You are welcome to contribute to the bridge contract if you have time and resources.
We had such collaboration before with Colu and other projects.


#9

*checks in on this thread. (Wondering if we maybe need to attach a bounty to it or something)