Skip to main content
このページは AI による自動翻訳です。すべての内容は英語版を正とします。英語版を表示 →

不変量

CPMMは2つのヴォルト上で古典的な定数積不変量を維持します: x⋅y=kx \cdot y = k ここでxはvault0の残高で、受け取り時のToken-2022転送手数料を差し引いた後の値です。yも同様です。すべてのスワップは、LPに付与される取引手数料を考慮した後、k' ≥ kを満たす必要があります(プロトコル、ファンド、クリエイターバケットはkにカウントされません。ヴォルトに存在しますが、曲線ビューから除外されます。下記の曲線上の手数料を参照)。したがってkはLPが手数料を蓄積するにつれて時間とともに単調に増加します。 LPシェアはkではなくプールの準備金によって価格設定されます: token0でのLP価格=xlpSupply,token1でのLP価格=ylpSupply\text{token0でのLP価格} = \frac{x}{\text{lpSupply}}, \qquad \text{token1でのLP価格} = \frac{y}{\text{lpSupply}} ΔLP個のLPトークンをバーンすると、正確にΔLP × x / lpSupplyのtoken0とΔLP × y / lpSupplyのtoken1が返されます。曲線もkも預金や引き出しで動きません。スワップだけが価格を変更します。

スワップパス上の手数料モデル

CPMMはすべてのスワップに2つの独立した手数料を適用します:
  • 取引手数料は入力側で取られ、AmmConfig.trade_fee_rateで課金されます。その後、LP、プロトコル、ファンドシェアに分割されます(LPシェアはヴォルトに留まりkを増加させます。プロトコルとファンドシェアはヴォルト会計から抽出されます)。
  • クリエイター手数料(enable_creator_fee == trueの場合のみアクティブ)はAmmConfig.creator_fee_rateで課金されます。PoolState.creator_fee_onとスワップ方向に応じて、入力側または出力側で取られます(products/cpmm/feesを参照)。独立したバケットです。取引手数料のスライスではありません。
クリエイター手数料のプロトコルシェアはこのページのどこにも表示されず、それは意図的です。 これはCollectCreatorFeeが曲線がすでに除外している2つのカウンター間で蓄積された手数料を移動するときに適用されます。スワップ数学、見積もり、kはそれがあってもなくても同じです。products/cpmm/feesを参照してください。
定義:
  • FEE_RATE_DENOMINATOR = 1_000_000
  • trade_fee_rate — AmmConfigから、例:2500 = 関連するボリュームサイドの0.25%
  • creator_fee_rate — AmmConfigから、例:1000 = 関連するボリュームサイドの0.10%
  • protocol_fee_rate、fund_fee_rate — ボリュームではなく、取引手数料の1/FEE_RATE_DENOMINATOR単位で表示
クリエイター手数料が入力側にある場合:
クリエイター手数料が出力側にある場合:
どちらの場合も取引手数料は同じ方法で分割されます:
protocol_fee + fund_fee + creator_feeの金額はヴォルトに保持されていますが、プール状態で別途追跡されます(protocol_fees_token*、fund_fees_token*、creator_fees_token*)。定数積不変量がk' ≥ kをチェックするとき、ヴォルト残高から3つすべての蓄積されたが未処理の手数料を差し引いた値を使用します。したがってLPはlp_feeのみをキャプチャします。 products/cpmm/feesで収集命令と計算例を参照してください。

SwapBaseInput(入力確定)

「ユーザーは入力ミントの正確にamount_inを提供し、出力ミントの少なくともminimum_amount_outを受け取ります。」 Token-2022を一時的に無視すると:
代数的に: amount_out=y⋅Δxnetx+Δxnet\text{amount\_out} = \frac{y \cdot \Delta x_{\text{net}}}{x + \Delta x_{\text{net}}} ここでΔx_net = amount_in_after_trade_feeです。 プログラムはその後、ヴォルト会計を更新して、プロトコル/ファンド/クリエイターに属するtrade_feeの部分が「蓄積」バケットに座り(次のスワップの曲線xに含まれない)、LPシェアが次のスワップのためにxに参加するようにします。

入力側のToken-2022

入力ミントに転送手数料拡張がある場合、ミントはユーザー→ヴォルトの転送時に手数料を差し引きます。したがってヴォルトは実際にamount_in − transfer_fee_in(amount_in)を受け取ります。CPMMプログラムは以下を計算します:
そしてamount_in_after_trade_feeに対して曲線を実行します。これが重要な理由は、曲線価格はユーザーの見出し金額ではなく、ヴォルトに実際に到着した正味金額から計算されるからです。

出力側のToken-2022

