repayBorrow() with cToken

USDT, USDC, WBTC, and TUSD* are all pausable tokens. This means a central admin can pause them at any time, halting all transfers. When a token is paused, it will be bad news for Compound users on both sides. Depositors will be unable to withdraw their underlying token, and borrowers will be stuck with their collateral locked, since they cannot repay their loan.

*TUSD could be paused with an implementation upgrade.

Let’s add a new repayBorrow function that allows repayment with the correct amount of cToken rather than the underlying. With this in place, when a token is paused we can expect a market to develop for the cToken (e.g. on Uniswap). Depositors will now be able to exit their position by simply selling their cToken. And borrowers will be able to exit theirs by buying the cTokens and using the new repayBorrow function.

Another minor benefit: COMP farmers who borrow and lend the same token will be able to exit their positions more easily.

This would be a major improvement to the platform, giving users much more confidence in using a pausable token on Compound. In fact, this change will create an entirely new reason to hold cTokens: they’ll be transferable and there’ll be a market for them even when the underlying token is paused! This could be a major draw for folks who otherwise hold large balances of a pausable token.

Any other thoughts on what happens if a token calls pause()?
Any downsides to implementing this? Or upsides not mentioned here?
Anybody want to apply for a grant and work on this with me?


When does a token get paused? Has it happened before?

A token gets paused when the owner on the smart contract for the token calls the pause() function. They can do this at any time at their own discretion. To my knowledge, there has not yet been a high profile token that has called pause(), but it’s a matter of “when”, not “if”. I think the most likely scenario where we’d see it happen is when a stablecoin, such as Tether, loses its peg. It would make a lot of sense for the controlling organization to call pause() in an attempt to halt a hysteria of sales causing further depreciation relative to the peg target (dollar).

It’s surprising how few realize this is possible. In much the same way, few realize that Tether has the ability to blacklist any user and freeze their funds, which they’ve already used to freeze about $50m.

I really support this initiative.

I’ve had a problem with pausable tokens elsewhere. SingularityNET paused their token (AGI) and replaced it with a new token (AGIX), bricking my TokenSets set.

If Compound were to support that token, I could have wrapped AGI in cAGI so that I wouldn’t have to worry about pausable tokens bricking my set, as well as getting interest on the asset.

If Compound were to implement this change, I could see liquidity pools developing on DEXs for the reasons already outlined. It’d be safer for the end-user not to have to worry about getting restricted or blocked by the admins of pausable tokens.

Side note: We could create rewards pools for people who provide liquidity to DEXs to further develop cToken markets.


I like this idea. It’s so natural that had it been included in the protocol at the start we wouldn’t give it another thought.

Back when we were discussing whether to include WBTC as an asset, there was concern about infinite minting and pausing of WBTC. I proposed a wrapped version (wWBTC) as a way to enable a supply cap (by limiting the amount of wWBTC that could be minted) and to insulate against pauses. But that added a undesired layer of complexity. I don’t think it occurred to us that cWBTC could provide the pause protection on its own.

I would extend the current proposal to also add a new liquidateBorrow() method that accepts CTokens as the repaid asset. That would allow liquidations to proceed as designed even if the repaid underlying is paused, so long as there is a liquid market for the CTokens. I expect that anything serious enough to trigger a pause would be accompanied by volatile market conditions, so it’s important that the liquidation system continues to operate in that scenario.


This makes sense to me. It also has the added benefit that deleveraging when liquidity in a given market is squeezed (e.g., Dai during Black Thursday) is a little simpler. It essentially allows the balance sheet to be changed in a more direct way that is not as constrained by the tight liquidity (but has the same end effects collateral-wise).

Not necessarily a downside to this per se, but it’s worth further considering that if these tokens were ever paused, Compound would face significant collateral value risk. May want to have floating oracle prices for these tokens (vs. taking the prices of the asset they wrap) since a paused token shouldn’t be worth as much as the raw asset itself. And also consider how liquidations would work on these collateral types.

1 Like

I took a first pass at implementing this and didn’t run into any major issues or questions. Since the function is essentially a concatenation of redeemFresh() and repayBorrowFresh(), there is a lot of repeated code. But I suspect it’s not worth the additional complexity to refactor it in a way where that code is shared.

I agree with @pyggie–it seems natural to also include a function for liquidation with cTokens. I haven’t written this yet but I’ll do so soon.

Now @aklamun you make a very good point. The Comptroller uses a fixed value of $1 for USDT, USDC, and TUSD, which could lead to many problems. I think your idea to switch them to floating oracles is so good that I made a separate thread for it.

Having duplicate repay/liquidate events that accept cTokens (instead of underlying) makes sense, and I’m excited for these changes. It removes one edge case (that might never occur) but is worth designing around.

Great work @llama0 in spearheading this!

The only “cost” of these changes would be in the technical risk or complexity; I would lean towards not refactoring core functions unless theres an extremely compelling reason to do so.

1 Like