Dex223 Development Report: Margin Trading Progress, Production-Ready Core, and the ERC-20 Security Push

This article is a development report for the Dex223 decentralized exchange.
We’re building an exchange to speed up the adoption of the ERC-223 token standard. ERC-223 was created to address a security problem in the older ERC-20 standard. The security issue in ERC-20 has caused over $100M in losses on Ethereum in 2023. Take a look at other Dex223 development reports.
Browse other Dex223 development reports here.
The implementation of the core platform is completed. The final version of the core contracts can be found here: https://github.com/EthereumCommonwealth/Dex223-contracts/tree/d99da952dfb472762e4c28f62a80202549e46ea8/contracts/dex-core
The core contracts include: Factory, Pools, Auto-Listing registry and Aut-listing contracts.
This version of the contracts is deployed on Ethereum mainnet, verified and is ready for production use:
| Name | Address |
|---|---|
| WETH9 | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
| TOKEN_CONVERTER | 0xe7E969012557f25bECddB717A3aa2f4789ba9f9a |
| POOL_LIBRARY | 0xfA5930D2Ef1b6231e220aeDda88E28C4E8F0F3a0 |
| FACTORY | 0x8dae173016f65F61e90631Ee5f28C9E47b1ebc06 |
| SWAP_ROUTER | 0xbeBAB9Ab58f8099fbFEb15E14b663615D19304Fa |
| POSITION_MANAGER | 0xFd4cE11db9db9433286734304049526E9336139E |
| POOL_INIT_CODE_HASH | 0xa5fa1f34aae4b83ab2690d3f3df6f78e99959a1f2eb8aa4c11ba10586677338d |
| POOL_USDC_WETH | 0x82Cc735b39a3992be7b47bEb9AE7519aC92ed562 |
| CORE_AUTOLISTING | 0x029f10E06Dc7d6264f9432ACA3F52572543c48e0 |
| FREE_AUTOLISTING | 0xa7089d8cbcc47543388a346dd6ebf0b05106a477 |
| AUTOLISTINGS_REGISTRY | 0x105F43A70aFCEd0493545D04C1d5687DF4b3f48f |
The UI of the core platform is also finalized at this point, we've added the last fixes, finalized tooltip texts and it must be fully operational.
We consider the platfrom to be technically complete and ready for production use (except the margin trading module).
The bulk of the development this month was done in the margin module domain. In June we had a working prototype of the module which was audited internally and tested.
The testing indicated no issues in the math of the margin module or its workflow but we detected a huge quantity of problems related to Oracles and potential vulnerabilities that could allow order owners to intentionally design their margin orders in such a way that would allow them to pull funds from the borrowers.
Oracles passed a huge number of update iterations (which can be tracked by commits history here and here and I'll not cover every potential problem that was fixed in this report). This is just the first "default" Oracle that governs prices for the Dex223 margin module. We are planning to have at least two different Oracles at the launch of this module: (1) "default" Oracle would pull prices from the actual liquidity reserves in Dex223 pools and (2) LINK Oracle would be an alternative version which uses prices provided by ChainLINK Oracles as the mark price for liquidations.
The "default" oracle we are currently working with has an intrinsic problem related to in-contract computations. Uniswap and Dex223 store "price" in a Q64.96 format.
For example 1:1 price in a USDT-USDC pool look like this 79237389755455049773827871756. In order to calculate the actual price we would need to divide this number by 2**96 and then the result needs to be squared. In EVM there are no fixed-point numbers so if the price in the pool is less than 2**96 then the result of all these computations will inevitably become zero. In order to bypass this computational limitation of EVM we are raising the price to the power of 2 first then dividing it by 2**192, however we hit another limitation of EVM such that if any of the results of this computations would overflow uint256 (which can potentially happen) - it would cause the Oracle to return an invalid price for a completely functional pair of tokens and a functional Pool with existing liquidity.
Another problem with this price and automated price reading is that the "price" is only valid for one token swap, if we have token1 and token2 then the "price" in the pool is the amount of token2 that we would receive for 1 token1. If we would need to swap token1 for token2 then the price needs to be actually reverted and we need to make sure that nothing will overflow or slash out extra digits once again thanks to EVM not being able to process the most basic math.
Therefore the decision was made to simplify the computations and simply slash the price to the first 6 digits within Oracle. This would guarantee the safety of auto-computations but in return it negatively impacts precision.
We are aware of a number of potential problems with the current implementation of the default Oracle:
Even though the margin module was completed quite some time ago it was highly unoptimized and when the contract-UI integration started we had to re-implement a lot of functions in a way that would allow making multiple actions in one transaction.
It would have taken 5 transactions just to set up an Order at first (create an order template, tell the Order which tokens are allowed for trading, tell the Order which tokens are allowed to be a collateral, deposit funds to the Order which can be borrowed, enable Order).
In the current implementation we managed to reduce the number of transactions where its possible to just approval + action, however when setting up the Order we couldn't separate the step where funds are being deposited to the Order from the initial Order setup.
Also, we've built the monitoring system that will pull data from the contracts (by tracking their state on-chain) and feed it onto UI. The Orders need to be tracked and displayed, positions also need to be tracked as well as their status and liquidation risks. This data needs to be displayed here: https://test-app.dex223.io/en/margin-trading
The backend part of the Orders/Positions state displaying is completed. The current prototype deployed on test-app is unreliable but positions will be properly tracked in the next update.
The margin module is especially hard-to-debug system as its workflow is not straightforward but requires a set of conditions to be met every time a particular scenario is being executed. Each Pool it interacts with must have a specific amount of liquidity, the Oracle must pull the price and respond correctly, transactions must be executed at a specific time because everything is time-sensitive in margin module since it calculates interest based on the timestamp of each last block.
In order to simplify the testing of the contract and allow UI developers to execute particular scenarios in a fixed environment a special contract that simulates a "trader" was introduced:
That contract does two things:
Anyone can interact with the "trader contract". The contract is deployed on Sepolia here: https://sepolia.etherscan.io/address/0xBca81278ff25E0BA088fcdFd3E2D798CDC3D2358
It can set up a new Oracle but this one is the most up-to-date one we have at the moment: https://sepolia.etherscan.io/address/0xc569D09E6de44679A2a7f1a31CC82eEB5feA0dC3
Functions called x0_MakeTokens(..), x1_MakePool10000(), x2_Liquidity() set up tokens.
Functions called step1_, step2_, step3_ etc. execute actions.
The default scenario involves:
Steps 7-8-9 from different scenarios conflict with each other.
For any early testers we strongly recommend using the Utility contract for setting up your tokens (with functions x0-x2) and making an Order (functions step1-step3). Anyone would be able to take loans from this Orders but in case we will need to investigate a reported problem - we will at least know that the amount of liquidity and Order settings were correct at the beginning.
Revenue contracts were built but we don't have a UI that would allow a smooth interaction with them yet. The implementation of the UI will begin once the margin module UI is ready.
The contract source codes are published here: https://gist.github.com/Dexaran/9601c5369000f20069bb0b54fe7c9357
This version is not properly tested.
Most of the UI updates were also related to the margin module implementation.
The latest Figma templates can be found here: https://www.figma.com/design/8ogeGWWFTcmjUBDWXLlIMU/%F0%9F%94%84-DEX223-Exchange---All-mockups---Current-version--Copy-?node-id=2460-62488&t=uPJgy4R8eJIXHMq7-1
Margin module has its own Figma: https://www.figma.com/design/dcgcSLN3cQKtq3umsEsK0C/Margin-module--Copy-?node-id=0-1&t=BJiFJOPtSyIULLHT-1
In 2021 OWASP introduced a new category of vulnerabilities that ERC-20 flaw perfectly fits in - insecure by design.
In 2017 when the ERC-20 flaw was discovered there was no such category and advocating for adding ERC-20 to any common vulnerabilities lists was difficult since the flaw was not actually an "exploitable vulnerability that could lead someone into hacking a contract and directly causing damage" but rather "a way for users to damage themselves when using this system in a common way".
With this new addition we gained a strong argument to advocate for ERC-20 flaw being classified as an actual vulnerability.
The success of the project depends on our ability to make the problem of ERC-20 standard known and recognized. Therefore we will focus on giving this one some exposure outside of crypto-related resources this time.
At the other hand the severity of ERC-20 problems was highlighted in the official Ethereum documentation as the moderators finally approved the pull request into one of the ethereum.org releases ethereum/ethereum-org-website#13218 (comment)
It took about a year of bureaucratic fight to make this happen but finally this is happening.
Once we will have a working prototype of the DEX we are planning to launch a campaign of warning existing projects that use ERC-20 standard (well, almost all projects in the Ethereum ecosystem that should be) about the problems associated with it and the possibility of using ERC-7417 Converter to mitigate them.
— Dexaran
Founder of Dex223