MIP22: Centrifuge Direct Liquidation Module

MIP22: Centrifuge Direct Liquidation Module


MIP#: 22
Title: Centrifuge Direct Liquidation Module
Author(s): Lucas Vogelsang (@spin on forum.makerdao.com, [email protected])
Contributor(s): Lea Schmitt ([email protected]), Lev Livnev (@equivrel on forum.makerdao.com)
Type: Technical
Status: Accepted
Date Proposed: 2020-09-02
Date Ratified: 2020-10-27
Dependencies: none
Replaces: none
Licenses: AGPL


Sentence Summary

This proposal provides a vault liquidation mechanism for Tinlake based short-term loan collateral that entails letting a portfolio of said short term assets mature or refinance them off-chain and using loan repayments to settle the Vault balance.

Paragraph Summary

For Vaults of Centrifuge pooled short term loans, auctioning off a portfolio of short term loans is not necessarily the most effective way for Maker to liquidate a vault. When these assets are very illiquid the discount a keeper would want outweights the benefit of just waiting for maturity of the underlying loans. Centrifuge has built the Tinlake contracts to manage the liquidations of loan portfolios on chain. This mechanism allows the Maker smart contracts to get direct access to these repayments without the need for any external keepers.

Component Summary

MIP22c1: Collateral Prerequisites
Describes the requirements for the collateral type to make use of the proposed liquidation module.

MIP22c2: Liquidation Mechanism
Describes the mechanism by which Vaults are liquidated when the described adapter is used.

MIP22c3: Definitions
Adapter Component Definitions

MIP22c4: Proposed Code
An explanation of the logic along with code

MIP22c5: Usage of Code & Test Cases
Still outstanding

MIP22c6: Security Considerations
Still outstanding

MIP22c7: License
The code is licensed under APGL.


As we have stated in previous threads and discussions we believe that adding real world assets (RWA) to MCD is the path forward to scale Dai supply and balance the collateral risk portfolio through uncorrelated assets.

A key issue preventing the addition of RWA to the Maker Protocol has been the absence of a reliable process to liquidate a Maker vault that is backed by these assets.

When a legal entity invests in a Tinlake pool that is backed by RWA they enter a legal contract with the issuer and therefore get a legal claim on the underlying collateral (the real world asset).

When Maker liquidates a Vault backed by these tokens it must have a way to get the DAI repaid that was generated in the Vault without having to enter a legal contract with the issuer.

We are proposing a liquidation mechanism that solves for that whenever a Vault is backed by by short-term loan collateral. This mechanism does not require an auction and no additional legal structures. We see this solution as a major push towards making RWA in MCD a reality near term.

The solution proposed in this MIP requires that the pool of loans that is tokenized through Centrifuge is either:

  1. Of very short maturity and waiting for loan maturity is economically viable.


  1. The loans can be sold off (refinanced) by the issuer off chain and there is a process in place for the liquidation of the pool in case any DROP token holder (such as Maker)

Whether the proposed liquidation component should be used for a given collateral type should be part of the Risk Assessment and discussed on an asset by asset basis. If that is desired, the below code should be configured to be used when adding a new collateral with the MIP12 executive vote.


MIP22c1: Collateral Prerequisites

Assets that should be able to use this collateral have a few requirements:

  • This only works for collateral that is using Centrifuge’s Tinlake smart contracts to tokenize their off-chain loans.
  • There must be sufficient investors besides MakerDAO that ensure the correct operation of the legal recoure.
  • The Risk Domain Teams deem this liquidation mechanism for the collateral type sufficient.

MIP22c2: Liquidation Mechanism

When the liquidation of a Vault is kicked, the proposed liquidation adapter forces the Tinlake pool into liquidation by submitting an order to redeem all collateral in the Vault. The Tinlake contracts than automatically allocate all incoming cash-flows from borrowers to investors (i.e. the Maker Vault) for redemptions.

MIP22c3: Definitions

  • Tinlake Flipper: the contract that can liquidate a Vault by going to the Tinlake Pool contracts to redeem DROP for DAI and then transfer the raised DAI to the Vow
  • DROPJoin: An adaptor based heavily on GemJoin which allows only a selected Tinlake pool contract to add collateral to the Maker Vault.
  • Tinlake Pool: a pool of asset backed loans settled in DAI
  • DROP: the senior pool share ERC20 token which is redeemable against a share of the DAI repaid by the loans in the Tinlake Pool

MIP22c4: Proposed Code

