XRPL AMMの概要
AMMとは
AMMとはトークンのペアをプールし、アルゴリズムに従ってトレーダーに流動性を提供する仕組みのことをいいます。
AMMはトレーダーに対して取引量に応じた手数料を課し、流動性の提供者は提供したトークンの割合に応じてトレーダーが支払った手数料から利益を得ることができます。
代表的なAMMプロダクトとしてはUniswapが存在し、EthereumやPolygonチェーンなどに展開されています。
XRP LedgerのAMM
2022年に自動マーケットメーカー(AMM)の機能の提案であるXLS-30dが提出されました。
この提案ではXRP LedgerでAMMを利用するために幾つかのトランザクションが追加されており、いくつかのユニークな機能も搭載しています。(後述)
これらはXRPLにプロトコルネイティブな機能(スマートトランザクタ)として実装されており、AMMの流動性はCLOBの流動性と同じくXRP Ledger内のグローバルな流動性として利用できます。
特徴
XRPL AMMの特徴的な機能として手数料割引権利のオークション(オークションスロット)と手数料の投票機能が挙げられます。
オークションスロット
オークションスロットはトレーダー向けの機能であり、連続オークションの仕組みで他のアカウントとスロットの保有権を競い合います。
オークションスロットを保有している間、保有アカウントとそのアカウントに許可された4アカウント(合計5アカウント)がAMMに対して割引された取引手数料(1/10)でのトレードが可能になります。
1つのオークションスロットの有効期間は24時間であり、保有中のスロットが24時間経過前に他者から落札された場合、残り時間に応じて自身の落札金額の一部が払い戻されます。
スロットを落札するには該当のAMMプールのLPトークン(流動性プロバイダートークン)を使う必要があります。
落札金額と払い戻し金額の差額は全てプールに返還され、流動性提供者の1LPトークンあたりの価値を高めることになり、流動性提供者の利益となります。
トレーダーはAMMプールの取引手数料に対してボラティリティが小さい場合でもスロットを落札することで裁定取引を行うことができ、利益に繋げることができます。
取引手数料の投票
流動性提供者はAMMプールの取引手数料に対して0.001%単位(最大1%)で投票できます。投票は投票者のLPトークンの保有量によって重み付けされ、上位8アカウントの投票から取引手数料が決定されます。
高すぎる手数料は取引量の減少につながり、低すぎる手数料は手数料収益の減少に繋がるため、流動性提供者は自身の利益を最大限にするような投票をするべきです。
トレーダーの利益
トレーダーは他のAMMと同様に価格変動による裁定取引により利益を得ることができます。
加えて、オークションスロットを保有することにより、次の2点から利益を得ることができます。
- 本来利益とならない取引手数料分からも利益を得ることができる。
- ボラティリティがAMMプールの取引手数料より小さい場合であっても裁定取引を行うことができる。
- 例えばAMMプールの取引手数料が1%で、価格の乖離が0.5%の場合、本来は裁定取引を行えませんが、オークションスロットにより取引手数料が0%になるため、価格が乖離している0.5%分から利益を得ることが可能になります。
流動性提供者の利益
他のAMMと同様、トレーダーの取引手数料が流動性提供者の利益となります。
加えて、次の点から利益を得ることができます。
- トレーダーによるオークションスロットの落札金額(の一部)
取引手数料を含むこれらの利益は直接LPトークン等が流動性提供者に配布されるのではなく、LPトークンがバーンされLPトークンの総量が減ることによりLPトークンあたりの価値が増加することによって実現されます。
追加される要素
トランザクション
AMMCreate
AMMプールを作成するトランザクションです。XRPとトークンまたはトークンとトークンのペアと入金金額を指定してAMMプールを作成します。既に存在するペアのAMMプールは作成できません。
トランザクションの例
{
"Account" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"Amount" : {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
"value" : "25"
},
"Amount2" : "250000000",
"Fee" : "10",
"Flags" : 2147483648,
"Sequence" : 6,
"TradingFee" : 500,
"TransactionType" : "AMMCreate"
}
AMMDeposit
AMMプールに対して資産を入金し、入金した資産の量に対するLPトークンを受け取ります。ペアの両方の通貨の入金(ダブルアセット入金)も、一方の通貨のみの入金も可能(シングルアセット入金)です。
ダブルアセット入金の場合は、手数料なしで入金できますが、シングルアセット入金の場合は、資産の半分をAMMプールを通してもう一方の資産へ変換する際の手数料と同等額がかかります。
トランザクションの例
{
"Account" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"Amount" : {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
"value" : "2.5"
},
"Amount2" : "30000000",
"Asset" : {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
},
"Asset2" : {
"currency" : "XRP"
},
"Fee" : "10",
"Flags" : 1048576,
"Sequence" : 7,
"TransactionType" : "AMMDeposit"
}
AMMWithdraw
AMMへLPトークンを返還し、LPトークンの量に対する資産を受け取ります。ペアの両方の通貨の出金(ダブルアセット出金)も、一方の通貨のみの出金(シングルアセット出金)も可能です。
ダブルアセット出金の場合は、手数料なしで入金できますが、シングルアセット出金の場合は、ダブルアセット出金後に一方の資産をAMMプールを通してもう一方の資産へ変換する際の手数料と同等額がかかります。
トランザクションの例
{
"Account" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"Amount" : {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
"value" : "5"
},
"Amount2" : "50000000",
"Asset" : {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
},
"Asset2" : {
"currency" : "XRP"
},
"Fee" : "10",
"Flags" : 1048576,
"Sequence" : 10,
"TransactionType" : "AMMWithdraw"
}
AMMVote
AMMプールの取引手数料に対して投票します。0~1%を0.001%刻みで投票できます。
トランザクションの例
{
"Account" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"Asset" : {
"currency" : "XRP"
},
"Asset2" : {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
},
"Fee" : "10",
"Flags" : 2147483648,
"Sequence" : 8,
"TradingFee" : 600,
"TransactionType" : "AMMVote"
}
AMMBid
AMMプールのオークションスロットへ入札します。追加で最大4つのアカウトを指定でき、スロットの保有中はこの4つのアカウントも手数料の割引対象となります。
トランザクションの例
{
"Account" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"Asset" : {
"currency" : "XRP"
},
"Asset2" : {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
},
"AuthAccounts" : [
{
"AuthAccount" : {
"Account" : "rMKXGCbJ5d8LbrqthdG46q3f969MVK2Qeg"
}
},
{
"AuthAccount" : {
"Account" : "rBepJuTLFJt3WmtLXYAxSjtBWAeQxVbncv"
}
}
],
"BidMax" : {
"currency" : "039C99CD9AB0B70B32ECDA51EAAE471625608EA2",
"issuer" : "rE54zDvgnghAoPopCgvtiqWNq3dU5y836S",
"value" : "100"
},
"Fee" : "10",
"Flags" : 2147483648,
"Sequence" : 9,
"TransactionType" : "AMMBid"
}
Payment
すでに存在するトランザクションです。
AMMを通してトークンをスワップに使用します。スワップする際の流動性として、AMM DEXだけでなくCLOB DEXも自動的に利用します。
Path機能を使用することで複数の経路を利用し、最良レートでのスワップも行えます。
またスワップだけでなく、クロスカレンシーペイメントの流動性としても使用可能です。
トランザクションの例(スワップ)
{
"TransactionType" : "Payment",
"Account" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"Destination" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"Amount" : "5000000",
"SendMax": {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
"value" : "5"
},
"Fee": "12",
"Flags": 2147483648,
"Sequence": 2,
}
レジャーオブジェクト
AccountRoot
すでに存在するオブジェクトです。
2つの資産を持つAMMプールは既存のアカウントオブジェクト:AccountRootとして表されます。
この特殊なアカウントはプール資産としてXRPとトークンまたはトークンとトークンを保有し、LPトークンの発行者となります。
AMM
AMMオブジェクトには資産ペアやオークションスロット、手数料投票の状況、現在の取引手数料などの情報が格納されます。
オブジェクトの例
{
"AMMAccount" : "rE54zDvgnghAoPopCgvtiqWNq3dU5y836S",
"Asset" : {
"currency" : "XRP"
},
"Asset2" : {
"currency" : "TST",
"issuer" : "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
},
"AuctionSlot" : {
"Account" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"AuthAccounts" : [
{
"AuthAccount" : {
"Account" : "rMKXGCbJ5d8LbrqthdG46q3f969MVK2Qeg"
}
},
{
"AuthAccount" : {
"Account" : "rBepJuTLFJt3WmtLXYAxSjtBWAeQxVbncv"
}
}
],
"DiscountedFee" : 0,
"Expiration" : 721870180,
"Price" : {
"currency" : "039C99CD9AB0B70B32ECDA51EAAE471625608EA2",
"issuer" : "rE54zDvgnghAoPopCgvtiqWNq3dU5y836S",
"value" : "0.8696263565463045"
}
},
"Flags" : 0,
"LPTokenBalance" : {
"currency" : "039C99CD9AB0B70B32ECDA51EAAE471625608EA2",
"issuer" : "rE54zDvgnghAoPopCgvtiqWNq3dU5y836S",
"value" : "71150.53584131501"
},
"TradingFee" : 600,
"VoteSlots" : [
{
"VoteEntry" : {
"Account" : "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"TradingFee" : 600,
"VoteWeight" : 100000
}
}
]
}
APIメソッド
amm_info
AMMオブジェクトの情報を取得するためのAPIメソッドです。
リクエストの例
{
"command": "amm_info",
"asset": {
"currency": "XRP"
},
"asset2": {
"currency": "TST",
"issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
}
}
レスポンスの例
{
"result": {
"amm": {
"amm_account": "rp9E3FN3gNmvePGhYnf414T2TkUuoxu8vM",
"amount": "296890496",
"amount2": {
"currency": "TST",
"issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd",
"value": "25.81656470648473"
},
"asset2_frozen": false,
"auction_slot": {
"account": "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"auth_accounts": [
{
"account": "r3f2WpQMsAd8k4Zoijv2PZ78EYFJ2EdvgV"
},
{
"account": "rnW8FAPgpQgA6VoESnVrUVJHBdq9QAtRZs"
}
],
"discounted_fee": 0,
"expiration": "2023-Jan-26 00:28:40.000000000 UTC",
"price": {
"currency": "039C99CD9AB0B70B32ECDA51EAAE471625608EA2",
"issuer": "rp9E3FN3gNmvePGhYnf414T2TkUuoxu8vM",
"value": "0"
},
"time_interval": 0
},
"lp_token": {
"currency": "039C99CD9AB0B70B32ECDA51EAAE471625608EA2",
"issuer": "rp9E3FN3gNmvePGhYnf414T2TkUuoxu8vM",
"value": "87533.41976112682"
},
"trading_fee": 600,
"vote_slots": [
{
"account": "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"trading_fee": 600,
"vote_weight": 9684
}
]
},
"ledger_current_index": 316725,
"validated": false
},
"status": "success",
"type": "response"
}
まとめ
現在開発が進められているAMM機能はXRP LedgerのDEX環境に非常に大きなインパクトとなるでしょう。CLOB DEXとAMM DEXの流動性が集約され、トレーダーにとってより良い取引レートでトレードが行えるようになります。
また、XRPやトークンのホルダーは流動性を提供することでインセンティブを得ることができるようになります。
興味を持たれた方はXRP Ledger開発者のDiscordチャンネルへ是非お越しください!
日本語チャンネルもありますので、英語ができなくても大丈夫です!
Discussion
XRPLにおけるAMMを活用した時のスワップの時のトランザクションデータについて質問です。
この場合、トランザクションの宛先 DestinationにはAMMのアカウントのアドレスを設定するのでしょうか?それともスワップするアカウントのアドレスを入力するのでしょうか?
ご教示いただければ幸いです!
下記のようにトランザクションデータを作成してswapを試みましたがエラーが返ってきました。
エラーの内容は、error occuered while swaping: Error sending transaction: tecNO_PERMISSION というものです。
よろしくお願いします!
スワップ時は
Destination
には自身のアカウント(=Account
フィールド)を指定します!また、
Amount
フィールドとSendMax
フィールドで同じ通貨コードを指定する場合、Paths
フィールドが必要になります。AMM AccountへのPaymentは出来ないようになっています。
Paymentトランザクション内でAMMに関する情報を指定する必要はなく、変換元と変換先のトークンの情報(金額含む)を指定するだけで、あとは自動的にDEX(CLOB,AMM)を使った変換を行います。
ありがとうございます!!
いただいた助言元にしてトランザクションデータを修正して再度トライしてみました・・・。
エラーは変わったのですが以前上手く処理されない状況が続いています。
エラーの内容は以下の通りです。
シーケンス番号が不正な値になっているということなので別のAPIを叩いて最新の値を手動で入れた方がいいんですかね?
修正後のトランザクションデータは下記の通りです。
swapの他、 AMMwithdrawとAMMDepositでも全く同じエラーが発生しています・・
AMMBidとAMMCreate、AMMvoteでは発生していません!
お手数ですがご確認よろしくお願いします!
Swap関数全体としては以下のような実装としています!
Paymentトランザクションに
SendMax
の指定がないためですね。ローカル環境で確認したところ
temREDUNDANT
でした。Swapする場合は
Account
=Destination
かつSendMax
の指定も必要となります。AMMwithdraw
とAMMDeposit
に関してはトランザクション情報がないため分からないです…xrpl.jsのclient.submitAndWait
はコンセンサスステージ前のトランザクションフォーマットチェック段階でエラーの場合、LastLedgerSequenceが無効になるまでトランザクションの送信を試行します。LastLedgerSequence
に関するエラーの場合は基本的にトランザクションのフォーマットが間違っている可能性が高いです👍ありがとうございます!
もう一度見直してみたいと思います!!
↑ このページを確認しました!
↑ この仕様に従ってPaymentトランザクションデータを作る必要があるんですね!
pathを指定してみたんですが、invalidPathというエラーが返っている状況です・・、
すみません、見直すポイントについてご教示いただけると幸いです。
よろしくお願いします!
↑ すみません、Pathsについてはこの記事参考に直してみましたがやはりエラーが返ってきました・・。
パス情報がやはり間違っていそうなのでPaymentの直前で、 path_findのAPIを叩いてパス情報を取得してみました。
その結果がこちらです。
今の最新のSwap用のトランザクションデータは下記のように作成しています。
もう一度見直したらSwapできました!!!
お騒がせました!!!
※ でもまだ AMM Depositと AMM Withdrawが動かない・・・
でもXRPLの真の力の一端に触れられました!! スマコン作らないでこの機能が使えるのは本当にすごいですね!!!
トランザクションデータは、最終的に以下のようになりました。
トランザクションハッシュ値以下の通りです!!
おめでとうございます🎉🎉
Pathsはその時々で流動性が変化するため手動設定するよりもpath_findを利用する方が良いですね!
AMM DepositとAMM Withdrawのエラーとなるトランザクション情報を共有していただけますか?
ご確認ありがとうございます!!
実はこちらも見直したらできました!!!
Flagの指定が抜けていたのが原因だったみたいです!!
実際にAMMにDepositした時のトランザクション
2CA07EFC85DC96BC05CFDAB34454FA89120932242A237C05DB29DE2C3F6B568A
実際にAMMからWithdrawした時のトランザクション
3519A06BBA59E6D6B017BB465AA596BF01ABCC10D193E12830339BA93B3D9A02
AMM関連のトランザクションを一通り動かしてみることができたのであれば、他のほとんどのトランザクションはそれ以下のコストで学ぶことができると思います👍
個人的にはAMM関連(特にDeposit, Withdraw)のトランザクションはどちらかというと複雑な方だと思ってます