Blog Article

Liquidity, liquidity, liquidity...


George Kudrayvtsev

Publishing date

Protocol upgrade



In early November, validators will vote on whether to upgrade the Stellar network to Protocol 18, which implements a new feature first proposed in CAP-38, aptly titled Automated Market Makers. This upcoming feature has had both the ecosystem and the Foundation buzzing for months. SDF’s "technical trident" (as I call it) tackled the problem from three perspectives: the Core team focused on integrating liquidity pool functionality deep into the protocol, the Horizon team focused on exposing their properties to developers through new API endpoints and SDK support, and the Product Engineering team made it easy to interact with them in the Laboratory. In parallel with SDF working to expose automated market making functionality, the ecosystem is working on exciting new products to leverage that same functionality and let the world take advantage of Protocol 18’s feature set on Day 1.

Though AMMs were popularized by Uniswap in 2018, this upgrade will make Stellar the first L1 blockchain to integrate AMM capabilities directly into its protocol. This means the performance, trustworthiness, and unique features of the Stellar network will all come along for the ride.One of said features is path payments, which let you combine payments and asset exchange: you send one asset, and your recipient receives another. This send-and-convert combo is possible as long as there's some path between the assets, and it’s how Stellar natively caters towards cross-border payments.

Protocol 18 will “super size” this feature, making paths easier to find, support larger quantities, and achieve exchange rates that are even more reliable. In a word, path payments will be more liquid.

Liquidity pools

If you hold asset A on the Stellar network and want to pay someone who only accepts asset B (like buying European products from the United States), you need to convert A to B by finding someone willing to make a trade. Prior to Protocol 18, that “someone” would be one or more orders on the decentralized exchange; after Protocol 18, that someone could also be a liquidity pool.

In their simplest form, liquidity pools enable exchanges for a particular trading pair: a set of two assets. They contain reserves of each asset, and the ratio of the reserves impacts the exchange rate (or price). The reserves come from participants, who deposit both assets in the pair in return for pool shares, and who can withdraw those shares to get assets back out.

A liquidity pool works by automatically adjusting its price based on how users interact with it, whether that be through deposits, withdrawals, or just exchanges. Its price curve is powered by a mathematical equation, and the first type of liquidity pool developers will be able to create on the Stellar network is controlled by what’s called a constant product price curve.

What’s a constant product, anyway?

(Anyone that follows the world of decentralized finance knows this topic is a dead horse, so feel free to skip ahead to what AMMs mean for Stellar if you don’t need yet another AMM primer.)

First manifested into the DeFi world by Uniswap, the constant product price curve preserves liquidity by forcing a particular equation to always be true (this is known as an invariant).

In theory…

A simplified form of this invariant is:

Here, L is a particular amount of liquidity, while X and Y are the initial reserves of the two assets in the pool. The idea is simple: any adjustments to one reserve should correspondingly adjust the other such that L stays the same (that is, we maintain a constant product). Visually,


For example, suppose we start with a EUR⇄USD liquidity pool with reserves of €180 and $100. This means L=18000. Then, we offer €20 to the pool; how many dollars should we get in exchange?

Our offering makes the euro reserves grow to 200, but we still need to preserve L = 18000. That means:

The pool currently has $100, so it needs to pay out $10 to preserve the constant product. In other words, I just exchanged my €20 for $10 from the pool!

Notice that this exchange rate is different (1:2) than the ratios defined by the pool (1:1.8). This is because the actual exchange rate differs based on amount: the larger the change in the final asset ratio, the larger the disparity between the "apparent" exchange rate (spot price) and the actual exchange rate. This means both large reserves and small trades lead to exchange rate stability within a particular liquidity pool.

To demonstrate this point, suppose we offered €0.10 to the pool. The amount of dollars in the pool would adjust as follows:

This is an exchange rate of around 1:1.67, a lot closer to what we would expect. Putting in just €0.01 would get us an exchange rate of 1:1.1801. In other words, the reserve ratio defines the "infinitesimal" exchange rate, but reality adjusts based on the amount exchanged.

In practice…

The actual equation is a little more complicated:

For all intents and purposes of this blog post, these differences aren’t very relevant, but we can summarize them briefly:

  • What's F? This value defines a fee for trading with the pool. These fees incentivize users to actively participate in the pool through deposits (as opposed to just passively exchanging with the pool), giving participants a chance to withdraw more liquidity than they put in. Like Uniswap, the Stellar protocol defines the fee as 0.3%, so F = 0.003.
  • What about x and y? These encode the deltas occurring in the pool that were part of the intermediate equations earlier. As we saw, x was the amount of the asset X being introduced into the pool during a particular exchange.
  • Why \(\bf\le\)? Ironically, this makes “constant product” a bit of a misnomer in the world of automatic price curves: the product isn’t constant at all anymore. This is because of the fee: the invariant now specifies that the amount of liquidity can grow over time from the initial pool reserves XY.

