TLDR: The 0x team recently stopped all trades on 0x exchanges in order to patch a vulnerability that enables attackers to fill certain orders with invalid signatures. We believe that events like these demonstrate why many DEX smart contract systems aren’t as decentralized as their users might think.
0x Vulnerability Exposed and Patched
Recently, a third party white hat hacker responsibly disclosed a critical 0x transaction vulnerability.
The vulnerability would allow for an attacker to submit forged orders, which could lead to stolen funds. By crafting a special signature, an attacker could bypass faulty validation in 0x smart contracts.
Luckily, the 0x team patched the vulnerability before anybody exploited the bug. They did an excellent job at transparently communicating their resolution process with their users.
Unfortunately, situations like these highlight faulty design patterns that are rife in the majority of smart contracts. In this blogpost, we will address the inadvisable design practices we see in the DEX space, including: hub contracts, kill switches, and upgradeable clauses.
Inadvisable Design Practice #1: Centrally-Controlled, Third Party Hub Contracts
“0x is an open protocol that enables the peer-to-peer exchange of assets on the Ethereum blockchain.” The 0x team allows third parties to hook into their protocol, in order to facilitate the decentralized exchange of Ethereum-based assets (eg. ETH, ERC20s, etc.).
Such third party facilitators, like Radar Relay and Paradex, funnel users to a central hub contract, controlled by the 0x team. This contract executes all cryptocurrency swaps that occur within the 0x protocol.
This figure, taken from their white paper, highlights the 0x DEX contract. We can see that this central contract intermediates token transfers between every maker and taker in the 0x network. Though the contract does not take custody of the parties’ funds, the makers and takers are not actually transacting P2P.
In order for this DEX contract to transfer tokens, the users of the 0x protocol must allow it to access their balances (steps 1 and 5 in the figure above). They do so by giving the DEX contract access to allowances - dedicated subsets of their overall balances.
In a regular 0x trade, a maker must sign-off on an order and broadcast it over an arbitrary communication medium (steps 2 and 3). A taker of the maker’s signed order then submits it to the DEX contract (steps 4 and 6). The DEX contract:
- Authenticates the maker’s signature
- Verifies that the order has not expired
- Verifies that the order has not already been filled
- Then transfers tokens between the two parties at the specified exchange rate (step 7)
However, the vulnerability exposed a way for bad actors to bypass the contract’s signature validation. The contract could transfer funds by improperly authenticating forged signatures. Considering that every 0x swap must flow through this central point, it’s easy to see the 0x DEX hub contract as a single point of failure that could cause a system-wide catastrophe.
Here is a non-exhaustive list of other decentralized exchange protocols that use centrally-controlled hub contracts to execute token swaps:
- Ether Delta
- Fork Delta
Inadvisable Design Practice #2: Admin-Controlled Kill Switches + Upgradeability Clauses
As mentioned above, the 0x team addressed the vulnerability before it was exploited. Having implemented kill switches into their hub contracts, they were able to stop exchange functionality and prevent systemic damage.
What's the benefit of having a kill switch? The 0x team ensured that a malicious actor could not pull off a system-wide attack. We believe the 0x team made the best decision under their circumstances. After activating the kill switch, they responsibly abandoned the faulty hub contract and created a new one.
What if instead they had implemented an “upgradeable” clause? Well, they could've just updated the contract’s code and similarly prevent the exploit. However, that capability enables the owner of the contract to update the its code at any time. In our opinion, upgradeability is worse than a kill switch; what benefit is a smart contract if it can be changed under you at any time? It's not deterministic; it's not censorship resistant; frankly, it's not secure. This kind of upgradeability can lead to disasters like the $12M Bancor hack.
Thankfully, 0x did not have an “upgradeable” clause in their contract, and were able to defend against catastrophic failure via kill switch.
So then what is the drawback of having a kill switch? Well, because the kill switch is still accessible to a central actor, the users of that smart contract are still subject to the whims of those who control it.
Here, we can see why “decentralized” exchange protocols aren’t really decentralized. We expect neutrality, censorship-resistance, etc., but with the flip of a switch, the 0x team killed the DEX hub contract and blocked all its orders from executing. What would happen if the contract owner’s keys get compromised?
Or what's to stop a government body, now having seen this kill switch, from demanding 0x to censor and stop all transactions? If a third party has the ability to short-circuit a system, how is a “decentralized” system any better than a centralized one?
We need to understand the implications of the design decisions we are making today. Kill switches can easily lend themselves to disruption, downtime, manipulation, or censorship. They negate the benefits of “unstoppable code”.
A third party should never have the ability to stop and censor your transactions in any situation. The transacting parties should be the ones in control.
Liquality User-Owned-and-Deployed, Disposable Contracts
Through examples like this, we learn that “decentralized” solutions do not necessarily cultivate disintermediation. By understanding the malpractices described above, Liquality contributors decided to architect P2P atomic swap contracts from the following principles:
Design Philosophy #1: Remove single points of failure and instead architect security from the edges, not the center.
Design Philosophy #2: Build systems that fit the can’t vs. won’t narrative.
We recognized disintermediation as the key enabler for achieving these design patterns. We needed to create a way for users to easily deploy their own smart contracts to eliminate hubs, admin controls, and other systemic vulnerabilities.
By using a cookie-cutter template based on HTLC standards BIP199 and ERC1630, parties could easily deploy and control their own contracts on a per transaction basis. In case of emergencies, it would be up to the parties themselves, not a central actor, to decide when to stop using a faulty contract. Through disintermediation, users could gain the benefits of permissionless and deterministic smart contracts.
But would this approach make sense economically? It turns out that this disposable, user-owned-and-deployed contract method is slightly cheaper than existing complex central hub contracts. Below, we compare Liquality and 0x’s gas economics in an ETH to ERC20 swap:
- Contract deployment: 84,494 gas (x2 = 168,988 gas)
- Claiming funds: 14,513 gas (x2 = 29,026 gas)
- Total = 99,007 gas (x2 = 198,014 gas)
^ We doubled these figures, as the two parties involved in an atomic swap both need to deploy and claim their funds
- 0x fill: 130,766 gas
- 0x transfer: 141,579 gas
- Total = 272,345 gas
However, note that it is difficult to directly compare fee economics between Liquality atomic swaps and other DEXes, as Liquality software:
- Is based on hash time locked contracts, not central hub contracts
- Can operate across other blockchains beyond Ethereum
- Requires that each swap consists of multiple transactions
By taking this disintermediation-first approach, we’ve eliminated many of the single points of failure that most decentralized exchange protocols face. In doing so, the security architecture of the system is removed from the center and pushed to the edges, where users are in control of their financial sovereignty; where censorship cannot happen; where a more open and equitable future can exist.
Swap without intermediation.
#DiFi, not #DeFi