recommendation: change how ETH is handled in pairs
wschwab opened this issue · comments
Hi there! We were reviewing Helios on a a Solidity Friday (link to shameless self-plug here), and had an observation we'd like to share. First I just wanted to say that this is a really cool idea, and we really enjoyed reading through it.
As of now, when ETH is sent while creating a pair, ETH becomes the token0
of the pair, and is represented by the zero address. This assignment is done after token0
and token1
are sorted, ensuring that token0
is the address with the higher number (source). This means that in the current structure, the following considerations must be made when creating pairs with ETH:
- two addresses must be passed into the function (source)
- the lower of these addresses will be the token paired with ETH
- the higher will be replaced by the zero address, which is used when ETH is in a pair
This would make the "best" address to pass in with the token address to pair with ETH 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF
, since it will be higher than any other address passed in, and will then be replaced with the zero address for ETH. I'd like to recommend changing this. For one, it makes ETH pairs behave differently than all other pairs - in all other pairs the higher address is token0
, whereas since ETH is represented by the zero address, in ETH pairs it will always be lower address first. In addition, 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF
is just a bit of a pain to work with.
One possibility would be replacing token1
with the zero address to represent ETH instead of token0
. This would make it possible to pass in the zero address as one of the token addresses, which is easy to use both in Solidity (address(0)
) and in helper libraries in other languages (eg ethers.constants.AddressZero
in ethers.js). It will always be sorted as token1
too, and ETH pairs will behave just like any other pair in terms of ordering by the higher address first.
This would mean taking this and replacing it with:
// if ETH attached, overwrite token0 and token0amount
if (msg.value != 0) {
token1 = address(0);
token1amount = uint112(msg.value);
token0._safeTransferFrom(msg.sender, address(this), token0amount);
} else {
token0._safeTransferFrom(msg.sender, address(this), token0amount);
token1._safeTransferFrom(msg.sender, address(this), token1amount);
}
I wanted to open this as an issue instead of a PR just because I figured you may have additional reasons why you did things this way, but would be happy to make a PR myself if you'd like.
Cheers!
would it help if we make the smaller address token0
?
I think that would also work, the main reason I suggested this way was since I didn't know how big of a pain it would be to change that. I had also thought at the time that Uniswap also did larger first, but just went and looked it up (here) and it looks like Uniswap is also lower first, so then I'd think it's better to go that way just to keep consistency between platforms too.