Transaction Chaining on Cardano
Concurrency, and the solutions around it, has been a hotly debated and contentious topic within the Cardano community and beyond. In this article, we want to take a closer look at transaction chaining, the logic Optim Finance’s upcoming Liquidity Bonds will use to scale without the need for batching and without the many problems it presents.
As you might already know, the Cardano blockchain is based on the eUTXO model. This means that, unlike account-based blockchains such as Ethereum, there’s no shared global state, and all transactions occur in parallel to each other (concurrently). While this design choice brings a wide array of benefits, such as determinism, lower transaction fees and less MEV/front-running, it has also brought its fair share of difficulties to dApps that need access to a global state (such as DEXs).
As such, Cardano DEXs like Minswap or Sundaeswap have resorted to “batching” — a solution where one or a series of off-chain sequencers are in charge of aggregating (or batching) a number of UTXOs, before they are submitted on chain and executed. This off-chain batching model presents a series of outsized problems for a DeFi dApp, namely:
- Centralization: this batching model means that batchers can decide to stop processing orders and can stop the trading or the adding/withdrawing of liquidity on the DeFi dApp at any time, which is antithetical to the spirit of decentralization.
- Custodiality: related to the former, since batchers can stop the withdrawal of liquidity, this also means they have control over your funds (whether or not to let you withdraw it) once you have provided them to the DeFi protocol.
- Batcher Extractable Value (BEV): batchers can constantly sandwich attack users because they can reorder the transactions freely. They can extract BEV for free, and with no repercussions (as batchers have no competition).
For example, let’s say an order comes in to buy 1,000 $ADA of Token A with 1% slippage set, meaning it turns into a limit order for buying 990 $ADA of Token A. A batcher could use this to profit themselves by buying Token A on the market such that the price moves and the order gets executed to buy 990 $ADA of Token A. Then, after the user has bought at a markup, the batcher could sell Token A for a profit. So the batcher would buy first, move the price up, execute the order, and then sell for a profit.
In essence, the eUTXO is a novel model with plenty of advantages and caveats. While some simple solutions have been designed to deal with some of its pain points (such as concurrency) it is high time new solutions were created that allow the entire Cardano DeFi space to move forward to a more optimal, fair and decentralized state. That is precisely the aim of Transaction Chaining.
Transaction Chaining — Overview
Essentially, Transaction Chaining adds another vertical where UTXOs, instead of having to be bundled and ordered by batchers off-chain (which can lead to manipulation), are simply ordered virtually in a “first-come-first-served” manner. The Transaction Chain is created and enforced in a publicly visible, immutable, and decentralized way. As a result, instead of limiting who can consume which UTXOs, Transaction Chaining allows anyone to do so by having a system for consuming UTXOs that haven’t yet made it on-chain, essentially creating a virtual chain of transactions without the need for batching them.
We say that Transaction Chaining “adds another vertical”, because it allows for much lower latency in the processing of orders. This means that the application optimistically assumes that orders will make it on-chain, and if they don’t, then they are simply reverted without a loss of funds. Therefore, Transaction Chaining leads to a higher degree of throughput that would be otherwise possible, which can be further augmented with Input Endorsers.
The first step in creating a tx chain is transaction submission to the mempool which verifies its correctness. Once this happens a users signature is now associated with the state of a particular UTXO*. If this UTXO changes the transaction will no longer execute. Given that the transaction may only be minted if the unique, unchanged UTXO is present in the input, a clear chain of dependencies between transactions is formed. This is immutable. A user gets exactly what they ordered or the transaction is not minted.
Our partners at Liqwid Finance recently implemented Transaction Chaining themselves as well in order to help them scale their batching system. Wallets such as Typhoon have made use of Transaction Chaining too, allowing users to spend funds that are yet to be confirmed on the chain and are sitting in the mempool, which saves users time and allows them to do more transactions without having to wait for every transaction to get confirmed.
There are many applications and use cases for Transaction Chaining. In Optim Finance’s upcoming Liquidity Bonds, Transaction Chaining will be utilized to enable a new use case: the chaining of pooled funds through Pool Transaction Chaining.
Pool Transaction Chaining
Optim’s Liquidity Bonds will use Pool Transaction Chaining in order to enable several smaller actors to pool their liquidity to fulfill one bond request. Pool Transaction Chaining efficiently allows for the submission and sequential ordering of all interactions with a pool’s smart contract without having to wait for each transaction to be included in a block on chain.
An Optim Liquidity Bond is essentially a smart contract that allows for the lending and borrowing of staking rights to ADA. ADA is deposited into a smart contract, a borrower can attach their staking key to the ADA in the contract, and terms such as interest payments and duration are enforced. If terms are broken, the ADA is released from the contract. A lender receives Bond Tokens representing their lending position which are redeemable for underlying ADA + interest at the end of a Bonds duration.
Here is how Pool Transaction Chaining works in the case of an SPO Bond:
User Journey, the steps for pool creation is the following set of actions:
- A borrower (SPO) needs an $ADA Liquidity Bond (likely to delegate to themselves). Thus, the SPO puts up a bond borrow offer.
- A lender sees the bond offer and wants to lend but their balance is not enough to satisfy the entire bond offer amount by themselves.
- The bond tokens can be redeemed for the underlying $ADA plus accrued interest according to the terms of the bond offer at maturity.
- The lender can create a lending pool consisting of pool tokens. Other lenders can buy pool tokens from this pool until there are no more pool tokens to buy (the bond has been fully funded).
- The pool now contains enough $ADA to satisfy the bond offer.
- The pool is matched against the bond offer.
- Lenders can now exchange their pool equity tokens for the bond tokens.
On-chain, those steps for Pool Transaction Chaining translate to the following set of actions:
- When a lender creates a lending pool consisting of pool tokens, they are essentially minting pool tokens and sending them to UTXO → OpenPool
- When a lender buys pool tokens, then UTXO → OpenPool with pool tokens is replaced by UTXO → OpenPool with less pool tokens and more $ADA.
- When the lending pool consisting of pool tokens is filled, it is matched against the bond offer. This means, UTXO → OpenPool is spent and its $ADA goes to another UTXO at a different validator. Bond tokens are minted and sent to the UTXO → ClosedPool
- When the lender exchanges pool tokens for bond tokens UTXO → ClosedPool with bond tokens is replaced by UTXO → ClosedPool with less bond tokens and more pool tokens.
Mempool: [tx 1: (o1 -> o2) ; tx2: (o2 -> o3) ; tx3 (o3 -> o4)]
The pools are identified by the token name of the pool token, and this also exists in the datum. Therefore there should only be 1 UTXO for each pool across both OpenPool and ClosedPool script addresses.
This means that there are pool transactions that (transaction) chaining is useful for:
- Buying/Withdrawing pool tokens in a not yet filled (open) pool.
- Matching a filled pool against a borrow offer.
- Exchanging pool tokens for bond tokens in a filled and matched (closed) pool.
As explained above, transaction Chaining provides a solution for contention that is not centralized in any way. It aggressively orders the transactions before they make it on-chain. Having innovative, decentralized solutions that push transaction speed and leverage Cardano’s unique architecture is necessary to facilitate the ecosystem’s growth and ensure long-term viability.