# Dynamic Function Market Makers

# Dynamic Function Market Makers

Automated Market Makers (AMMs) have been extensively studied in DeFi and usually appear in the form of Constant Function Market Makers (CFMMs). I will discuss a more general class of AMMs called Dynamic Function Market Makers (DFMMs) for which CFMMs are a special case.

**Key idea:** CFMMs maintain a constant trading function while DFMMs can allow for the trading function to change.

## What's the point?

Before I continue further, I don't want you to feel as if what you are about to read is abstract nonsense. The point of this model of DFMMs is to allow for more flexibility in the design of AMMs and to allow for more complex trading functions that can be tailored to an individual's desire. This particular design also allows for the tokenization of liquidity positions which can be used to create new financial instruments. None of what you are about to read is inherently unknown to the DeFi community, but I think that the DFMM framework presented here is a convenient formalism. Furthermore, making the mechanism design of AMMs rigorous allows for more principled analysis of their properties which in turn makes them easier to test and safer to operate.

With DFMMs, you get a derivative exposure on the tokens inside of the pool. The derivative comes in the form of a specially catered payoff curve or portfolio value function that can adjust over time and due to market state. However, you also get the benefit of being able to trade in and out of the position at any time and you do not need a counterparty. Furthermore, with tokenized LP positions, you can engage in borrowing and lending of liquidity positions which can be used to attain convex exposure. Last but not least, as now popular in DeFi, you can also use DFMMs to have a market-making-style derivative where you can also think about the location of your open two-sided orders (liquidity depth) at a given price.

With this in mind, we can consider the DFMM as a building block for decentralized portfolio management.

## Background

There are many resources discussing CFMMs, but I recommend The Geometry of Constant Function Market Makers by Angeris et. al. In essence, a key result of the paper is that a CFMM's trading function is the boundary of a convex set $S$ of reachable states and there is a unique homogeneous trading function in an equivalence class of such functions.

### Notation

We will use the following notation for a DFMM pool:

- $\varphi$ is the trading function.
- $\boldsymbol{R} = (R_1, \dots, R_n) \in \R^n_+$ are the
*reserves*. - $\boldsymbol{x} \in \mathcal{X}$ are the
*pool parameters*. - $L$ is the
*liquidity*which has dimensions of tokens. - $\boldsymbol{b} \in \mathcal{B}$ are the
*blockchain state*. For instance, this could be block number and block timestamp or even functions applied to the previous state of the pool. - $\boldsymbol{q} = (\boldsymbol{R}, L, \boldsymbol{x}, \boldsymbol{b}) \in \mathcal{Q} = \R^n_+ \times \R_+ \times \mathcal{X} \times \mathcal{B}$ is the
*pool state*. - $\ell \in \R^+$ is the
*share balance*of a pool or user. - $E \in \R^+$ is the
*share redemption rate*. - $P$ is the quoted price of the pool.
- $\gamma$ is the
*fee parameter*, i.e., a 30bps fee yields $\gamma=0.997$.

Note that I will later use $S$ for price so I apologize for the mix of notation but the context should be clear.

### Rework

Let's rework the CFMM case just slightly to prepare for the DFMM case. In the referenced work, we have $\varphi \colon \R^n_+ \to \R$ where the choice of image $k \in \R$ defines the boundary of a reachable set. Instead, consider $\varphi \colon \R^n_+ \times \R_+ \to \R$ where the second input is a liquidity parameter $L$. To define the boundary of a reachable set, we pick $L \in \R_+$ and consider $\ker \varphi(\_, L)$. That is, the set of reserves where $\varphi(\_,L) =0$ (also called the kernel) where $\_$ signifies an open input, i.e., $\varphi(\_,L) \colon \R^n_+ \to \R$.

Moving forward, we will consider the kernel of $\varphi \colon \mathcal{Q} \to \R$ for which the CFMM is a special case where pool parameters are fixed, there is no influence from the blockchain state. Prices of tokens in the pool can still be defined as a map $P \colon \mathcal{Q} \to \R^+$.

## DFMMs

Picture a DFMM as a parameterization by $\boldsymbol{q}$ of reachable sets in the set of all possible reachable sets $\mathcal{S}$. Naturally, the oracle-free parameter choices are those listed above as $\mathcal{Q}$. For posterity, $\mathcal{Q}$ can be extended to be any parameter space that is appropriate for your application at hand and could include external data feeds such as market prices or volatility.

### Scale invariance

