MinSwap is a decentralized AMM exchange running on Cardano. On January 21, 2021, the team announced that smart contracts will undergo a security audit by Tweag. Tweag is a software innovation lab specialized in Haskell development for fintech applications and platforms. The auditors found a total of 13 bugs, including 3 with severity Critical and two with severity High.
The MinSwap team released an article on Medium on February 21, 2022, stating that the audit is complete and all bugs have been addressed. Subsequently, the exchange was launched on the Cardano main-net on 9 March. In a relatively short time, Total Value Locked (TVL) reached almost $200M.
On March 19, the team announced that both smart contracts and the audit report are open-sourced available on GitHub. All interested parties could take a look at the source code of the smart contracts and the WingRiders team enters the scene.
The WingRiders team noticed a few bugs when examining smart contracts. Multiple bugs were critical. The WingRiders team tried to contact the MinSwap team on March 21 in the UTC evening and notified them of critical vulnerabilities that would allow someone to drain all the liquidity in the smart contracts.
The team responded to WingRiders’s notification in the morning. Even though the MinSwap team knew there was a critical vulnerability in the code, they left the exchange running for several hours. On March 22 in the evening, the team announced that the MinSwap exchange would go into maintenance mode. The published reason was that several issues were found that needed to be fixed. Users were not able to swap, withdraw and harvest their yield farming rewards. The team ensured users that funds are SAFU!
Let’s add that on March 22, Tweag was also informed of the vulnerability.
On March 24, the team informed users that the functionality of the MinSwap exchange had been migrated to an improved and more secure smart contract. No users lost funds, LP tokens, or positions. The team managed to restore the functionality of the MinSwap exchange.
A day later, on March 25, the team announced that it was notified about vulnerabilities that had been addressed and published an article explaining it. The MinSwap team admitted that one of the vulnerabilities was critical and it allowed to drain all the liquidity in the smart contract.
MinSwap was running on the main-net for less than one full month before the smart contract had to be modified. The vulnerability was really very critical and an experienced team was able to discover it quite quickly. User deposits were thus at significant risk of loss.
The MinSwap team thanked the WingRiders team for their help and for highlighting the vulnerabilities.
The Tweag team has also investigated the vulnerability and described it on their site. The auditors admitted that they had overlooked the bug, adding that this oversight is precisely the reason why machine learning and the formal verification process need to be incorporated into the audit.
MinSwap is an AMM exchange. To understand the vulnerability, one must understand how this kind of exchange works.
The AMM exchanges are non-custodial. It means that users remain in control of their assets by receiving LP tokens in return for providing tokens like ADA and others to the liquidity pools. The liquidity pools are managed by code and they are not controlled by humans. LP tokens represent the right to a share of the assets in a given liquidity pool. Holding LP tokens allow users complete control over when they can withdraw assets back from the pool. No middleman is required to do this. Users return LP tokens for which they get their deposit back. Users must be aware that they must pay fees and furthermore must take into account impermanent loss.
Note that whoever owns LP tokens, or gets control over them, can collect back the assets in the given amount. To protect assets, it must be ensured that no one can print LP tokens out of thin air. Furthermore, it must be ensured that LP tokens can only be used within the pool with the given assets. For example, LP tokens received by a user within pool A for providing assets X/Y cannot be used within pool B with assets M/N. This type of guarantee must be well implemented directly in the source code.
To create a new liquidity pool on the MinSwap exchange, a special Pool NFT is minted and locked inside the pool by the initial liquidity provider. Once an NFT Pool exists, LP tokens can be minted so users can provide liquidity to the pool. To mint LP tokens or accept them back to return assets locked in the liquidity pool, it is always necessary to operate with a given Pool NFT.
It is assumed that every single pool will always be represented by a unique Pool NFT. Even in the case where there would be more pools trading the same pair of assets. For this to be true, the source code must guarantee that there will always be only one Pool NFT for a given pair. These assumptions did not hold.
The root cause of the vulnerability was in the Pool NFT minting policy. An attacker could create Pool NFTs that matched with already existing pools. The first check in the critical part of the source code dedicated to the minting policy checked that a transaction minted exactly one Pool NFT corresponding to the UTxO reference. It was missing a check that no other Pool NFT token was minted for this policy, though. To put it simply, the attacker could duplicate what is supposed to be a unique token.
The attacker could keep ownership of Pool NFTs and put them in any script which was under his control. Using the maliciously minted and unlocked Pool NFT, the attacker could simply mint any number of LP tokens for any already existing liquidity pool. Having maliciously minted LP tokens, an attacker could siphon liquidity from all existing pools.
In other words, it was possible to extract assets from liquidity pools through fraudulently minted LP tokens. the attacker could thus rob assets that were inserted by liquidity providers and completely empty all existing pools essentially for free.
Luckily, the vulnerability was not exploited thanks to the professional approach of the WingRiders team. The team did exactly what is expected. They contacted the team and disclosed the vulnerability over a secure channel. The team described the vulnerability in detail in their blog.
There was no hack, users were saved, the community wins
It is important to say that neither MinSwap nor anyone else would be able to manipulate assets in pools if there was no bug in the code. The reality is that anyone who noticed the vulnerability could exploit it. As we described above, this is not possible to manipulate assets without owning LP tokens. The team has implemented safeguards in the smart contract. Subsequently, the team had to exploit vulnerabilities to siphon liquidity and migrate assets to new liquidity pools. This gave the team LP tokens that can be distributed to the original owners. The vulnerability has been patched and all funds are hopefully safe. It is worth noting that the patch did not pass a security audit.
Cardano is a platform that allows you to write smart contracts. If there’s a bug in it, it’s always the team’s fault. A programming language is a tool that allows you to write specific functionality. However, the language itself cannot influence whether the written piece of code will work as expected by the author.
For security reasons, it is extremely important that the source code is publicly available and ideally critical parts have undergone a third-party security audit. All projects that are to earn the trust of users must be open-source. This will allow experts in the field to find vulnerabilities, much like the WingRiders team did in this case. Users can be assured that there are no backdoors in the source code and that the service is indeed fully decentralized.
There is no source code without bugs. Bugs may be found during testing and security auditing, but even this activity cannot guarantee the absence of bugs. The only thing humanly possible is to follow good-practices standards and maximize bug-finding efforts. Still, even with passed audits and publicly available source code, there will never be 100% certainty that a given piece of code is flawless.
We certainly don’t want to denigrate anyone for making a mistake, but it turns out that there are some differences between the quality of teams working on decentralized applications. The WingRiders team spotted the bugs in the MinSwap code relatively quickly because they are working on their own solution. The team had to think about the design of the WingRiders exchange and did so more carefully. Recall that the source code of the WingRiders DEX also passed a source code audit by CERTIK, which found no bugs of any severity Critical or High.
In this case, everything turned out well. The winner is mainly the Cardano community. The WingRiders team are the heroes of the moment, as they have shown that they can help a competing project. In doing so, they essentially protected the users’ deposits. If only everyone in the blockchain industry had this spirit.
We do not know if the team has fixed all the vulnerabilities pointed out by the WingRides team and if MinSwap is now fully secure. Their blog post talks about fixing only one vulnerability.
If a hack occurs, transparency with users and efforts to save deposits are important. The team should have a plan B and know what to do when someone manages to steal user funds. It is smart to expect that hacks will occur. Cardano has been a smart contract platform for less than a year at the time of writing. At this stage, we are likely to see issues of a similar nature. Over time, as developers become more familiar with Cardano’s tools and environment, things will improve. Learning takes time and it is natural to make mistakes. Few people fully realize how difficult it is to write a well-functioning decentralized application.