Skip to main content

Agregacja płynności wielu podmiotów i dowód uczciwości opłat

Ten dokument zawiera pełny dowód matematyczny, model księgowy, przykłady liczbowe oraz weryfikację w testach on-chain wykazujące, że Biatec CLAMM (BIATEC-CLAMM-01-06-08) pobiera i dystrybuuje opłaty w sposób całkowicie dokładny, gdy wielu użytkowników dostarcza i wypłaca płynność w tej samej puli w różnym czasie.

W szczególności niniejszy przewodnik dowodzi, że:

  1. Brak utraty opłat: 100% opłat transakcyjnych (swap) oraz dystrybuowanych nagród stakingowych jest rejestrowanych on-chain i dzielonych pomiędzy dostawców płynności (LiquidityUsersFromFees) a protokół (LiquidityBiatecFromFees) bez żadnego nieprzypisanego wycieku.
  2. Brak przejmowania opłat przez późnych uczestników: Dostawca płynności, który dołącza do puli po naliczeniu opłat, nie może wypłacić żadnej części opłat wypracowanych przed jego depozytem.
  3. Brak rozwodnienia obecnych dostawców płynności (LP): Dotychczasowi dostawcy płynności zachowują 100% swojego kapitału początkowego oraz 100% wcześniej naliczonych opłat, gdy do puli dołączają nowi dostawcy płynności, a ich naliczone opłaty automatycznie procentują (compoundują) jako aktywna płynność przy kolejnych transakcjach.
  4. Wypłaty niezależne od kolejności: Gdy wielu dostawców płynności opuszcza pulę, wypłata dla każdego uczestnika jest niezależna od tego, kto wypłaca jako pierwszy (z dokładnością do ≤2\le 2 atomowych jednostek aktywa wynikających z całkowitoliczbowego zaokrąglania w dół, które zawsze działa na korzyść puli).

1. Zmienne księgowe on-chain i niezmiennik zachowania płynności​

Każdy kontrakt BiatecClammPool utrzymuje cztery podstawowe wielkości płynności w 9-dziesiętnej skali bazowej (SCALE=109\text{SCALE} = 10^9):

SymbolStan kontraktu / WzórOpis
LLLiquidity (L)Całkowita skoncentrowana płynność wyznaczona ze śledzonych rezerw (x,y)=(assetABalanceBaseScale,assetBBalanceBaseScale)(x, y) = (\text{assetABalanceBaseScale}, \text{assetBBalanceBaseScale}).
DDdistributedLpTokeny LP w obiegu poza kontem puli, przeskalowane do 9 miejsc dziesiętnych: D=(TOTAL_SUPPLY−poolLpBalance)×1000D = (\text{TOTAL\_SUPPLY} - \text{poolLpBalance}) \times 1000.
LuL_uLiquidityUsersFromFees (Lu)Skumulowana płynność z opłat/nagród należąca proporcjonalnie (pro rata) do posiadaczy tokenów LP będących w obiegu.
LbL_bLiquidityBiatecFromFees (Lb)Skumulowana płynność opłat protokołu należąca do wykonawcy opłat Biatec (addressExecutiveFee).

Fundamentalny niezmiennik zachowania płynności​

W każdym punkcie cyklu życia puli całkowita płynność krzywej LL spełnia równanie:

L=D+Lu+Lb+UL = D + L_u + L_b + U

gdzie:

  • D+LuD + L_u to całkowite roszczenie płynnościowe wszystkich posiadaczy tokenów LP (do wypłacenia przez removeLiquidity),
  • LbL_b to całkowite roszczenie płynnościowe wykonawcy opłat protokołu (do wypłacenia przez removeLiquidityAdmin),
  • UU to reszta z całkowitoliczbowego zaokrąglenia w dół poniżej mikrojednostki LP (0≤U<1000 jednostek bazowych=10−6 LP0 \le U < 1000\text{ jednostek bazowych} = 10^{-6}\text{ LP} na depozyt), która może zostać w dowolnym momencie dopisana do LuL_u (lub LbL_b, jeśli D=0D = 0) za pomocą reconcileLiquidity.