We will work with an equivalent condition of $\varphi$ being homogeneous (as described in Angeris et. al.) in reserves as we have found this be more computationally viable. Namely, consider functions for which the reserves $\boldsymbol{R}$ such that $\varphi(\boldsymbol{R}, L, \boldsymbol{x}, \boldsymbol{b})=0$ defines a hypersurface in $\R^n$ for which $L$ is solely a scaling factor. That is, if $\boldsymbol{R}$ is a solution to

then if we scale $\boldsymbol{R}$ by $\lambda$, we have that

for some $L'$ so long as $\lambda>0$.
This condition itself is weaker than homogeneity as we are not requiring that $L'=\lambda L$.
In the case that $L'=\lambda L$, we say that $\varphi$ is *scale invariant* in the reserves and we can see this is equivalent to homogeneity of degree $1$ in the reserves.
To prove this, consider $\tilde{\varphi}(\boldsymbol{R}) - L$ where $\tilde{\varphi}(\_) = \varphi(\_,L)$.
If $\tilde{\varphi}$ is homogeneous, then

This must only be true if $\epsilon_L=0$ so by definition of $\tilde{\varphi}$ we have the result.

### Parameters

In a different scenario where the pool parameters and blockchain state changes: $\boldsymbol{x} \mapsto \boldsymbol{x}'$ and $\boldsymbol{b} \mapsto \boldsymbol{b}'$, we can determine a new value of $L'$ such that

This is to say that changing parameters while leaving reserves invariant may cause a change in liquidity parameter $L$. We have examples of this in Dollar cost averaging, Covered call below, and Liquidity tracker strategy.

### DFMMs as *state machines*

Allow us now to extend the state of the pool to include a *share balance* $\ell$ and a *share redemption rate* $E$.
Later on, this will let us tokenize liquidity positions.
By abuse of notation, we will now think of

If you'd like, you can place $\ell$ and $E$ into $\mathcal{B}$ as $\mathcal{B}$ is a bit of a catch-all for any and all blockchain state.

Let $\boldsymbol{q}_m \in \mathcal{Q}$ be the current state of the DFMM at step $m$ (including our $\ell$ and $E$ as above), then the DFMM can be thought of as a *state machine* that takes in current $\boldsymbol{q}_m$ and the next state $\boldsymbol{q}_{m+1}$ and produces $\top$ if and only if the pair $(\boldsymbol{q}_m, \boldsymbol{q}_{m+1})$ is *valid* and the machine continues the state transition and otherwise produces $\bot$ (*invalid*) and rejects the state transition, halting progress.
We use the machine's built in map $\texttt{ASSERT} \colon \{\texttt{true}, \texttt{false}\} \to \{\top, \bot\}$ where $\texttt{true} \mapsto \top$ and $\texttt{false} \mapsto \bot$.

The DFMM has two possible instructions each of which carry a payload of two states:

- $\texttt{SWAP}\colon \mathcal{Q} \times \mathcal{Q} \to \{\top, \bot\}$
- $\texttt{CHANGE\_ALLOCATION}\colon \mathcal{Q} \times \mathcal{Q} \to \{\top, \bot\}$

**Definitions.**

- ($\texttt{SWAP}$) We say that a $\texttt{SWAP}$ instruction is
*valid*if and only if the new state is in the kernel of the extended trading function $\varphi$ and if the fee yields at least $L_{m+1}$. Concretely, assuming we can determine $L_m'$ a-la Equation (1) and the tokens we tender are in the list $T$, we get the expression:

- ($\texttt{CHANGE\_ALLOCATION}$) We say that a $\texttt{CHANGE\_ALLOCATION}$ instruction is
*valid*if $\varphi(\lambda \boldsymbol{R}, L_{m+1}, \boldsymbol{x}_m, \boldsymbol{b}_m) = 0$ and if the LPTs are credited at the share redemption rate $E$. If so, then the LP is credited $\ell$ LPTs upon allocation, and debited $\ell$ LPTs upon deallocation (hence $\ell \in \R$ and not $\R^+$). Specifically:

For the $\texttt{SWAP}$ definition, I should say that determining the $L'$ from the parameter updates is not always possible analytically and may require a numerical solution such as bisection search.

For the $\texttt{CHANGE\_ALLOCATION}$, we are implicitly assuming pool parameter nor blockchain state values are changing within this instruction, though allowing for this is possible and would be a straightforward modification. Second, in the case the trading function is scale invariant, we get $L_{m+1} = \lambda L_m$. Third, it follows that the quoted price $P_{m+1}$ is equivalent to the current quoted price $P_m$. The fact that price is invariant under $\texttt{CHANGE\_ALLOCATION}$ is under the assumption that only $\texttt{SWAP}$ should lead to a change in quoted price from an AMM.

