Skip to main content

Overview

In this version of the ALTBC we incorporate liquidity additions and liquidity withdrawals. Trading works in a similar way as in the ALTBC v1.1. In order to process liquidity additions and liquidity withdrawals we will need to mint and burn NFTs that have two fields: amount and last_revenue_claim. These NFT will play the role of the LP tokens.

Definitions

Initialization Parameters

DescriptionVariableDefinition or bounds
Initial amount of tokens to be deposited into the TBCxaddx_{\textnormal{add}}xadd>0x_{\textnormal{add}} > 0
The yy-intercept upon initialization of the TBCplowerp_{\textnormal{lower}}plower0p_{\textnormal{lower}}\geq 0
Vector Field ParameterVVV>0V > 0
Initial Concentration parameterC0C_0C0>0C_0 > 0
The initial minimum value of the variable xxxmin(0)x_{\textnormal{min}}^{(0)}xmin(0)>0x_{\textnormal{min}}^{(0)} > 0
The quantity of liquidity units assigned to the deployer at pool initializationW0W_0W0>0W_0 > 0
The quantity of the deployer’s inactive liquidity units at launchW0IW_0^IW0>W0I0W_0 > W_0^I \geq 0
Initial trading feeϕ0\phi_0ϕ00\phi_0 \geq 0
Initial protocol feeψ0\psi_0ψ00\psi_0 \geq 0

Functions

We will now define some functions that will be used several times throughout the spec. D(xn+1,bn,cn)=12bnxn+12+cnxn+1{\bf D}(x_{n+1},b_n,c_n) = \frac{1}{2} b_n x_{n+1}^2 + c_n x_{n+1} b(xn,Cn,V)=Vxn+Cn{\bf b}(x_n, C_n, V) = \frac{V}{x_n + C_n} c(xn+1,bn+1,bn,cn)=12(bnbn+1)xn+1+cn{\bf c}(x_{n+1},b_{n+1},b_n,c_n) = \frac{1}{2} (b_n - b_{n+1}) x_{n+1} + c_n p(xn,bn,cn)=bnxn+cn{\bf p}(x_n,b_n,c_n) = b_n x_n + c_n L(xn,bn,cn,xmin(n),Cn,V)=12xmin(n)(bnxn+2cn+Vln(xmin(n)+Cnxn+Cn)){\bf L}(x_n,b_n,c_n,x_{\textnormal{min}}^{(n)},C_n,V) = \frac{1}{2} x_{\textnormal{min}}^{(n)} \left( b_n x_n + 2 c_n + V \cdot \ln\left(\frac{x_{\textnormal{min}}^{(n)} + C_n}{x_n + C_n}\right) \right) h(xn,bn,cn,xmin(n),Cn,V,Wn,WnI,Φn,Zn)=L(xn,bn,cn,xmin(n),Cn,V)+ZnWnWnI+Φn{\bf h}(x_n,b_n,c_n,x_{\textnormal{min}}^{(n)},C_n,V,W_n, W_n^I, \Phi_n, Z_n) = \frac{{\bf L}(x_n,b_n,c_n,x_{\textnormal{min}}^{(n)},C_n,V) + Z_n}{W_n - W_n^I} + \Phi_n In the formula for L\bf{L}, the ln\ln denotes the natural logarithm function.

State variables (TBC maintained quantities)

DescriptionVariableInitial value
Vector Field ParameterVVVV, Note: In this spec, this variable remains constant. We omit the subscript n.
Value of the variable xx before the nn–th transactionxnx_nx0=xmin(0)x_0=x_{\textnormal{min}}^{(0)}
Area under the TBC curve over the interval [0,xn][0,x_n] before the nn–th transactionDnD_nD0=D(xmin(0),b(0,C0,V0),plower)D_0={\bf D}(x_{\textnormal{min}}^{(0)},{\bf b}(0,C_0, V_0),p_{\textnormal{lower}})
Value of the parameter bb before the nn–th transactionbnb_nb0=b(xmin(0),C0,V0)b_0= {\bf b}(x_{\textnormal{min}}^{(0)}, C_0, V_0)
Value of the parameter cc before the nn–th transactioncnc_nc0=c(xmin(0),b(xmin(0),C0,V0),b(0,C0,V0),plower)c_0={\bf c}(x_{\textnormal{min}}^{(0)}, {\bf b}(x_{\textnormal{min}}^{(0)}, C_0, V_0), {\bf b}(0, C_0, V_0), p_{\textnormal{lower}})
Spot price before the nn–th transactionpnp_np0=p(xmin(0),b0,c0)p_0={\bf p}(x_{\textnormal{min}}^{(0)},b_0,c_0)
Concentration parameterCnC_nC0C_0
Minimum value of the variable xxxmin(n)x_{\textnormal{min}}^{(n)}xmin(0)x_{\textnormal{min}}^{(0)}
Maximum value of the variable xxxmax(n)x_{\textnormal{max}}^{(n)}xmax(0)=xmin(0)+xaddx_{\textnormal{max}}^{(0)}=x_{\textnormal{min}}^{(0)} + x_{\textnormal{add}}
Sum of the amount fields of all the NFTs minted by the poolWnW_nW0W_0
The quantity of the deployer’s inactive liquidity unitsWnIW_n^IW0IW_0^I
A balancing quantity that needs to be added to LL for fair LP fee accountingZnZ_nZ0=0Z_0=0
Trading fee ratioϕ\phiϕ0\phi_0, Note: In this spec, this variable remains constant. We omit the subscript n.
Protocol fee ratioψ\psiψ0\psi_0, Note: In this spec, this variable remains constant. We omit the subscript n.
Claimable trading fee per liquidity unitΦn\Phi_n00
Total protocol feeΨn\Psi_n00
Notational Notes: In some steps below, to simplify notation, we will use SnS_n to denote the collection of state variables before the nn-th transaction. If there is no ambiguity, we might write hn=h(Sn)h_n=\textbf{h}(S_n) to mean, in plain language, “we are defining hnh_n to be the value of the function h\textbf{h} using the relevant state variable values from SnS_n” instead of writing out explicitly hn=h(xn,bn,cn,xmin(n),Cn,V,Wn,WnI,Φn,Zn)h_n=\textbf{h}(x_n,b_n,c_n,x_{\textnormal{min}}^{(n)},C_n,V,W_n, W_n^I, \Phi_n, Z_n) For another example, we might write pn+1=p(Sn+1)p_{n+1}=\textbf{p}(S_{n+1}) instead of writing pn+1=p(xn+1,bn+1,cn+1)p_{n+1}=\textbf{p}(x_{n+1},b_{n+1},c_{n+1}) The NFT with amount field value equal to aa and last_revenue_claim field value equal to rr will be denoted by NFT({amount ⁣:a, last_revenue_claim ⁣:r})\textbf{NFT}(\{\texttt{amount}\colon a,\ \texttt{last\_revenue\_claim}\colon r\}) In addition, the value of the last_revenue_claim field of the NFT jj at step nn will usually be denoted by rj(n)r_j^{(n)}. Recall that these values are not tracked by the pool since they are stored in the corresponding NFT.

Transactions

Pool initialization

When the pool is initialized, the state variables are defined as described in the previous table. In addition, an amount xaddx_{\textnormal{add}} of tokens must be deposited into the pool. For reference in what follows, D0=D(xmin(0),b(0,C0,V0),plower)D_0 = {\bf D}(x_{\textnormal{min}}^{(0)},{\bf b}(0,C_0, V_0),p_{\textnormal{lower}}) Two NFTs must be minted and given to the pool deployer (or game owner) upon initialization of the pool. The first will have amount field value equal to W0W0IW_0 - W_0^I and last_revenue_claim field value equal to D0W0W0I\frac{D_0}{W_0 - W_0^I}. With our notation, this NFT is NFT({amount ⁣:W0W0I, last_revenue_claim ⁣:D0W0W0I})\textbf{NFT}(\{\texttt{amount}\colon W_0 - W_0^I,\ \texttt{last\_revenue\_claim}\colon \frac{D_0}{W_0 - W_0^I}\}) The second, which will henceforth be referred to as the inactive-fee NFT (and which is unique in this way), will have amount field value equal to W0IW_0^I and last_revenue_claim field value equal to \infty. With our notation, this NFT is NFT({amount ⁣:W0I, last_revenue_claim ⁣:})\textbf{NFT}(\{\texttt{amount}\colon W_0^I,\ \texttt{last\_revenue\_claim}\colon \infty\}) Note that \infty can be replaced by any appropriate number or object that handles the following three actions appropriately for the inactive-fee NFT: 1. Extracting revenue: the transaction should be immediately reverted (described below). 2. Withdrawing liquidity: the transaction is allowed with some modifications (described below - for example, step 8 in Liquidity withdrawals). 3. Adding liquidity: the transaction should be immediately reverted (described below). We emphasize that a pool may have at most one inactive-fee NFT at any stage in its lifetime. The deployer must mint one at inception and if this inactive-fee NFT is liquidated by the deployer, there will never be another.

Trades

Suppose that the nn-th trade comes into the pool, and that the current values of the state variables is SnS_n. We perform the trade using the algorithm defined by the following steps. Step 1. We update the state variables xnx_n and DnD_n according to four different situations as described below.
  • If the user submits an order to buy an amount an>0a_n > 0 of token XX, we check that
xn+anxmax(n)x_n + a_n \leq x_{\textnormal{max}}^{(n)} If this condition does not hold, we do not perform the transaction. Otherwise, if the previous condition holds, we update the parameters xx and DD as follows. xn+1=xn+anDn+1=D(xn+1,bn,cn)\begin{aligned} x_{n+1} & = x_n + a_n \\ D_{n+1} & = {\bf D}(x_{n+1},b_n,c_n) \end{aligned} In this case, we define Uin=Dn+1Dn1ϕψU_{\textnormal{in}} = \frac{D_{n+1} - D_n}{1 - \phi - \psi} and an amount UinU_{\textnormal{in}} of collateral is transferred from the user to the pool, and an amount ana_n of token XX is transferred from the pool to the user. In addition, the state variables Φn\Phi_n and Ψn\Psi_n are updated as follows: Φn+1=Φn+ϕUinWnWnIΨn+1=Ψn+ψUin\begin{aligned} \Phi_{n+1} &= \Phi_n + \frac{\phi \cdot U_{\textnormal{in}}}{W_n - W_n^I} \\ \Psi_{n+1} &= \Psi_n + \psi \cdot U_{\textnormal{in}} \end{aligned}
  • If the user submits an order to sell an amount an>0a_n > 0 of token XX, we check that
xnanxmin(n)x_n - a_n \geq x_{\textnormal{min}}^{(n)} If this condition does not hold, we do not perform the transaction. Otherwise, if the previous condition holds, we update the parameters xx and DD as follows. xn+1=xnanDn+1=D(xn+1,bn,cn)\begin{aligned} x_{n+1} & = x_n - a_n \\ D_{n+1} & = {\bf D}(x_{n+1},b_n,c_n) \end{aligned} The trading fee and protocol fee are defined, respectively, as M=ϕ(DnDn+1)N=ψ(DnDn+1)\begin{aligned} M& = \phi \cdot (D_{n} - D_{n+1}) \\ N & = \psi\cdot(D_{n} - D_{n+1}) \end{aligned} The state variables Φn\Phi_n and Ψn\Psi_n are updated as follows: Φn+1=Φn+MWnWnIΨn+1=Ψn+N\begin{aligned} \Phi_{n+1} &= \Phi_n + \frac{M}{W_n - W_n^I} \\ \Psi_{n+1} &= \Psi_n + N \end{aligned} Then, the amount ana_n of token XX is transferred from the user to the pool, and the amount (DnDn+1)MN(D_{n} - D_{n+1}) - M -N of collateral is transferred from the pool to the user (with the latter two terms representing LP and protocol fees collected by the pool rather than transferred to the user).
  • If the user submits an order to buy an amount Uout>0U_{\textnormal{out}} > 0 of token YY (collateral), we define