出力ミントに転送手数料がある場合、プールはそのヴォルトからamount_outをユーザーに送信します。ミントは出力時に手数料をスキミングするため、ユーザーはamount_out − transfer_fee_out(amount_out)を受け取ります。プログラムは通常通り曲線からamount_outを計算しますが、見積もりを表示するときにプールの「ヴォルト送信」数をユーザーの「受け取り」数に変換するのはインテグレーターの責任です。

スリッページチェック

amount_outを計算した後:
出力ミントが転送手数料を課金する場合、SDKはスリッページ定数がヴォルトが送信する金額ではなくユーザーが実際に受け取る金額で表示されるように、転送手数料をminimum_amount_outを設定する前に適用します。

SwapBaseOutput(出力確定)

「ユーザーは出力ミントの正確にamount_outを受け取り、入力ミントの最大maximum_amount_inを支払う意思があります。」 Δx_netの曲線を反転: Δxnet=⌈x⋅amount_outy−amount_out⌉\Delta x_{\text{net}} = \left\lceil \frac{x \cdot \text{amount\_out}}{y - \text{amount\_out}} \right\rceil シーリングは重要です。整数切り捨て後にk' ≥ kを保証します。その後:
Token-2022入力では、以下でラップします:
ユーザーがミントの転送手数料控除後もプールがgross_neededを受け取るのに十分な金額を支払うようにします。

スリッページチェック

計算例

プール状態、Token-2022を無視:
  • x = 1_000_000_000_000(token0の1,000,000.000000、6デシマル)
  • y = 2_000_000_000_000(token1の2,000,000.000000、6デシマル)
  • AmmConfig:trade_fee_rate = 2500、protocol_fee_rate = 120_000、fund_fee_rate = 40_000、creator_fee_rate = 0
ユーザー:amount_in = 1_000_000_000(token0の1,000.000000)でSwapBaseInputを実行。クリエイター手数料は無効(enable_creator_fee = false)。
同じプールがenable_creator_fee = trueでcreator_fee_rate = 1000(0.10%)を入力側に設定していた場合、プログラムはtotal_input_fee = ceil(1_000_000_000 * 3500 / 1_000_000) = 3_500_000を課金し、creator_fee = 1_000_000とtrade_fee = 2_500_000に分割します。trade_feeのプロトコル/ファンド/LP計算は上記の例から変わりません。クリエイター手数料は独立したバケットで、creator_fees_token0に蓄積され、プロトコルとファンドバケットとともにcurve_xから除外されます。 入力ミントが1%のToken-2022転送手数料を持つ場合、ヴォルトは1_000_000_000トークンの代わりに990_000_000トークンを受け取り、その後のすべての計算がその正味金額を使用します。

オブザベーション更新ルール

すべてのスワップで、プログラムはリングバッファに新しいオブザベーションをプッシュするかどうかを評価します:
2つの特性:
  • スポット価格ではなく累積価格。 単一のオブザベーションは価格ではありません。時刻t0からt1までのTWAPを取得するには、各端に最も近いオブザベーションを読み取り、(cumulative(t1) − cumulative(t0)) / (t1 − t0)を計算します。
  • サンプルはレート制限されています。 同じスロット内の連続したスワップは1つのオブザベーションを共有する場合があります。スワップの直後にオブザベーションを読み取ると、1スロット古く見える場合があります。これは正常です。
詳細はproducts/clmm/accountsを参照してください。

曲線上の手数料

これは微妙な部分であり、呼び出す価値があります。曲線計算は正味ヴォルト残高に対して機能します。つまり、生のSPL残高から蓄積されたプロトコル、ファンド、クリエイター手数料を差し引いた値です(3つすべてが独立したバケットです。products/cpmm/feesを参照)。具体的な図:
インテグレーターへの影響:
  • 生の残高から見積もらないでください。 最初に蓄積手数料フィールドを差し引くか、SwapBaseInputをシミュレーションとして呼び出して戻り値を取得してください。
  • CollectProtocolFeeはトークンをヴォルトから移動させます。 収集後、raw_vault_balanceは低下しますが、curve_balanceは変わりません。プールの価格は動きません。これは意図的です。

精度とオーバーフロー

  • すべての曲線計算はx * yのオーバーフローを防ぐためにu128中間値を使用します。
  • 除算はゼロに向かって丸められます。ただし、SwapBaseOutputのΔx_netは切り上げられ、手数料計算ではtrade_feeで切り上げられ、サブスプリットで切り下げられます。これらの丸め方向は、不変量が整数切り捨てのために減少しないように選択されています。
  • 極端なヴォルト比率(数十億:1)を持つプールは小さなトレードで精度フロアに達する場合があります。プログラムはその場合ZeroTradingTokensを返します。reference/error-codesを参照してください。

次のステップ

ソース: