Title: Automated Market Maker on XRPL Revision: 4 (2023-08-08)
Author: Aanchal Malhotra David J. Schwartz Affiliation: Ripple
The XRPL decentralized exchange (DEX) currently provides liquidity exclusively by manual market making and order books. This proposal adds non-custodial automated market maker (AMM) as a native feature to the XRPL DEX in a way that provides increased returns to those who provide liquidity for the AMM and minimizes the risk of losses due to volatility.
We propose a unique mechanism where the AMM instance continuously auctions off trading advantages to arbitrageurs, charging them and giving these earnings to its liquidity providers. This allows liquidity providers to take a large share of the profits that would normally be taken by arbitrageurs.
The AMM instance charges a spread on the trades that change the ratio of tokens in the instance's pools. This trading fee is added to the AMM instance's capital pool, thus adding to the liquidity providers' returns.
The AMM instances also provide governance rights to the largest share holders of the AMM instance. This allows them to vote on the trading fee the instance charges.
XRPL's AMM based DEX interacts with XRPL's limit order book (LOB)-based DEX so that users of AMM pools have access to all order flow and liquidity on LOB DEX, and vice versa. The payment and order placement transactors automatically determine whether swapping within a liquidity pool or through the order book will provide the best price for the user and execute accordingly. Pathfinding considers paths with both order books and AMMs in various combinations to improve the overall exchange rate.
AMMs are agents that pool liquidity and make it available to traders according to a predetermined algorithm. This is a proposal for geometric mean market maker (GM3)-based DEX as a native XRPL feature. GM3 algorithmically discovers a fair exchange value, stabilized by arbitrage, to automatically produce liquidity. On XRPL, this would provide liquidity pools between XRP and issued assets as well as between any two issued assets. Arbitrageurs play a significant role in keeping the AMM DEX in a stable state with respect to external markets.
Several things that contribute to the costs that trading imposes on AMM pools are naturally much less significant on XRPL:
-
Low transaction fee: An arbitrageur only submits a transaction when the expected profit from the transaction exceeds the transaction fee. XRPL’s transaction fees are much lower than those on most DeFi chains. This benefits the AMM instance pools by narrowing the time windows in which the instance suffers decreased trading volume due to its spot-market price being off due to volatility or asymmetric trading.
-
Fast finality: Arbitrageurs take risk (for which they must be compensated at the instance pool’s expense) due to the block times. Prices may change while their transaction is in flux. XRPL has faster block times than many of the fastest competing major blockchains.
-
Canonical transaction ordering: Transactions on XRPL are canonically ordered. Other blockchains have block producers, miners, or stakers who try to extract value from arbitrage transactions by delaying, reordering, front-running, or selectively including them to extract more value from the pool and the arbitrageurs. XRPL doesn’t have this.
AMMs are more effective and lucrative when transactions execute quickly, cheaply, and fairly. This means that XRPL AMM could provide more liquidity at lower prices, yet still provide a compelling return.
- Conservation Function: We propose a weighted geometric mean market maker (GM3) for AMM price discovery:
where,
-
: Current balance of token in the AMM instance pool -
: Current balance of token in the AMM instance pool -
: Normalized weight of token in the AMM instance pool -
: Normalized weight of token in the AMM instance pool
In this version of the proposal, pools must be of equal value. The implicit normalized weights are
-
Liquidity Providers: Liquidity providers (LPs) are the traders who add liquidity to the AMM instance's pools, thus earning shares of the pools in the form of
LPTokens
. -
LPTokens: LP tokens represent the liquidity providers' shares of the AMM instance's pools.
LPTokens
are tokens on XRPL. EachLPToken
represents a proportional share of each pool of the AMM instance. The AMM instance account issues theLPTokens
to LPs upon liquidity provision.LPTokens
are balanced in the LPs trustline upon liquidity removal. -
Spot-Price: Spot-price (SP) is the weighted ratio of the instance's pool balances.
is the spot-price of asset relative to asset . is the trading fee paid by the trader for trades executed against the AMM instance.
-
Effective-Price: The effective price (EP) of a trade is defined as the ratio of the tokens the trader sold or swapped in (Token
) and the token they got in return or swapped out (Token ).
- Slippage: Slippage is defined as the percentage change in the effective price of a trade relative to the pre-swap spot-price.
AMM Instance Representation
- We propose the existing
AccountRoot
ledger entry and a new ledger entryAMM
to represent an AMM instance with two asset pools. New transaction typeAMMCreate
is used to createAccountRoot
and the correspondingAMM
ledger entries. In this version we propose to allow for the creation of only one AMM instance per unique asset pair.
Trading on AMM Instance
-
To enable adding and removing liquidity to and from the two pools of the AMM instance, we introduce two new transaction types
AMMDeposit
andAMMWithdraw
respectively. The proposal allows for both equal-asset as well as single-sided deposits and withdrawals. Adding liquidity to an AMM instance yields pool shares calledLPTokens
that are issued by the AMM instance represented as XRPL tokens.LPTokens
can be bought, sold and can be used to make payments exactly as other issued assets/tokens on the ledger. -
To enable exchanging one pool asset of the AMM instance for the other - a swap - we propose the existing
Payment
transaction.
Votable Trading Fee
- The AMM instance charges a trading fee on the portion of the trade that changes the ratio of tokens in the AMM instance. This fee is added to the AMM instance's pools and is distributed proportionally to the
LPToken
holders upon redemption ofLPTokens
. High trading fee may deter user participation, thus reducing the trading volume and consequently LPs revenue. On the other hand, low trading fee naturally means lower revenue for LPs. Instead of hardcoding the trading fee in the protocol, we propose it be a votable parameter for theLPToken
holders. The assumption is that LPs being the significant stakeholders in an AMM instance are best positioned to collectively make this decision in a balanced way.
Two-way Interoperable AMM and LOB-based DeXs
- XRPL's AMM-based and the existing LOB-based DeXs are two-way interoperable, i.e. the interleaved execution of the AMM trades with the existing order book based DeX on XRPL. The key to this integration is transparent injection of the AMM offer into the liquidity stream, which is fed into the payment execution engine. This ensures aggregated liquidity across different DeXs and better exchange rate for the traders.
Novel Feature: Continuous Auction Mechanism
-
Problem: Due to volatility or asymmetric trading, when relative price of assets in AMM pools goes out-of-sync with that of external markets, AMM does not adjust the prices automatically due to lack of external market information (price-feed) natively. As a result, arbitrageurs intervene, but they have to:
- Wait until the profit from the arbitrage transaction (and thus the pool’s expected loss) exceeds the trading fees
- Race/Compete against others, thus reducing their success probability
-
Implications: Liquidity Providers lose because:
- During the wait window, there is a decreased trading volume (and thus decreased revenue) for the pool
- Arbitrageurs make profits from arbitrage transaction at pool's (LPs’) expense
-
Our Approach: Create a mechanism that makes it:
- Easy (higher success probability) for arbitrageurs by eliminating the race condition, AND
- Profitable for liquidity providers by further narrowing the window of decreased trading volume for the pool and sharing the profits from arbitrage transaction
-
Our Innovative Solution: To achieve the above mentioned, we introduce a mechanism for the AMM instance to continuously auction-off trading advantages for a 24-hour slot at zero trading fee! Anyone can bid for the auction slot with the units of
LPtokens
. The slot-holder can send the arbitrage transaction immediately without the need to wait for their profits to exceed the trading fee, thus eliminating the race condition for them. This also reduces the time window for which the pool suffers decreased trading volume. Additionally, part of proceeds (LPTokens
) from the auction are deleted/burnt that effectively increases LP token holders' ownership in the pool proportionally. Since it's a continuous auction mechanism, if someone outbids an auction slot-holder, part of proceeds from the auction are refunded to the previous slot-holder (computed pro-rata). For details refer Section 5.
As slot holder will have significant advantages for arbitrage, it’s expected that arbitrageurs will bid up the price of the auction slot to nearly the value they extract through arbitrage.
- Expected Results
- Eliminates wait time & race condition for auction slot holder (arbitrageur)
- Narrows time windows in which the pool suffers decreased trading volume
- Liquidity providers additionally reap a share of profits that would otherwise go JUST to arbitrageurs
We propose the existing AccountRoot
object together with a new ledger object AMM
to represent an AMM instance. Currently, the AccountRoot
object type describes a single account, its settings, and XRP balance on the XRP ledger. The AccountRoot
and the AMM
objects that represent an AMM instance can be created using the new AMMCreate
transaction. XRP balance of the AMM instance pools is always tracked via the existing Balance
field of the AccountRoot
object. The issued asset balances of the AMM instance pools and LPTokens
are automatically tracked via trust lines. The AMM can be traded against using the new AMMDeposit
and AMMWithdraw
and the existing Payment
transactions. Additionally, the AMM instance in "empty" state can be deleted using the AMMDelete
transaction.
Note that in this version, only equal-weighted two asset pools are supported. However, differing weighted pools could be supported in future versions.
We introduce a new field called AMMID
to the AccountRoot
object. It provides an easy link to the corresponding AMM
object and a way to identify the AMM AccountRoot
.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
AMMID |
✔️ | string |
UINT256 |
AMMID
specifies the AMMID
as described below.
The unique ID of the AccountRoot
object, a.k.a. AccountRootID
is computed as follows:
- for (i = 0; i <= 256; i--)
- Compute
AccountRootID
=SHA512-Half
(i || Parent Ledger Hash ||AMMID
) - If the computed
AccountRootID
exists, repeat- else, return
AccountRootID
- else, return
- Compute
The unique ID of the new AMM
object , a.k.a AMMID
is computed as follows:
- Calculate the
SHA512-Half
of some of the following values:- The
issuer
of the issued asset; - The
currency
of the issued asset; - The
issuer
of the second issued asset, if there exists one; - The
currency
of the second issued asset, if there exists one;
- The
The order of the fields to compute the hash is decided canonically. The AMMID
associated with this AccountRootID
is this hash to ensure the uniqueness of the AMM instance. The applications can look-up the AccountRootID
for a specific AMM instance by providing the asset pair for that instance.
The AMM
ledger entry contains the following fields for the AccountRoot
object that represents the AMM instance.
-
Account
specifies the ID of theAccountRoot
object associated with thisAMM
ledger entry. -
TradingFee
specifies the fee, in basis point, to be charged to the traders for the trades executed against this AMM instance. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%. Trading fee is a percentage of the trade size. It is charged on the asset being deposited for theAMMDeposit
(if applicable) andPayment
transactions and on the asset being withdrawn for theAMMWithdraw
(if applicable) transaction. This fee is added to the AMM instance's pools and is distributed to the LPs in proportion to theLPTokens
upon liquidity removal. -
VoteSlots
represents an array ofVote
objects. -
AuctionSlot
represents theAuction
object. -
LPTokenBalance
specifies the balance of outstanding liquidity Provider Tokens (LPTokens). -
Asset
specifies the one of the assets of the AMM instance. -
Asset2
specifies the other asset of the AMM instance. -
OwnerNode
specifies the page hint for the DirectoryNode entry to link the account root and the corresponding AMM objects.
Once the AMM AccountRoot
object is created, we make sure that no further transactions can originate from this account. Conceptually, it is an account that is not owned by anyone. So every possible way of signing the transaction for this account MUST be automatically disabled.
We define a new transaction AMMCreate
specifically for creating a new AMM instance represented by an AccountRoot
object and the corresponding AMM
object.
Notes:
AMMCreate
is not allowed withLPTokens
AMMCreate
is not allowed if the token’s issuer hasDefaultRipple
flag disabled.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TransactionType |
✔️ | string |
UINT16 |
TransactionType
specifies the new transaction type AMMCreate
. The integer value is 35.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Fee |
✔️ | string |
AMOUNT |
Fee
specifies the integer amount of XRP, in drops, to be destroyed as a cost of creating an AMM instance. We DO NOT propose to keep a reserve for the AMM instance.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Amount |
✔️ | string or object |
AMOUNT |
Amount
specifies one of the pool assets (XRP or token) of the AMM instance.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Amount2 |
✔️ | string or object |
AMOUNT |
Amount2
specifies the other pool asset of the AMM instance.
Both Amount
and Amount2
that represent issued assets MUST have value
subfields specified.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TradingFee |
✔️ | number |
UINT16 |
TradingFee
specifies the fee, in basis point, to be charged to the traders for the trades executed against the AMM instance. Trading fee is a percentage of the trading volume. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%.
The AMMCreate
transaction MUST fail if the account issuing this transaction:
i. does not have sufficient balances, OR
ii. is NOT the issuer
of either token AND the RequireAuth
flag for the corresponding token is set AND the account initiating the transaction is not authorized.
If the transaction is successful,
i. Three new ledger entries AccountRoot
, AMM
and DirectoryNode
are created.
ii. The regular key for the AccountRoot
ledger entry is set to account zero, and the master key is disabled, effectively disabling all possible ways to sign transactions from this account.
iii. New trust lines are created.
A successful AMMCreate
transaction will automatically create the following trust lines:
- Trustlines that track the balance(s) of the issued asset(s) of the AMM instance's pool(s) between the AMM instance account and the issuer.
- Trustlines that track the balance of
LPTokens
between the AMM instance and the account that initiated the transaction.LPTokens
are uniquely identified by the following:-
issuer: AMM instance
AccountID
and; -
currency: the currency code for
LPTokens
for currency codes cur1 and cur2 is formed deterministically as follows: -
Compute
SHA256{cur1, cur2}
-
LPTokenID
= 0x03 + first 19 bytes from SHA256
-
The prefix 0x03 is added to identify LPTokens
The value
field is computed as follows:
where,
-
: Balance of asset -
: Balance of asset -
& : Normalized weights of asset and asset in the pool respectively
Initially by default,
Unlike other objects in the XRPL, there is no reserve for the AccountRoot
and AMM
ledger entries created by an AMMCreate
transaction. Instead there is a higher Fee
(~ 1 reserve) for AMMCreate
transaction in XRP which is burned as a special transaction cost.
On final withdraw (i.e. when LPTokens
balance is 0) the AMM instance automatically deletes up to 512 trust lines. If there are fewer then 512 trustlines then AMM
, AccountRoot
and DirecotoryNode
objects are deleted.
However, if there are more than 512 trustlines then AMM instance remains in empty state (LPTokens
balance is 0). To handle cleaning this up, we introduce a new transaction type AMMDelete
to delete the remaining trustlines. Anyone can call the AMMDelete
transactor. AMMDelete
also has a limit of 512 trustlines and deletes the AMM
, AccountRoot
and DirectoryNode
objects only if there are fewer than 512 trustlines at the time it executes. If there are more trustlines to delete, then AMMDelete
returns the tecINCOMPLETE
result code and the user should submit another AMMDelete
to delete more entries.
In order to avoid destroying assets of the AMM instance, the implementation of the AMMWithdraw
transaction MUST guarantee that the AMM instance has no asset reserves if no account owns its LPTokens
.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TransactionType |
✔️ | string |
UINT16 |
TransactionType
specifies the new transaction type AMMDelete
. The integer value is 40.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset |
✔️ | object |
ISSUE |
Asset
specifies one of the assets of the AMM instance against which the transaction is to be executed. The ISSUE
object
may have the following subfields:
Field name | Required? | Description |
---|---|---|
issuer |
✔️ | specifies the unique XRPL account address of the entity issuing the currency |
currency |
✔️ | arbitrary code for currency to issue |
If the asset is XRP, then the issuer subfield is not mentioned.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset2 |
✔️ | object |
ISSUE |
Asset2
specifies the other asset of the AMM instance against which the transaction is to be executed. The ISSUE
object
may have the following subfields:
Field name | Required? | Description |
---|---|---|
issuer |
✔️ | specifies the unique XRPL account address of the entity issuing the currency |
currency |
✔️ | arbitrary code for currency to issue |
Users can trade against specific AMM instances using the new transactions AMMDeposit
and AMMWithdraw
, and the existing Payment
transaction.
AMMDeposit
: The deposit transaction is used to add liquidity to the AMM instance pool, thus obtaining some share of the instance's pools in the form ofLPTokens
.AMMWithdraw
: The withdraw transaction is used to remove liquidity from the AMM instance pool, thus redeeming some share of the pools that one owns in the form ofLPTokens
.Payment
: The payment transaction is used to exchange one asset of the AMM instance for the other.
With AMMDeposit
transaction, XRPL AMM allows for both:
- all assets liquidity provision
- single asset liquidity provision
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TransactionType |
✔️ | string |
UINT16 |
TransactionType
specifies the new transaction type AMMDeposit
. The integer value is 36.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset |
✔️ | object |
ISSUE |
Asset
specifies one of the assets of the AMM instance against which the transaction is to be executed. The ISSUE
object
may have the following subfields:
Field name | Required? | Description |
---|---|---|
issuer |
✔️ | specifies the unique XRPL account address of the entity issuing the currency |
currency |
✔️ | arbitrary code for currency to issue |
If the asset is XRP, then the issuer subfield is not mentioned.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset2 |
✔️ | object |
ISSUE |
Asset2
specifies the other asset of the AMM instance against which the transaction is to be executed.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Amount |
string or object |
AMOUNT |
Amount
specifies the amount of one of the pools assets. If the asset is XRP, then the Amount
is a string
specifying the number of drops. Otherwise it is an object
with the following subfields:
Field name | Required? | Description |
---|---|---|
issuer |
✔️ | specifies the unique XRPL account address of the entity issuing the currency |
currency |
✔️ | arbitrary code for currency to issue |
value |
specifies the maximum amount of this currency, in decimal representation, that the trader is willing to add |
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Amount2 |
string or object |
AMOUNT |
Amount2
specifies the details of other pool asset that the trader is willing to add.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
EPrice |
string |
AMOUNT |
EPrice
specifies the effective-price of the token out after successful execution of the transaction. For AMMDeposit
transaction, the token out is always LPToken
.
Note that the relative pricing does not change in case of all-asset deposit transaction.
EPrice
is an invalid field for all assets deposits. It should only be specified in case of single sided deposits.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
LPTokenOut |
string |
AMOUNT |
LPTokenOut
specifies the amount of shares of the AMM instance pools.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TradingFee |
string |
UINT8 |
TradingFee
specifies the trading fee for the AMM instance. This field is only valid if the option flag tfTwoAssetIfEmpty
is set. In this case, the AMM instance is in the empty state and AMMDeposit
becomes AMMCreate
type transaction.
Let the following represent the pool composition of AMM instance before trade:
-
: Current balance of asset -
: Current balance of asset -
: Current balance of outstanding LPTokens
issued by the AMM instance
Let the following represent the assets being deposited as a part of AMMDeposit
transaction and the corresponding LPTokens
being issued by the AMM instance.
-
: Balance of asset being added -
: Balance of asset being added -
: Balance of LPTokens
issued to the LP after a successfulAMMDeposit
transaction
And let LPToken
holders.
If the trader deposits proportional values of both assets without changing their relative pricing, no trading fee is charged on the transaction. If
AND
Following is the updated pool composition of the AMM instance after successful transaction:
-
: Current new balance of asset -
: Current new balance of asset -
: Current new balance of outstanding LPTokens
Let
Also let
-
, then
Similarly, we can derive
Following is the updated pool composition of the AMM instance after successful trade:
-
: Current new balance of asset -
: Current new balance of outstanding LPTokens
The proposal allows for traders to specify different combinations of the above mentioned fields for AMMDeposit
transaction. The implementation will determine the best possible sub operations based on trader's specifications.
We introduce the following flags to the AMMDeposit
transaction to identify valid parameter combinations.
Flag Name | Hex Value | Description |
---|---|---|
tfLPToken |
0x00010000 | If set, it indicates LPTokenOut parameter and may optionally include Amount and Amount2 combination |
tfSingleAsset |
0x00080000 | If set, it indicates Amount parameter and may optionally include LPTokenOut parameter |
tfTwoAsset |
0x00100000 | If set, it indicates Amount and Amount2 parameter combination and may optionally include LPTokenOut parameter |
tfOneAssetLPToken |
0x00200000 | If set, it indicates Amount and LPTokenOut parameter combination |
tfLimitLPToken |
0x00400000 | If set, it indicates Amount and EPrice parameter combination |
tfWithdrawAll |
0x00020000 | If set, it indicates proportional withdrawal of all LPTokens |
tfTwoAssetIfEmpty |
0x00800000 | If set, it indicates that this deposit can only be submitted on an empty state AMM (LPTokens == 0) |
If tfTwoAssetIfEmpty
is set, both amounts have to be specified and deposited into AMM as is. It is sort of like AMMCreate
in an empty AMM state.
Following are the recommended valid combinations. Other invalid combinations may result in the failure of transaction.
LPTokenOut
,[Amount]
,[Amount2]
Amount
,[LPTokenOut]
Amount
,Amount2
,[LPTokenOut]
Amount
andLPTokenOut
Amount
andEPrice
Amount
,Amount2
,[TradingFee]
Details for above combinations:
- Fields specified:
LPTokenOut
,[Amount]
,[Amount2]
and Flag:tfLPToken
Such a transaction assumes proportional deposit of pools assets in exchange for the specified amount of LPTokenOut
of the AMM instance. Amount
and Amount2
, if included, have to be provided both and specify minimum deposit amounts for each asset.
Deposit fails if the min deposit condition is not met
- Fields specified:
Amount
,[LPTokenOut]
and Flag:tfSingleAsset
Such a transaction assumes single asset deposit of the amount of asset specified by Amount
. This is essentially an equal asset deposit and a swap.
If the asset to be deposited is a token, specifying the value
field is required, else the transaction will fail.
LPTokenOut
, if included, specified minimum LPTokens
amount that the user receives, else the transaction will fail.
- Fields specified:
Amount
,Amount2
,[LPTokenOut]
, and Flag:tfTwoAsset
Such a transaction assumes proportional deposit of pool assets with the constraints on the maximum amount of each asset that the trader is willing to deposit.
LPTokenOut
, if included, specified minimum LPTokens
amount that the user receives, else the transaction will fail.
- Fields specified:
Amount
andLPTokenOut
and Flag:tfOneAssetLPToken
Such a transaction assumes that a single asset Amount
is deposited to obtain some share of the AMM instance's pools represented by amount of LPTokenOut
. Since adding liquidity to the pool with one asset changes the ratio of the assets in the two pools, thus changing the relative pricing, trading fee is charged only on the amount of the deposited asset that causes this change.
- Fields specified:
Amount
andEPrice
and Flag:tfLimitLPToken
Such a transaction assumes single asset deposit with the following two constraints:
a. amount of asset1 if specified in Amount
specifies the maximum amount of asset1 that the trader is willing to deposit
b. The effective-price of the LPTokenOut
traded out does not exceed the specified EPrice
- Fields specified:
Amount
,Amount2
,[TradingFee]
and Flag:tfTwoAssetIfEmpty
Such a transaction assumes proportional deposit of pool assets in the empty state.
Following updates after a successful AMMDeposit
transaction:
- The deposited asset, if XRP, is transferred from the account that initiated the transaction to the AMM instance account, thus changing the
Balance
field of each account - The deposited asset, if tokens, are balanced between the AMM account and the issuer account trust line.
- The
LPTokenOut
~are issued by the AMM instance account to the account that initiated the transaction and a new trustline is created, if there does not exist one. - The pool composition is updated. Note that the conservation function is not preserved in case of liquidity provision.
For more details refer to Appendix A.
With AMMWithdraw
transaction, this proposal allows for both the following:
- all assets liquidity withdrawal
- single asset liquidity withdrawal
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TransactionType |
✔️ | string |
UINT16 |
TransactionType
specifies the new transaction type AMMWithdraw
. The integer value is 37.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset |
✔️ | object |
ISSUE |
Asset
specifies one of the assets of the AMM instance against which the transaction is to be executed.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset2 |
✔️ | object |
ISSUE |
Asset2
specifies the other asset of the AMM instance against which the transaction is to be executed.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Amount |
object or string |
AMOUNT |
Amount
specifies one of the pools assets that the trader wants to remove. If the asset is XRP, then the Amount
is a string
specifying the number of drops. Otherwise it is an object
with the following subfields:
Field name | Required? | Description |
---|---|---|
issuer |
✔️ | specifies the XRPL address of the issuer of the currency |
currency |
✔️ | specifies the currency code of the issued currency |
value |
specifies the minimum amount of this asset that the trader is willing to withdraw. |
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Amount2 |
string or object |
AMOUNT |
Amount2
specifies the other asset that the trader wants to remove.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
EPrice |
object |
AMOUNT |
EPrice
specifies the effective-price of the token out after successful execution of the transaction. For AMMWithdraw
transaction, the out is either XRP or issued token. The asset in is always LPToken
. So EPrice
is always an object
.
Note that the relative pricing does not change in case of all-asset withdrawal. EPrice
is an invalid field for all assets deposits. It should only be specified in case of single sided deposits.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
LPTokenIn |
object |
AMOUNT |
LPTokenIn
specifies the amount of shares of the AMM instance pools that the trader wants to redeem or trade in.
Let following represent the pool composition of the AMM instance before withdrawal:
-
: Current balance of asset -
: Current balance of asset -
: Current balance of outstanding LPTokens
issued by the AMM instance
Let following represent the assets being withdrawn as a part of AMMWithdraw
transaction and the corresponding LPTokens
being redeemed.
-
: Balance of asset being withdrawn -
: Balance of asset being withdrawn -
: Balance of LPTokens
being redeemed
Let LPToken
holders upon liquidity withdrawal.
If the trader withdraws proportional values of both assets without changing their relative pricing, no trading fee is charged on the transaction.
If
AND
Following is the updated pool composition of the AMM instance after successful trade:
-
: Current new balance of asset -
: Current new balance of asset -
: Current new balance of outstanding LPTokens
Single asset withdrawal can be conceptualized as two sub trades of equal asset withdrawal and a swap. Let asset
-
, then
Similarly, we can derive
Following is the updated pool composition of the AMM instance after successful trade:
-
: Current new balance of asset -
: Current new balance of outstanding LPTokens
The proposal allows for traders to specify different combinations of the above mentioned fields for AMMWithdraw
transaction. The implementation will figure out the best possible operations based on trader's specifications.
We introduce the following six transaction flags to the AMMWithdraw
transaction to identify valid parameter combinations. Other invalid combinations may result in the failure of transaction.
Flag Name | Hex Value | Description |
---|---|---|
tfLPToken |
0x00010000 | If set, it indicates LPTokenIn field parameter |
tfSingleAsset |
0x00080000 | If set, it indicates Amount field parameter |
tfTwoAsset |
0x00100000 | If set, it indicates Amount and Amount2 fields parameter combination |
tfOneAssetLPToken |
0x00200000 | If set, it indicates Amount and LPTokenIn fields parameter combination |
tfLimitLPToken |
0x00400000 | If set, it indicates Amount and EPrice fields parameter combination |
tfWithdrawAll |
0x00020000 | If set, it indicates withdrawal of both assets equivalent to all LPTokens held by the account |
tfOneAssetWithdrawAll |
0x00040000 | If set, it indicates withdrawal of single asset equivalent to all LPTokens held by the account |
LPTokenIn
Amount
Amount
andAmount2
Amount
andLPTokenIn
Amount
andEPrice
Implementation details for the above combinations:
- Fields specified:
LPTokenIn
Such a transaction assumes proportional withdrawal of pool assets for the amount of LPTokenIn
. Since withdrawing assets proportionally from the AMM instance pools does not change the ratio of the two assets in the pool and thus does not affect the relative pricing, trading fee is not charged on such a transaction.
- Fields specified:
Amount
Such a transaction assumes withdrawal of single asset equivalent to the amount specified in Amount
- Fields specified:
Amount
andAmount2
Such a transaction assumes all assets withdrawal with the constraints on the maximum amount of each asset that the trader is willing to withdraw.
- Fields specified:
Amount
andLPTokenIn
Such a transaction assumes withdrawal of single asset specified in Amount
proportional to the share represented by the amount of LPTokenIn
. Since a single sided withdrawal changes the ratio of the two assets in the AMM instance pools, thus changing their relative pricing, trading fee is charged on the amount of asset1 that causes that change.
- Fields specified:
Amount
andEPrice
Such a transaction assumes withdrawal of single asset with the following constraints:
a. amount of asset1 if specified in Amount
specifies the minimum amount of asset1 that the trader is willing to withdraw
b. The effective price of asset traded out does not exceed the amount specified in EPrice
Following updates after a successful transaction:
- The withdrawn asset, if XRP, is transferred from AMM instance account to the account that initiated the transaction, thus changing the
Balance
field of each account - The withdrawn asset, if token, is balanced between the AMM instance account and the issuer account.
- The
LPTokens
~are balanced between the AMM instance account and the account that initiated the transaction. - The pool composition is updated. Conservation function is not preserved in case of liquidity withdrawal (and is not expected to.)
For more details refer to Appendix B.
In order to exchange one asset of the AMM instance's pools for another, we DO NOT introduce a new transaction. Instead, we propose to use the existing Payment
transaction.
Let the following represent the pool composition of the AMM instance before a swap.
-
: Current balance of asset in the pool -
: Current balance of asset in the pool
Let the following represent the balances of assets Payment
transaction.
-
: Balance of asset being swapped out of the AMM instance's pool -
: Balance of asset being swapped into the AMM instance's pool
We can compute
Similarly, we can compute
To change the spot-price of token
We can compute the average slippage
where
We can compute the average slippage
where
The following is the updated pool composition after a successful transaction:
-
: Current new balance of asset -
: Current new balance of asset
Note that the conservation function is preserved, however the ratio of the two assets and hence their relative pricing changes after a successful swap.
Following updates after a successful transaction:
- The swapped asset, if XRP, is transferred from AMM instance account to the account that initiated the transaction or vice-versa, thus changing the
Balance
field of each account - The swapped asset, if token, is balanced between the AMM instance account and the issuer account.
- The pool composition is updated.
An XRPL Payment
transaction represents a transfer of value from one account to another. This transaction type can be used for several types of payments. One can accomplish an equivalent of a swap with the Payment
transaction. Following are the relevant fields of a Payment
transaction.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Amount |
Currency Amount |
AMOUNT |
Amount
field is used to specify the amount of currency that the trader wants to deliver to a destination account. For an AMM swap, this is the amount of currency that the trader wants to swap out of the pool.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Destination |
String |
AccountID |
Destination
field is used to specify the account that the trader wants to deliver the currency to. This should be either the same account as the transaction or any other account that the trader wishes to send this currency amount to.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
SendMax |
Currency Amount |
AMOUNT |
SendMax
field is used to specify the maximum amount of currency that the trader is willing to send from the account issuing the transaction. For an AMM swap, this is the amount of currency that the trader is willing to swap into the pool.
The tfLimitQuality
flag is used to specify the quality of trade. This is defined as the ratio of the amount in to amount out. In other words, it is the ratio of amounts in Amount
and SendMax
fields of a Payment
transaction.
For an AMM swap, if a trader wants to buy (swap out) one unit of currency specified in Amount
field for not more than X
units per currency specified in SendMax
, the trader would use the following equation:
$$ SendMax = X * Amount$$
where X
is equal to the LimitSpotPrice
for the trade, i.e. the threshold on the spot-price of asset out after trade.
We propose that the transfer fee is not applied to AMMCreate
, AMMDeposit
and AMMWithdraw
transactions.
AMM instance never pays the transfer fee. Transfer Fee will automatically apply to Payments
transaction and conditionally in offer-crossing through OfferCreate
.
This proposal allows for the TradingFee
of the AMM instance be a votable parameter. Any account that holds the corresponding LPTokens
can cast a vote using the new AMMVote
transaction.
We introduce a new field VoteSlots
associated with each AMM instance in the AMM
ledger entry. The VoteSlots
field keeps a track of up to eight active votes for the instance.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
VoteSlots |
array |
ARRAY |
VoteSlots
is an array of VoteEntry
objects representing the LPs and their vote on the TradingFee
for this AMM instance.
Each member of the VoteSlots
field is an object that describes the vote for the trading fee by the LP of that instance. A VoteEntry
object has the following fields:
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Account |
✔️ | string |
AccountID |
Account
specifies the XRPL address of the LP.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TradingFee |
✔️ | number |
UINT16 |
TradingFee
specifies the fee, in basis point. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
VoteWeight |
✔️ | number |
UINT32 |
VoteWeight
specifies the LPTokens
owned by the account that issued the transaction. It is specified in basis points. Valid values for this field are between 0 and 100000. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing the percentage ownership in the instance between 0% and 100%.
TradingFee
for the AMM instance is computed as the weighted mean of all the current votes in the VoteSlots
field.
where VoteWeight
and the FeeVal
of the corresponding VoteEntry
.
We introduce the new AMMVote
transaction. Any XRPL account that holds LPTokens
for an AMM instance may submit this transaction to vote for the trading fee for that instance.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Account |
✔️ | string |
AccountID |
Account
specifies the XRPL account that submits the transaction.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TransactionType |
✔️ | string |
UINT16 |
TransactionType
specifies the new transaction type AMMVote
. The integer value is 38.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset |
✔️ | object |
ISSUE |
Asset
specifies one of the assets of the AMM instance against which the transaction is to be executed.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset2 |
✔️ | object |
ISSUE |
Asset2
specifies the other asset of the AMM instance against which the transaction is to be executed.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TradingFee |
✔️ | number |
UINT16 |
TradingFee
specifies the fee, in basis point. Valid values for this field are between 0 and 1000 inclusive. A value of 1 is equivalent to 1/10 bps or 0.001%, allowing trading fee between 0% and 1%.
AMMVote
transaction always checks if all VoteEntry
objects in the VoteSlots
array are up-to-date, i.e. check if there is a change in the number of LPTokens
owned by an account in the VoteEntry
and do the following:
-
If one or more accounts in the
VoteEntry
does not hold theLPTokens
for this AMM instance any more, then remove thatVoteEntry
object from theVoteSlots
array or If the number ofLPTokens
held by one or more account in theVoteEntry
has changed,- recompute the weights of all the votes and readjust them. Also recompute the
TradingFee
for the AMM instance and update it in theAMM
object of that instance.
- recompute the weights of all the votes and readjust them. Also recompute the
-
Check the
LPTokens
held by the account submitting theAMMVote
transaction. If the account does not hold anyLPTokens
, then the transaction fails with an error code. Otherwise, there are following cases:-
If there are fewer than eight
VoteEntry
objects in the updatedVoteSlots
array, then: a. Compute the weight of the current vote, add the computed weight of that vote asVoteWeight
field to the object and readjust in the object. b. Add thatFeeVal
of the current vote to theVoteEntry
object. c. Compute theTradingFee
for the AMM instance as described above and update theTradingFee
field value in theAMM
object of the AMM instance. -
If all eight
VoteEntry
slots are full, but this account holds moreLPTokens
, i.e. higherVoteWeight
than theVoteEntry
object with the lowestVoteWeight
, this vote will replace theVoteEntry
with the lowestVoteWeight
. (Followed by same steps as above.) -
If the account that submitted the transaction already holds a vote, then update that
VoteEntry
andTradingFee
based on the transaction fields.
-
We introduce a novel mechanism for an AMM instance to auction-off the trading advantages to users (arbitrageurs) at a discounted TradingFee
for a 24 hour slot. Any account that owns corresponding LPTokens
can bid for the auction slot of that AMM instance. This is a continuous auction, any account can bid for the slot any time. Part of the proceeds from the auction, i.e. LPTokens
are refunded to the current slot-holder computed on a pro rata basis. Remaining part of the proceeds - in the units of LPTokens
- is burnt, thus effectively increasing the LPs shares.
The bid price to purchase the slot must adjust dynamically to function as an auction. If the slot is full, i.e. if an account owns the auction slot, the following should hold:
- the price should drop as the slot gets older.
- one must pay more (per unit time) than the value at which the slot was bought.
- the previous slot holder may lose their slot, in which case they receive a pro-rata refund (for their remaining time) and the rest goes to the pool (LPs).
The complex mechanism is how the price to buy the slot should drop as the occupied slot gets older. We introduce the slot price-schedule algorithm to answer the following questions:
- How is the additional price one must pay per unit time to replace the holder of an existing slot determined?
- How is the additional amount shared between the pool and the account losing its slot?
- What is the amount per unit time for a slot when the slot is empty?
The minimum price to buy a slot for 24-hour period is called MinSlotPrice
(M
). Total slot time of 24-hours is divided into 20 equal intervals. An auction slot can be in one of the following states at any given time:
-
Empty - no account currently holds the slot.
-
Occupied - an account owns the slot with at least 5% of the remaining slot time (i.e. in one of the 1-19 intervals).
-
Tailing - an account owns the slot with less than 5% of the remaining time (i.e, in the last interval).
The slot-holder owns the slot privileges when in State 2 or 3.
I. Slot state - Empty or Tailing, then
Slot Price = M
II. Slot state - Occupied, then
Let the price at which the slot is bought be B
- specified in Amount
of LPTokens
. Let t
represent the fraction of used slot time for the current slot-holder. Note that for each interval t
has a discrete value (0.05, 0.1, , ..., 1). Let M
represent the minimum slot price.
Interval | t |
---|---|
(0,1] | 0.05 |
(1,2] | 0.1 |
(19, 20] | 1 |
The algorithm to compute the minimum bid price of the slot at any given time enforces the following rules:
- The minimum bid price of the slot in the first interval is, i.e. for
t
= 0.05:
- The slot price decays exponentially over time. For the price to decay very very slowly for most of the time intervals (~95%) and instantly drop to the MinSlotPrice as the slot gets closer to the expiration time (~5%), we choose a heuristic function that produces this behavior. The following equation determines the minimum bid price of the slot for
:
Notice that the slot price approaches M
as the slot approaches expiration (i.e., as t
approaches 1).
- The revenue from a successful
AMMBid
transaction is split between the current slot-holder and the pool. We propose to always refund the current slot-holder of the remaining value of the slot computed from the price at which they bought the slot. $$ f(t) = (1-t)*B $$
The remaining LPTokens
are burnt/deleted, effectively increasing the LPs share in the pool.
- Let
X
represent the minimum bid price computed by the price-scheduling algorithm, then,- If (
MinBidPrice
&&MaxBidPrice
):- return
- If (
MinBidPrice
):m- if (
MinBidPrice
<=X
): returnX
- else: return
MinBidPrice
- if (
- elif (
MaxBidPrice
):- if (
MaxBidPrice
>=X
): returnX
- else: return
MaxBidPrice
- else: return
- if (
- If (
We implement the following as the MinSlotPrice:
We introduce a new object field AuctionSlot
in the AMM
object associated with each AMM instance. The AuctionSlot
field has the following subfields:
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Account |
✔️ | string |
AccountID |
Account
represents the XRPL account that currently owns the auction slot.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Expiration |
✔️ | string |
UINT32 |
Expiration
represents the number of seconds since the Ripple Epoch. This marks the end of the time from when slot was bought.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
DiscountedFee |
✔️ | string |
UINT32 |
DiscountedFee
represents the TradingFee
to be charged to this account for trading against the AMM instance. By default it is TradingFee
/10.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Price |
✔️ | string |
AMOUNT |
Price
represents the price paid for the slot specified in units of LPTokens
of the AMM instance.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
AuthAccounts |
array |
Array |
AuthAccounts
represents an array of XRPL account IDs that are authorized to trade at the discounted fee against the AMM instance. The proposal allows for up to a maximum of four accounts.
We introduce a new transaction AMMBid
to place a bid for the auction slot. The transaction may have the following optional and required fields:
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Account |
✔️ | string |
AccountID |
Account
represents the XRPL account that submits the transaction.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
TransactionType |
✔️ | string |
UINT16 |
TransactionType
specifies the new transaction type AMMBid
. The integer value is 39.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset |
✔️ | object |
ISSUE |
Asset
specifies one of the assets of the AMM instance against which the transaction is to be executed.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
Asset2 |
✔️ | object |
ISSUE |
Asset2
specifies the other asset of the AMM instance against which the transaction is to be executed.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
MinBidPrice |
string |
STRING NUMBER |
MinBidPrice
represents the minimum price that the bidder wants to pay for the slot. It is specified in units of LPTokens
. This is not a required field. If specified let MinBidPrice
be X
and let the slot-price computed by price scheduling algorithm be Y
, then bidder always pays the max(X, Y).
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
AuthAccounts |
array |
Array |
AuthAccounts
represents an array of XRPL account IDs that are authorized to trade at the discounted fee against the AMM instance. The proposal allows for up to a maximum of four accounts.
Field Name | Required? | JSON Type | Internal Type |
---|---|---|---|
MaxBidPrice |
string |
STRING NUMBER |
MaxBidPrice
represents the maximum price that the bidder wants to pay for the slot. It is specified in units of LPTokens
. This is not a required field. If specified let MaxBidPrice
be X
and let the slot-price computed by price scheduling algorithm be Y
, then bidder always pays the min(X, Y).
The proposal allows for traders to specify different combinations of the fields for AMMDeposit
transaction. The implementation will figure out the best possible sub operations based on trader's specifications. Here are the recommended valid combinations. Other invalid combinations may result in the failure of transaction.
LPTokenOut
,[Amount]
,[Amount2]
Amount
,[LPTokenOut]
Amount
,Amount2
,[LPTokenOut]
Amount
andLPTokenOut
Amount
andEPrice
Amount
,Amount2
,[TradingFee]
Implementation details for above combinations:
- Fields specified:
LPTokenOut
,[Amount]
,[Amount2]
Such a transaction assumes proportional deposit of pools assets in exchange for the specified amount of LPTokenOut
of the AMM instance.
- Use equations 1 & 2 to compute the amount of each asset to be deposited, given the amount of
specified as LPTokenOut
If the account that initiated the transaction holds sufficient balances, the transaction is successful. It fails otherwise with an error code.
Similarly, if [Amount]
, [Amount2]
are specified and the amount of either asset computed above is less than the amounts specified in these fields, then the transaction fails.
- Fields specified:
Amount
,[LPTokenOut]
Such a transaction assumes single asset deposit of the amount of asset specified by Amount
. This is essentially an equal asset deposit and a swap.
- Check if the account that initiated the transaction holds the amount of
Amount
. - If not, the transaction fails with an error code. Otherwise,
- Use equation 3 to compute amount of
LPTokenOut
~to be issued, given either the amount of drops of XRP
or the amount of tokens inAmount
.
- Use equation 3 to compute amount of
If the asset to be deposited is a token, specifying the value
field is required, else the transaction will fail.
If LPTokenOut
field exists, and the amount of LPTokenOut
computed above is less than the that specified in this field, then the transaction fails.
- Fields specified:
Amount
,Amount2
and[LPTokenOut]
Such a transaction assumes proportional deposit of pool assets with the constraints on the maximum amount of each asset that the trader is willing to deposit.
- Use equation 1 to compute the amount of
, given the amount in Amount
. Let this beZ
- Use equation 2 to compute the amount of asset2, given
~ Z
. Let the computed amount of asset2 beX
.- If
X
<= amount inAmount2
:- The amount of asset1 to be deposited is the one specified in
Amount
- The amount of asset2 to be deposited is
X
- The amount of
LPTokenOut
to be issued isZ
- The amount of asset1 to be deposited is the one specified in
- If X > amount in
Amount2
:- Use equation 2 to compute
, given the amount in Amount2
. Let this beW
- Use equation 1 to compute the amount of asset1, given
~ W
from above. Let the computed amount of asset1 beY
- If
Y
<= amount inAmount
:- The amount of asset1 to be deposited is
Y
- The amount of asset2 to be deposited is the one specified in
Amount2
- The amount of
LPTokenOut
to be issued isW
- The amount of asset1 to be deposited is
- Use equation 2 to compute
- If
else, failed transaction.
If LPTokenOut
field exists, and the amount of LPTokenOut
computed above is less than the that specified in this field, then the transaction fails.
- Fields specified:
Amount
andLPTokenOut
Such a transaction assumes that a single asset asset1
is deposited to obtain some share of the AMM instance's pools represented by amount in LPTokenOut
. Since adding liquidity to the pool with one asset changes the ratio of the assets in the two pools, thus changing the relative pricing, trading fee is charged on the amount of the deposited asset that causes this change.
- Check if the account that initiated the transaction holds the amount of
Amount
. - If not, the transaction fails with an error code. Otherwise,
- Use equation 4 to compute the amount of asset1 to be deposited, given
represented by amount of LPTokenOut
- Use equation 4 to compute the amount of asset1 to be deposited, given
- Fields specified:
Amount
andEPrice
Such a transaction assumes single asset deposit with the following two constraints:
a. amount of asset1 if specified in Amount
specifies the maximum amount of asset1 that the trader is willing to deposit
b. The effective-price of the LPToken
traded out does not exceed the specified EPrice
- Use equation 3 to compute the amount of
LPTokenOut
out, given the amount ofAmount
. Let this beX
- Use equation
III
to compute the effective-price of the trade givenAmount
amount as the asset in and theLPTokens
amount ~X
as asset out. Let this beY
. - If
Y
<= amount inEPrice
:- The amount of asset1 to be deposited is given by amount in
Amount
- The amount of
LPTokenOut
to be issued isX
- The amount of asset1 to be deposited is given by amount in
- If (
Y
>EPrice
) OR (amount inAmount
does not exist):- Use equations 3 &
III
and the givenEPrice
to compute the following two variables:- The amount of asset1 in. Let this be
Q
- The amount of
LPTokenOut
out. Let this beW
- The amount of asset1 in. Let this be
- The amount of asset1 to be deposited is
Q
- The amount of
LPTokenOut
to be issued isW
- Use equations 3 &
Following updates after a successful AMMDeposit
transaction:
- The deposited asset, if XRP, is transferred from account that initiated the transaction to AMM instance account, thus changing the
Balance
field of each account - The deposited asset, if token, are balanced between the AMM account and the issuer account trustline.
- The
LPTokenOut
are issued by the AMM instance account to the account that initiated the transaction and a new trustline is created, if there does not exist one. - The pool composition is updated. Note that the conservation function is not preserved in case of liquidity provision (and is not expected to.)
The proposal allows for traders to specify different combinations of the above mentioned fields for AMMWithdraw
transaction. The implementation will figure out the best possible operations based on trader's specifications. Here are the recommended possible combinations. Other invalid combinations may result in the failure of transaction.
LPTokenIn
Amount
Amount
andAmount2
Amount
andLPTokenIn
Amount
andEPrice
Implementation details for the above combinations:
- Fields specified:
LPTokenIn
Such a transaction assumes proportional withdrawal of pool assets for the amount of LPTokenIn
. Since withdrawing assets proportionally from the AMM instance pools does not change the ratio of the two assets in the pool and thus does not affect the relative pricing, trading fee is not charged on such a transaction.
- Check if the account that initiated the transaction holds the amount of
LPTokenIn
. - If not, the transaction fails with an error code. Otherwise,
- Use equations 5 & 6 to compute the amount of both the assets in the AMM instance pool, given the redeemed
represented by LPTokenIn
- Use equations 5 & 6 to compute the amount of both the assets in the AMM instance pool, given the redeemed
- Fields specified:
Amount
Such a transaction assumes withdrawal of single asset equivalent to the amount specified in Amount
- Use equation 7 to compute the
, given the amount in Amount
.
If the account that submitted the transaction holds the amount of
- Fields specified:
Amount
andAmount2
Such a transaction assumes all assets withdrawal with the constraints on the maximum amount of each asset that the trader is willing to withdraw.
- Use equation 5 to compute
, given the amount in Amount
. Let this beZ
- Use equation 6 to compute the amount of asset2, given
~ Z
. Let the computed amount of asset2 beX
- If
X
<= amount inAmount2
:- The amount of asset1 to be withdrawn is the one specified in
Amount
- The amount of asset2 to be withdrawn is
X
- The amount of
LPTokenIn
redeemed isZ
- The amount of asset1 to be withdrawn is the one specified in
- If
X
> amount inAmount2
:- Use equation 5 to compute
, given the amount in Amount2
. Let this beQ
- Use equation 6 to compute the amount of asset1, given
~ Q
. Let the computed amount of asset1 beW
- The amount of asset2 to be withdrawn is the one specified in
Amount2
- The amount of asset1 to be withdrawn is
W
- The amount of
LPTokenIn
redeemed isQ
- Use equation 5 to compute
The transaction MUST fail if the account initiating the transaction does not hold the amount of LPTokenIn
computed above.
- Fields specified:
Amount
andLPTokenIn
Such a transaction assumes withdrawal of single asset specified in Amount
proportional to the share represented by the amount of LPTokenIn
. Since a single sided withdrawal changes the ratio of the two assets in the AMM instance pools, thus changing their relative pricing, trading fee is charged on the amount of asset1 that causes that change.
- Check if the account that initiated the transaction holds the amount of
LPTokenIn
. - If not, the transaction fails with an error code. Otherwise,
- Use equation 8 to compute the amount of asset1, given the redeemed
represented by LPTokenIn
. Let this beY
. - If (amount exists for
Amount
&Y
>= amount inAmount
) || (amount field does not exist forAmount
):- The amount of asset out is
Y
- The amount of
LPTokens
redeemed isLPTokenIn
- The amount of asset out is
- Use equation 8 to compute the amount of asset1, given the redeemed
else transaction fails.
- Fields specified:
Amount
andEPrice
Such a transaction assumes withdrawal of single asset with the following constraints:
a. amount of asset1 if specified in Amount
specifies the minimum amount of asset1 that the trader is willing to withdraw
b. The effective price of asset traded out does not exceed the amount specified in EPrice
- Use equations 8 &
III
and amount inEPrice
to compute the two variables, i.e.,- asset in as
LPTokenIn
. Let this beX
- asset out as that in
Amount
. Let this beY
- asset in as
- If (amount exists for
Amount
&Y
>= amount inAmount
) || (amount field does not exist forAmount
):- The amount of assetOut is given by
Y
- The amount of LPTokens is given by
X
- The amount of assetOut is given by
else transaction fails.
Following updates after a successful AMMWithdraw
transaction:
- The withdrawn asset, if XRP, is transferred from AMM instance account to the account that initiated the transaction, thus changing the
Balance
field of each account - The withdrawn asset, if token, is balanced between the AMM instance account and the issuer account.
- The
LPTokens
~are balanced between the AMM instance account and the account that initiated the transaction. - The pool composition is updated. Conservation function is not preserved in case of liquidity withdrawal (and is not expected to.)
The reference implementation of this spec can be found in rippled
: