← All news

The Liquidity Baking contract explained

Understand how the Liquidity Baking contract works and the features it offers

The Liquidity Baking contract explained

What is the Liquidity Baking contract?

The Granada upgrade introduced a new tool on the Tezos blockchain: the Liquidity Baking contract. This is a constant product market-making (or CPMM) decentralized exchange contract (or DEX) for the XTZ/tzBTC pair. It allows users to exchange XTZ for tzBTC and vice-versa at rates similar to those found for the XTZ/BTC pair on centralized exchanges, with some caveats.

Note: the liquidity baking contract may be referred as the “LB” contract in the rest of this article.

One of the main features of the LB contract is the constant and automatic provision of XTZ tokens to the DEX. Every time a block is baked on the Tezos blockchain, 1/16th of the rewards for a block is added to the XTZ pool of the DEX by calling its default entrypoint. At the time of writing, the rewards are 40 tez, which equals 2.5 tez per block.

Being a CPMM DEX, the liquidity baking contract uses a fairly simple mechanism to calculate the price of the tokens: any trade happening in the contract must change the liquidity pools in such a way that the product of those pools remains unchanged, i.e the product must be equal to a constant value. In other terms,xtz_pool * tzbtc_pool must always equal the same value, whatever may be the changes in the XTZ or the tzBTC supplies.

This quote explains exactly how these 2 values are maintained in balance (found in this article about CFMMs and CPMMs):

[CPMMs] are often used for secondary market trading and tend to accurately reflect, as a result of arbitrage, the price of individual assets on reference markets. For example, if the [CPMM] price is less than the reference market price, arbitrageurs will buy the asset on the [CPMM] and sell it on an order book-based exchange for a profit.

As a CPMM DEX, the LB relies on liquidity providers to fund the liquidity pool and on market participants taking advantage of arbitrage opportunities to maintain an accurate exchange rate. The unique subsidy added to the LB with each block baked can help create incentives for both liquidity providers and market participants to interact with the LB.

Whether you are connected to the Tezos mainnet or a testnet, the address of the liquidity baking contract is always the same: KT1TxqZ8QtKvLu3V3JH7Gx58n7Co8pgtpQU5. This makes it very easy to find on testnets after every update, but it can be a source of errors if you are looking at the wrong network. Let’s have a look at the storage of the contract!

Storage

The storage of the LB contract is pretty simple and made of 5 values:

  • tokenPool : a value of type nat (i.e a positive number) that represents the amount of token (in this case, tzBTC) held by the contract
  • xtzPool : a value of type mutez (i.e an amount of tez) that represents the amount of XTZ held by the contract
  • lqtTotal : a value of type nat that represents the amount of liquidity tokens (or LB tokens) the contract holds. The LB token is an FA1.2 token with its own contract that represents a pair of tokens consisting of XTZ and tzBTC provided to the contract as liquidity
  • tokenAddress : a value of type address (i.e the address of an implicit account or a contract) that holds the address to the tzBTC contract
  • lqtAddress : a value of type address that holds the address of the LB token

These five simple values are everything the contract needs to know in order to process exchange and liquidity provision transactions.

Entrypoints

The LB contract exposes 6 entrypoints necessary for the general functioning of the DEX: one entrypoint called to update the xtzPool value every time the 2.5 tez subsidy is added to the contract, two entrypoints to add and remove liquidity, and the last entrypoints to exchange XTZ for tzBTC and vice-versa.

Note: an “entrypoint” is a function of a smart contract used to interact with the contract from outside the blockchain. Entrypoints receive operations that are processed by the contract in order to update the state of the contract.

The structure of the contract is pretty simple, but its power comes from the code of each entrypoint that accomplishes complex operations to keep the LB contract safe and balanced:

- Default:

The %default entrypoint is called at each new block to add 2.5 tez to the contract and update the xtzPool value accordingly.

- XtzToToken:

The %xtzToToken entrypoint allows users to exchange XTZ for tzBTC. It takes 3 parameters: the address to send the newly bought tokens to, the minimum amount of tokens to buy, and a deadline for the transaction, along with an amount of XTZ to buy the tokens.