The code has been kept to a minimum and any functional changes are shown below. We will publish a Git repository after collecting feedback on this proposal (to be ammended). The code in full can be viewed here.

For each Tinlake pool there will only be one Vault owned by the pool. The pool will have the logic necessary to manage the Vault. We modify the standard GemJoin adapter to only allow the join method to be called by wards (i.e. it is an authorized call). This will prevent anyone else from opening a CDP with DROP tokens as they would not be able to add the collateral to the system.

The TinlakeJoin contract looks as follows. Note the added auth modifier in the join function. This is the only necessary change.

contract DROPJoin is GemJoin {
    function join(address usr, uint wad) external auth note {
        require(live == 1, "GemJoin/not-live");
        require(int(wad) >= 0, "GemJoin/overflow");
        vat.slip(ilk, usr, int(wad));
        require(gem.transferFrom(msg.sender, address(this), wad), "GemJoin/failed-transfer");

The Tinlake Flipper takes all of the collateral from a Vault and requests redemption from the pool. The Tinlake contracts then enforce that any payments on loans are disbursed to the any DROP holder that requests redemption. As DAI is redeemed from the Pool, the adapter transfers the DAI into the vow until the tab is recovered. At that point any additional DAI that could be redeemed with the DROP is given back to the Pool.

The auction mechanism is binary: only liquidating part of the collateral would not be desired from an economical perspective. Therefore the mechanism is designed to liquidate everything and only after return any excess DAI raised to the pool.

When a Vault is liquidated (Cat.bite is called), the Cat will call Flipper.kick which kicks off the liquidation. At first it withdraws the entire collateral (the DROP tokens) from the system and places a redeemOrder on the pool contract.

   function kick(address usr_, address gal, uint256 tab, uint256 lot, uint256 bid)
       public auth returns (uint256 id)
       vow = gal;
       usr = usr_;
       vat.flux(ilk, msg.sender, address(this), lot);

       dropJoin.exit(address(this), lot);

The redeem order will now be taken into account whenever loan repayments flow into the pool or other investors want to join the pool. As the pool redeems the DROP any user can call the function take. It moves the DAI available for withdrawal from the pool and either repays up outstanding debt (tab) to the vow or returns it to the pool. This method can be called multiple time to cause the pool to disburse more DAI and return it to the pool as funds available for borrowers.

    function take() public {
        uint returned, _ = pool.disburse();
        if (tab < returned) {
            dai.transferFrom(address(this), usr, sub(returned-tab));
            returned = tab;
        if (tab != 0) {
            dai.join(vow, returned);
            tab = sub(tab, returned);

The Tinlake smart contracts collect redeem orders and return any DAI returned by borrowers proportionally to all DROP token holders first. This means that to receive highest priority on the redemption the liquidation should request the entire DROP to be redeemed.

This can be done by setting the variable dunk to uint(-1). This raises the minimum size of the collateral to auction off during the liquidation to above the maximum collateral that can ever exist thus forcing liquidation of the entire Vault and not just part of it.

MIP22c5: Test Cases

Tinlake is undergoing an audit which will be published by Sep 22nd. We will ammend this section with information on the test cases we have covering both the GemJoin and the Flipper.

MIP22c6: Security Considerations

This section will be completed. The core Tinlake contracts have undergone security audits in the past (reports) and we will be publishing the audit we are conducting for the next release in the next few weeks as it is ready.

As for the contracts that interact directly with MakerDAO (TinlakeFlipper and DROPJoin) those will be submitted with extensive test coverage and have been written following MakerDAO/DappHub’s smart contract style guide, make use of no external libraries and are easy to audit totalling to less than 100 lines of code.

MIP22c7: License

  • All code is licensed under the AGPL license


Hi @spin and thank you for this MIP proposal. It even comes with the code.

Question: as far as I see it the precise liquidation trigger points are still adjustable? So Vault liquidation could be triggered at let’s say when TIN is down 50% or 80% er even completely wiped?

1 Like

Yes, the liquidation would still be triggered by the collateral value of the vault dropping. This would be dependent on the health of the pool (i.e. how much the TIN ratio is and how much the overall value of the pool is).

1 Like

Aight, going to go through line by line and just do feedback as it occurs to me. Hopefully some of it is useful.

Spelling on a couple of these. Makerdoa and centrifug.

Previously (though not always) items in the references section have been included within the MIPs repository so that they can be fixed at time of submission. It’s probably fine not to do this with forum threads (and we haven’t before.) But it’s important to remember that the forum content isn’t guaranteed to be static.

Is this proposal unique to centrifuge assets? I haven’t got to the meat of it yet, but feels like this is probably the case. It should be specified in the Sentence Summary.

Formatting-wise leave a space between the components. I believe in markdown you can achieve this by ending the line with two space characters. Possibly this has just been lost in translation to the forum from the source. Either way I would still add newlines between these to make this more readable.

Not sure this is accurate. Feels like the component would be more accurately summarized as: “Describes the requirements for the collateral type to make use of the proposed liquidation module.”

Can you be more specific here? Both with the component name and description. Adaptor Component Definitions? Not sure what fits best.

Maybe: “Includes the proposed adaptor code and a description of the smart contract logic and liquidation process.”

addet -> added. Seeing a couple of typos of this nature. Maybe run the whole thing through grammarly or somesuch to catch the obvious stuff?

I would actually maybe reword this slightly too it it were me. “A key issue preventing the addition of RWA to the Maker Protocol has been…”?

I know what SPV means, you know what SPV means. I’m fairly sure that some don’t, and to be fair beyond knowing it stands for ‘Special Purpose Vehicle’ and that it’s some sort of legal entity, I’m drawing blanks. Maybe link this to a definition somewhere? Maybe give the full name in brackets so less-business oriented readers can go google it.

I’m not sure I’m understanding point 2 here, not sure that statement makes sense as written.

Switching gears here slightly. Does this affect all DROP investors? IE, does this command liquidate the entire pool, or just enough to return DAI to the Maker Vault? If it’s the whole pool, are other drop investors happy with this setup? Do they also have the ability to trigger liquidation of the tinlake pool which would affect Maker?

Can we name this ShortTinJoin or something? :smiley: Also, can you maybe reword the explanation here? Something like: “An adaptor based heavily on GemJoin which allows only a selected tinlake pool contract to add collateral to the Maker Vault.”

Maybe needs a slight reword. “the senior pool share ERC20 token which is redeemable against a share of the DAI repaid by the loans in the Tinlake Pool”?

I would use ‘github repository’ here rather than repo. Again, just so this is slightly more understandable by non-tech users. ammended -> amended.

Could this be included in the reference section?

On a more general note, the idea seems sounds to me. I’m not really the right person to comment on the smart contract code, but going by the description of its operation it seems workable. I’m looking forward to seeing it in practice, and thanks for pushing this as a solution to the liquidation issue with short-term loan collateral.

I think my two main content-based questions are ones I mentioned above (but will repeat here):

  • If Maker liquidates the whole pool, is this going to annoy other holders of DROP?
  • Can other holders of DROP also liquidate the whole pool and potentially annoy Maker?

I’ve added the small changes you suggested to the pull request (Commit).

To answer these two questions: yes, other investors are affected by Maker liquidating. The pool will redeem DROP to investors on a pro-rata basis. Any investor (incl. Maker) can submit redemption requests and if not enough DAI is available to redeem all, it will be given out proportionally to the size of your redeem request. Maker is treated like any other investor.

It ultimately depends on whether Maker is the only stakeholder that thinks the pool is a bad investment or other investors as well. In fact if other investors want to join this pool and Maker wants out, Maker doesn’t even need to wait for any loan repayments but the investment of these investors can be used to redeem Maker.

1 Like

This proposal has been moved to the Request for Comments (RFC) phase and will have a 1 month feedback period before being eligible for Formal Submission.

1 Like

We’re now formally submitting this MIP.


This MIP is on vote and is currently passing with 54% (3 people against) while the linked MIP13 is passing with 100%.

Feel free to add any argument against in the post (or DM me) so we can keep that in mind while working on onboarding Centrifuge collateral (you can create a new account if you want to remains anonymous).


The smart contracts team has reviewed this technical MIP, and while the overall idea is conveyed, the technical implementation is mostly prototype code. We would suggest the next steps would be to fully flesh out the Flipper implementation, get it to compile, and update it for LIQ-1.2. You can do this by starting with a template flip.sol from the dss repo:

As for the GemJoin with the auth modifier, we would prefer you use the AuthGemJoin located here:

Obviously, before any final deploy of any code, DROP tokens would need to follow the typical collateral onboarding process. This will require that this technical MIP, as well as dependancies like the redeemer will be pulled into scope for review. Part of that collateral onboarding process means rigorous integration tests must be passed. We may require that liquidations, redemptions, and emergency shutdown be proven in this process.


Have the test cases mentioned in “MIP22c5: Test Cases” been done and published yet? If so, can you please add them to that section of the MIP

1 Like