DeFi is taking the world by storm. At the time of writing, there are more than 3.9M ETH worth of wrapped ERC20 tokens locked up as collateral in MakerDAO's smart contracts. A newer product such as MIMO has seen over 15M€ being invested in it over the past few days.
Because of DeFi's prominence on Ethereum, it would seem like Bitcoin is destined to miss out. Wrapping your bitcoin in an ERC20 token on Ethereum to access DeFi products is a possibility, but it doesn't appeal to everyone.
True DeFi for Bitcoin is starting to become a necessity.
Trustless Collateralized Loans
Inspired by traditional finance, collateralized loans have become very popular in the DeFi world. They are relatively simple: a borrower needs to stake a certain amount of one asset to receive a loan in a different asset. The amount the borrower has to put up is determined by the loan's Loan-to-Value (LTV) ratio. For conventional loans, assets such as real estate, cars or shares can be used as collateral; DeFi loans are backed by cryptocurrencies instead.
The point of these DeFi loans is to give the borrower access to the fiat value of their crypto assets without having to sell them; the lender gets some interest in return. Blockfi and Hodl Hodl are well-known service providers in the DeFi borrowing space. While Blockfi is a fully custodial service, Hodl Hodl aims for peer-to-peer lending, but the platform remains part of the multi-signature smart contract to resolve any disputes.
It turns out that true trustless peer-to-peer loans are indeed possible using transaction covenants on Liquid.
When you broadcast a Bitcoin transaction, the network ensures that certain consensus rules are enforced e.g. that your transaction doesn't create (or destroy) money.
The network also verifies that you have met the spending conditions of all the transaction inputs. For standard payments this just means looking for a valid signature on the stack. If instead you're redeeming a HTLC, the preimage of a particular hash would be required.
These spending conditions are determined by a script that accompanies the UTXO to be spent. The ability to express spending conditions for a UTXO which restrict the overall form of the transaction they're included in is what is known as a covenant.
Covenant scripts are not possible on Bitcoin (yet), but they can be used on Liquid, which is as close as it gets to real Bitcoin.
Our current version of loans on Liquid looks like this:
A lender publishes loan offers somewhere on the internet.
One such offer would include: the
principal amount they are willing to lend; the required
collateral amount a borrower would need to contribute; the
interest which the borrower would need to pay in the event of reclaiming the collateral; how long the principal can be borrowed for, or
As an example, the lender could offer L-USDt-based loans, asking for L-BTC as collateral.
After a borrower accepts the loan offer, the two parties collaboratively create the
This transaction consists of 2 inputs
- the borrower's collateral, in L-BTC;
- the lender's principal, in L-USDt;
and 2 outputs
collateral contractwhere the collateral L-BTC will be locked up;
- an address controlled by the borrower, where the principal ends up.
After publishing the
loan transaction, the borrower has L-USDt to spend and the collateral remains in the
This contract enforces the conditions of the loan.
It ensures that the borrower can reclaim the collateral if and only if he pays back the
principal amount plus
interest to the lender.
Additionally, it guarantees that the lender can gain ownership of the collateral if the the borrower hasn't paid back the loan by the end of the
These constraints are expressed using Liquid's scripting language, which is an extension of Bitcoin Script.
Our implementation of the
collateral contract, together with the loan protocol, can be found in this soon-to-be-merged PR.
While the script may seem very complex, the logic is actually quite simple. It is split in two branches:
The second branch simply allows the lender to spend the
collateral contract if enough time has passed since the
loan transaction was mined.
The first branch is substantially more verbose, primarily because it represents a transaction covenant.
Instead of explaining this branch step by step, we'll try to convey the general idea.
collateral contract using this branch requires the borrower to include almost all the transaction data in the corresponding witness stack, alongside a valid
The only transaction element that is omitted is the
principal repayment output, which is instead hard-coded in the
principal repayment output is the transaction output which pays the
principal amount plus
interest to the lender.
By rearranging the stack and concatenating all the transaction elements (including the
principal repayment output) using
OP_CAT1, a correctly
serialized transaction is constructed.
OP_CHECKSIGFROMSTACK2, we verify that the
signature from the witness stack is valid for the
serialized transaction with respect to the borrower's public key.
It may seem that this is enough to prove that the borrower has constructed a transaction which includes the
loan repayment output, but we are not there yet.
The missing step is to show that the reconstructed
serialized transaction is actually equivalent to the published transaction.
OP_CHECKSIG3 with the same
signature and the borrower's public key, we can verify that the
signature is both valid for the published transaction and the reconstructed
Since signature's are specific to a single message, this demonstrates that both transactions are one and the same.
What made implementing this particularly interesting and challenging was using confidential transaction outputs. Using them, an uninvolved party cannot even tell that a loan has been issued.
The interested reader may have noticed that the implementation described above lacks one important part of a borrower-lender contract: the ability to liquidate the loan. As implemented, the borrower does not risk being liquidated if the value of the collateral drops and the LTV ratio reaches the critical threshold.
In our future work, we would like to explore exactly this and combine our simple covenant script with a DLC to allow the lender to liquidate the loan if the price (coming from an oracle) warrants it.
As the immediate next step we plan to integrate the protocol into our browser extension Waves so that it can actually be used. We are super excited about this, because we're inching closer to having truly trustless borrowing and lending for our precious Bitcoin.
Cheers, Lucas, Philipp and the rest of the COMIT Team.
PS Does the work we do sound enticing? We are hiring! Drop us an email at job at coblox.tech and tell us why you think you are a great fit.
PPS Do you want to learn more and stay up to date? Join our matrix channel: comit-liquid.
OP_CATtakes the two elements at the top of the stack and concatenates them.↩
OP_CHECKSIGFROMSTACKtakes three inputs: a signature, a message, and a public key. The opcode performs a single SHA-256 hash of the message and then checks that the signature is valid for the hashed message and the provided public key.↩
OP_CHECKSIGtakes two inputs: a public key; and a signature concatenated with the signature hash type. A double SHA-256 hash of the transaction data is computed and then verified against the signature and the public key.↩