2. Jak opłaty są pobierane przy każdym swapie i dystrybucji nagród​

2.1 Naliczanie opłat transakcyjnych (swap)​

Gdy trader wymienia kwotę wejściową Δin\Delta_{\text{in}} (w skali bazowej):

  1. Potrącenie opłaty przed wyceną na krzywej: Kontrakt oblicza efektywny mnożnik opłat na podstawie parametru fee puli oraz poziomu użytkownika w BiatecIdentityProvider:

    feesMultiplier=s−⌊fee⋅user.feeMultiplieruser.base⌋,s=109\text{feesMultiplier} = s - \left\lfloor \frac{\text{fee} \cdot \text{user.feeMultiplier}}{\text{user.base}} \right\rfloor, \quad s = 10^9

    Wyłącznie kwota netto Δin,afterFee=⌊Δin⋅feesMultiplier/s⌋\Delta_{\text{in,afterFee}} = \lfloor \Delta_{\text{in}} \cdot \text{feesMultiplier} / s \rfloor jest używana do obliczenia kwoty wyjściowej drugiego aktywa Δout\Delta_{\text{out}} wzdłuż krzywej stałej płynności LoldL_{\text{old}}.

  2. Ochrona zaokrąglania kwoty wyjściowej: Podczas konwersji Δout\Delta_{\text{out}} z 9-dziesiętnej skali bazowej na natywne miejsca dziesiętne aktywa wyjściowego każda niezerowa reszta ułamkowa powoduje zmniejszenie wypłaty o 1 natywną jednostkę aktywa (realSwapBDecimals = realSwapBDecimals - 1), dzięki czemu konwersja całkowitoliczbowa nigdy nie uszczupla rezerw puli.

  3. Aktualizacja rezerw i przeliczenie płynności: Pełna kwota wejściowa Δin\Delta_{\text{in}} (wraz z częścią stanowiącą opłatę Δin−Δin,afterFee\Delta_{\text{in}} - \Delta_{\text{in,afterFee}}) jest dodawana do rezerwy wejściowej, natomiast od rezerwy wyjściowej odejmowana jest wyłącznie faktycznie przelana kwota Δout,real\Delta_{\text{out,real}}. Następnie kontrakt przelicza płynność puli:

    Lnew=setCurrentLiquidityNonDecreasing(Lold)≥LoldL_{\text{new}} = \text{setCurrentLiquidityNonDecreasing}(L_{\text{old}}) \ge L_{\text{old}}
  4. Wyczerpujący podział opłaty (ΔLu+ΔLb=diff\Delta L_u + \Delta L_b = \text{diff}): Przyrost płynności diff=Lnew−Lold\text{diff} = L_{\text{new}} - L_{\text{old}} jest dzielony pomiędzy posiadaczy LP a Biatec:

    ΔLu=⌊diff⋅(s−fbiatec)s⌋,ΔLb=diff−ΔLu\Delta L_u = \left\lfloor \frac{\text{diff} \cdot (s - f_{\text{biatec}})}{s} \right\rfloor, \quad \Delta L_b = \text{diff} - \Delta L_u

    Ponieważ ΔLb\Delta L_b jest zdefiniowane jako diff−ΔLu\text{diff} - \Delta L_u, suma ΔLu+ΔLb=diff\Delta L_u + \Delta L_b = \text{diff} zachodzi tożsamościowo, z zerową stratą na zaokrągleniach.

2.2 Dystrybucja nagród stakingowych i nadwyżki aktywów (distributeExcessAssets)​

Gdy nagrody stakingowe lub zewnętrzny zysk są dopisywane przez distributeExcessAssets, kontrakt weryfikuje fizyczne pokrycie w saldach (ensurePoolBalancesWithinHoldings), oblicza diff=Lnew−Lold\text{diff} = L_{\text{new}} - L_{\text{old}} i stosuje identyczny wyczerpujący podział ΔLu+ΔLb=diff\Delta L_u + \Delta L_b = \text{diff}.


