210 Matching Annotations
  1. Apr 2020
    1. Effect of emergency shutdown on various components of the maker protocol,

      Dai Adapter

      Exit is frozen and users cannot create new Dai ERC20 token balances.

      Collateral Adapters

      Join is frozen and users cannot bring collateral balances into the system even for existing collateral types.

      Cat

      Bite function is frozen and vaults cannot be liquidated.

      Flap

      All auction functionality is frozen.

      Yank function can be called by anyone to give bids not yet processed through deal their MKR back.

      Flop

      All functions: Kick, Tend, and Deal are frozen.

      Yank function can be called by anyone to give bids not yet processed through deal their Dai back.

      Flip

      Functions are not frozen and existing auctions can continue unless governance executes the restricted yank function to stop on-going auctions still in the first phase during the emergency shutdown cooldown period.

      Jug

      No functions are frozen.

      Pot

      File is frozen to freeze DSR at 0% which is set when emergency shutdown is triggered.

      Spot

      All functions are frozen. Cannot update prices and collateralization ratios for all collateral types.

      Vat

      Cannot change authorization permissions for other contracts.

      All debt ceilings are now frozen.

      All vault operations are frozen. Excess collateral from vault can be withdrawn using free function on End.

      Internal collateral and dai balances can be transferred between addresses.

      Locked collateral and debt can transferred between vaults.

      Vow

      No functions are frozen.

      Dai Token

      No functions are frozen.

  2. Mar 2020
    1. dsr = ONE;

      You will notice that all functions except file are not restricted after the system is caged. Although drip() can be executed any number of times, it won't accumulate any new savings for Dai depositors in Pot because dsr is set to ONE when Pot is caged.

  3. Feb 2020
    1. function drip() external note returns (uint tmp) {

      The LogNote event generated by the note modifier does not log the time at which drip is called as well as the new chi value. Chi value is not captured in logs elsewhere. Best bet right now is to ping an archive node the value of chi at a particular block number. Or use any of the external API services.

  4. Dec 2019
    1. Urn

      Vault. (New name for a CDP)

    2. It will be helpful to learn these words before reading the annotations on this page.

      • Vat - Name for this contract which stores the Dai and vault database.
      • rate - Used to record the stability fee accrued in vaults. It continuously increases every second by the value set in duty inside the Jug contract, but updated whenever drip is called.
      • Vow - contract which takes care of settling bad debt in the system after vault liquidations.
    3. Public Functions open for everyone to call,

      • flux - transfer collateral
      • move - transfer dai
      • frob - manipulate vault balances
      • fork - transfer balances between vaults
      • heal - cancel sin balance

      Restricted Functions that only authorized addresses/contracts can call,

      • init - collateral type initialization
      • file - setter methods
      • cage - emergency shutdown for vat
      • slip - deposit collateral in vat
      • grab - confiscate vault balances
      • suck - generate dai without opening a vault
      • fold - assess stability fees on all vaults of a collateral type
    4. ilk.rate = add(ilk.rate, rate);

      A positive value increases the rate of a collateral type to add debt to all its vaults simultaneously.

      Please note that the outstanding debt of a vault at all times is calculated by multiplying it's normalized debt value with the rate variable stored for it's collateral type.

    5. fold(bytes32 i, address u, int rate)

      fold increases rate of a collateral type i to proportionally increase the outstanding debt of all its vaults, typically to assess the stability fee. It also increases the dai balance of address u to add a surplus to the Vow contract.

      It can also decrease the debt of all vaults in collateral type i by debiting the dai balance of address u to reduce the debt of all vaults in a collateral type by decreasing the dai balance of Vow.

      The following addresses/contracts are currently authorized to call this restricted function.

      As compared to Single Collateral Dai, we can now,

      • Continually assess stability fee every block and not just collect when debt is repaid by the vault.
      • Remove the need for vault owners to pay this fee in MKR.
    6. suck(address u, address v, uint rad)

      Generates dai on address u and accounted as bad debt on address v without opening a vault.

      Governors of the system can call this restricted function through an executive vote to create dai and let Vow handle the resulting bad debt in the system.

      No addresses/contracts are currently authorized to call this restricted function.

    7. // both sides non-dusty require(either(utab >= i.dust, u.art == 0), "Vat/dust-src"); require(either(vtab >= i.dust, v.art == 0), "Vat/dust-dst");

      Checks to ensure both vaults respect the dust limit set for the collateral type.

    8. urn.ink = add(urn.ink, dink); urn.art = add(urn.art, dart); ilk.Art = add(ilk.Art, dart);

      Both locked collateral and debt of a vault can be decreased even with the add function because their inputs are signed numbers.

      Total amount of debt issued against a collateral type is also updated.

    9. grab(bytes32 i, address u, address v, address w, int dink, int dart)

      Can increase/decrease locked collateral and outstanding debt on a vault.

      Changes in debt on a vault u is balanced with an increase or decrease of sin balance on address w, typically Vow.

      Changes in the amount of locked collateral on a vault is balanced with an increase or decrease of collateral balance of address v

      Only sin balance on an address can be modified and dai balance of an address cannot be changed.

      The following addresses/contracts are currently authorized to call this restricted function.

    10. // both sides safe require(utab <= mul(u.ink, i.spot)); require(vtab <= mul(v.ink, i.spot));

      Checks to ensure both the vaults remain safe after the adjustments

    11. // both sides consent require(wish(src, msg.sender) && wish(dst, msg.sender));

      Both vaults need to authorize the msg.sender to perform this action even if it could be a safe action on one vault.

    12. u.ink = sub(u.ink, dink); u.art = sub(u.art, dart); v.ink = add(v.ink, dink); v.art = add(v.art, dart);

      Positive values of dink and dart would decrease locked collateral and outstanding debt amounts on the src vault and the increased by the same amounts in the dst vault.

    13. fork(bytes32 ilk, address src, address dst, int dink, int dart)

      Moves locked collateral and/or outstanding debt from one vault src to another vault dst by dink and dart amounts.

      This is a public function that can be called by an address that is authorized by both src and dst vaults.

    14. gem[i][v] = sub(gem[i][v], dink); dai[w] = add(dai[w], dtab);

      The amount of collateral to update in a vault is directly specified by the input dink.

      Changes in the vault are now balanced by adding or removing collateral balance from address v, and updating the balance of dai on address w as well as the total sum of debt issued by Vat.

    15. // urn has no debt, or a non-dusty amount require(either(urn.art == 0, tab >= ilk.dust));

      Dust limits are set to ensure there is a minimum amount of outstanding debt in a vault.

    16. // either debt has decreased, or debt ceilings are not exceeded require(either(dart <= 0, both(mul(ilk.Art, ilk.rate) <= ilk.line, debt <= Line)), "Vat/ceiling-exceeded"); // urn is either less risky than before, or it is safe require(either(both(dart <= 0, dink >= 0), tab <= mul(urn.ink, ilk.spot)), "Vat/not-safe"); // urn is either more safe, or the owner consents require(either(both(dart <= 0, dink >= 0), wish(u, msg.sender)), "Vat/not-allowed-u"); // collateral src consents require(either(dink <= 0, wish(v, msg.sender)), "Vat/not-allowed-v"); // debt dst consents require(either(dart >= 0, wish(w, msg.sender)), "Vat/not-allowed-w");

      The set of actions a user can perform on a vault using frob- adding collateral, paying down dai debt, drawing more dai debt, etc. can be classified as either safe or unsafe actions from the perspective of a vault.

      Frob allows any user is allowed to perform safe actions like paying down debt of a vault. Unsafe actions like removing locked collateral can only be performed by the owner or an authorized address of a vault.

      Cool is true when the action pays down outstanding debt of a vault. Firm is true when additional collateral is locked in the vault.

      Calm is true when the debt ceilings that limit the total amount of dai that can be issued for a collateral type and globally across the entire system are respected. The changes already made to the vault are also taken into account.

      Safe is true when the vault is safely over collateralized after the changes are made to dai balance and locked collateral balance. Spot takes into account both the price of token reported by the price feed oracles as well as the liquidation ratio set for the collateral type by MKR holders.

      Irrespective of the msg.sender, one of the following has to evaluate to true for the frob action to succeed:

      • cool && firm
      • calm && safe
      • cool && safe

      The owner of the vault or an authorized has to call frob if the action isn't both cool and firm. The caller has to be authorized if collateral balance of v is being debited. The caller has to be authorized to debit dai from address w to pay down outstanding debt of a vault.

      Safe actions on a vault are unsafe actions for the owners of addresses whose collateral and dai balances are being decreased, hence the negation on cool and firm.

    17. int dtab = mul(ilk.rate, dart); uint tab = mul(ilk.rate, urn.art); debt = add(debt, dtab);

      The total change in debt of a vault is determined by multiplying the input dart with the current rate of the collateral type i.

      If a user wants to increase their debt by 100 dai, they will have to pre-calculate this value by looking at the current rate to find the dart input to call frob with.

      Similarly, the total debt issued for the collateral type after the vault balances are updated is calculated by multiplying rate of the collateral type with the final value stored in urn,art

    18. urn.ink = add(urn.ink, dink); urn.art = add(urn.art, dart); ilk.Art = add(ilk.Art, dart);

      Locked collateral and debt of a vault can be decreased even with the add function because their inputs are signed numbers.

      Total amount of debt issued against a collateral type is also updated.

    19. frob(bytes32 i, address u, address v, address w, int dink, int dart)

      Manipulates the locked collateral and outstanding debt balance of a vault u with collateral balance from address v and dai balance of address w

      Positive dink and dart values add to the existing balances while negative value subtract from them.

      The function also expects normalized values as inputs, which are then multiplied by rate to arrive at the amount of dai to add or subtract from on the user's address.

    20. slip(bytes32 ilk, address usr, int256 wad)

      This is a restricted function that primarily allows collateral token adapters to update internal collateral balances of users when they add or remove collateral.

      wad is a signed number and lets this function both add or subtract internal collateral balances.

      The balances here are not locked within vaults and cannot be ceased during liquidations.

    21. live

      Set to 0 when the system is in Emergency Shutdown mode and stops users from making any changes to their existing vaults.

      For detailed sequence of events please refer to End.

    22. gem

      Collateral balance of a user within the vault database that is not locked within a vault. This balance cannot be ceased during a vault liquidation.

      A user needs to first get this balance to lock additional collateral within a vault.

    23. urns

      Mapping to store the collateral locked and outstanding dai debt of all vaults

    24. dust

      Dust limits that limit the minimum amount of outstanding debt that a vault of this collateral type needs to be open.

      This ensures vaults with tiny amounts of collateral are not present in the system as they won't be economical for Keepers to liquidate because the gas fees incurred would be higher than the profits gained from liquidation.

    25. spot

      Price reported by the medianizer scaled with the collateralization ratio required by a vault.

      Ex: Price: 200 USD, Collateralization ratio for the collateral type: 120%. Spot will have 166.66. Which means a maximum of 166.66 in debt is allowed by the system for every unit of collateral locked in a Vault.

    26. rate

      Accumulated interest used in the multiplication to calculate the total debt owed either by a vault or an entire collateral type.

      Please read the "Intro to Rate Mechanism" developer guide to learn more about how rates work in Maker smart contracts

      https://github.com/makerdao/developerguides

    27. Art

      Total dai debt of all vaults of a collateral type

    28. can

      Addresses authorized by a vault to perform actions on its behalf.

    29. ink

      Collateral locked in a vault.

    30. art

      Total debt of a vault is always calculated by multiplying art with ilk.rate.

    31. line

      Debt ceiling allocated for a collateral type.

      Ex: 3M dai. A maximum of 3M in dai can be generated by all vaults of a collateral type. Once this limit is reached new dai cannot be generated until governance raises it by updating this risk parameter.

    32. function hope(address usr) external note { can[msg.sender][usr] = 1; }

      The caller(msg.sender) can authorize an address usr to manipulate their collateral balances and locked collateral or outstanding debt in a Vault.

    1. contract Jug is LibNote {

      Please read the "Intro to Rate Mechanism" developer guide to understand how a contract can store user balances that increase every second based on a rate.

      https://github.com/makerdao/developerguides

    2. require(now >= ilks[ilk].rho, "Jug/invalid-now"); (, uint prev) = vat.ilks(ilk); rate = rmul(rpow(add(base, ilks[ilk].duty), now - ilks[ilk].rho, ONE), prev); vat.fold(ilk, vow, diff(rate, prev)); ilks[ilk].rho = now;

      drip(bytes32 ilk) performs stability fee collection for a specific collateral type when it is called (note that it is a public function and may be called by anyone). drip does essentially three things:

      1) calculates the change in the rate parameter for the collateral type specified by ilk based on the time elapsed since the last update and the current instantaneous rate (base + duty);

      2) calls Vat.fold to update the collateral's rate, total tracked debt, and Vow surplus;

      3) updates ilks[ilk].rho to be equal to the current timestamp.

      The change in the rate is calculated as:

      $$\Delta rate = (base+duty)^{now-rho} \cdot rate- rate$$

      where "now" represents the current time, "rate" is Vat.ilks[ilk].rate, "base" is Jug.base, "rho" is Jug.ilks[ilk].rho, and "duty" is Jug.ilks[ilk].duty. The function reverts if any subcalculation results in under- or overflow. Refer to the Vat documentation for more detail on fold.

    3. function drip(bytes32 ilk) external note returns (uint rate) {

      Collect stability fees for a given collateral type.

      If drip() is called very infrequently for some collateral types (due, for example, to low overall system usage or extremely stable collateral types that have essentially zero liquidation risk), then the system will fail to collect fees on CDPs opened and closed between drip() calls. As the system achieves scale, this becomes less of a concern, as both Keepers and MKR holders are have an incentive to regularly call drip (the former to trigger liquidation auctions, the latter to ensure that surplus is accumulated to drive MKR valuation); however, a hypothetical asset with very low volatility yet high risk premium might still see infrequent drip calls at scale (there is not at present a real-world example of this—the most realistic possibility is base being large, elevating rates for all collateral types).

    1. contract Pot is LibNote {

      Please read the "Intro to Rate Mechanism" developer guide to understand how a contract can store user balances that increase every second based on a rate.

      https://github.com/makerdao/developerguides

    2. tmp = rmul(rpow(dsr, now - rho, ONE), chi);

      tmp is a ray

      Remember,

      • rmul(wad, ray) -> wad
      • rmul(ray, ray) -> ray
      • rmul(rad, ray) -> rad
    1. function rmul(uint x, uint y) internal pure returns (uint z) { z = mul(x, y) / RAY; }

      Note,

      • rmul(wad, ray) -> wad
      • rmul(ray, ray) -> ray
      • rmul(rad, ray) -> rad
    2. function flow(bytes32 ilk) external note { require(debt != 0, "End/debt-zero"); require(fix[ilk] == 0, "End/fix-ilk-already-defined"); (, uint rate,,,) = vat.ilks(ilk); uint256 wad = rmul(rmul(Art[ilk], rate), tag[ilk]); fix[ilk] = rdiv(mul(sub(wad, gap[ilk]), RAY), debt); }
      • Important notes
        • fix[ilk] is the exchange ratio between collateral and Dai. This is where the haircut could be applied to dai holders. The gap[ilk] is the aggregation of insolvency across all under water CDPs
    3. function thaw() external note { require(live == 0, "End/still-live"); require(debt == 0, "End/debt-not-zero"); require(vat.dai(address(vow)) == 0, "End/surplus-not-zero"); require(now >= add(when, wait), "End/wait-not-finished"); debt = vat.debt(); }
      • Important notes
        • Before this wait time (assuming auctions skipped) Flip auctions in tend phase may still be processing; remember tend phase affects the amount of debt owned by DCS
        • Assumes that all under-collateralized CDPs are processed
    4. function skim(bytes32 ilk, address urn) external note { require(tag[ilk] != 0, "End/tag-ilk-not-defined"); (, uint rate,,,) = vat.ilks(ilk); (uint ink, uint art) = vat.urns(ilk, urn); uint owe = rmul(rmul(art, rate), tag[ilk]); uint wad = min(ink, owe); gap[ilk] = add(gap[ilk], sub(owe, wad)); require(wad <= 2**255 && art <= 2**255, "End/overflow"); vat.grab(ilk, urn, address(this), address(vow), -int(wad), -int(art)); }
      • Important notes to consider
        • Vow is empty → dai holders
        • Surplus in the vow → then it will eventually be canceled (or "burned") with the incoming sin. And since the every collateral's art (and thus DCS debt) is unaltered, then this dai burning is distributing the surplus to dai holders in the form of greater share of the pie
          • e.g. 10 MM Dai claims 1 MM eth. If 1 MM Dai is in the form of surplus and is subsequently burned, then each Dai now has a great claim on eth when only 9 MM Dai is remaining)
        • Bad debt in the vow → increases the ending balance of Sin within the Vow. This bad debt would otherwise be covered by MKR holders, but now, it is actually covered by Dai holders
        • Undercollateralized CDPs → more sin is accrued in the vow than ink accrued in the End
          • These are present when CDPs have not yet been bitten when ES is initiated. They are unfortunately not penalized if they're not bitten.
        • Overcollateralized CDPs → exact amount of sin is accrued in the vow as ink value in End
    5. function skip(bytes32 ilk, uint256 id) external note { require(tag[ilk] != 0, "End/tag-ilk-not-defined"); (address flipV,,) = cat.ilks(ilk); Flippy flip = Flippy(flipV); (, uint rate,,,) = vat.ilks(ilk); (uint bid, uint lot,,,, address usr,, uint tab) = flip.bids(id); vat.suck(address(vow), address(vow), tab); vat.suck(address(vow), address(this), bid); vat.hope(address(flip)); flip.yank(id); uint art = tab / rate; Art[ilk] = add(Art[ilk], art); require(int(lot) >= 0 && int(art) >= 0, "End/overflow"); vat.grab(ilk, usr, address(this), address(vow), int(lot), int(art)); }
      • Important notes
        • First vow.suck used to accrue (TODO - still not entirely sure, but I think it has something to do with refunding the last bidder with their Dai bid)
        • Second vow.suck accrues the amount of dai in End from the last bid to be returned to the bid.usr(which is the bitten urn) in the form of art
        • The final vat.grab returns dai and collateral from End to bid.usr. This same process decreases the amount of sin that was accrued in the second vow. Now the CDP is an over/undercollateralized and can be skim'ed
        • Skip doesn't have a material impact on the auction or vow accounting. For more gas, it simply stops the tend auctions, returns the dai bid to the last bidder and transfers the collateral from the flip auction to End and finally back to the bid.usr. In other words, it pulls a CDP back into a state that can be skim'ed
    1. id = Kicker(ilks[ilk].flip).kick({ urn: urn , gal: address(vow) , tab: rmul(tab, ilks[ilk].chop) , lot: lot , bid: 0 });

      Calls kick on the collateral's Flipper contract.

      Debt tab is multiplied by the collateral's liquidation penalty to get the total tab for the auction,

      • gal: address(vow) sets up the Vow as the recipient of the Dai income for this auction
      • rmul is used as ilks[ilk].chop is a ray and mul(art,rate) is a rad. tab then becomes a rad too.
      • bid: 0 indicates that this is the opening bid

      This moves the collateral from the Cat's gem to the Flipper's gem in the Vat.

      Note on rmul,

      • rmul(wad, ray) -> wad
      • rmul(ray, ray) -> ray
      • rmul(rad, ray) -> rad
    2. require(spot > 0 && mul(ink, spot) < mul(art, rate), "Cat/not-unsafe");

      Require the CDP to be unsafe (see definition above).

    3. art = min(art, mul(lot, art) / ink);

      Sets the amount of debt to be covered by the auction. Smaller of either the outstanding debt in the CDP or the proportion of debt that is represented by the collateral being auctioned as calculated by,

      Amount of Collateral for Auction * Total Normalized Debt) / Total Locked Collateral

      For instance if an unsafe CDP has 3 locked collateral units and 200 units of normalized debt:

      Assuming lot=1, art = (1 * 200) / 3 = 66.6666667

    1. require(live == 1, "DaiJoin/not-live");

      After emergency shutdown, new ERC20 Dai cannot be minted.

    1. require(bids[id].guy != address(0), "Flipper/guy-not-set"); require(bids[id].bid < bids[id].tab, "Flipper/already-dent-phase"); vat.flux(ilk, address(this), msg.sender, bids[id].lot); vat.move(msg.sender, bids[id].guy, bids[id].bid); delete bids[id];

      In the case of Global Settlement, the End is able to call yank on the Flipper. Yank closes a tend-phase auction by returning the guy's Dai bid and moving the Gems from the Flipper to the End. dent-phase auctions can continue to the deal phase as they have already raised the necessary Dai and are in the process of returning Gems to the original CDP holder.

    2. require(bids[id].guy != address(0), "Flipper/guy-not-set"); require(bids[id].tic > now || bids[id].tic == 0, "Flipper/already-finished-tic"); require(bids[id].end > now, "Flipper/already-finished-end"); require(bid == bids[id].bid, "Flipper/not-matching-bid"); require(bid == bids[id].tab, "Flipper/tend-not-finished"); require(lot < bids[id].lot, "Flipper/lot-not-lower"); require(mul(beg, lot) <= mul(bids[id].lot, ONE), "Flipper/insufficient-decrease"); vat.move(msg.sender, bids[id].guy, bid); vat.flux(ilk, address(this), bids[id].usr, bids[id].lot - lot); bids[id].guy = msg.sender; bids[id].lot = lot; bids[id].tic = add(uint48(now), ttl);

      Note: This phase must start before tic expires and before bid.end is passed.

      1 Bidder 2 (and all the other bidders within the auction) decide it is no longer worth it to continue to increase their bids, so they stop bidding. Once the Bid.tic expires, Bidder 1 calls deal and new MKR tokens are minted to their address (MKR token contract.balances(Bidder1) = MKR.balances(Bidder1) + lot).

      Note: An auction can also end in the tend phase by not reaching tab before the tic or end are reached. If this happens, then the winning bidder is awarded using the deal function and the difference between the final bid and the tab stays as bad debt in the Vow to be dealt with during a Flop auction.

    3. require(bids[id].guy != address(0), "Flipper/guy-not-set"); require(bids[id].tic > now || bids[id].tic == 0, "Flipper/already-finished-tic"); require(bids[id].end > now, "Flipper/already-finished-end"); require(lot == bids[id].lot, "Flipper/lot-not-matching"); require(bid <= bids[id].tab, "Flipper/higher-than-tab"); require(bid > bids[id].bid, "Flipper/bid-not-higher"); require(mul(bid, ONE) >= mul(beg, bids[id].bid) || bid == bids[id].tab, "Flipper/insufficient-increase"); vat.move(msg.sender, bids[id].guy, bids[id].bid); vat.move(msg.sender, bids[id].gal, bid - bids[id].bid); bids[id].guy = msg.sender; bids[id].bid = bid; bids[id].tic = add(uint48(now), ttl);

      1 Bidder 1 makes a bid that increases the bid size by beg. Bidder 1's DAI balance in the Vat is decreased by bid and the Vow's DAI balance in the Vat is increased by bid.

      2 Bidder 2 makes a bid that increases Bidder 1's bid by at least beg. Bidder 2's DAI balance in the Vat is decreased by bid and Bidder 1's DAI balance in the Vat is increased by bid (thereby refunding Bidder 1 for their now-losing bid). Bidder 2's DAI balance in the Vat is decreased by bid - Bidder 1's bid and the Vow's DAI balance is increased by the same number. tic is reset to now + ttl

      3 Bidder 1 makes a bid that increases Bidder 2's bid by at least beg. Bidder 1's DAI = Vat.dai[bidder1] - Bidder 2's previous bid; Bidder 2's DAI = Vat.dai[bidder2] + Bidder 2's previous bid. Then Bidder 1's DAI = Vat.dai[bidder1] - (bid - Bidder 2's bid) and Vow's DAI = Vat.dai[bidder1] + (bid - Bidder 2's bid). tic is reset to now + ttl

      4 Once a new bid comes in that is equal to the tab the tend phase is complete.

  5. Oct 2019
    1. Design Characteristics

      • Dai no-race condition: every dai holder will be able to redeem the same quantity of collateral, regardless of when they interact with the contract.
      • CDP Parity: CDP Owners are prioritized and are allowed to redeem their excess collateral before Dai hodlers.
        • At the time of Emergency Shutdown (ES), individual CDPs, entire collateral types, or the Maker protocol can be undercollateralized, which is when the value of debt exceeds the value of collateral; in other words, "negative equity"
        • Maker's current implmenentation favors CDPs owners in all underwater cases by allowing them to free their entire amount of excess collateral. As a result, Dai holders recieve a "haircut" to their claim on collateral.
      • Immediate CDP redemption: After ES is initiated, CDP owners are allowed to free their collateral immediately, provided that they execute all contract calls atomically.
      • No off-chain calculations: The system does not require the cage authority to supply any off-chain calculated values (e.g. it can rely entirely on the last OSM feed prices).
      • Buffer Assistance: After ES is initiated, surplus (and bad debt) in the buffer acts as a reward (and penalty) distributed pro-rata to all Dai Holders. e.g. if 10% of total system debt is in the form of net surplus in the Vow, then Dai holders recieve 10% more collateral.

      Fun Fact → Single Collateral Dai (Sai)'s only difference is it's priority to Dai holders (Dai Parity)

    2. User Stories


      I'd like to know how each agent type interacts with End after Emergency shutdown has been initiated. Each step assumes that it has not been called already.

      Most holders will sell Dai on secondary markets

      Dai redemption will likely be completed by Redemption (or Super) Keepers that are better equipped to:

      • Find liquidity for all collateral types
      • Handle permissioned collateral that require KYC, such as tokenized securities

      Preface:

      • All stories start with Step #0 cage(), which is called by:

        • Emergency shutdown oracles
        • Emergency shutdown module (ESM)
      • Each step assumes that it has not been called already

      • Undercollateralized CDPs = debt > collateral or urn.art * ilk.rate > urn.ink*ilk.spot

      CDP Owners of single ilk type

      I own a CDP and wish to free my excess collateral from the DCS

      Overcollateralized CDPs

      1. Value the collateral in their CDP → cage(ilk)
      2. Settle their outstanding debt with their locked collateral -> skim(ilk, urn)
      3. Unlock excess collateral in CDP → free(ilk)

      Overcollateralized CDPs that were bitten and are in the tend phase

      1. Value the collateral in their CDP → cage(ilk)
      2. Either wait until their tend auction phase OR speed up collateral processing → skip(ilk, id)
      3. Settle their outstanding debt with their locked collateral → skim(ilk, urn)
      4. Unlock excess collateral in CDP → free(ilk)

      Undercollateralized CDPs → not incentivized to do anything

      Dai holders

      I want to convert my Dai into its claim on the underlying collateral basket

      1. Transition system into the Dai withdrawl phase → thaw()
      2. Set the Dai-to-collateral exchange rate (fix[ilk]) for each collateral type → flow(ilk)
      3. Send all their Dai to the DCS → pack(wad)
      4. Retrieve a portion of each collateral type → cash(ilk, wad)

      DCS Stakeholders

      Scope: larger Dai holders/custodians, MKR goveners, Redemption keepers, etc

      I want to ensure that emergency shutdow is completed and accounts for all CDPs

      Note that their story may overlap with the above stories

      1. Value the collateral in all CDP types → cage(ilk) multiple times
      2. Either wait until their tend auction phase OR speed up collateral processing → skip(ilk, id) for multiple flip auctions over all collateral types
      3. Settle all over/under collateralized CDPs → skim(ilk, urn) multiple times
      4. Transition system into the Dai withdrawl phase → thaw()
      5. Set the Dai-to-collateral exchange rate (fix[ilk]) for each collateral type → flow(ilk) multiple times
    3. out[ilk][msg.sender] = add(out[ilk][msg.sender], wad);

      Out balance for the bag holder for a given ilk is recorded.

    4. vat.flux(ilk, address(this), msg.sender, rmul(wad, fix[ilk]));

      Gem collateral moved from End to the bag holder in proportion to their bag size and the fix ratio.

    5. function cash(bytes32 ilk, uint wad) external note {

      Exchange packed DAI for collateral/exchange some stablecoin from bag for a given gem, share proportional to bag size.

      Called after a bag has been packed by Dai holders

    6. vat.move(msg.sender, address(vow), mul(wad, RAY)); bag[msg.sender] = add(bag[msg.sender], wad);

      dai is moved from the dai holder to the vow.

      An equal amount of credited to them in their bag.

    7. function pack(uint256 wad) external note {

      At this point we have computed the final price for each collateral type and dai holders can now turn their dai into collateral. Each unit 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 transferrable. More dai can be added to a bag later.

    8. function flow(bytes32 ilk) external note {

      After vat.debt() has been fixed, the exchange ratio can be calculated (fix([ilk])

    9. function thaw() external note {

      After wait period, vat.debt( ) can become fixed.

      Called after wait has elapsed and skim(ilk, urn) has been called to cancel Vow surplus

    10. function free(bytes32 ilk) external note {

      Called when a CDP owner wanted to free their excess collateral after skim(ilk, urn)

    11. vat.grab(ilk, bid.usr, address(this), address(vow), int(lot), int(art));

      Finally, the collateral and debt is moved away from End and to the CDP owner, and sin is decreased in the Vow.

    12. flip.yank(id);

      Collateral is yanked from the flip auction in the tend phase

      • lot size of flip auction is moved from Flipper to End
      • Last dai bid is refunded to the last auction bidder
    13. vat.suck(address(vow), address(this), bid.bid);

      sin and dai of flip auction last bid size added to the Vow and End, respectively

    14. vat.suck(address(vow), address(vow), bid.tab);

      sin and dai of flip auction debt size added to the Vow

    15. function skip(bytes32 ilk, uint256 id) external note {

      Skip will cancel all ongoing auctions and seizes the collateral.

      This allows for faster processing at the expense of more processing calls. This option allows dai holders to retrieve their collateral faster.

    16. uint256 public wait; // processing cooldown length

      Processing cooldown duration / the length of processing cooldown (allowing under collateralized CDPs to be skimmed).

      Set the cooldown period to be at least as long as the longest auction duration, which needs to be determined by the cage administrator. This takes a fairly predictable time to occur but with altered auction dynamics due to the now varying price of dai.

    17. vat.grab(ilk, urn, address(this), address(vow), -int(wad), -int(u.art));

      Finally, the collateral and debt is moved to the End address, and the sin is increased in the vow

    18. gap[ilk] = add(gap[ilk], sub(owe, wad));

      Determines the gap after settling a CDP. Gap is the difference of debt and collateral and is present if debt > collateral in USD.

      If u.ink (collateral) is less than what they owe, then that difference is recorded at sub(owe,wad) and considered a gap and is added to global gap variable. Only happens for undercollateralized CDPs

    19. uint wad = min(u.ink, owe);

      wad is the smaller amount of collateral in CDP and what they owe. If they have more collateral that what they owe, than owe is assigned to wad, but if they have less collateral that what they own, that u.ink is assigned to wad.

    20. uint owe = rmul(rmul(u.art, i.rate), tag[ilk]);

      owe is the amount of debt in CDP (urn) in units of collateral (ink)

    21. tag[ilk] = wdiv(spot.par(), uint(spot.ilks(ilk).pip.read()));

      Determine the cage price, which is tag[ilk] = ilk/usd in math notation ($200 for ETH/USD would lead to a tag[eth] of 1/200).

    22. function cage(bytes32 ilk) external note {

      Called to set the cage price for each collateral type only once and after cage() is called.

    23. pot.cage();

      Sets live = 0, and dsr = ONE ray (effectively resets the dsr so that it can't be called again during emergency shutdown).

    24. vow.cage();
      • Sets live = 0
      • Sets Sin (total queued debt) and Ash (on-auction debt) = 0
      • Flapper.cage(...) → sets live = 0 and moves Dai from Flapper to Vow
      • Flopper.cage() → sets live = 0. Auctioned stopped after the last bid
      • Vow.heal(min of vow's Dai and Sin)
    25. cat.cage();

      Sets live = 0, no more CDPs can be bitten.

    26. vat.cage();

      Sets live = 0, frob (CDP adjustment) and fold(rate accumulation) is disabled.

    27. function cage() external note auth {

      Called in times of upgrade, extreme market volatility, and uncovered vulnerabilities.

      This is done by freezing the user-facing actions, canceling flip and flop auctions, locks the rest of system's contracts, and starts the cool-down period.

    28. function skim(bytes32 ilk, address urn) external note {

      The skim(ilk) function works to cancel all of the CDP debt. Any excess collateral remains within the CDP(s) for the owner(s) to claim. Then, the backing collateral is taken.

    29. Public Functions open for everyone to call,

      • cage(ilk)
      • skip
      • skim
      • free
      • thaw
      • flow
      • pack
      • cash

      Restricted Functions that only authorized addresses/contracts can call,

      • cage
      • file

      End is authorized to call the following contracts, *

    30. mapping (bytes32 => mapping (address => uint256)) public out; // [wad]

      Cash out / the amount of already exchanged stablecoin for a given address.

    31. mapping (address => uint256) public bag; // [wad]

      Dai packed for cash / untransferrable stablecoins ready to exchange for collateral.

    32. mapping (bytes32 => uint256) public fix; // final cash price [ray]

      Final cash price / the cash price for an ilk (amount per stablecoin).

    33. mapping (bytes32 => uint256) public Art; // total debt per ilk [wad]

      Total debt per Ilk/outstanding stablecoin debt.

    34. mapping (bytes32 => uint256) public gap; // collateral shortfall [wad]

      Collateral shortfall / shortfall per collateral considering undercollateralised CDPs.

    35. mapping (bytes32 => uint256) public tag; // cage price [ray]

      Cage price / price per collateral type at time of settlement.

    36. uint256 public debt; // total outstanding dai following processing [rad]

      Outstanding DAI after processing / outstanding stablecoin supply, after system surplus/deficit has been absorbed.

    37. live = 0;

      This occurs when live = 1 in all of the “live" contracts. 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 process

    38. It will be helpful to learn these words before reading the annotations on this page. *

    1. Public Functions open for everyone to call,

      • Restricted Functions that only authorized addresses/contracts can call,

      • drip

      Jug is authorized to call the following contracts,

      • file
      • init
    2. function rpow(uint x, uint n, uint b) internal pure returns (uint z) {

      rpow(uint x, uint n, uint b), used for exponentiation in drip, is a fixed-point arithmetic function that raises x to the power n. It is implemented in assembly as a repeated squaring algorithm. x and the returned value are to be interpreted as fixed-point integers with scaling factor b. For example, if b == 100, this specifies two decimal digits of precision and the normal decimal value 2.1 would be represented as 210; rpow(210, 2, 100) should return 441 (the two-decimal digit fixed-point representation of 2.1^2 = 4.41). In the current implementation, 10^27 is passed for b, making x and the rpow result both of type ray in standard MCD fixed-point terminology. rpow's formal invariants include "no overflow" as well as constraints on gas usage.

    3. struct Ilk { uint256 duty; uint256 rho; }

      Ilk : contains two uint256 values—duty, the collateral-specific risk premium, and rho, the timestamp of the last fee update

    4. contract Jug is DSNote {

      The primary function of the Jug smart contract is to accumulate stability fees for a particular collateral type whenever its drip() method is called. This effectively updates the accumulated debt for all CDPs of that collateral type as well as the total accumulated debt as tracked by the Vat (global) and the amount of Dai surplus (represented as the amount of Dai owned by the Vow).

    5. It will be helpful to learn these words before reading the annotations on this page. *

    1. Public Functions open for everyone to call,

      • tick
      • dent
      • deal
      • yank

      Restricted Functions that only authorized addresses/contracts can call,

      • file
      • kick
      • cage

      Flop is authorized to call the following contracts, *

    2. function dent(uint id, uint lot, uint bid) external note {

      Bidder 1 makes a bid that decreases the lot size by beg from the initial amount. Bidder 1's DAI balance in the Vat is decreased by bid and the Vow's DAI balance in the Vat is increased by bid.

      Bidder 2 makes a bid that decreases Bidder 1's lot by beg. Bidder 2's DAI balance in the Vat is decreased by bid and Bidder 1's DAI balance in the Vat is increased by bid (thereby refunding Bidder 1 for their now-losing bid).

    3. function deal(uint id) external note {

      Once the Bid.tic expires, Bidder 1 calls deal and new MKR tokens are minted to their address (MKR token contract.balances(Bidder1) = MKR.balances(Bidder1) + lot).

    4. uint256 public beg = 1.05E18; // 5% minimum bid increase

      During an auction, lot amounts will decrease by a percentage with each new dent decreasing the lot by the beg for the same bid of Dai. For example, the beg could be set to 5%, meaning if the current bidder has a lot of 10 (MKR) for a bid of 100 (Dai), then the next bid must pass at most a lot of 9.5 (MKR) for a bid of 100 (Dai).

    5. function tick(uint id) external note {

      If the auction expires without receiving any bids, anyone can restart the auction by calling tick(uint auction_id). This will do two things:

      1. It resets bids[id].end to now + tau
      2. It resets bids[id].lot to bids[id].lot * pad / ONE
    6. contract Flopper is DSNote {

      Debt Auctions are used to recapitalize the system by auctioning off MKR for a fixed amount of Dai. In this process, bidders compete with their willingness to accept decreasing amounts of MKR for the Dai they will end up paying.

      The Flop Auction process begins with Maker Governance voters determining the system debt limit (Vow.sump). Debt Auctions are then triggered when the system has Dai debt that has passed that specified debt limit.

      In order to determine whether the system has net debt, the surplus, accrued stability fees, and debt must be reconciled. Any user can do this by sending the heal transaction to the system contract named Vow.sol. Provided there is sufficient debt (i.e. debt after healing > Vow.sump), any user can send a Vow.flop transaction to trigger a debt auction.

      The Flop is a reverse auction, where keepers bid on how little MKR they are willing to accept for the fixed Dai amount (lot) they have to pay at auction settlement. The bidders will basically compete with decreasing lot amounts of MKR for a fixed bid amount of Dai. Once kicked, the bid is set to the flop auction bid size (Vow.sump) and lot is set to a sufficiently large number (Vow.dump). The auction will end when the latest bid duration (ttl) has passed OR when the auction duration (tau) has been reached. The payback process begins when the first bid is placed. The first bid will pay back the system debt and each subsequent bid will pay back the previous (no longer winning) bidder. When the auction is over, the process ends by simply cleaning up the bid and minting the MKR for the winning bidder.

    7. uint48 end;

      When the auction will finish / max auction duration

    8. uint256 lot;

      Quantity up for auction / gems for sale (MKR)

    9. uint256 bid;

      Bid amount inDAI / DAI paid

    10. It will be helpful to learn these words before reading the annotations on this page. *

    1. uint256 chop; // Liquidation Penalty [ray]

      Auction Grinding

      Auction grinding allows an attacker to generate debt, allow their CDP to be bitten, win their own auction to get their collateral back at a discount. This type of failure is most possible when the liquidation penalty is set too low.

      For full details about this risk, see @livnev's Paper: https://github.com/livnev/auction-grinding/blob/master/grinding.pdf

    2. struct Ilk { address flip; // Liquidator uint256 chop; // Liquidation Penalty [ray] uint256 lump; // Liquidation Quantity [wad] }

      Ilk is the struct with,

      • address of the collateral auction contract (flip)
      • penalty for that collateral to be liquidated (chop)
      • maximum size of collateral that can be auctioned at once (lump).
    3. It will be helpful to learn these words before reading the annotations on this page.

      • Vow - Dai Settlement Module
    4. Public Functions open for everyone to call,

      • bite

      Restricted Functions that only authorized addresses/contracts can call,

      • file

      Cat is authorized to call the following contracts,

      • Flip
    5. function cage() external note auth {

      Called during Emergency Shutdown.

    6. emit Bite(ilk, urn, lot, art, tab, ilks[ilk].flip, id);

      Emits an event about the bite to notify actors (for instance keepers) about the new auction.

    7. vow.fess(tab);

      Adds the tab to the debt-queue in Vow (Vow.Sin and Vow.sin[now])

    8. vat.grab(ilk, urn, address(this), address(vow), -int(lot), -int(art));

      Called in this way, vat.grab will:

      • Remove the lot and the art from the bitten CDP (urn)
      • Adds the collateral (lot) to the Cat's gem
      • Adds the debt (art) to the Vow's debt (vat.sin[vow])
      • Increases the total unbacked dai (vice) in the system
    9. require(lot <= 2**255 && art <= 2**255);

      Protects against int overflow when converting from uint to int

    10. uint tab = mul(art, i.rate);

      Multiplies the accumulated rate by the normalized debt to be covered to get the total debt tab (debt + stability fee) for the auction.

    11. uint lot = min(u.ink, ilks[ilk].lump);

      Sets the amount of collateral to be auctioned (smaller of either the collateral in the CDP or the Cat's ilk's lump)

    12. function bite(bytes32 ilk, address urn) external returns (uint id) {

      bite can be called at anytime but will only succeed if the CDP is unsafe. A CDP is unsafe when its locked collateral (ink) times its collateral's liquidation price (spot) is less than its debt (art times the fee for the collateral rate). Liquidation price is the oracle reported price scaled by the collateral's liquidation ratio.

    13. contract Cat is DSNote {

      The Cat is the system's liquidation agent: it enables keepers to mark positions as unsafe and send them to be auctioned.

    1. function deal(uint id) external note {

      Claim a winning bid / settles a completed auction.

      Once the auction's last bid has expired or the auction itself has reached the end anyone can call deal to payout the highest bidder (Bid.guy). This moves Gem's from the Flipper's balance in the Vat to the bidder's balance.

    2. function dent(uint id, uint lot, uint bid) external note {

      Second phase of an auction. Set Dai bid for a decreasing lot of Gems.

      During the dent-phase bidders compete for decreasing lot amounts of Gem for the fixed tab amount of Dai. Forfeited Gem is returned to the liquidated Urn for the owner to retrieve. The point of the dent phase is to return as much collateral to the CDP holder as the market will allow.

    3. function tend(uint id, uint lot, uint bid) external note {

      First phase of an auction. Increasing Dai bids for a set lot of Gems.

      Starting in the tend-phase, bidders compete for a fixed lot amount of Gem with increasing bid amounts of Dai. Once tab amount of Dai has been raised the auction moves to the dent-phase. The point of the tend phase is to raise Dai to cover the system's debt.

    4. function kick(address usr, address gal, uint tab, uint lot, uint bid)

      Start an auction / Put collateral up for auction.

      CDP liquidation penalty is added to the total debt of the CDP before the collateral auction is kick’ed

    5. Public Functions open for everyone to call,

      • kick
      • tick
      • tend
      • dent
      • deal

      Restricted Functions that only authorized addresses/contracts can call,

      • file
      • yank

      Flip is authorized to call the following contracts, *

    6. function yank(uint id) external note auth {

      Used during Global Settlement to move tend phase auctions to the End by retrieving the collateral and repaying dai to the highest bidder.

    7. function tick(uint id) external note {

      Restart an auction if there have been 0 bids and the end has passed

    8. bytes32 public ilk;

      id of the Ilk for which the Flipper is responsible

    9. struct Bid { uint256 bid; uint256 lot; address guy; // high bidder uint48 tic; // expiry time uint48 end; address usr; address gal; uint256 tab; }

      State of a specific Auction

      • bid - Bid amount (DAI)/ DAI paid
      • lot - quantity up for auction / collateral gems for sale
      • guy - high bidder (address)
      • tic - Bid expiry
      • end - when the auction will finish / max auction duration
      • usr - address of the CDP being auctioned. Receives gems during the dent phase
      • gal - recipient of auction income / receives dai income (this is the Vow contract)
      • tab - total dai wanted from the auction / total dai to be raised (in flip auction)
    10. contract Flipper is DSNote {

      Collateral Auctions are used to sell collateral from CDPs that have become undercollateralized in order to preserve the collateralization of the system. The Cat sends bitten collateral to the Flip module to be auctioned to keepers.

    11. It will be helpful to learn these words before reading the annotations on this page. *

    1. function deal(uint id) external note {

      Claim a winning bid / settling a completed auction.

      The surplus auction officially ends when the bid duration ends (ttl) without another bid getting placed OR when auction duration (tau) has been reached. At auction end, the MKR received for the surplus DAI is then sent to be burnt thereby contracting the systems MKR supply.

      If no Auction Keeper bids before bid.end < now, then no MKR is burned and the Dai gets moved back to the Vow's address since it is still guy. This would increase the Vow's surplus and allow another auction to be started. This changed as we implemented a tick function in the flap contract.

    2. uint256 public beg = 1.05E18; // 5% minimum bid increase

      Minimum bid increase (default: 5%).

      The beg could be set to 3%, meaning if the current bidder has placed a bid of 1 MKR, then the next bid must be at least 1.03 MKR. Overall, the purpose of the bid increment system is to incentivize early bidding and make the auction process move quickly.

    3. function kick(uint lot, uint bid) external auth returns (uint id) {

      Start an auction / put up a new DAI lot for auction.

      System surplus is determined in the Vow when the Vow has no system debt and has accumulated enough DAI to exceed the Surplus auction size (bump) plus the buffer (hump).

      Once the auction has begun, a fixed amount (lot) of DAI is put up for sale. Bidders then complete for a fixed lot amount of DAI with increasing bid amounts of MKR. In other words, this means that bidders will keep placing MKR bid amounts in increments greater than the minimum bid increase amount that has been set (this is the beg in action).

    4. function tick(uint id) external note {

      Resets the end value if there has been 0 bids and the original end has passed.

    5. function yank(uint id) external note {

      Is used during Emergency Shutdown to move tend phase auctions to the End by retrieving the collateral and repaying DAI to the highest bidder.

    6. uint256 public kicks = 0;

      Total auction count.

    7. GemLike public gem;

      MKR Token

    8. function tend(uint id, uint lot, uint bid) external note {

      Make a bid, thus increasing the bid size / submit an MKR bid (increasing bid).

    9. uint48 public tau = 2 days; // 2 days total auction length

      Maximum auction duration (default: 2 days)

    10. uint48 public ttl = 3 hours; // 3 hours bid duration

      Bid lifetime / max bid duration (default: 3 hours)

    11. mapping (uint => Bid) public bids;

      Storage of all Bids by id.

    12. struct Bid { uint256 bid; uint256 lot; address guy; // high bidder uint48 tic; // expiry time uint48 end; }

      Bid - State of a specific Auction[Bid]

      • bid - quantity being offered for the lot (MKR) [uint]
      • lot - lot amount (DAI) [uint]
      • guy - high bidder [address]
      • tic - Bid expiry [uint48]
      • end - when the auction will finish [uint48]
    13. contract Flapper is DSNote {

      Flapper is a Surplus Auction. These auctions are used to auction off a fixed amount of the surplus Dai in the system for MKR. This surplus Dai will come from the Stability Fees that are accumulated from CDPs. In this auction type, bidders compete with increasing amounts of MKR. Once the auction has ended, the Dai auctioned off is sent to the winning bidder. The system then burns the MKR received from the winning bid.

    14. Public Functions open for everyone to call,

      • tick
      • tend
      • deal
      • yank

      Restricted Functions that only authorized addresses/contracts can call,

      • kick
      • cage
      • file

      Flap is authorized to call the following contracts, *

    15. It will be helpful to learn these words before reading the annotations on this page. *

    1. function permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) external

      permit is a signature-based approval function. This allows for an end-user to sign a message which can then be relayed by another party to submit their approval. This can be useful for applications in which the end-user does not need to hold ETH.

      More ideas on using permit in contracts can be found in the ds-dach repo.

    2. function transferFrom(address src, address dst, uint wad)

      transferFrom in the DAI contract works in a slightly different form than the generic transferFrom function. The DAI contract allows for "unlimited approval". Should the user approve an address for the maximum uint256 value, then that address will have unlimited approval until told otherwise.

    3. wad

      Fixed point decimal with 18 decimals (for basic quantities, e.g. balances).

    4. contract Dai is DSNote {

      The Dai contract is the user facing ERC20 contract maintaining the accounting for external Dai balances. Most functions are standard for a token with changing supply, but it also notably features the ability to issue approvals for transfers based on signed messages.

    5. Public Functions open for everyone to call,

      • transfer / transferFrom / push / pull / move
      • burn
      • approve
      • permit

      Restricted Functions that only authorized addresses/contracts can call,

      • mint

      Dai token is authorized to call the following contracts, *

    6. It will be helpful to learn these words before reading the annotations on this page. *

    1. function flop() external note returns (uint id) {

      Trigger a deficit auction (flopper.kick).

    2. id = flopper.kick(address(this), dump, sump);

      (Debt auctions) - If the deficit is not covered in the forward auction portion of the flip auction, then debt auctions are used for getting rid of the Vow’s debt by auctioning off MKR for a fixed amount of Dai. Once the auction ends, the Flopper will then send the received Dai to the Vow in order to cancel its debt. Lastly, the Flopper will mint the MKR for the winning bidder.

    3. function flap() external note returns (uint id) {

      Trigger a surplus auction (flapper.kick).

    4. id = flapper.kick(bump, 0);

      (Surplus auctions) - These are used for getting rid of the Vow’s surplus by auctioning off a fixed amount of internal Dai for MKR. Once the auction ends, the Flapper burns the winning MKR bid and sends internal Dai to the winning bidder.

    5. require(sump <= sub(sub(vat.sin(address(this)), Sin), Ash));

      The Sin is stored when it is in the debt queue, but the debt available to auction isn't explicitly stored anywhere. This is because the debt that is eligible for auction is derived by comparing the Sin (i.e. debt on the holding queue) with the dai balance of the Vow as recorded in Vat.dai[Vow]. For instance, if Vat.sin[Vow] is greater than Vow.Sin (and the Ash (debt currently on auction)) then the difference is eligible for a Flop auction.

      Flop can process only up to sump amount of Sin in a single auction.

    6. contract Vow is DSNote {

      It is important to note that the Dai Credit System will deviate from its equilibrium. This occurs when it receives system debt and system surplus through the collateral auctions and CDP stability fee accumulation. The Vow contract contains the logic to trigger both the debt and surplus auctions, which work to correct the system’s monetary imbalances.

      • System Debt: In the case where CDPs are bitten (liquidated), their debt is taken on by the Vow contract as a Sin (the system debt unit). The Sin amount is then placed in the Sin queue. Note: When the Sin is not covered by a flip auction (within the dedicated wait time, the Sin is considered to have bad debt to the Vow. This bad debt is then covered through a debt auction (flop) when it exceeds a minimum value (the lot size).
      • System Surplus: Occurs from stability fee accumulation, resulting in additional internal Dai in the Vow. This surplus is then discharged through a surplus auction (flap).
    7. Public Functions open for everyone to call,

      • flog
      • heal
      • kiss
      • flop
      • flap

      Restricted Functions that only authorized addresses/contracts can call,

      • fess
      • cage

      Vow is authorized to call the following contracts,

      • Vat
      • Flip
      • Flap
    8. live

      Set to 0 if the system went through a successful emergency shutdown.

    9. function cage() external note auth {

      Called during Emergency Shutdown.

    10. function kiss(uint rad) external note {

      Cancels out surplus and on-auction debt. Release on-auction debt and Heal (vat.heal).

    11. function heal(uint rad) external note {

      Vow calls heal on the vat contract to cancel out surplus and debt.

    12. function flog(uint era) external note {

      Release queued debt for auction (realize debt from the queue).

    13. function fess(uint tab) external note auth {

      Pushes bad debt to the auctions queue (add debt to the queue).

    14. It will be helpful to learn these words before reading the annotations on this page.

      • Vow - System Stabilizer
      • Flop - Debt Auctions
      • Move - Transfers stablecoin between users
      • Kick - Starts an auction
    15. dump

      Debt auction lot size, i.e. the starting amount of MKR offered to cover the lot/sump

    16. hump

      Surplus buffer, must be exceeded before surplus auctions are possible

    17. bump

      Surplus auction lot size, i.e. the fixed surplus quantity to be sold by any one surplus auction

    18. sump

      Debt auction bid size, i.e. the fixed debt quantity to be covered by any one debt auction.

    19. wait

      Length of the queue.

    20. Ash

      Total amount of debt being processed in debt auctions.

    21. sin

      Chunks of debt waiting to be cancelled against surplus at a future time.

    22. Sin

      Total amount of debt yet to be processed.

    1. Public Functions open for everyone to call,

      • Restricted Functions that only authorized addresses/contracts can call,

      Spot is authorized to call the following contracts, *

    2. It will be helpful to learn these words before reading the annotations on this page. *

    1. Public Functions open for everyone to call,

      • Restricted Functions that only authorized addresses/contracts can call,

      Pot is authorized to call the following contracts, *

    2. It will be helpful to learn these words before reading the annotations on this page. *

    1. Public Functions open for everyone to call,

      • join
      • exit

      Restricted Functions that only authorized addresses/contracts can call,

      • None

      GemJoin, DaiJoin, and ETHJoin are authorized to call the following contracts,

      • Vat
    2. It will be helpful to learn these words before reading the annotations on this page.

      • Vat - cdp and internal token balance database
    3. GemJoin

      Allows standard ERC20 tokens to be deposited for use with the system.

    4. vat.slip(ilk, msg.sender, -int(wad));

      vat.slip gets a negative wad number as input to reduce the collateral type balance for msg.sender

    5. vat.slip(ilk, usr, int(wad));

      vat.slip issues wad amount to the usr address for the collateral type.

    6. join(address usr, uint wad

      Adds wad amount from the msg.sender token balance to the usr address

    7. ONE

      ray - 27 decimal fixed-point number

    8. dai

      Address of the dai token

    9. gem

      Address of the ilk for transferring

    10. ilk

      id of the Ilk for which a GemJoin is created for

    11. vat

      Storage of the Vat’s address

    12. DaiJoin

      Allows users to withdraw their Dai from the system into a standard ERC20 token.

    13. ETHJoin

      Allows native Ether to be used with the system.

    1. function file(bytes32 ilk, bytes32 what, uint data) external note auth {

      Setter methods for Line, and to update spot, line, and dust for each collateral type.

  6. Aug 2019
    1. Authorization note on auth logic

      All authorized addresses can also call rely/deny to update the list of authorized addresses.

    2. int rad = mul(ilk.Art, rate); dai[u] = add(dai[u], rad); debt = add(debt, rad);

      Dai balance of the address u and global debt are updated based on whether debt was collected or paid back for a collateral type.

    3. vice = add(vice, rad); debt = add(debt, rad);

      Total debt and bad debt in the system are increased.

    4. sin[u] = sub(sin[u], rad); dai[u] = sub(dai[u], rad); vice = sub(vice, rad); debt = sub(debt, rad);

      heal accepts a positive number as an input.

      Dai balance and bad debt balance of the address are reduced.

      Total bad debt and debt in the system are reduced.

    5. heal(uint rad)

      Allows anyone to cancel the bad debt present on an address with its own dai balance.

      All bad debt in the system is currently accounted for on the address of the Vow contract.

      A MKR debt auction can be triggered to cover the remaining bad debt after all the surplus on Vow is used up.

    6. int dtab = mul(ilk.rate, dart); gem[i][v] = sub(gem[i][v], dink); sin[w] = sub(sin[w], dtab); vice = sub(vice, dtab);

      Collateral balance of address v and bad debt balance sin of address w are updated.

      Global bad debt amount vice is also updated.

    7. // ilk has been initialised require(ilk.rate != 0);

      Collateral type has to be initialized for the frob operation to succeed.

    8. // system is live require(live == 1);

      Ensures the system is still live and isn't going through the emergency shutdown process.

    9. move(address src, address dst, uint256 rad)

      Public function used to transfer internal dai balance of user within Vat to another address.

    10. flux(bytes32 ilk, address src, address dst, uint256 wad)

      Public function used to transfer internal collateral balance of collateral type ilk within Vat from src to dst address.