MIP30: Farmable cUSDC Adapter (CropJoin)

@LongForWisdom @MakerMan liquidations could be disabled for this collateral type, with the same justification as USDC-A. The collateral here is more risky, but follows a very predictable and slow interest accumulation on the compound side. You can think of this as a USDC adapter with an added investment strategy, cUSDC is just an implementation detail.

Auction participants deal in internal Maker collateral balances, rather than the external asset. The winner of an auction would have an internal collateral balance which they would have to exit to real collateral, likely preceded by an unwind to make the liquidity available, just like any other holder of balances in this adapter. Available compound liquidity is a risk, as noted in the MIP.

The oracle price is given by nps * usdc_price, the net assets per internal collateral unit multipled by the usdc/dai price (currently 1, as in USDC-A). The code for this will be added soon.

Emergency shutdown is the same as for other collateral types - we reason in terms of internal collateral balances, with a price given at the time of ES. Holders of this collateral after ES then have to unwind and exit via this adapter.


Yep, I read this in the MIP, which is fine. I think it makes sense. I’m more concerned that people might let them drop below the ratio, at which point we need to liquidate manually. In this situation, what does the liquidation process look like?

I guess my question is what does the internal collateral balance represent in this case? A share of the recycled USDC position on Compound? I guess I don’t understand how this position is divided, it doesn’t have it’s own token, right? cUSDC represents the supplied portion, but not the recycled borrows?


There wouldn’t be anything special about the liquidation. It would be the same as if USDC-A liquidations were to occur. However, we can just have liquidation enabled from the outset.

The internal collateral balance represents your share of the net asset valuation of the adapter. The nav is given by the outstanding Compound supply less the outstanding Compound borrows, plus any unused USDC in the adapter. The value of your adapter balance will change over time, depending on the Compound borrow-supply spread.

Usually the nav will slowly decrease in terms of USDC, although sometimes (like now) it can increase if Compound is paying more for supply than it is taking for borrowing.


Okay, am I correct in assuming that the auction winner would be the one to unwind the vault and claim the USDC collateral (leaving some for the owner, assuming the auction performs well enough)?

Okay, so in an ES situation at redemption an entity would presumably accumulate a reasonable amount of the collateral share for this collateral, and then call unwind on the vault so they could access their share of the USDC?

Okay, am I correct in assuming that the auction winner would be the one to unwind the vault and claim the USDC collateral (leaving some for the owner, assuming the auction performs well enough)?

Yes, there is an exit_ argument to unwind, which lets them specify exactly how much USDC should be released from Compound, for them to then exit with.

Okay, so in an ES situation at redemption an entity would presumably accumulate a reasonable amount of the collateral share for this collateral, and then call unwind on the vault so they could access their share of the USDC?

I’m not sure what you mean by “reasonable”, but they would want to have at least enough to make the gas fees worth it and then unwind with an appropriate exit_ as above.

1 Like

Hah, this is what I meant. Perhaps reasonable was a poor choice of words. An amount that makes it net-beneficial to pay the gas fees.

I’ll note here that the gas costs of using this adapter can be substantial, due to the Compound interactions. Worst case, which would be exiting a huge position with no loan support, wind and unwind can cost 1.9M and 2.3M gas each. More normally we could expect 800k / 1M. The wind cost doesn’t matter so much as callers can wait until there is sufficient collateral to be worth calling, but the unwind cost is intrinsic to the cost of exiting.


Is this vault to be plug to the PSM?

This vault type is entirely separate from the PSM. You can view farmable assets as desirable collateral much like ETH / BTC where people will primarily be using it for leverage. These are assets we can continue to charge Stability Fees on.

The PSM on the other hand should be viewed as a safety net to keep the peg in line. We would prefer these other assets, but worst case we still want the peg to be stable.

That being said, we could use a farmable join adapter like this on the PSM as well to earn revenue for the protocol.


Yes sorry,
I meant convert USDC to CUSDC in the PSM on the gemToDai using the Cusdc vault.
and in return CUSDC to USDC on daiToGem.

Compound contract :
function mint(uint mintAmount) external returns (uint) {}
function redeem(uint redeemTokens) external returns (uint) {}

The only issue here is to get the exact amount on the redeem.

1 Like

Why not use YFI instead?

I don’t think anyone else mentioned it, but the proposed crop.sol breaks compatibility of API behavior.
Applications that are using the low level vat.flux, will have to add vat.tack in some cases (otherwise they will not be able to call gemjoin.exit().

Take DssProxyActions as a very simple example, the freeGem would revert if a malicious actor sent 1 wei of cUSDC to the user CDP (via the vat system) prior to the call (and/or while the tx is pending).

It is not unthinkable that others dapps at the very least will not be able to support the new collateral without a change in their smart contract code, even in the absence of a malicious actor.
In some cases it might even cause dapp funds to get stuck, but this is just a speculation.

  • Given cUSDC is not an existing collateral in any current dapp, maybe it is not a deal breaker, but maybe something worth noticing.

** I only took a quick look at the code, I could be wrong.


I am formally submitting MIP30 (CropJoin) for the January governance cycle.


I didn’t see a reply to this. Is the above an issue or no? At the moment considering voting no on this one just because the above is still unresolved as far as I can tell.

1 Like

Thanks for bringing this up. This issue is addressed at a high level in the readme, however you are right that the specific implications for libraries like DssProxyActions should be mentioned too. At the moment, it is inevitable that integrations using this ilk would have to be specialised, to some degree, to ensure compatibility. Note that even setting aside the tack issue, a user of the CropJoin has to be able to call specialised functions like unwind and flee in some circumstances, meaning that a generic support contract would not be sufficient.


Yeah I thought about it and voted no just because I don’t like to see incompatibilites that could hamper 3rd party access implementations. I think that is bad policy to break something and make someone else fix it unless it is really ‘necessary’.

To be clear I want something like this farming adapter. I have some mixed feelings around some of the issues discussed but think we want things like this generally.

When there is clarity on implementation etc. I am a yes to this.

Thanks for the quick reply.


I’ve spent some time trying to come up with alternative implementations that remove the tack() requirement, but from what I can see this is the most non-invasive way to do it. Happy to be proven wrong, but it’s either we don’t have farm tokens or we have to deal with this api ugliness. Personally I think the trade off is worth it.


I agree with you. I believe the extra effort for API compatibility would come at a great cost (smart contract complexity, therefore cost & risk). In addition given we’re not breaking any existing APIs, I think adding this is better than not adding any support for farm-able collateral.

We can always improve on the design later and upgrade the collateral type if we see that this is a bigger issue than expected.

1 Like

Is the unusual APIs for keepers mostly?

If someone is doing programmatic vault creation does it also cause issues? Assuming the program has been hardcoded as per vanilla ilks

This mip was accepted 01/28/21 with the Jan MIPs bundle

1 Like