Why 0x is not as trustless as it may seem

One of the main benefits of DEXs is that they are trustless and non-custodial, they allow users to trade their funds without having to hand them over to a centralized entity for a certain amount of time. 0x is also amongst the DEXs which are known for being trustless, in fact most relayers building on 0x advertise exactly that fact. However when digging a little deeper, one can see that 0x is not as trustless as it may seem and many may not actually be aware of that fact.

The flaw in the 0x protocol that renders the trustless claims false is found in a fundamental contract of the protocol. The contract in question is called the TokenTransferProxy, it is essentially responsible for transferring tokens from one address to another. The solution was developed to ensure that users would not need to set the allowance of their tokens everytime the exchange was updated. Essentially improving the overall user experience.

0x architecture diagram detailing how the proxy handles token transfers.

The current proxy mechanism allows the owner to register a new authorized address, which then has the right to transfer tokens through the proxy. This is exactly where the issue lies, the owner has the ability to authorize any address they please, this could for example result in the owner verifying a malicious address that then proceeds to transfer all the allowed funds to their own wallet.

How 0x mitigates the issue

0x does not solve the issue, however it does mitigate it. This is done by making the owner of the proxy a multisig, which has a timelock before a transaction can be executed. This would allow users to set the allowance to 0 if they see that the team were trying to execute a transaction that could be malicious. This solution however comes with flaws of its own, as it makes various assumptions which may not be true:

  1. It assumes that people are actively looking at the multisig to scan for malicious transactions.
  2. It assumes that users would be notified fast enough in case there is malpractice.

So although this is a solution that makes an attack less likely, it does not fully eliminate it. It would still allow a malicious actor to gain full custody of tokens that are approved through the proxy after a certain amount of time.

One thing to note is that this implemented solution also makes it harder to upgrade the Exchange contract if a critical bug is to be found as the timelock still applies.

The multisig implemented by the 0x team is currently a placeholder with the goal of being replaced by a community governance model. However if the proxy is not restructured, one could argue that there is still a flaw here, users could be automatically migrated to using a new exchange which they were never fully aware of.

As Nick Johnson mentioned, it’s worth pointing out that a community governance model could be worse than the current multisig; it’s easy to imagine a situation where someone puts forth a proposal that distributes all the non-conspirators’ tokens to all the conspirators.

Additionally, if a malicious address were to be approved, there is a linear overhead for the user to protect their funds as they would need to change the allowance for all the tokens they have approved for the proxy to spend. This could prove to be hard for many users, especially once relayers start appearing where you can trade any token similar to how etherdelta works.

A simpler solution

As this is an issue I have had to deal with, I spent a lot of time trying to figure out a scheme which works and does not create too much overhead. Of course any solution implemented will create minor amounts of overhead, but I would argue that most users would take the overhead if it guaranteed more security to their funds.

So how would such a solution look? Quite simply we would require a double approval mechanism, where first the owner of the proxy contract authorizes a new address and then the user additionally authorizes that address to transfer their tokens. This not only allows for the same flexibility as the 0x protocol aims to achieve, but it would also allow the user to be selective with which versions of the exchange their tokens can be traded through. On top of that, this solution also eliminates the need for a timelock allowing for fast updates.

Example double approval mechanism

Although the issue is not major, it’s definitely an interesting one to look at. It’s not a security problem which would be caught in an audit as it is rather an issue of trust, I also question how this plays out on the non-custodial argument, as theoretically custody can be gained. The issue may not be major, and it may not even be considered by many to be an issue, but the argument can be made that users need to trust the 0x team more than they should be comfortable with while other DEXs may not even have said issue.

Disclosure: I am currently working together with a team building DEXY, a decentralized exchange. Nonetheless I would be happy to help the 0x team implement a temporary solution to this issue. It is my belief that issues of trust be addressed open and neutrally.