Let us illustrate these concepts with some examples.

## Examples

We will provide two examples of CFMMs and their DFMM counterparts. First is the Geometric Mean Market Maker (GMMM) and the second is the Log Normal Market Maker (LNMM).

### Geometric Mean Market Maker

The GMMM is a CFMM that maintains the following invariant:

where $w_i$ are the *weights* (i.e., $w_i$ is the portfolio weight of token $i$), and $L$ is the liquidity parameter which we can see has dimensions of tokens.
In our notation before, $\boldsymbol{x} = \boldsymbol{w}$ and $\boldsymbol{b} = \emptyset$.
We also require that $w_i \in [0,1]$ and $\sum_{i=1}^n w_i = 1$.
Finally, the fee parameter $\gamma$ is constant, and I dropped it from the notation of the pool state $\boldsymbol{q}$ for this example.

This trading function $\varphi(\boldsymbol{R},L,\boldsymbol{w})$ is scale invariant. To see this, note

**Remark.** You could consider $\tilde{\varphi}(\boldsymbol{R},L) =\prod_{i=1}^n R_i^{w_i} - L$ to be the trading function of the GMMM as the kernel is the same set and the kernel is all we need to definee when an instruction is valid.
However, computationally it is better to work with $\varphi$ as it is scale invariant in the reserves and liquidity parameter to be near 1 as opposed to $L$.
This matters for stability of numerical approximations.

Since this CFMM is scale invariant, if we change the reserves to $\lambda \boldsymbol{R}$ via $\texttt{CHANGE\_ALLOCATION}$, then this is validated if $L_{m+1} = \lambda L_m$.

#### As a DFMM

The DFMM counterpart allows for the weights be arbitrary functions of the additional parameters $\boldsymbol{b}$. We will denote the varying weights by $w_i(\boldsymbol{b})$ where $\boldsymbol{b}$ is a choice of blockchain state, i.e., we could let:

where $t$ is the block timestamp. Hence the state of our example DFMM is:

#### Dollar Cost Averaging

For simplicity, consider a pool with two tokens $X$ and $Y$ with weights solely dependent on time. That is, we have $w_X(t) = w(t)$ and $w_Y(t) = 1-w(t)$ respectively. Then the DFMM trading function is:

where $L(t)$ is the liquidity over time. As a reminder, since $w(t)$ is dynamic and reserves may not change from one step to the next, $L(t)$ will change over time along with $w(t)$ based on our discussion in Parameters.

For sake of concreteness, we can let $t \in [0,1]$ and take $w(t) = t$ so that the weights are linearly interpolated between $X$ and $Y$.
The pool will start out with $0$ weight on $X$ and $1$ weight on $Y$ and end with $1$ weight on $X$ and $0$ weight on $Y$.
This can be thought of as a means of *dollar cost averaging* from $Y$ into $X$ over time $t$.

##### Liquidity Update

