Steal collateral during `end` process, by earning DSR interest after `flow`.
High
B
BlockDev Sp. Z o.o
Submitted None
Actions:
Reported by
lucash-dev
Vulnerability Details
Technical details and impact analysis
## Summary:
The `end` contract in MCD controls the process of shutting down
the MCD contracts and allowing for users to redeem their DAI for
collateral -- presumably to migrate to a new implementation of DAI.
The process, however, doesn't prevent the continued functioniong
of DAI savings accounts (`pot` contract), which allows for continued
minting of DAI after all other contracts have been "caged", resulting
in theft (possibly involuntary) of collateral.
## Detailed Description
The `end` contract is responsible for orchestrating the complex sequence
of steps for shutting down the MCD eco-system, settling all existing DAI
into collateral during the process.
The first step in the process is the method `cage`, which ensures that other
MCD contracts stop operating in the normal way, and enter a "not-live" mode.
In particular, the `vat` contract is updated to prevent the creation of new
CDP's, and also prevents the accrual of interest (`vat.fold`). This is obtained by
calling the `cage` method in the `vat` contract.
Puzzingly, however, the `end.cage` method doesn't affect the state of the `pot`
(savings account) contract, allowing for interests to be continuously earned
-- and new DAI to be minted --indefinitely during all the phases of the `end`
process. Most significantly, it allows a user to mint new DAI even after the
final DAI/collateral rate has been fixed (`end.flow`).
The consequence is that it's possible to inflate the DAI supply so that there
isn't enough collateral for all of it to be redeemed. In that case the last
users to try to redeem will have their collateral stolen by the faster ones, as
they might well be unable to redeem any DAI at all.
An example might help clarify the problem:
- Suppose there are two users, Ali and Bob, who each control 50% percent of the
DAI supply, lets say 10 DAI each.
- Now let's assume the `end` process is initiated and proceeds as usual --
eventually reaching the `flow` stage, with a fixed exchange rate of 1 DAI / ETH.
- Let's also assume that there is a DSR rate of 100% a month (unrealistic, but makes
the numbers easier).
- After the `end.flow` is called, Ali notices that the he can still use `pot` to earn
interests, so he deposits all his DAI in `pot`. Meanwhile Bob can't do the same
as his funds are locked inside a Dapp (let's say an Augur market).
- After one month, Ali calls `pot.exit` and gets back 20 DAI. That corresponds to
the total original supply of DAI before `end.flow` was called. So, Ali calls
`end.pack` and `end.cash` to convert his 20 DAI into 20 ETH -- all the collateral
in the MCD contracts.
- When Bob tries to redeem his DAI, there is no collateral left. His `end.cash`
calls fail and he ends up with no tokens -- DAI or ETH -- at all.
## Steps to Reproduce
I've attached to this report a version of `end.t.sol` that adds a test scenario
(`test_steal_collateral_using_dsr_after_thaw`) to reproduce this attack (in fact, the example above).
Please don't hesitate to contact me if you need more help reproducing it.
## Possible Remediation
The issue could be completely prevented by introducing a `cage` functionality into
the `pot` contract, and not allowing the `pot.drip` method to be called when
not in live mode.
Please note that the above solution is provided as proof that the reported issue
is fixable. I make no claim that the above is the best available solution.
## Impact
Please refer to the "Impact Analysis" field for more details.
## Final Note
Please don't hesitate to contact me if you need any further clarification around
this issue, or help reproducing and evaluating it.
## Impact
## Impact Analysis
As clearly demonstrated above, the reported bug can be used to steal collateral
from the `end` contract. Even more disturbingly, the bug can likely cause users
that own DSR deposits to unwittingly steal collateral in case of a shutdown.
Let's evaluate how much collateral can be stolen in this scenarios. The amount
stolen depends on three factors:
1 - DSR savings rate.
2 - Portion of DAI kept in DSR deposits.
3 - Time distribution of users calling `end.pack`.
It's impossible to know beforehand either. But we can make educated guesses
about a worst-case scenario.
It's possible that the DSR rate will be set at a high value at some point.
Considering that the previous incarnation of DAI saw a the CDP rate reach
25% at some point, it's definitely possible for DSR to reach a slightly lower
rate, say 20%. Furthermore, it's likely all users (including Dapps) will keep
their DAI holdings in DSR deposits, doing so has a possible upside, and minimal
gas costs.
As for the time-distribution of users redeeming their DAI, it's again entirely
possible that a large portion of the DAI supply will be used to interact with
Dapps rather than held speculatively. Augur V2, for example, has plans to use
DAI for making bets on prediction markets. Since these markets might take
quite a long time to be resolved -- up to several months -- it's unlikely
that a DAI shutdown would cause an immediate withdrawal of DAI by Augur users
-- if the reported vulnerability isn't known.
Other Dapps might well have similar characteristics, though it's again impossible
to know beforehand.
Given the above -- DSR rates up to 20% and most of DAI locked in DSR deposits
inside Dapps for months -- it's perfectly possible that the bug leads to
a loss of 10% or more of the collateral in the MCD contracts.
That scenario might happen even without an intentional attack.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Business Logic Errors