Whitepaper
Erratum
The original whitepaper had the following errors that have been fixed in this version.
- Numbers in Figure 1
OP_EQUALVERIFY
missing in contract appendix.
Cauldron: An efficient Constant Product Market Maker Contract on Bitcoin Cash Through Micro-Pools
Dagur Valberg Johannsson dagurval@pvv.ntnu.no https://cauldron.quest
Abstract
This paper introduces Cauldron, a novel implementation of Constant Product Market Maker (CPMM) contracts on Bitcoin Cash using a micro-pools approach. By harnessing the inherent properties of Bitcoin Cash, particularly the UTXO model's ability to hold tokens and BCH simultaneously, Cauldron enables decentralised liquidity pools tailored for the Bitcoin Cash ecosystem. The micro-pools approach circumvents the need for a global state by allowing individual users to operate their own CPMM contracts, offering unparalleled scalability. The absence of a Decentralised Exchange (DEX) in Bitcoin Cash highlights the significance of Cauldron as an essential building block for fostering a vibrant token ecosystem. Through micro-pools, Cauldron efficiently facilitates decentralised trading, which is particularly critical for a blockchain network that is actively accommodating an expanding suite of tokens.
Introduction
In recent years, Constant Function Market Makers (CFMMs) have gained popularity within decentralised finance (DeFi) as an innovative solution for providing liquidity in digital asset exchanges. CFMMs utilise a deterministic pricing rule, altering the process of liquidity provisioning for market making and democratising access to global capital pools [1].
As of this writing, Bitcoin Cash, known for its low transaction fees and scalability, does not have a native Decentralised Exchange (DEX). This paper introduces Cauldron, a CPMM implementation on Bitcoin Cash that leverages the network's unique properties.
Cauldron employs a novel micro-pools approach, allowing individual users to operate small-scale CPMM contracts. This design, taking advantage of Bitcoin Cash's UTXO model and capability to hold tokens and BCH in the same UTXO, aims for scalability and efficiency, fostering the growth of the token ecosystem on Bitcoin Cash.
The paper further details the preliminaries of Bitcoin Cash essential for Cauldron, the contract structure, and potential applications.
Bitcoin Cash Preliminaries
Bitcoin Cash employs the Unspent Transaction Output (UTXO) model. A notable feature is the capability of UTXOs to store both tokens and BCH. In Cauldron, this is exploited to ensure that the UTXO contains quantities of tokens and BCH satisfying the CPMM formula. Moreover, Bitcoin Cash’s scripting language supports introspection, a crucial building block for the contract as it combines native tokens with introspection capabilities to enforce the CPMM constraints.
CPMM Contract Structure
Micro-Pools Concept
This implementation deviates from the traditional single large liquidity pool model by utilising multiple small-scale CPMM contracts called micro-pools. Each liquidity provider operates their own set of micro-pools.
Constant Product Property
The contract adheres to the constant product formula, K = x * y, where K is the constant value, and x and y represent the quantities of tokens and BCH, respectively.
Contract Encoding and Logic
Coded in Bitcoin Cash Script, the contract enforces the constant product property. It employs introspection to ensure that the UTXO, when spent in a trade, is reconstituted in one of the transaction outputs with the constant product maintained, accounting for a small fee that accrues to the liquidity provider.
flowchart LR
cIn[
Contract with 10
TOKEN and 10 BCH
k = 10 * 10
k = 100
]
tx[
Bitcoin Cash
Transaction
]
cOut[
Contract with 9
TOKEN and 11.12 BCH
k = 9 * 11.12
k = 100]
cIn --> tx --> cOut
bchIn[
P2PKH with 11.12 BCH
]
bchOut[
P2PKH with
1 Token
]
bchIn --> tx --> bchOut
Figure 1: A trade where 1 token is purchased for BCH.
The example in figure shows a transaction trading 11.12 BCH for 1 TOKEN. First input of the transaction is a cauldron contract, and the first output replicates the contract, rebalanced but maintaining K. The second input is the BCH funding the trade and the second output is the token traded.
For withdrawing the contract, the original creator of the contract is able to bypass the CPMM constraint by providing his public key and signature.
flowchart LR
cIn[
Contract with
BCH and TOKEN
]
tx[
Bitcoin Cash
Transaction
]
tokenOut[
P2PKH with
TOKEN
]
bchOut[
P2PKH with
BCH
]
cIn --> tx
tx --> tokenOut
tx --> bchOut
Figure 2: Contract owner withdrawing all funds.
A typical withdrawal would be taking the contract as input, providing public key and signature, then having one output each for token and BCH to the user. The full contract code is provided as an appendix.
Aggregating Micro-Pools
The Cauldron contract allows for aggregation of micro-pools to increase liquidity for trades. Multiple contracts can be used as inputs, combining their liquidity. This enables a trade to be executed as though it were interacting with a larger pool.
flowchart LR
c1In[
Contract1 with
TOKEN
]
c2In[
Contract2 with
TOKEN
]
bchIn[
P2PKH with
BCH
]
tx[
Bitcoin Cash
Transaction
]
c1Out[
Contract1 with
TOKEN
]
c2Out[
Contract1 with
TOKEN
]
tokenOut[
P2PKH with
TOKEN
]
bchOut[
P2PKH with
BCH change
]
c1In --> tx
c2In --> tx
bchIn --> tx
tx --> c1Out
tx --> c2Out
tx --> tokenOut
tx --> bchOut
Figure 3: A token trade using two contracts for extra liquidity.
In a typical trade, multiple micro-pools are used as inputs along with additional inputs to fund the trade. Contract UTXOs are recreated in corresponding output positions, and additional outputs send new funds back to the user. While funds are commonly held in P2PKH UTXOs, the contract does not mandate this.
Use Cases
The primary use case for the CPMM contract is to facilitate a decentralised exchange. Additionally, it can streamline merchant payments, allowing buyers to pay in tokens they don’t hold by utilising the contract.
flowchart LR
cIn[
Contract with
USDC
]
bchIn[
Payment with
BCH
]
tx[
Bitcoin Cash
Transaction
]
cOut[
Contract with
USDC
]
merchantOut[
Merchant
payment in
USDC
]
bchOut[
BCH change to
customer
]
cIn --> tx
bchIn --> tx
tx --> cOut
tx --> merchantOut
tx --> bchOut
Figure 4: Paying a merchant in USDC, without the user owning any USDC.
For instance, a user with BCH can directly pay a merchant requesting USDC by engaging a Cauldron contract to perform the exchange within the transaction itself.
Conclusion
Cauldron's implementation of CPMM contracts on Bitcoin Cash leverages micro-pools and the Bitcoin Cash Script to efficiently facilitate decentralised exchanges and enable innovative applications in decentralised finance.
References
[1] D. Berenzon, "Constant Function Market Makers: DeFi’s 'Zero to One' Innovation," Bollinger Investment Group, Apr. 23, 2020. [Online]. Available: https://medium.com/bollinger-investment-group/constant-function-market-makers-defis-zero-to-one-innovation-968f77022159. [Accessed: June 20, 2023].
Acknowledgments
Thanks to Andrew Stone for introducing me to CPMM and suggesting its feasibility on the UTXO-based Nexa blockchain.
Thanks to Tom Harding for concept reviewing the contract.
Thanks to bitcoincashautist for reviewing and finding size optimizations in the contract.
Appendix - Cauldron contract
The following code in Bitcoin Cash Script makes up the code of the cauldron contract.
# If there is an input, it must be a pubkey and signature.
# This means that the owner wants to withdraw the contract.
OP_DEPTH,
OP_IF,
# It’s a withdrawal
OP_DUP,
OP_HASH160,
withdraw_pkh,
OP_EQUALVERIFY,
OP_CHECKSIG,
OP_ELSE,
# It's a trade
# Verify it is the correct category ID.
OP_INPUTINDEX,
OP_OUTPUTTOKENCATEGORY,
OP_INPUTINDEX,
OP_UTXOTOKENCATEGORY,
OP_EQUALVERIFY,
# Enforce version 2
# Enforcing version is to make sure that tools that
# use this contract stay compatible, when and if
# transaction format changes in the future.
OP_TXVERSION,
2,
OP_EQUALVERIFY,
# Verify that this contract lives on on the output with
# the same input as this contract.
OP_INPUTINDEX,
OP_OUTPUTBYTECODE,
OP_INPUTINDEX,
OP_UTXOBYTECODE,
OP_EQUALVERIFY,
# Calculate target K
OP_INPUTINDEX,
OP_UTXOVALUE,
OP_INPUTINDEX,
OP_UTXOTOKENAMOUNT,
OP_MUL,
# On stack: K
# Calculate fee for trade. Fee is ~0.3%.
# (abs(bch out - bch in) * 3) / 1000
OP_INPUTINDEX,
OP_UTXOVALUE,
OP_INPUTINDEX,
OP_OUTPUTVALUE,
OP_SUB,
OP_ABS,
3,
OP_MUL,
1000,
OP_DIV,
# On stack: BCH FEE, target K
# Get effective output K when including the fee.
OP_INPUTINDEX,
OP_OUTPUTVALUE,
# Subtract fee
OP_SWAP,
OP_SUB,
OP_INPUTINDEX,
OP_OUTPUTTOKENAMOUNT,
OP_MUL,
# Verify that effective K > target K
OP_SWAP,
OP_GREATERTHANOREQUAL,
OP_ENDIF