The risk of secondary markets for depegged collateral tokens | Moonwell Bug Disclosure
On August 1st, 2022 the Nomad bridge for the Moonbeam chain was hacked and several bridged assets such USDC.mad, ETH.mad, and WBTC.mad lost their peg.
Lending markets on Moonbeam rely on Chainlink price feeds for their operation. However, Chainlink price oracles quote the underlying asset, and not the price of the bridged asset. For example: the oracle returns the price of ETH in the global market, and not the price of bridged ETH.mad, which was depegged, and traded at a significantly lower price.
In the absence of a valid price oracle for the depegged assets, Moonwell, one of the leading lending platforms on Moonbeam, continued to rely on Chainlink, but paused further deposits and borrows of all assets in their market to mitigate further accrual of bad debt (see Gauntlet report and recommendations here).
On August 14th, the Risk DAO team reached out to Moonwell contributors and outlined an additional attack vector that was not mitigated. The attack vector is launching a secondary market for defunct cTokens that allows users to cheaply buy cUSDC.mad collateral tokens, and consequently drain the platform from some of its non-pegged assets.
Following our report, Moonwell paused transfers of cTokens and awarded us with a $10,000 bug bounty report via the Immunefi bug bounty platform.
In the next section we give the background on how lending platforms work, what is a cToken, and the risk of bad debt. Then we explain the secondary market attack vector and how to mitigate it.
Background
Compound (v2) compatible lending market
In a lending market, collateral assets are deposited into a cToken smart contract (one cToken contract for every asset). The cToken contract implements an ERC20 functionality, and the user cToken balance increases whenever it provides additional supply.
Users can also borrow against their collaterals, and the permissionless nature of the system dictates that the value of user collateral must always be higher than the value of user debt.
This stems from the fact that the user identity is unknown, and the only incentive he has to ever repay his debt is to be able to withdraw his collateral in full. Hence, the system should never allow a user to withdraw his collateral if it results in having a borrow balance that is greater than his collateral balance.
A bad debt accrues whenever user debt exceeds his collateral (e.g., because the collateral depreciates in price and for some reason was never liquidated). Bad debt may prevent users from fully withdrawing their supplied collateral as the borrowed collateral will never be repaid.
The attack
At the time of the report, the Moonwell lending market consisted of defunct assets such as USDC.mad, and solid assets such as GLMR. In the absence of a better alternative, USDC.mad assets were still priced at $1, while their market value on local DEXes ranged between $0.1-$0.3 (albeit with low liquidity).
To explore the attack, let us consider a user, Alice, with a debt that is backed by GLMR collateral. By pausing deposits, Moonwell prevented Alice from buying defunct (and discounted) USDC.mad in the market and providing it as additional collateral, which would in turn allow Alice to withdraw her GLMR collateral, and pocket a net profit (as USDC.mad is traded below $1) on the expense of additional bad debt accrual in the system (as debt backed by USDC.mad might never be repaid).
However, if a user Bob had previously supplied USDC.mad as a collateral, and holds a cUSDC.mad collateral token. And further, if Bob never borrowed any asset, then he would benefit from selling his cUSDC.mad token to Alice with some premium over the USDC.mad market price. Alice would benefit from buying the cUSDC.mad as it will allow her to withdraw her GLMR collateral.
Hence, both Alice and Bob pocket a profit, on the expense of additional bad debt accrual in Moonwell.
Shortly after we disclosed the attack vector to Moonwell, the ability to transfer cTokens was paused. To the best of our knowledge, the attack was never exercised.
Conclusion
Compound (v2) is a popular lending market implementation, however it is not at all resilient to bad debt accrual and hacks.
When things go south (and in this case because of a bridge hack and not because of a bug in Moonwell) the behaviour becomes highly complex to analyse (also see our previous writeup about bugs in the Inverse Finance platform recovery plan).
Whenever deposits and borrows are paused, one should also check if it is required to pause the ability to transfer cTokens.