What Is a CDP in Crypto? Abracadabra Money Explained
Quick answer. A CDP (collateralized debt position) lets you borrow a stablecoin against deposited collateral, always for less than the collateral is worth. Abracadabra Money's MIM works this way, with liquidation past the LTV limit.
Understanding core DeFi archetypes is one of the best ways to get better as a smart contract developer or security researcher.
This guide uses Abracadabra Money, famous for the MIM stablecoin, to explain the collateralized debt position (CDP) at a deeper level. Once it clicks, many other DeFi protocols become much easier to read.
It covers what a CDP protocol does, how Abracadabra Money is architected, and then the actual code for depositing, withdrawing, borrowing, repaying and liquidating.
What a CDP Protocol Does
A CDP protocol lets anyone deposit collateral and borrow a stablecoin against it.
Say you deposit 5 ether, and ether is $5,000. You have put down $25,000 of value, and you might be able to borrow 20,000 stablecoins. In Abracadabra Money, that stablecoin is MIM (Magic Internet Money).
Notice the key rule: you always deposit more value than you can borrow.
The core invariant behind the peg
For every MIM in circulation, there should always be at least $1 of debt backing it. This is how a CDP stablecoin holds its peg.
A stablecoin holds its peg as long as it is worth $1 to somebody. If it drops to 90 cents, that somebody will buy it at 90 cents and redeem it for $1.
In a CDP, that somebody is every borrower who owes the stablecoin. If you owe 20,000 MIM, you would love to buy your $1 units of debt at 90 cents and repay the loan with $18,000.
Why you cannot borrow 1:1
If you could borrow $25,000 against $25,000, normal crypto volatility would break the system.
Your 5 ether could easily fall to $24,500. Your collateral is now worth less than your debt, so you walk away with what you borrowed and leave the protocol your collateral.
That is an insolvent position, and the system now has bad debt. Requiring more collateral than debt prevents exactly this.
The LTV Ratio
This rule is formalized as the loan-to-value (LTV) ratio. Each collateral type, such as wrapped ether, gets its own.
With a 70% LTV, $1 of wrapped ether lets you borrow at most 70 cents, or 0.7 MIM.
If your position slips past that ratio, say 70 cents borrowed against 98 cents of collateral, it is liquidatable. The protocol wants to close it before it gets any less healthy.
The situation to avoid is 70 cents borrowed against 68 cents of collateral. The borrower walks away, and the position leaves that gap as bad debt.
So the protocol keeps a cushion. As soon as you cross the 70% LTV, it force-closes your position, repays your borrow and takes an extra liquidation fee.
Abracadabra Money's Architecture
Two main contracts implement this.
- The Cauldron is the entry point that users interact with. It keeps the per-user accounting: who deposited how much collateral, who borrowed how much MIM, and whether they are solvent or liquidatable.
- The DegenBox holds the funds and the core token accounting. It is a licensed version of the original BentoBox, renamed. Only the Cauldron may call its important accounting functions.
When you deposit collateral through the Cauldron, the tokens go to the DegenBox. The DegenBox issues collateral shares to the Cauldron, and the Cauldron records your portion.
Shares exist because the DegenBox can deploy collateral into a strategy contract to earn yield while it sits in positions. That yield could even pay down your debt while your position is open.
This guide ignores strategy details and focuses on the Cauldron and the DegenBox.
One more design detail: every borrow accrues interest per second. The interest accrues in MIM itself and must be repaid in MIM.
Adding Collateral
In CauldronV4, the function is addCollateral. It does three things:
- Adds the share amount to
userCollateralSharefor the address you are depositing for. - Increases the Cauldron's total collateral share.
- Moves the shares from you to the Cauldron with
bentoBox.transfer.
Why shares and not amounts? Say that at time 0, one collateral token equals one share.
If a good strategy earns interest, the DegenBox's collateral balance grows. By time 10, one share might equal 1.3 tokens.
The DegenBox's transfer function moves shares in its balanceOf mapping, the source of truth for shares. It subtracts them from the user and credits them to CauldronV4.
Your collateral is then tracked in the Cauldron's userCollateralShare mapping. An after-collateral hook follows; it is empty in the base contract, but contracts inheriting from CauldronV4 may use it.
Removing Collateral
The removeCollateral function first calls accrue, which is how interest is charged. More on that below.
It then subtracts the shares from userCollateralShare, reduces the total collateral share and runs the after hook.
Finally bentoBox.transfer moves the shares from the Cauldron to the to address. It is the exact inverse of depositing.
Cook and the DegenBox Deposit
Before addCollateral, you need shares in the DegenBox. The cook function bundles both steps into one transaction by taking a list of actions.
- Bento deposit. Calls
depositon the DegenBox. You usually give an amount and leave share as zero. - Add collateral. Calls
addCollateral, which moves the new shares to the Cauldron. You are ready to borrow.
Inside deposit, the DegenBox converts your amount to shares at the current exchange rate. One share might be worth 1.3 tokens, 17 or 5, depending on the strategy's results so far.
It increases your balanceOf by those shares and transfers your tokens in.
Base and elastic
The DegenBox tracks the conversion between shares and tokens with two numbers, base and elastic.
Picture a filled circle in the middle: that is the base, the share amount, and it does not change on its own. Around it is a ring that can grow and shrink: that is the elastic, the token amount.
- At the start, one share equals one token.
- A deposit adds to base and elastic at the existing ratio, so the ratio does not change.
- Strategy rewards grow the elastic while the base stays the same. That is what moves the ratio, to two tokens per share, for example.
Borrowing MIM
Inside _borrow, the important steps are:
- Take the amount and calculate a borrow opening fee.
- Add to the contract's total borrow, and validate it against a cap.
- Record the user's borrow part in
userBorrowPart. - Convert the amount to MIM shares, and transfer them from the Cauldron to the
toaddress through the DegenBox.
The part works like a share. It is the fixed inner circle, and the amount owed is the elastic ring.
At time 0, one part equals one MIM. As interest accrues the elastic grows, and one MIM you borrowed might later take 1.2 MIM to repay.
The Cauldron can only lend MIM it holds. At deployment it is allocated a balance of MIM shares in the DegenBox, and you cannot borrow more than that. That is how borrows are limited.
Repaying and Interest
The repay function starts by calling accrue.
The accrue function checks how much time has elapsed, calculates the interest for that period and adds it to the elastic amount of the total borrow. This is where the outer ring grows and the conversion rate rises.
Then totalBorrow.sub, from the BoringRebase library, does two things:
- Converts your part (base) to an elastic amount: the base times the ratio of elastic to base.
- Subtracts it from the total and returns that elastic amount, which is what you must repay, interest included.
The Cauldron then pulls the matching MIM shares from msg.sender through the DegenBox.
This can be confusing because two systems are at work: the DegenBox's share logic, and the rebase logic for the total borrow. Both use the same idea of a growing elastic supply.
Liquidations
Anyone can call liquidate, with a list of users. The function loops through them, and for each one that is not solvent:
- It computes the borrow amount the liquidator must repay to close the position.
- It adds up the matching collateral share, times a liquidation multiplier of something like 1.06x or 1.07x. That extra 6% or so is the liquidator's incentive.
After the loop, it updates the total borrow and total collateral share. Part of the liquidation bonus is distributed to SPELL stakers; SPELL is the protocol's governance token.
The order matters. The liquidator receives the collateral before they pay back the MIM.
So a liquidator can pass a swapper address, swap the collateral for the MIM owed and repay with it. The sliver of collateral left over is their profit.
When Is a Position Liquidatable?
That is decided by the isSolvent check, and the name is technically a misnomer.
With 99 cents of collateral for every 70 cents of debt, you are still solvent: your collateral is worth more than your debt. But isSolvent returns false, because you are past the 70% LTV.
That is the point of the LTV ratio: never let a position become truly insolvent. The function would be better named "is not liquidatable".
Here is what it computes:
- Take the user's borrow part and convert it to the amount owed.
- Convert the collateral share to an amount of collateral tokens, through the DegenBox.
- Multiply through to get the collateral's value, and apply the collateralization rate.
- Compare the result to the value of the debt.
Each Cauldron accepts one type of collateral, with its own configured collateralization rate. For wrapped ether at 70%, that is 70,000, divided by 1e5.
Above the threshold, isSolvent returns true and liquidate cannot touch you. Below it, you can be liquidated.
What to Carry to Other CDPs
- Find the core invariant. Every unit of stablecoin should be backed by at least $1 of debt. The peg depends on it.
- Find where bad debt comes from. Positions that slip past their collateral value before liquidation leave the protocol with the gap.
- Read the solvency check closely. Names like
isSolventmay not mean what they say. - Learn the base and elastic pattern. Shares and interest-bearing debt both use it, here and in many other protocols.
For the original CDP stablecoin, see how MakerDAO and DAI work. For the bugs that hide in this code, see liquidation vulnerabilities.
How Guardian Helps
Guardian has conducted several reviews with the Abracadabra Money team, including their GMX V2 cauldrons, MultiRewards staking and MIMSwap.
A smart contract audit builds invariant suites around solvency, accounting and rounding, then puts senior researchers on the logic that is left.
Frequently Asked Questions
What is a CDP in crypto?
A collateralized debt position is a loan backed by deposited collateral. You lock collateral, such as ether, and borrow a stablecoin worth less than it. Cross the protocol's LTV limit and your position can be liquidated.
What is MIM?
MIM, or Magic Internet Money, is Abracadabra Money's stablecoin. Users borrow it against collateral deposited through a Cauldron. Its peg rests on borrowers, who can always repay their debt with MIM bought below $1.
What is the difference between the Cauldron and the DegenBox?
The Cauldron is the user entry point and keeps per-user collateral, borrow and solvency accounting. The DegenBox, a licensed BentoBox, holds the tokens, issues shares and can deploy collateral into yield strategies.
How does Abracadabra Money charge interest?
Each borrow is recorded as a fixed part. The accrue function adds interest for elapsed time to the total borrow's elastic amount, so each part is worth more MIM over time. Repaying converts the part to that larger amount.
Sources
Get your CDP's solvency math reviewed
Guardian writes your protocol's solvency rules as invariants, then pressure-tests every reachable state against them.