an=Uout1ϕψa_n = \frac{U_{\textnormal{out}}}{1 - \phi - \psi} and we check that DnanD(xmin(n),bn,cn) .D_{n} - a_n \geq {\bf D}(x_{\textnormal{min}}^{(n)},b_n,c_n) \ . If this condition does not hold, we do not perform the transaction. Otherwise, if the previous condition holds, we update the parameters xx and DD as follows. Dn+1=Dnanxn+1=2Dn+1cn+cn2+2bnDn+1\begin{aligned} D_{n+1} & = D_n - a_n \\ x_{n+1} & = \dfrac{2 D_{n+1}}{c_n + \sqrt{c_n^2 + 2 b_n D_{n+1}}} \end{aligned} In this case, an amount xnxn+1x_{n} - x_{n+1} of token XX is transferred from the user to the pool, and an amount UoutU_{\textnormal{out}} of collateral is transferred from the pool to the user. In addition, the state variables Φn\Phi_n and Ψn\Psi_n are updated as follows: Φn+1=Φn+ϕanWnWnIΨn+1=Ψn+ψan\begin{aligned} \Phi_{n+1} &= \Phi_n + \frac{\phi \cdot a_n}{W_n - W_n^I} \\ \Psi_{n+1} &= \Psi_n + \psi \cdot a_n \end{aligned}
  • If the user submits an order to sell an amount Uin>0U_{\textnormal{in}} > 0 of token YY (collateral), we define the trading fee and protocol fee, respectively, by
M=ϕUinN=ψUin .\begin{aligned} M& = \phi \cdot U_{\textnormal{in}} \\ N & = \psi \cdot U_{\textnormal{in}}\ . \end{aligned} Then, we update the state variables Φn\Phi_n and Ψn\Psi_n are updated as follows: Φn+1=Φn+MWnWnIΨn+1=Ψn+N .\begin{aligned} \Phi_{n+1} &= \Phi_n + \frac{M}{W_n - W_n^I} \\ \Psi_{n+1} &= \Psi_n + N\ . \end{aligned} Then, we define an=UinMNa_n = U_{\textnormal{in}} - M - N and we check that Dn+anD(xmax(n),bn,cn) .D_{n} + a_n \leq {\bf D}(x_{\textnormal{max}}^{(n)},b_n,c_n) \ . If this condition does not hold, we do not perform the transaction. Otherwise, if the previous condition holds, we update the parameters xx and DD as follows. Dn+1=Dn+anxn+1=2Dn+1cn+cn2+2bnDn+1\begin{aligned} D_{n+1} & = D_n + a_n \\ x_{n+1} & = \dfrac{2 D_{n+1}}{c_n + \sqrt{c_n^2 + 2 b_n D_{n+1}}} \end{aligned} In this case, an amount UinU_{\textnormal{in}} of collateral is transferred from the user to the pool, and an amount xn+1xnx_{n+1} - x_n of token XX is transferred from the pool to the user. Step 2. We update the state variables bnb_n and cnc_n as follows bn+1=b(xn+1,Cn,V)cn+1=c(xn+1,bn+1,bn,cn) .\begin{aligned} b_{n+1} & = {\bf b}(x_{n+1}, C_n, V) \\ c_{n+1} & = {\bf c}(x_{n+1},b_{n+1},b_n,c_n)\ . \end{aligned} Step 3. We update the spot price pnp_n as pn+1=p(Sn+1) .p_{n+1} = {\bf p}(S_{n+1}) \ . The remaining state variables do not have to be updated.

The revenue parameter

In order to enable liquidity providers to collect their corresponding share of revenue and fees from the pool, we introduce the revenue parameter function, which is defined by h(xn,bn,cn,xmin(n),Cn,V,Wn,WnI,Φn,Zn)=L(xn,bn,cn,xmin(n),Cn,V)+ZnWnWnI+Φn{\bf h}(x_n,b_n,c_n,x_{\textnormal{min}}^{(n)},C_n,V,W_n, W_n^I, \Phi_n, Z_n) = \frac{{\bf L}(x_n,b_n,c_n,x_{\textnormal{min}}^{(n)},C_n,V) + Z_n}{W_n - W_n^I} + \Phi_n Now, if xn,bn,cn,xmin(n),Cn,V,Wn,WnI,Φn,Znx_n,b_n,c_n,x_{\textnormal{min}}^{(n)},C_n,V,W_n, W_n^I, \Phi_n, Z_n are the current values of the corresponding pool variables, we define the current revenue parameter (per unit of amount) as hn=h(xn,bn,cn,xmin(n),Cn,V,Wn,WnI,Φn,Zn) .h_n = {\bf h}(x_n,b_n,c_n,x_{\textnormal{min}}^{(n)},C_n,V,W_n,W_n^I,\Phi_n, Z_n) \ . It is important to mention that this parameter is invariant with respect to proportional liquidity deposits and liquidity withdrawals.

Liquidity deposits