3. Dowód matematyczny: agregacja płynności wielu podmiotów w różnym czasie​

Rozważmy dwóch niezależnych dostawców płynności — Stronę A (Dotychczasowy LP) oraz Stronę B (Nowy LP) — którzy wpłacają środki do tej samej puli w różnych momentach t0<t2t_0 < t_2, przy czym swapy odbywają się zarówno przed (t1t_1), jak i po (t3t_3) dołączeniu Strony B.

Krok 1 (t0t_0): Strona A dostarcza początkową płynność​

Strona A wpłaca aktywa dodające ΔLA\Delta L_A płynności do pustej puli (D0=0,Lu,0=0,Lb,0=0D_0 = 0, L_{u,0} = 0, L_{b,0} = 0).

  • Strona A otrzymuje dA=⌊ΔLA/1000⌋d_A = \lfloor \Delta L_A / 1000 \rfloor mikrotokenów LP, co odpowiada DA=1000 dA=ΔLA−rAD_A = 1000 \, d_A = \Delta L_A - r_A jednostkom bazowym (0≤rA<10000 \le r_A < 1000).

  • Stan puli po t0t_0:

    D1=DA,Lu,1=0,Lb,1=0,L1=DA+rAD_1 = D_A, \quad L_{u,1} = 0, \quad L_{b,1} = 0, \quad L_1 = D_A + r_A

Krok 2 (t1t_1): Swapy naliczają opłaty F1F_1, gdy w puli jest tylko Strona A​

Swapy w przedziale [t0,t1][t_0, t_1] generują płynność opłat dla użytkowników F1>0F_1 > 0 oraz płynność opłat protokołu B1≥0B_1 \ge 0.

  • Stan puli w chwili t1t_1:

    D1=DA,Lu,1=F1,Lb,1=B1,L1′=DA+F1+B1+rAD_1 = D_A, \quad L_{u,1} = F_1, \quad L_{b,1} = B_1, \quad L_1' = D_A + F_1 + B_1 + r_A
  • Ponieważ Strona A posiada 100% tokenów LP w obiegu (D1=DAD_1 = D_A), całkowite uprawnienie płynnościowe Strony A w chwili t1t_1 wynosi:

    ClaimA(t1)=DA+⌊Lu,1⋅DADA⌋=DA+F1\text{Claim}_A(t_1) = D_A + \left\lfloor \frac{L_{u,1} \cdot D_A}{D_A} \right\rfloor = D_A + F_1
  • Każda jednostka bazowa tokenu LP w obiegu ma teraz pokrycie w DA+F1DA>1\frac{D_A + F_1}{D_A} > 1 jednostkach płynności użytkowników.

Krok 3 (t2t_2): Strona B wpłaca ΔLB\Delta L_B do puli​

W chwili t2t_2 Strona B wpłaca aktywa zwiększające płynność puli z L1′L_1' do L2=L1′+ΔLBL_2 = L_1' + \Delta L_B.

W metodzie processAddLiquidity kontrakt oblicza skorygowaną o opłaty ilość mintowanych tokenów LP XbaseX_{\text{base}}:

Xbase=⌊ΔLB⋅DADA+F1⌋X_{\text{base}} = \left\lfloor \frac{\Delta L_B \cdot D_A}{D_A + F_1} \right\rfloor

Dla Strony B mintowane jest dB=⌊Xbase/1000⌋d_B = \lfloor X_{\text{base}} / 1000 \rfloor mikrotokenów LP (DB=1000 dB=Xbase−rBD_B = 1000 \, d_B = X_{\text{base}} - r_B, gdzie 0≤rB<10000 \le r_B < 1000), a niewymintowana płynność ΔLB−Xbase\Delta L_B - X_{\text{base}} zostaje dopisana do LiquidityUsersFromFees:

Lu,2=F1+(ΔLB−Xbase)L_{u,2} = F_1 + (\Delta L_B - X_{\text{base}})

Całkowita liczba LP w obiegu wynosi teraz D2=DA+DBD_2 = D_A + D_B, a całkowita płynność należąca do użytkowników to:

D2+Lu,2=(DA+Xbase−rB)+(F1+ΔLB−Xbase)=DA+F1+ΔLB−rBD_2 + L_{u,2} = (D_A + X_{\text{base}} - r_B) + (F_1 + \Delta L_B - X_{\text{base}}) = D_A + F_1 + \Delta L_B - r_B

Twierdzenie 1 (Strona B nie może przejąć wcześniej naliczonych opłat)​

Jeśli Strona B natychmiast wywoła removeLiquidity dla wszystkich swoich tokenów DBD_B w chwili t2+t_2^+, wypłata płynności dla Strony B wyniesie:

ClaimB(t2+)=DB+⌊Lu,2⋅DBDA+DB⌋=⌊(DA+DB+Lu,2)⋅DBDA+DB⌋\text{Claim}_B(t_2^+) = D_B + \left\lfloor \frac{L_{u,2} \cdot D_B}{D_A + D_B} \right\rfloor = \left\lfloor \frac{(D_A + D_B + L_{u,2}) \cdot D_B}{D_A + D_B} \right\rfloor

Ponieważ DB≤Xbase≤ΔLB⋅DADA+F1D_B \le X_{\text{base}} \le \frac{\Delta L_B \cdot D_A}{D_A + F_1}, otrzymujemy:

DBDA+DB≤XbaseDA+Xbase≤ΔLBDA+F1+ΔLB\frac{D_B}{D_A + D_B} \le \frac{X_{\text{base}}}{D_A + X_{\text{base}}} \le \frac{\Delta L_B}{D_A + F_1 + \Delta L_B}

Mnożąc przez DA+DB+Lu,2=DA+F1+ΔLB−rB≤DA+F1+ΔLBD_A + D_B + L_{u,2} = D_A + F_1 + \Delta L_B - r_B \le D_A + F_1 + \Delta L_B, uzyskujemy:

ClaimB(t2+)≤ΔLB\text{Claim}_B(t_2^+) \le \Delta L_B

Wniosek: Strona B nigdy nie może wypłacić więcej płynności niż ΔLB\Delta L_B (dokładnie tyle płynności, ile wpłaciła). Strona B otrzymuje zero jednostek z wcześniej naliczonych opłat F1F_1.

Twierdzenie 2 (Strona A zachowuje 100% kapitału oraz wcześniej naliczonych opłat)​

Bezpośrednio po dołączeniu Strony B w chwili t2+t_2^+ roszczenie płynnościowe Strony A wynosi:

ClaimA(t2+)=DA+⌊Lu,2⋅DADA+DB⌋=(DA+F1+ΔLB−rB)−ClaimB(t2+)≥DA+F1\text{Claim}_A(t_2^+) = D_A + \left\lfloor \frac{L_{u,2} \cdot D_A}{D_A + D_B} \right\rfloor = (D_A + F_1 + \Delta L_B - r_B) - \text{Claim}_B(t_2^+) \ge D_A + F_1

Wniosek: Uprawnienie Strony A ClaimA(t2+)\text{Claim}_A(t_2^+) nigdy nie ulega zmniejszeniu wskutek depozytu Strony B (a wręcz wzrasta o maksymalnie rB<1000r_B < 1000 jednostek bazowych zaokrąglenia na korzyść puli).

Krok 4 (t3t_3): Kolejne swapy naliczają opłaty F2F_2, gdy obie strony są w puli​

W przedziale [t2,t3][t_2, t_3] zarówno Strona A, jak i Strona B posiadają kapitał aktywnie zapewniający płynność w puli:

  • Aktywna płynność Strony A w chwili t2t_2 wynosi Lactive,A=DA+F1L_{\text{active},A} = D_A + F_1 (początkowy kapitał Strony A powiększony o skapitalizowane opłaty F1F_1 z Epoki 2).
  • Aktywna płynność Strony B w chwili t2t_2 wynosi Lactive,B=ΔLBL_{\text{active},B} = \Delta L_B.

Ponieważ DB≈ΔLB⋅DADA+F1D_B \approx \frac{\Delta L_B \cdot D_A}{D_A + F_1}, stosunek tokenów LP w obiegu posiadanych przez Stronę A i Stronę B spełnia zależności:

DADA+DB=DA+F1DA+F1+ΔLB=Lactive,ALactive,A+Lactive,B\frac{D_A}{D_A + D_B} = \frac{D_A + F_1}{D_A + F_1 + \Delta L_B} = \frac{L_{\text{active},A}}{L_{\text{active},A} + L_{\text{active},B}} DBDA+DB=ΔLBDA+F1+ΔLB=Lactive,BLactive,A+Lactive,B\frac{D_B}{D_A + D_B} = \frac{\Delta L_B}{D_A + F_1 + \Delta L_B} = \frac{L_{\text{active},B}}{L_{\text{active},A} + L_{\text{active},B}}

Gdy nowe swapy w chwili t3t_3 dodają F2F_2 do LiquidityUsersFromFees (Lu,3=Lu,2+F2L_{u,3} = L_{u,2} + F_2):

  • Całkowite roszczenie Strony A wynosi:

    ClaimA(t3)=(DA+F1)+DA+F1DA+F1+ΔLBF2\text{Claim}_A(t_3) = (D_A + F_1) + \frac{D_A + F_1}{D_A + F_1 + \Delta L_B} F_2
  • Całkowite roszczenie Strony B wynosi:

    ClaimB(t3)=ΔLB+ΔLBDA+F1+ΔLBF2\text{Claim}_B(t_3) = \Delta L_B + \frac{\Delta L_B}{D_A + F_1 + \Delta L_B} F_2

Wniosek: Nowe opłaty F2F_2 są rozdzielane dokładnie proporcjonalnie do aktywnej płynności każdej ze stron w puli w okresie [t2,t3][t_2, t_3], automatycznie kapitalizując wcześniejsze zyski z opłat F1F_1 Strony A.

Krok 5 (t4,t5t_4, t_5): Wypłaty niezależne od kolejności (removeLiquidity)​

Gdy Strona i∈{A,B}i \in \{A, B\} wypłaca swoje tokeny LP DiD_i jako pierwsza w chwili t4t_4:

  1. lpWithOthers =DA+DB= D_A + D_B.
  2. myPortionOfFeesCollected =⌊Lu,3⋅DiDA+DB⌋= \lfloor \frac{L_{u,3} \cdot D_i}{D_A + D_B} \rfloor.
  3. lpDeltaWithFees =Di+myPortionOfFeesCollected=Claimi(t3)= D_i + \text{myPortionOfFeesCollected} = \text{Claim}_i(t_3).
  4. LiquidityUsersFromFees zostaje pomniejszone do Lu,4=Lu,3−myPortionOfFeesCollectedL_{u,4} = L_{u,3} - \text{myPortionOfFeesCollected}.
  5. Rezerwy puli (x,y)(x, y) są wypłacane proporcjonalnie według współczynnika Claimi(t3)L\frac{\text{Claim}_i(t_3)}{L}, pozostawiając L−Claimi(t3)L\frac{L - \text{Claim}_i(t_3)}{L} rezerw (x,y)(x, y) w puli.

Gdy pozostała Strona j≠ij \ne i wypłaca swoje tokeny LP DjD_j w chwili t5t_5:

  1. lpWithOthers =Dj= D_j (ponieważ tokeny LP Strony ii wróciły do puli w chwili t4t_4).
  2. myPortionOfFeesCollected =⌊Lu,4⋅DjDj⌋=Lu,4= \lfloor \frac{L_{u,4} \cdot D_j}{D_j} \rfloor = L_{u,4}.
  3. Strona jj otrzymuje Dj+Lu,4=Claimj(t3)D_j + L_{u,4} = \text{Claim}_j(t_3), a LiquidityUsersFromFees spada do 00.

Przegląd cyklu życia​

4. Konkretny przykład liczbowy​