After checking that the deadline hasn’t expired, the entrypoint calculates the amount of XTZ to exchange for the provided amount of tzBTC, as well as the burn fee. The xtzPool and tokenPool are updated accordingly in the storage before a new transaction is forged to credit the user’s account with tzBTC tokens.

- TokenToXtz:

The %tokenToXtz entrypoint is the opposite version of the previous entrypoint, it exchanges tzBTC for XTZ. The entrypoint takes 4 parameters: the address to send the XTZ to, the amount of tzBTC tokens to be sold, the minimum amount of XTZ tokens to be bought, and a deadline.

After checking that the deadline hasn’t expired and that the amount of XTZ is not zero, the contract calculates the amount of XTZ to be sent according to the amount of tzBTC that will be sold. The burn fee is calculated and 3 operations are forged before being broadcasted: 1 operation to transfer the user’s tzBTC tokens to the contract, 1 operation to send the XTZ to the user’s account, and 1 operation to burn XTZ. Then, the liquidity pool values for XTZ and tzBTC are updated.

- TokenToToken:

The %tokenToToken entrypoint is a special entrypoint that facilitates the exchange of tokens between two contracts that use the LB contract as an intermediate. Calling this entrypoint is the equivalent of calling %tokenToXtz in the first contract followed by %xtzToToken in the second. The workings of these two entrypoints are explained above.

- AddLiquidity:

The %addLiquidity entrypoint allows users to provide both XTZ and tzBTC tokens to the exchange. After providing these two tokens, the users receive a liquidity provider token (or LP token) that represents the liquidity added to the XTZ and tzBTC pools. However, the price of the LPT is calculated based on the values of the XTZ and tzBTC pools, so it may change over time.

The entrypoint requires four parameters: the account address that will be credited with the LP tokens, the minimum amount of LP tokens that must be minted, the maximum amount of tzBTC tokens to be deposited into the contract and the deadline. This entrypoint also expects an amount of XTZ to be sent with the transaction.

After checking that the deadline is not expired, the entrypoint calculates internally the amount of LP tokens to be credited to the user. If this amount is less than the minimum value provided in the parameters, the different values of the pools are updated in the storage, the tzBTC tokens are transferred to the contract and the user is credited with LP tokens that are redeemable through the %removeLiquidity entrypoint.

- RemoveLiquidity:

The %removeLiquidity entrypoint can be called to redeem an amount of liquidity provider tokens for its corresponding XTZ and tzBTC values.

The entrypoint takes five parameters: the account address to credit with XTZ and tzBTC tokens, the amount of LP tokens to be burned, the minimum amount of XTZ to be withdrawn, the minimum amount of tzBTC tokens to be withdrawn, and a deadline.

As it was the case for the other entrypoints, the contract first checks whether the deadline is still valid. If that’s the case, the contract also verifies that no tez has been sent along the transaction. Then, the amounts of XTZ and tzBTC to be credited are calculated internally before being compared to the values provided by the user. If everything checks out, the new values for the LP pool, the XTZ pool and the tzBTC pool are calculated, the storage is updated and 2 new transactions are forged: one to send XTZ to the account address provided in the parameters and one to send it tzBTC.

Sunset level and escape hatch

The liquidity baking contract includes two security measures in order to operate properly. The first one is called the sunset level. The sunset level is a period after which the contract stops receiving its subsidy after each block is baked. At the time of writing this article, the sunset level is 6 months. This period can be renewed by protocol amendment.

Note: The sunset level period was extended during the Hangzhou upgrade to take into account various delays that can happen with upgrades in order to avoid the expiry of the subsidy before a new upgrade of the protocol is injected.

In addition to the sunset level, the LB contract features an escape hatch. Every time a block is baked, the baker can choose to add a flag to the block to request the end of the subsidy. The flag is persisted to the next blocks and more bakers can add their own flag. If enough bakers add their flag to blocks, the escape hatch is activated and the subsidy ends. Later on, the subsidy can be reactivated by protocol amendment.

Documents of interest