End
's purpose is to coordinate Shutdown. In short, Shutdown closes down the system and reimburses Dai holders. This process can occur during upgrades (Dai iterations), as well as for security reasons in the event that implementation flaws arise in both in the code and in the design.cage
- Locks the system and initiates shutdown. This is done by freezing the user-facing actions, canceling flap
and flop
auctions, locking the rest of the system's contracts, disabling certain governance actions that could interfere with the settlement process, and starting the cool-down period.cage(ilk)
- Tags the Ilk prices / Sets the final price for an ilk (tag
).skim
- Settles a Vault at the tagged price / Cancels owed Dai from the Vaultfree
- Remove (remaining) collateral from a settled Vault. This occurs only after there is no debt in the Vault.thaw
- Fixes the Dai supply after all Skims / Fixes the total outstanding supply of stablecoin.flow
- Calculates the fixed price for an ilk, possibly adjusting the cage
price with surplus/deficit.pack
- Locks Dai ahead of Cash / Puts some stablecoin into a bag
in preparation for cash
.cash
- Exchange pack
ed Dai for collateral / Exchange some Dai from bag
for a given gem
, share proportional to bag
size.file
- The Governance configuration—sets various parameter values.skip
- optionally cancel live auctions.wards(usr: address)
- Auth Mechanismvat
- Vat contractcat
- Cat contractvow
- Vow contractspot
- Spotter contractlive
- Cage flaglive
= 1, indicating the system is running normally. Thus, when cage()
is invoked, it sets the flag to 0. This includes the End
contract, which means that cage()
can only be invoked once and the subsequent functions cannot be invoked until we are "dead" and in the End processilk
- A collateral typewhen
- Time of cage / the time of settlement.wait
- Processing cooldown duration / the length of processing cooldown.debt
- Outstanding Dai after processing / outstanding stablecoin supply, after system surplus/deficit has been absorbed.tag
- Cage price / price per collateral type at time of settlement.gap
- Collateral shortfall / shortfall per collateral considering undercollateralised Vaults.Art
- Total debt per Ilk/outstanding stablecoin debt.fix
- Final cash price / the cash price for an ilk (amount per stablecoin).bag(usr: address)
- Dai packed for cash
/ nontransferable stablecoins ready to exchange for collateral.out
- Cash out / the amount of already exchanged stablecoin for a given address.skip
- Optionally cancel live auctions.wad
- Some quantity of tokens, usually as a fixed point integer with 10^18 decimal places.urn
- A specific Vault.tend
- To make a bid, increasing the bid size.bid
- The quantity being offered for the lot
.lot
- The quantity up for auction.dent
- To make a bid, decreasing the lot size.cage
is the most complex mechanism within the Maker Protocol. This is because the cage
must alter the behavior of almost every component of the system as well as perform under a variety of possible undercollateralization regimes. Listed below are a number of key properties, such as Dai and Vault parity, or the lack of race conditions, which are desirable (nice-to-have) properties of Shutdown, and are not, in fact, all satisfied by the real-world implementation of Shutdown.cage
.cage
will be the equity value of the Vault before cage
, as judged by the collateral price used by cage
, or zero, whichever is greater.cage
.cage
.cage
authority to supply any off-chain calculated values. For example, it can rely entirely on the last OSM price feed values.skim
first on the Vault to remove the debt and the backing collateral and then calling free
to release the remaining collateral from the Vault).flip
auction at any time by calling skip(ilk, auction-id)
after the ilk
has been cage
d (with cage(ilk)
). Flap and flop auctions are frozen by the initial cage()
. Both Flap and Flop auctions can be yank
ed to return the bids to the last bidder.skip
for flip auctions or call yank
directly for flap and flop auctions. If no one calls these functions, the auctions will not be canceled.End
's purpose is to coordinate the Shutdown of the system. This is an involved and stateful process that takes place over the nine following main steps.cage()
:ilk
). This is done by freezing the following user entry points:yank
on the respective auction contract. One reason these auctions get frozen and canceled is because the shutdown process was designed to pass along the system surplus or system debt to Dai holders. Additionally, there are no guarantees regarding the value of MKR during a shutdown, so mechanisms that rely on MKR's market value cannot be relied upon, which means there is no reason to keep running the auctions that impact MKR supply. More specifically, the reason for flop
and flap
auctions getting canceled is as follows:flap
auctions will no longer serve their purpose. This is because, after a shutdown, the surplus is designed to be allocated to Dai holders. Thus, canceling flap
auctions during shutdown allows the system to return the surplus Dai back to the Vow
’s balance and ultimately back to Dai holders.flop
auctions also stop serving their purpose. This is because the bad debt is passed as a haircut (lower-than-market-value placed on an asset being used as collateral in a Vault) back to Dai holders if there is no other system surplus available.flip
auctions, they are not immediately canceled (but can be canceled by any user) because they are still tied to the valuable collateral in the system. Collateral auctions continue to run and Keepers can continue to bid on them, and if not, the auctions can be skipped
.cage()
is called.cat.bite
cannot be called as the function requires live == 1
, disabling liquidations after shutdown. Additionally, after the End begins, all vaults must be skim
med and then free
d.skip()
(similar logic to flap
auctions). If an auction is skipped, the bids are returned to bidders and collateral is returned to the original Vault (with the liquidation penalty applied in the form of increased debt).flip
:yank
on the Flipper.yank
closes a tend
-phase (allows bids to be made, thereby increasing the bid
size) of the auction by returning the guy's Dai bid and moving the Gems from the Flipper to the End.dent
phase auctions (allows bids to be made, decreasing the lot
size) continue to the deal
phase as they have already raised the necessary Dai and are already in the process of returning Gems to the original Vault holder.End
contract. The last step in this process is to begin the cooldown period.cage(ilk)
:cage(ilk)
works by setting the cage
price for each ilk
. It does this by reading off of the price feed. This is required as we must first process the system state before it is possible to calculate the final Dai/collateral price. In particular, we need to determine two things:gap
, which is the collateral shortfall per collateral type by considering under-collateralized Vaults. (b) The debt
, which is the outstanding Dai supply after including the system surplus/deficit.skim
function described below. Next, you can see how (b) unfolds below.skim(ilk, urn)
skim(ilk)
function works to cancel all of the owed DAI from the Vault. Any excess collateral remains within the Vault(s) for the owner(s) to claim. Then, the backing collateral is taken.Flip
) model not allowing for any more Dai to be generated. This means that the Dai generation comes from tend
auctions. Thus, if everything is in dent
we know the generation is over. This occurs when all auctions are in the reverse (dent) phase. In addition to ensuring that the auctions will not generate any further Dai, the Dai Savings Rate (pot.drip
) must also be shut off during the End so that the total debt does not change.dent
- reverse auctions) no longer affect any more of the total debt, as the Dai was already recovered. Lastly, for the auctions in the first phase, they can be canceled and return the collateral and debt to the Vault.wait
; orskip
.wait
or skip
wait
sets the cooldown period. The time duration of wait
only needs to be long enough to be able to skim
all of the undercollateralized Vaults and skip
all tend
-phase auctions. This means that it can, in fact, be quite short (for example 5 minutes). However, due to the possibility of scenarios such as network congestion occurring, it may be set longer. skip
, it will cancel all ongoing auctions and seize the collateral. This allows for faster processing of the auctions at the expense of more processing calls. This option allows Dai holders to retrieve their collateral much faster. The skip(ilk, id)
will then proceed to cancel each of the individual flip auctions in the forward phase (tend
) and retrieve all of the collateral and return Dai to the bidder. After this occurs, the reverse phase (dent
) auctions can continue as they normally would, by performing either wait
or skip
.skip
being enabled on a per-auction basis. When a Vault has been processed and has no debt remaining, the remaining collateral can be removed.free(ilk)
:free(ilk)
method will then remove the collateral from the caller's Vault. After skim
has been called, free(ilk)
allows the owner to call as they need. It will remove all of the collateral remaining after step 3, basically, all of the collateral that was not backing the debt. If you did not have debt in your Vault at the time of the End
you do not need to do step 3 and can proceed directly to this step to free your collateral.thaw()
thaw
function. The assumption is that all under-collateralized Vaults are processed and all auctions have unwound. The purpose of thaw
is to fix the total outstanding supply of Dai. Note that it may also require extra Vault processing to cover the vow
surplus. The vat.dai(vow) == 0
requirement is what guarantees that the vow surplus has been taken into account, which means that before you can thaw
, you must skim
as many Vaults as needed in order to cancel any Dai surplus in the vow. Canceling Dai surplus is done by calling vow.heal
before thaw
.flow(ilk)
flow(ilk)
function will calculate the cash price for a given ilk (fix
) and adjusts the fix
in the case of deficit/surplus. At this point in the mechanism, we have computed the final price for each collateral type and Dai holders can now turn their Dai into collateral. Each unit of Dai can claim a fixed basket of collateral. Dai holders must first pack
some Dai into a bag
. Once packed, Dai cannot be unpacked and is not transferable. More Dai can be added to a bag later.pack(wad)
pack(wad)
will place Dai into a bag in preparation for cash
, which dispenses collateral to bag
holders. The bigger the bag
, the more collateral can be released.cash(ilk, wad)
cash(ilk, wad)
to exchange some of the Dai from your bag
for gems from a specific ilk. Note that the number of gems will be limited by how much packed Dai you have (how big your bag
is).End
process. Due to this fact, we depend on third parties to buy up post-cage Dai to use for reclaiming large portions of Dai. Overall, there will be large amounts of Dai leftover in the system.cash
cash
through each ilk in the system to completely cash out their Dai.cash(ilk, wad)
to redeem the proportional amount of the specified collateral that corresponds to the amount of Dai that was pack
’ ed, where the pack
function is used to aid with the redeeming of the different collaterals in different transactions. For example, let’s say you have 1000 Dai. You first pack
for the respective collateral types (ilks
), then for each cash
call, you will redeem what the 1000 Dai represents from the total Dai supply. In return, you will get the same proportion of that same collateral that was locked for all Dai holders. Therefore, the best approach a Dai holder can take is to cash
every collateral type (ilk
).ilks
are undercollateralized, Dai holders will end up taking a bit of a cut as a result. This is because other ilks
will not be used to "cover for" an underwater collateral type.thaw
function should ensure that Vow.heal()
is called within the same transaction.vat
to the vow
. This would prevent thaw
from being called and thus, End from progressing. To prevent this, we would call heal
to clear out that excess Dai and proceed with thaw
.wait
period. If you set an incorrect wait
/cooldown period (if this is set early on) then auctions are later extended and this is not reset.wait
allows thaw
to be called too early, all the Flip
auctions may not have completed and the system may have an incorrect accounting of total debt
.skip
ped and skim
applies to all Vaults (not just the undercollateralized ones).wait
value should not be too large, so governance should advise for this at least.End
will read the Collateral price from the pip
, this can result in the collateral price being only as accurate as the last recorded price. If pip
returns a bad price due to oracles getting hacked, the End
will be affected.End
reads the price off of the pip
(for reference, this occurs on line 261 of end.sol
).tag
before the price is called on Global Settlement.median
, it takes approximately 30 min for the OSM, and then the Global Settlement process takes over an hour to work. Therefore, by the time it triggers, you will have a bad price in the pip
and this will cause the system to fail.End
.End.wait
when set to maximum can result in it not being possible to call thaw
and therefore resulting in the Shutdown not being able to proceed.End.wait
, when set to the minimum, can result in thaw
being called before all auctions have finished, resulting in debt being calculated incorrectly and ultimately setting a wrong collateral price.End.cage
is called, all Dai holders are left holding an unstable asset in place of their desired stable asset. This could result in a market price crash across all collateral due to liquidations & sell-offs.End.vat
/ End.vow
/ End.cat
/ End.spot
- when set to attacker (address
: set to attacker-controlled address), can cause shutdown to fail. This is unfixable. For this scenario to occur, the malicious entity (governance or otherwise) would need to be auth
'ed on the End
.