Załóżmy, że pula o stałej cenie (P=1.0P = 1.0, biatecFee=10%\text{biatecFee} = 10\%) przechodzi przez następującą sekwencję zdarzeń:

  1. Epoka 1 (t0t_0) — Alice wpłaca 100 A+100 B100\text{ A} + 100\text{ B}:

    • ΔLA=200×109\Delta L_A = 200 \times 10^9
    • Alice otrzymuje 200,000,000200,000,000 mikro-LP (DA=200×109D_A = 200 \times 10^9).
    • Stan puli: L=200×109,  D=200×109,  Lu=0,  Lb=0L = 200 \times 10^9, \; D = 200 \times 10^9, \; L_u = 0, \; L_b = 0.
  2. Epoka 2 (t1t_1) — Naliczane są opłaty/nagrody w wysokości 20 A+20 B20\text{ A} + 20\text{ B} (40×10940 \times 10^9 płynności):

    • 90%90\% trafia do użytkowników (ΔLu=36×109\Delta L_u = 36 \times 10^9), a 10%10\% trafia do Biatec (ΔLb=4×109\Delta L_b = 4 \times 10^9).
    • Stan puli: L=240×109,  D=200×109,  Lu=36×109,  Lb=4×109L = 240 \times 10^9, \; D = 200 \times 10^9, \; L_u = 36 \times 10^9, \; L_b = 4 \times 10^9.
    • Uprawnienie płynnościowe Alice wynosi DA+Lu=236×109D_A + L_u = 236 \times 10^9 (118 A+118 B118\text{ A} + 118\text{ B}).
  3. Epoka 3 (t2t_2) — Bob wpłaca 60 A+60 B60\text{ A} + 60\text{ B} (ΔLB=120×109\Delta L_B = 120 \times 10^9 płynności):

    • Kontrakt oblicza zdyskontowaną ilość LP do wymintowania dla Boba:

      Xbase=⌊120×109×200×109(200+36)×109⌋=101,694,915,254X_{\text{base}} = \left\lfloor \frac{120 \times 10^9 \times 200 \times 10^9}{(200 + 36) \times 10^9} \right\rfloor = 101,694,915,254
    • Bob otrzymuje dB=101,694,915d_B = 101,694,915 mikro-LP (DB=101,694,915,000D_B = 101,694,915,000 jednostek bazowych).

    • Niewymintowana korekta rozwodnienia opłat ΔLB−Xbase=18,305,084,746\Delta L_B - X_{\text{base}} = 18,305,084,746 zostaje dodana do LuL_u:

      Lu,2=36×109+18,305,084,746=54,305,084,746L_{u,2} = 36 \times 10^9 + 18,305,084,746 = 54,305,084,746
    • Całkowita liczba LP w obiegu: D2=301,694,915,000D_2 = 301,694,915,000.

    • Sprawdzenie natychmiastowych roszczeń w chwili t2+t_2^+:

      • Roszczenie Boba: 101,694,915,000+⌊54,305,084,746×101,694,915,000301,694,915,000⌋=119,999,999,700≤120×109101,694,915,000 + \lfloor \frac{54,305,084,746 \times 101,694,915,000}{301,694,915,000} \rfloor = 119,999,999,700 \le 120 \times 10^9 (Bob nie może przejąć żadnej części z 36×10936 \times 10^9 opłat Alice).
      • Roszczenie Alice: 200×109+⌊54,305,084,746×200×109301,694,915,000⌋=236,000,000,046≥236×109200 \times 10^9 + \lfloor \frac{54,305,084,746 \times 200 \times 10^9}{301,694,915,000} \rfloor = 236,000,000,046 \ge 236 \times 10^9 (Alice zachowuje 100% swojego depozytu oraz 100% opłat z Epoki 2).
  4. Epoka 4 (t3t_3) — Naliczane są dodatkowe opłaty/nagrody w wysokości 10 A+10 B10\text{ A} + 10\text{ B} (20×10920 \times 10^9 płynności):

    • 90%90\% trafia do użytkowników (ΔLu=18×109\Delta L_u = 18 \times 10^9), a 10%10\% trafia do Biatec (ΔLb=2×109\Delta L_b = 2 \times 10^9).
    • Lu,3=54,305,084,746+18×109=72,305,084,746L_{u,3} = 54,305,084,746 + 18 \times 10^9 = 72,305,084,746.
    • Udział Boba w nowych opłatach 18×10918 \times 10^9 wynosi 120236+120×18×109≈6.0674×109\frac{120}{236 + 120} \times 18 \times 10^9 \approx 6.0674 \times 10^9 (≈3.0337 A+3.0337 B\approx 3.0337\text{ A} + 3.0337\text{ B}).
    • Udział Alice w nowych opłatach 18×10918 \times 10^9 wynosi 236236+120×18×109≈11.9326×109\frac{236}{236 + 120} \times 18 \times 10^9 \approx 11.9326 \times 10^9 (≈5.9663 A+5.9663 B\approx 5.9663\text{ A} + 5.9663\text{ B}).
    • Całkowita opłata protokołu Biatec wynosi Lb=6×109L_b = 6 \times 10^9 (3 A+3 B3\text{ A} + 3\text{ B}).

