This post was first published on Medium.
Decentralized finance, or DeFi, has experienced rapid growth recently, due to its claims to solve problems inherent in legacy financial systems.
DeFi has not been associated with Bitcoin, due to the conventional wisdom that Bitcoin cannot support it.
In this series, we will demonstrate not only is DeFi feasible on Bitcoin, but also it is actually more advantageous to run DeFi on Bitcoin than on other blockchains, in terms of cost, security, composability, and scalability. We will cover DeFi infrastructure and primitives, which can be combined as lego blocks to build all kinds of DeFi applications such as exchanges, lending platform, and NFT marketplace.
In the first part of the series, we show how to implement fungible tokens and swap them atomically.
In its essence, a fungible token contract is a table/ledger. Each entry contains a user (identified as a Bitcoin public key here) and the number of tokens she owns. Optionally, an issuer can mint new tokens. The following contract implements such a basic token, similar to ERC20 token standard in Ethereum.
It is a stateful contract (Line 5), containing a table mapping each user to its token balance (Line 6).
- mint: mint new tokens and assign it to a receiver. Only the issuer (minter at Line 3) can mint new tokens, checked at Line 11. Line 13 checks the old balance of the receiver¹ and Line 14 increments it. Line 16 persists the state using OP_PUSH_TX as we always do.
- transferFrom: transfer tokens from a sender to a receiver. Line 22 authenticates the sender. Line 24 checks its balance and Line 23 ensures she has enough tokens, after which her balance is deducted and receiver’s balance is increased by the same amount. Line 30 persists the state as before.
Note that SigHash.SINGLE is used at Line 35, ensuring the contract will always be in the same indexed output as the input it is called from.
Now that we have tokens, let us swap them.
In a typical token swap, Alice trades x amount of A tokens with y amount of B tokens from Bob. In the example below, x is 10 and y is 20, meaning each A token is worth 2 B tokens.
We want to swap them atomically: either Alice receives 20 B tokens and Bob receives 10 A tokens, or neither receives any tokens. To achieve this, we leverage Bitcoin’s UTXO model: each transaction can have multiple inputs and outputs. Alice or Bob (or a third party like an exchange) creates transaction tx2. Its first and second input spends from tx0 and tx1, one of whose outputs contains the latest A and B token contract, respectively. Its first and second output contains the updated A and B token contract, respectively.
Alice can verify everything (e.g., exchange rate and amount) is correct before signing. So can Bob. It is worth noting that after one party signs (either Alice or Bob can sign first), the other party cannot alter tx2 unilaterally without invalidating the existing signature. Since a transaction can only be accepted or rejected by miners as a whole, the swap is made atomic.
Compared to Ethereum
A token swap in Ethereum usually works in two steps:
- Alice and Bob authorize a swap contract to spend a certain amount of her tokens, called approving an allowance in ERC20.
- The swap contract executes the actual exchange.
The swap contract essentially acts as a trusted third party. After step 1, a rogue contract can transfer the tokens anyway it wants and steal them. Or the swap contract has a bug that leads to approved tokens being burnt or stolen. In our token swap, users have full control of the exchange rate and amount at all time and does not have to trust a third party. It is thus non-custodial and more secure.
Watch: CoinGeek New York presentation, Smart Contracts & Computation on Bitcoin
New to Bitcoin? Check out CoinGeek’s Bitcoin for Beginners section, the ultimate resource guide to learn more about Bitcoin—as originally envisioned by Satoshi Nakamoto—and blockchain.