Suppose that we want to update the liquidity $L(t)$ of the pool at time $t$ to $L(t')$ where $t' > t$. Then we can solve for $L(t')$ such that $\varphi(R_X,R_Y,L(t'),t')=0$. Quickly:

##### Visualization

Let's imagine now that we want to maintain the reserves $R_X$ and $R_Y$ constant over time and we want to update the liquidity $L(t)$ over time so that the reserves maintain on the graph of the trading function. For instance, if we have $w=0.2$ and $L=1$, then we can take $R_X = 1.5$, $R_Y \approx = 0.9036$ to be a point on the graph of the trading function. Now, we can update $w$ to be $0.5$ for which we would find $L\approx 1.1642$ and if we updated again to $w=0.8$, we would find $L\approx 1.3554$. See the figure below for a visualization of this process.

#### Volatility Targeting

Suppose that we want to maintain a constant volatility of the pool over time. Then we can define the volatility of the pool as the standard deviation of the price of the pool over time and if we know the volatilities of each token in the pool, we can pick a set of weights $\boldsymbol{w}$ that will allow for the pool to attempt to maintain a constant volatility. This is certainly not a new idea as Aera provides this using Balancer and decentralized parameter submitters.

### Log Normal Market Maker

The LNMM is a CFMM that maintains the following invariant:

where $\boldsymbol{q} = (R_X, R_X, L, K, \sigma, \tau, \gamma)$, $\Phi^{-1}$ is the inverse of the cumulative distribution function of the standard normal distribution, $K$ is the *mean price* of Token X with respect to Y, $\sigma$ is the *width parameter*, $\tau$ is the *time parameter*, and $\gamma$ is the fee parameter.
Note that this $\varphi$ is also scale invariant in the reserves and liquidity parameter.
Once again, we assume a constant $\gamma$ and dropped it from this notation.

Why do we call this the Log Normal Market Maker?
We call it this because if we look at the *liquidity distribution* of the pool, we see that it is log normal i.e., normally distributed in the log space:

We can see how the trading function behaves as parameters change while reserves remain constant below. In essence, when parameters change, the resulting curve may not pass through our current reserves, but we are free to rescale the curve using $L$ as a scale parameter. It is necessarily the case that the curve will pass through the reserves for some value of $L'\in \R^+$. The proof is in the picture by taking advantage of the scale invariance of the curve!

#### Covered Call

Let's consider the DFMM counterpart of the LNMM that adapts the parameters over time. Suppose that we let $\tau = T-t$ where $T$ is the time to expiry of the pool. Then the DFMM invariant is:

Now, how does, or should, $L(t)$ change over time?

First, let's plot the value of a position with respect to price $S$ with liquidity $L(t)$ at time $t$:

Note that if $L(t)=L$ then $V(S,t)$ the value of the Black-Scholes Covered Call strategy.

In order for $L(t)$ to be constant while $T-t$ decreases, we actually have to effectively increase the reserves $R_X$ and $R_Y$. This is only possible if we apply a fee upon the $\texttt{SWAP}$ instruction. Suppose that a user wishes to call $\texttt{SWAP}$ with a new state $\boldsymbol{q}_{t'}$, we can define that if we have $L_t$ that

if the user was swapping in token $X$. This is what we specified in Equation (2) for the $\texttt{SWAP}$ instruction. Also, note that I now parameterized $\boldsymbol{q}$ using $t$ and $t'$ instead of $m$ and $m+1$ for convenience due to the explicit dependence on time in this mechanism.

From this, we can define the trading rule for a valid $\texttt{SWAP}$ of the Replicating Portfolio for the Covered Call strategy:

- Update the parameter $\tau = T-t'$ for the new time $t'$, hold reserves constant, and solve to get a new liquidity $L'$ such that $\varphi(R_X,R_Y,L',t')=0$.
- Assert that for $\boldsymbol{q}_{t'} = (R_X+\delta_X, R_Y+\delta_Y,L' + \delta_L, t')$ satisfies $L' + \delta_L \geq L$ Given (1) and (2), we can see that $V(S, t)$ achieves the payoff of at least the Black-Scholes Covered Call strategy. Keep in mind this $\delta_L$ comes from Equation (4) above and depends on the fee and trade size.

This extra need to accrue liquidity over time as it is diminished by $t$ approaching $T$ is equivalent to the positive theta of the Covered Call strategy. Supposing that $L(T) > L(0)$ and no allocations or deallocations were made, then this contributes extra value to the pool that can be thought of as akin to earning a portion of the options premium on the Covered Call over time.

**Remark.** It is likely not worth enforcing this strict trading rule above as it can lead to the pool being driven into a "dead" state.
If it took too long for swaps to occur on the pool, then the pool is effectively behind in its liquidity accrual and thus you require a larger and larger fee revenue on a single swap to get past this gap the longer you wait.
Instead, it's best to just ignore this condition and let the pool accrue liquidity as it can.

#### Liquidity Tracker Strategy

For a second example using LNMM, we can consider a strategy that tracks the liquidity distribution of the pool over time to the emergent token behavior. Current price is intrinsic to the LNMM (and so it falls into block state) and from this we can build a DFMM model that moves and scales the liquidity distribution of the LNMM to track the current price and volatility of the pool. Further, this strategy could employ a dynamic fee parameter $\gamma$ to track the volatility of the pool, so we include this explicitly now in $\boldsymbol{q}$.

Take the LNMM with constant $\tau=1$ and take $K_0$ and $\sigma_0$ to be initially chosen parameters for the pool. Then, we can define the state of the DFMM via $\boldsymbol{q} = (R_X,R_Y,L,K,\sigma,P,\gamma)$. We assert additional conditions on $\texttt{SWAP}$:

- $P_m=K_m$ for all $m$ (including $m=0$).
- $\sigma_{m+1} = \frac{|P_{m+1} - P_m|}{P_{m}(t_{m+1}-t_m)}$ where $\sigma_{m+1}$ will have volatility in the same units of time as $t_m$ which is the block timestamp at step $m$. This must be picked for $m=0$ by hand. Further, $\sigma$ could be averaged out over a history of price changes if desired.
- $\gamma_{m+1} = 1-\exp(\frac{1}{2}\lambda |P_{m+1}-P_m|)$ so that the fee increases for larger price impact trades and the rate of increase is based on a choice of $\lambda$. See exponential distribution.

**Remark.** This choice of fee parameter was chosen somewhat arbitrarily, but it has the effect of disuading swaps from occuring in periods of high volatility and compensating LPs more for the risk of high volatility.
Perhaps it is somewhat like a soft circuit breaker.

We can see what an example of this would look like. If we had a market consistently increasing in volatility while the price also increased, our liquidity distribution would adjust like so: This specific case increased both $K$ and $\sigma$ as time moved on. If you wanted to, you could set a parameter range like this for shorter term liquidity management if you expect price to increase, but assume there is random motion in the market (i.e., this matches a drift-diffusion model).

## Tokenization

I mentioned previously that this DFMM framework allows for the tokenization of liquidity positions in a pool and we materialized this a bit in the $\texttt{CHANGE\_ALLOCATION}$ instruction (see Equation (3)). With our framework, DFMM Liquidity Provider Tokens (LPTs) are fungible and can be traded on secondary markets, including placed into other DFMMs, or lent out as collateral, or used as a margin balance. When calling $\texttt{CHANGE\_ALLOCATION}$, the user must specify the amount of liquidity they wish to add or remove $\delta_L$ from the pool as the pool need to handle the reserves and pass the state transition. As worked out before, the amount of reserves added or removed will scale accordingly.

An LP, Alice, will maintain a balance of shares $\ell_{\textrm{Alice}}$ (credited to them on allocation) that represent their claim on the pool's liquidity $L$. The pool itself also tracks an $\ell_{\textrm{Pool}}$ for how many shares (or LPTs) have been created for the pool. Therefore if $L$ changes there must be a change in the redemption rate $E$ that is used to convert the pools share balance $\ell_{\textrm{Pool}}$ to $L$ in order to properly credit the LP such as Alice with the correct amount of underlying tokens upon deallocation.

### The process

Upon pool initialization, we can make the assumption that the initial liquidity $L_0$ is the same as the initial share balance of the pool $\ell_{\textrm{Pool},0}$ and therefore the initial liquidity redemption rate is $E_0=1$. If Alice is the LP who allocated this $L_0$ is given back

LPTs.

**Parameter change:**If the parameters of the pool change, then we note that $L$ must change as well. Let's assume that the parameter change occurs in the first step, we have $L_0 \mapsto L_1$ and therefore the redemption rate $E_0 \mapsto E_1 = \frac{L_1}{L_0}$. This means that $\ell_{\textrm{Pool}, 0} \cdot E_1 = L_1$. Of course, Alice can use her $\ell_{\textrm{Alice}} = \ell_{\textrm{Pool},0}$ LPTs to make claim on the whole pool, i.e., the new liquidity $L_1$.**Swap:**If a swap instruction occurs, then if a fee is applied on the swap, then $L$ will change again. Assume that this happens at the first step, then we again just have $L_0 \mapsto L_1$ and $E_0 \mapsto E_1 = \frac{L_1}{L_0}$.

The two cases above resolve to the same problem in tracking change of liquidity that isn't due to an allocation. This is done by keeping an redemption rate $E$ between LPTs $\ell$ and pool liquidity $L$.

**Liquidity (de)allocation:**In the case that liquidity is allocated at step $m$ to $m+1$, we will know that $E_m$ is the redemption rate. Suppose a new user, Bob, creates a $\texttt{CHANGE\_ALLOCATION}$ instruction with a $\delta_L = L_{m+1} - L_{m}$, then there is a credit/debit of $\ell_{\textrm{Bob}} = \frac{\delta_L}{E_m}$ LPTs to the user's account. The total share balance of the pool is $\ell_{\textrm{Pool}, m+1} = \ell_{\textrm{Alice}} + \ell_{\textrm{Bob}}$.

Tokenization of DFMM positions provides a new way to compose DeFi tools together and create new products. This design space is quite open and I am excited to see what people come up with.

## Wrapping up

This post was meant to be a formal overview of DFMMs and I hope that it has been helpful. If you would like to see implementation details of DFMMs, please see the DFMM-based contracts in the Excalibur repository. Throughout the repo, you can find more details on these two examples as well a Arbiter simulations that are being completed. We plan to rigorously test our implementations and once we are confident in their safety, we will have them deployed. Stay tuned to see some specific instruments we build using DFMMs as primitives. Please get in touch by joining our Discord server if you have any questions or would like to build on top of the DFMM framework.