5. Weryfikacja w zestawach testów on-chain​

Wszystkie niezmienniki dotyczące opłat i agregacji płynności wielu podmiotów są stale weryfikowane na żywej maszynie wirtualnej Algorand LocalNet AVM w zestawach testów Jest:

Plik testowyZweryfikowane scenariusze
__test__/pool/multi-party-fee-aggregation.test.ts1. Dwóch dostawców płynności (LP) dołączających w różnym czasie w trakcie dwóch epok swapów dzieli się opłatami ściśle proporcjonalnie do aktywnej płynności (DA+Lu,1):ΔLB(D_A + L_{u,1}) : \Delta L_B.
2. Niezależność wypłat od kolejności (najpierw Alice vs. najpierw Bob) oraz izolacja opłat protokołu Biatec (LbL_b).
3. Trzech LP (Alice, Bob, Charlie) dołączających w trzech różnych momentach z częściowymi (50%) i pełnymi wypłatami.
4. Dystrybucja nagród stakingowych / nadwyżki aktywów (distributeExcessAssets) pomiędzy wielu LP dołączających w różnym czasie.
5. Szybkie 5-krotne cykle wpłat i wypłat wykonywane przez drugi podmiot nigdy nie przejmują opłat ani nie zmniejszają fizycznych zasobów puli.
__test__/pool/liquidity.test.tsNowy dostawca płynności dołączający po dwukierunkowych swapach i natychmiast wypłacający środki nie może przejąć wcześniej naliczonych opłat (deltaA <= 0, deltaB <= 0).
__test__/pool/mainnet-replay-3720188642.test.tsPełne odtworzenie 242 transakcji z historii MainNet puli Gold/GoldDAO 3720188642 weryfikujące zachowanie równania L=D+Lu+LbL = D + L_u + L_b po każdym depozycie, swapie i pełnym umorzeniu.
__test__/pool/reconcile-liquidity.test.tsWeryfikacja, że pył z zaokrąglania poniżej mikrojednostki LP trafia do LuL_u, gdy D>0D > 0, oraz do LbL_b, gdy D=0D = 0, a także że wywołanie reconcileLiquidity jest ograniczone wyłącznie do addressExecutiveFee.
__test__/pool/fees.test.tsDeterministyczne naliczanie opłat swap, wypłata LP wraz z opłatami, pobieranie opłat protokołu przez removeLiquidityAdmin oraz distributeExcessAssets w różnych przedziałach cenowych.

Lokalne uruchomienie zestawu weryfikacyjnego​

# Upewnij się, że Algorand LocalNet jest uruchomiony
algokit localnet start

# Uruchom dedykowany zestaw testów agregacji opłat wielu podmiotów
npx jest __test__/pool/multi-party-fee-aggregation.test.ts

# Uruchom pełne budowanie kontraktów oraz cały zestaw testów
npm run test