The first point is probably the most important: providing liquidity to a pool gives you an opportunity to pocket some of the fees incurred from its usage. For more on enabling liquidity pool participation, check back in for a Glossary entry (coming soon!) on the topic.

With our powers combined...

Now that we understand how liquidity pools work, let’s uncover their true power. By combining them alongside Stellar’s existing path payment mechanisms, something beautiful emerges. Before getting into that, though, let’s refresh our memory on how those work.

A brief aside on path payments

(This section is intended as a quick primer on the topic, feel free to skip ahead if you’re already familiar with path payments; alternatively, check out either Kolten’s write-up or the relevant operations if you’re craving more.)

Suppose, for example, that I’m a US customer (holding US dollars) and you’re a European merchant (holding euros). I want to buy something from you, but you only accept euros. As luck would have it, though, I have a couple of friends really into forex: Alice and Bob. Alice is always looking to get dollars for her Argentinian pesos, and Bob is looking to get pesos for his euros. I can trade my dollars with Alice, trade the resulting pesos with Bob, and finally pay you in euros.

This would obviously be a tedious process to do in real life, especially if there were a lot of "hops" between the assets I had and the assets you accepted. More importantly, in the real trading world, every trade impacts exchange rates, and doing a USD→ARS then a subsequent ARS→EUR trade separately might give a different exchange rate than you initially expect, because the first trade could impact the price of the second.

Path payments on the Stellar network solve these concerns. The intermediate hops necessary to make paths from assets you have to assets your recipients accept are irrelevant: I just say that I want my recipient to receive X euros for my Y dollars, and Horizon will automagically suggest efficient chains of potential trades to make that payment happen. Furthermore, the network executes the entire chain through the orderbook atomically, meaning you always lock in the current price.

This feature, coupled alongside Stellar's native support for representing any asset you can imagine, makes for an incredibly efficient payment mechanism. It also makes for a fantastic asset exchange platform, since a path payment to yourself is just a trade. So yeah, path payments through the exchange are powerful, but this isn't even their final form...

The power of liquidity pools

Like Freiza during the War on Namek, path payments will transform into something far more powerful with Protocol 18. Now, a path between any trading pair can jump both across orders in the exchange and through liquidity pools.

Let’s imagine an orderbook without liquidity pools (note that the exchange rates here are purely imaginary and used for demonstration purposes):

Finding optimal trading paths from dollars to euros by hand is a little tedious, but doable. We can trade (approximately):

Notice a fundamental limitation: We can’t get more than 7 euros by the simple virtue of the fact that there are only 7 euros for sale in the entire orderbook.

This is where the beauty of liquidity pools shine: let’s introduce one for ARS⇄EUR. We’ll start it out with 100 euros and 170 pesos.

Now, in this example not only can we get more euros overall, but we can even get better prices at certain ratios!

We tapped out the 2 EUR @ 1.7 AST order with just 3.4 pesos, but there are 6.6 more in the orderbook. We need to be careful, though: as mentioned before, liquidity pool prices depend on quantities. This pool pays out €3.75 for 6.6 pesos, but that’s a lower effective rate than what other paths through the orderbook can offer. We can buy up to 5.6 AST, though, and outperform the yen-based orders.

Overall, the potential exchanges we can make increase drastically:

This isn’t even an exhaustive list: the ellipses in the table indicate that an entire range of trades can be made as an optimal hop in a path. Each one has slightly-varying exchange rates depending on the amount, and the liquidity pool may make trades between the other “tiers” possible. The overall potential only expands as there are more reserves or liquidity pools available to exchange with.

Fundamentally, liquidity pools introduce a simple, fluid way to lock in good prices for payments and trades without relying on static orders.

If and when the validators vote for the Protocol 18 upgrade to hit the network, developers building on Stellar will be able to add new liquidity pool participation features to their applications by allowing users to create, deposit, withdraw, and (possibly!) collect fees. Developers and users alike will also enjoy increased liquidity and exchange rate reliability anywhere they already take advantage of path payments. The beauty of the seamless integration of liquidity pools into path payments is that any valid pool will automatically be considered as users make cross-border payments, exchange assets, or perform trades.

What's next?

The introduction of liquidity pool capabilities in Protocol 18 is a massive technical leap forward. Stellar is the first major network to enable them natively into its protocol, and anyone building products utilizing this new feature gets deep integration alongside everything else Stellar has to offer.

That said, the Protocol 18 version of liquidity pool functionality is really just a starting point. The protocol continues to evolve based on ecosystem feedback, and the future of liquidity pools holds a lot of potential: dynamic fees, exchanging 3+ assets per pool, different price curves, and more! The best perk of this native support for liquidity pools is seamless integration: if you just want to trade asset A for asset B via path payments, future efforts will continue to make that easier and more reliable; no changes necessary on your end. Whatever happens, you automatically gain the advantages of continued evolution and improvements to the network’s liquidity pool capabilities!

Love what you’ve seen? Head over to the Laboratory to get familiar with Protocol 18’s new operations, or check out the glossary entry for a deeper technical dive alongside accompanying SDK examples to start working with liquidity pools!