Let SnS_n be the current values of all state variables. Suppose that a user wants to provide liquidity to the pool approving up to amounts A~0\tilde A \geq 0 of token XX and B~0\tilde B \geq 0 of collateral, with (A~,B~)(0,0)(\tilde A, \tilde B) \neq (0,0). Before proceeding, check if the deposit is associated with the inactive-fee NFT. If so, revert the transaction. In all other cases, in order to process this liquidity deposit we proceed as follows. Step 1. We will determine the amounts AA and BB of the respective tokens that will actually be taken so that the liquidity deposit is proportional. Let Ln=L(Sn)L_n = {\bf L}(S_n). If B~(xmax(n)xn)A~(DnLn),\tilde B \cdot \left (x_{\textnormal{max}}^{(n)}- x_n\right ) \leq \tilde A \cdot \left (D_n - L_n \right ), then set B=B~A={xmax(n)xnDnLnB~, if DnLn0A~, if DnLn=0q={BDnLn, if DnLn0Axmax(n)xn, if DnLn=0 .\begin{aligned} B &= \tilde B \\ A &= \begin{cases} \frac{x_{\textnormal{max}}^{(n)}- x_n}{D_n - L_n} \cdot \tilde B, &\text{ if } D_n - L_n \neq 0 \\ \tilde A, &\text{ if } D_n - L_n = 0 \\ \end{cases} \\ q &= \begin{cases} \frac{B}{D_n - L_n}, &\text{ if } D_n - L_n \neq 0 \\ \frac{A}{x_{\textnormal{max}}^{(n)}- x_n}, &\text{ if } D_n - L_n = 0 \ . \\ \end{cases} \\ \end{aligned} If B~(xmax(n)xn)>A~(DnLn),\tilde B \cdot \left (x_{\textnormal{max}}^{(n)}- x_n\right ) > \tilde A \cdot \left (D_n - L_n \right ), then set A=A~B=DnLnxmax(n)xnA~q=Axmax(n)xn .\begin{aligned} A &= \tilde A \\ B &= \frac{D_n - L_n}{x_{\textnormal{max}}^{(n)}- x_n} \cdot \tilde A \\ q &= \frac{A}{x_{\textnormal{max}}^{(n)}- x_n} \ . \\ \end{aligned} Note that AA~A \leq \tilde A and BB~B \leq \tilde B. If A=B=0A = B = 0, the deposit should be reverted. In all other cases, move through the remaining steps with the computed values for AA, BB, and q.q. Step 2. Now we update the variables xx and DD of the TBC, as follows. xn+1=(1+q)xnDn+1=(1+q)Dn\begin{aligned} x_{n+1} &= (1+q) \cdot x_n \\ D_{n+1} &= (1+q) \cdot D_n \end{aligned} Step 3. We update the parameters xmaxx_{\textnormal{max}} and xminx_{\textnormal{min}} of the pool in the following way. xmax(n+1)=(1+q)xmax(n)xmin(n+1)=(1+q)xmin(n) .\begin{aligned} x_{\textnormal{max}}^{(n+1)} &= (1+q) \cdot x_{\textnormal{max}}^{(n)} \\ x_{\textnormal{min}}^{(n+1)} &= (1+q) \cdot x_{\textnormal{min}}^{(n)} \ . \end{aligned} Step 4. We update the parameter CC of the pool, as follows. Cn+1=(1+q)Cn\begin{aligned} C_{n+1} &= (1+q) \cdot C_n \end{aligned} Step 5. We update the parameters bb and cc of the ALTBC as follows: bn+1=bn1+qb_{n+1} = \frac{b_n}{1+q} and cn+1=cn .c_{n+1} = c_n \ . Note that bn+1=b(xn+1,Cn+1,V)b_{n+1} = {\bf b}(x_{n+1}, C_{n+1}, V) and that cn+1=c(xn+1,bn+1,bn1+q,cn)c_{n+1} = {\bf c}(x_{n+1},b_{n+1},\frac{b_n}{1+q},c_n). We also update the spot price pnp_n as pn+1=pn .p_{n+1} = p_n \ . Note that pn+1=p(xn+1,bn+1,cn+1)p_{n+1} = {\bf p}(x_{n+1},b_{n+1},c_{n+1}). Step 6. We update the parameters WW and WIW^I of the TBC in the following way. Wn+1=(1+q)Wn\begin{aligned} W_{n+1} &= (1+q) \cdot W_n \end{aligned} Wn+1I=WnI\begin{aligned} W_{n+1}^I &= W_n^I \end{aligned} Step 7. We update (recall LnL_n computed at the beginning of this section) Zn+1=Zn+qWnIWnWnI(Ln+Zn)+qZn,Z_{n+1} = Z_n + q \cdot \frac{W_n^I}{W_n - W_n^I} \cdot \left (L_n + Z_n \right) + q \cdot Z_n, we define wj=qWn,w_j = q W_n, and we update hn+1=h(Sn+1).h_{n+1} = {\bf h}(S_{n+1}). Step 8. We transfer the amounts A0A \geq 0 of token XX and B0B \geq 0 of collateral to the pool. Step 9.
  • Case 1. If the liquidity provider has provided an NFT to which the new deposit should be added we proceed in the following way. Let
NFT({amount ⁣:w^, last_revenue_claim ⁣:r^})\textbf{NFT}(\{\texttt{amount}\colon \widehat{w},\ \texttt{last\_revenue\_claim}\colon \widehat{r}\}) be the NFT to which the new liquidity deposit should be added. We update the given NFT to NFT({amount ⁣:w^+wj, last_revenue_claim ⁣:hn+1wj+r^w^w^+wj})\textbf{NFT}(\{\texttt{amount}\colon \widehat{w} + w_j,\ \texttt{last\_revenue\_claim}\colon \frac{h_{n+1} w_j + \widehat{r} \widehat{w}}{\widehat{w} + w_j} \})
  • Case 2. If the liquidity provider has not provided an NFT to which the new deposit should be added, we mint the NFT defined by
NFT({amount ⁣:wj, last_revenue_claim ⁣:hn+1})\textbf{NFT}(\{\texttt{amount}\colon w_j,\ \texttt{last\_revenue\_claim}\colon h_{n+1}\}) and transfer it to the liquidity provider.

Extracting revenue

We need to define a pool function that enables the game developers and liquidity providers to extract, at any moment, any excess of collateral from the pool as revenue. In order to give a liquidity provider the fair amount of collateral that his/her NFT accrued we do the following. Before proceeding, check if we are dealing with the inactive-fee NFT. If so, revert the transaction. In all other cases, we proceed as follows. Suppose that liquidity provider jj owns the NFT defined by NFT({amount ⁣:wj, last_revenue_claim ⁣:rj(n)}) .\textbf{NFT}(\{\texttt{amount}\colon w_j,\ \texttt{last\_revenue\_claim}\colon r_j^{(n)}\}) \ . Let SnS_n be the current values of the state variables, and let hn=h(Sn)h_n = {\bf h}(S_n) be the current value of the revenue parameter. Then, the maximum amount of collateral that the liquidity provider is entitled to collect is given by the formula wj(hnrj(n)) .w_j \cdot (h_n - r_j^{(n)}) \ . If the liquidity provider jj intends to extract an amount QQ of revenue we proceed as follows. Step 1. We check that Qwj(hnrj(n)) .Q \leq w_j \cdot (h_n - r_j^{(n)}) \ . If so, we proceed. Otherwise we reject the transaction. Step 2. We update the value of the variable rj(n)r_j^{(n)} (of the last_revenue_claim field of the liquidity provider’s NFT) as rj(n+1)=rj(n)+Qwj .r_j^{(n+1)} = r_j^{(n)} + \frac{Q}{w_j} \ . This is, the NFT that the liquidity provider owns is updated to NFT({amount ⁣:wj, last_revenue_claim ⁣:rj(n+1)}) .\textbf{NFT}(\{\texttt{amount}\colon w_j,\ \texttt{last\_revenue\_claim}\colon r_j^{(n+1)}\}) \ . Step 3. We transfer an amount QQ of collateral to the liquidity provider’s account.

Liquidity withdrawals

Let SnS_n be the current values of the state variables. Suppose that liquidity provider jj wants to redeem liquidity corresponding to the NFT defined by NFT({amount ⁣:wj, last_revenue_claim ⁣:rj(n)}) .\textbf{NFT}(\{\texttt{amount}\colon w_j,\ \texttt{last\_revenue\_claim}\colon r_j^{(n)}\}) \ . Suppose, in addition, that the liquidity provider wants to redeem the part of the liquidity corresponding to the previous NFT given by an amount value of uju_j with 0<ujwj0 < u_j \leq w_j. In order to process the liquidity withdrawal, we proceed as follows. First, determine whether the NFT in question is the inactive-fee NFT. Step 1. We define q=ujWnq = \frac{u_j}{W_n} and hn=h(Sn) .h_n = {\bf h}(S_n) \ . Note that if we are dealing with the inactive-fee NFT, hnh_n does not need to be computed. Step 2. Using our computed value of LL from the previous step (obtained when computing hnh_n), define Ln=L(Sn).L_n = {\bf L}(S_n). Then, define the amounts of token and collateral that the liquidity provider will receive by AX=q(xmax(n)xn)AY=q(DnLn)\begin{aligned} A_X & = q \cdot (x_{\textnormal{max}}^{(n)} - x_n ) \\ A_Y & = q \cdot (D_n - L_n) \end{aligned} Step 3. We update the variables xx and DD of the TBC, as follows. xn+1=(1q)xnDn+1=(1q)Dn\begin{aligned} x_{n+1} &= (1-q) \cdot x_n \\ D_{n+1} &= (1-q) \cdot D_n \end{aligned} Step 4. We update the parameters xmaxx_{\textnormal{max}} and xminx_{\textnormal{min}} of the pool in the following way. xmax(n+1)=(1q)xmax(n)xmin(n+1)=(1q)xmin(n) .\begin{aligned} x_{\textnormal{max}}^{(n+1)} &= (1-q) \cdot x_{\textnormal{max}}^{(n)} \\ x_{\textnormal{min}}^{(n+1)} &= (1-q) \cdot x_{\textnormal{min}}^{(n)} \ . \end{aligned} Step 5. We update the parameter CC of the pool, as follows. Cn+1=(1q)Cn\begin{aligned} C_{n+1} &= (1-q) \cdot C_n \end{aligned} Step 6. We update the parameter bb of the ALTBC as follows. bn+1=bn1qb_{n+1} = \frac{b_n}{1-q} The parameter cnc_n and the spot price pnp_n do not need to be updated. This is, we define cn+1=cnpn+1=pn\begin{aligned} c_{n+1} & = c_n \\ p_{n+1} & = p_n \end{aligned} Step 7. We update the parameter WW of the TBC in the following way: Wn+1=Wnuj\begin{aligned} W_{n+1} &= W_n - u_j \end{aligned} If we are dealing with the inactive-fee NFT, we must also update WIW_I of the TBC in the following way: Wn+1I=WnIuj\begin{aligned} W_{n+1}^I &= W_n^I - u_j \end{aligned} Otherwise, define Wn+1I=WnI.W_{n+1}^I = W_n^I. Finally, if Wn+1Wn+1I=0W_{n+1} - W_{n+1}^I = 0 and Wn+1I>0W_{n+1}^I > 0, revert the transaction. Otherwise, proceed. Step 8. If we are dealing with the inactive-fee NFT, this step must be skipped. We give the liquidity provider jj the remaining revenue to which he/she is entitled (if there is any left) corresponding to the amount value uju_j, which is given by the formula uj(hnrj(n)) .u_j \cdot (h_n - r_j^{(n)}) \ . Step 9. The NFT used by the liquidity provider is updated to NFT({amount ⁣:wjuj, last_revenue_claim ⁣:rj(n)}) .\textbf{NFT}(\{\texttt{amount}\colon w_j - u_j,\ \texttt{last\_revenue\_claim}\colon r_j^{(n)}\}) \ . (or burned if uj=wju_j = w_j), and the liquidity provider receives an amount AXA_X of token XX and an amount AYA_Y of collateral. Note that if we are dealing with the inactive-fee NFT, the last_revenue_claim persists at \infty (this is just noted for emphasis, not because a different action is required). Note that only the amount field of the NFT is updated. Step 10. If we are dealing with the inactive-fee NFT, we will update ZZ as Zn+1=Zn+qLn.Z_{n+1} = Z_n + q \cdot L_n. In all other cases (i.e. whenever we are dealing with an active-fee NFT), we update ZZ as Zn+1=ZnqWnIWnWnI(Ln+Zn)qZn.Z_{n+1} = Z_n - q \cdot \frac{W_n^I}{W_n - W_n^I} \cdot \left (L_n + Z_n \right) - q \cdot Z_n.