mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-20 11:45:50 +00:00
Start AMM concept, AMM-Devnet support
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
DEFAULT_ADDRESS_1 = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn"
|
||||
DEFAULT_ADDRESS_2 = "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX"
|
||||
TST_ISSUER = "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"
|
||||
|
||||
Request("Account Methods")
|
||||
|
||||
@@ -475,6 +476,22 @@ Request('ripple_path_find', {
|
||||
}
|
||||
})
|
||||
|
||||
Request('amm_info', {
|
||||
description: "Looks up info on an Automated Market Maker instance.",
|
||||
link: "amm_info.html",
|
||||
status: "not_enabled",
|
||||
body: {
|
||||
"command": "amm_info",
|
||||
"asset": {
|
||||
"currency": "XRP"
|
||||
},
|
||||
"asset2": {
|
||||
"currency": "TST",
|
||||
"issuer": TST_ISSUER
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Request("Payment Channel Methods")
|
||||
|
||||
Request('channel_authorize', {
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
html: automated-market-makers.html
|
||||
parent: decentralized-exchange.html
|
||||
blurb: Automated Market Makers (AMMs) provide liquidity between asset pairs, complemeting the order books in the decentralized exchange while providing passive income for their liquidity providers.
|
||||
status: not_enabled
|
||||
labels:
|
||||
- XRP
|
||||
- Decentralized Exchange
|
||||
- AMM
|
||||
---
|
||||
# Automated Market Makers
|
||||
|
||||
An Automated Market Maker (AMM) is a type of smart contract, built into the XRP Ledger, that provides liquidity in the decentralized exchange. An AMM holds a pool of two fungible assets, which can be XRP or [tokens](tokens.html), and allows users to swap between them for a fee. [Offers](offers.html) and [Cross-Currency Payments](cross-currency-payments.html) automatically use a combination of Offers and AMMs to achieve cost-effective exchanges between assets.
|
||||
|
||||
{% include '_snippets/amm-disclaimer.md' %}
|
||||
|
||||
For any given pair of assets, there can be up to one AMM in the ledger. Anyone can create an AMM for an asset pair if it doesn't exist yet, or deposit to an existing AMM's pools. Those who deposit assets into an AMM are called _liquidity providers_ (LPs) and receive "LP Tokens" from the AMM in proportion to the amounts of assets they deposit. LP Tokens are like other fungible tokens in the XRP Ledger, except that they also give special privileges for the AMM that issues them:
|
||||
|
||||
- Liquidity providers can redeem their LP Tokens to withdraw a corresponding share of the assets in the AMM's pool, including fees collected.
|
||||
- Liquidity providers can vote to change the AMM's fee settings. The votes are weighted based on how many LP Tokens the voters hold.
|
||||
- Liquidity providers can bid some of their LP Tokens to receive a temporary discount on the AMM's trading fees.
|
||||
|
||||
When the flow of funds between the two assets in a pool is relatively active and balanced, the fees provide a source of passive income for liquidity providers. However, when the relative price between the assets shifts, the liquidity providers can take a loss on the [currency risk](https://www.investopedia.com/terms/c/currencyrisk.asp).
|
||||
|
||||
## How the AMM Works
|
||||
|
||||
[Kris Machowski's Introduction to Automated Market Makers](https://www.machow.ski/posts/an_introduction_to_automated_market_makers/) is a good in-depth explanation on the economics and principles of AMMs in general. The XRP Ledger implements a _constant product_ AMM, where the cost of trading between the two assets in its pool scales so that multiplying the amounts of the two pools together always comes out to the same value. For example, if the AMM holds 5 ETH and 5 USD, the "constant product" value is 5×5=25. To buy 1 ETH, you'd have to spend 1.25 USD, because after removing 1 ETH from the pool and adding 1.25 USD, the constant product value is 4×6.25=25. The AMM also charges a configurable trading fee, which can be as low as 0 or as high as 1%, so you would have to pay a little more for that as well.
|
||||
|
||||
**Note:** The XRP Ledger's AMM is designed to be extensible so that, with future protocol amendments, it would be possible to create an AMM where the pools are be weighted unevenly, which would make it a more general _geometric mean market maker_. However, the current implementation always uses a weight parameter of 0.5, so it functions like a constant product AMM.
|
||||
|
||||
Due to the way the constant product rule works, the bigger a proportion of the AMM's pools a trade involves, the higher the costs. This also means that, the larger the amounts in the AMM's pools, the lower the cost of making a specific trade. For example, trading 5 USD through an AMM that only holds 10 USD is more expensive than trading 5 USD through an AMM that holds 1000 USD. This is separate from the trading fee, which is always strictly a percentage of the amounts involved.
|
||||
|
||||
An AMM can hold two assets: at most one of these can be XRP, and one or both of them can be [tokens](tokens.html). Tokens with different issuers are considered different assets for this purpose. This means that there can be an AMM for two tokens with the same currency code but different issuers ("FOO issued by WayGate" is different than "FOO issued by StableFoo"), or the same issuer but different currency codes. The order does not matter; the AMM for FOO.WayGate to XRP is the same as for XRP to FOO.WayGate.
|
||||
|
||||
|
||||
## Flow of Funds
|
||||
|
||||
Whoever creates the AMM becomes the first liquidity provider, and receives LP Tokens that represent 100% ownership of assets in the AMM's pool. They can redeem some or all of those LP Tokens to withdraw assets from the AMM in proportion to the amounts currently there. (The proportions shift over time as people trade against the AMM.) The AMM does not charge a fee when withdrawing both assets.
|
||||
|
||||
For example, if you created an AMM with 5 ETH and 5 USD, then someone bought 1 ETH by spending 1.25 USD, the pool has 4 ETH and 6.25 USD in it. You can spend half your LP Tokens to withdraw 2 ETH and 3.125 USD.
|
||||
|
||||
Anyone can deposit assets to an existing AMM. When they do, they receive new LP Tokens based on how much they deposited. The amount that a liquidity provider can withdraw from an AMM is based on the proportion of the AMM's LP Tokens they hold compared to the total number of LP Tokens outstanding.
|
||||
|
||||
LP Tokens are like other tokens in the XRP Ledger, so you can use them in many [types of payments](payment-types.html), trade them in the decentralized exchange, or even deposit them as assets for new AMMs. (To receive LP Tokens as payment, you must set up a trust line with a nonzero limit with the AMM Account as the issuer.) However, you can _only_ send LP Tokens directly to the AMM (redeeming them) using the [AMMWithdraw][] transaction type, not through other types of payments. Similarly, you can only send assets to the AMM's pool through the [AMMDeposit][] transaction type.
|
||||
|
||||
The AMM is designed so that an AMM's asset pool is empty if and only if the AMM has no outstanding LP Tokens. This situation can only occur as the result of an [AMMWithdraw][] transaction; when it does, the AMM is automatically deleted.
|
||||
|
||||
### LP Token Currency Codes
|
||||
|
||||
LP Tokens use a special type of currency code that use the 160-bit hexadecimal ["non-standard" format](currency-formats.html#nonstandard-currency-codes). These codes have the first 8 bits `0x03`. The remainder of the code is a SHA-512 hash, truncated to the first 152 bits, of the two assets' currency codes and their issuers. (The assets are placed in a "canonical order" with the numerically lower currency+issuer pair first.)
|
||||
|
||||
|
||||
## Representation in the Ledger
|
||||
|
||||
In the ledger's state data, an AMM consists of two [ledger entries](ledger-object-types.html):
|
||||
|
||||
- An [AMM object][] describing the automated market maker itself.
|
||||
- A special [AccountRoot object][] that holds the AMM's funds and issues LP Tokens.
|
||||
|
||||
The address of this AccountRoot is chosen somewhat randomly when the AMM is created, and it is different if the AMM is deleted and re-created. This is to prevent people from funding the AMM account with excess XRP in advance.
|
||||
|
||||
There are also [trust lines](trust-lines-and-issuing.html) for the tokens in the AMM's pool as well as the LP Tokens it issues.
|
||||
|
||||
These objects are not owned by any account, so the [reserve requirement](reserves.html) does not apply to them. However, to prevent spam, the transaction to create an AMM has a special [transaction cost](transaction-cost.html) that requires the sender to burn a larger than usual amount of XRP.
|
||||
|
||||
<!--{# common link defs #}-->
|
||||
{% include '_snippets/rippled-api-links.md' %}
|
||||
{% include '_snippets/tx-type-links.md' %}
|
||||
{% include '_snippets/rippled_versions.md' %}
|
||||
@@ -59,6 +59,8 @@ An example of the request format:
|
||||
|
||||
<!-- MULTICODE_BLOCK_END -->
|
||||
|
||||
[Try it! >](websocket-api-tool.html?server=wss%3A%2F%2Famm.devnet.rippletest.net%3A51233%2F#amm_info)
|
||||
|
||||
The request includes the following parameters:
|
||||
|
||||
| `Field` | Type | Description |
|
||||
|
||||
@@ -18,6 +18,7 @@ If you don't [run your own `rippled` server](install-rippled.html), you can use
|
||||
| Ripple[¹][] | Testnet | `https://s.altnet.rippletest.net:51234/` | `wss://s.altnet.rippletest.net/` | Testnet public server |
|
||||
| XRPL Labs | Testnet | `https://testnet.xrpl-labs.com/` | `wss://testnet.xrpl-labs.com/` | Testnet public server with CORS support |
|
||||
| Ripple[¹][] | Devnet | `https://s.devnet.rippletest.net:51234/` | `wss://s.devnet.rippletest.net/` | Devnet public server |
|
||||
| Ripple[¹][] | AMM-Devnet | `https://amm.devnet.rippletest.net:51234/` | `wss://amm.devnet.rippletest.net:51233/` | Special devnet for [XLS-30d Automated Market Maker](https://github.com/XRPLF/XRPL-Standards/discussions/78) development. |
|
||||
|
||||
[Network]: parallel-networks.html
|
||||
[¹]: #footnote-1
|
||||
|
||||
@@ -839,6 +839,11 @@ pages:
|
||||
targets:
|
||||
- ja
|
||||
|
||||
- md: concepts/decentralized-exchange/automated-market-makers.md
|
||||
targets:
|
||||
- en
|
||||
- ja
|
||||
|
||||
- md: concepts/decentralized-exchange/offers.md
|
||||
targets:
|
||||
- en
|
||||
|
||||
@@ -100,49 +100,71 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
{% for conn in [
|
||||
{
|
||||
"id": "wstool-1-connection-s1",
|
||||
"ws_url": "wss://s1.ripple.com/",
|
||||
"jsonrpc_url": "https://s1.ripple.com:51234/",
|
||||
"shortname": "Mainnet s1",
|
||||
"longname": "s1.ripple.com (Mainnet Public Cluster)"
|
||||
},
|
||||
{
|
||||
"id": "wstool-1-connection-xrplcluster",
|
||||
"ws_url": "wss://xrplcluster.com/",
|
||||
"jsonrpc_url": "https://xrplcluster.com/",
|
||||
"shortname": "Mainnet xrplcluster",
|
||||
"longname": "xrplcluster.com (Mainnet Full History Cluster)"
|
||||
},
|
||||
{
|
||||
"id": "wstool-1-connection-s2",
|
||||
"ws_url": "wss://s2.ripple.com/",
|
||||
"jsonrpc_url": "https://s2.ripple.com:51234/",
|
||||
"shortname": "Mainnet s2",
|
||||
"longname": "s2.ripple.com (Mainnet Full History Cluster)"
|
||||
},
|
||||
{
|
||||
"id": "wstool-1-connection-testnet",
|
||||
"ws_url": "wss://s.altnet.rippletest.net:51233/",
|
||||
"jsonrpc_url": "https://s.altnet.rippletest.net:51234/",
|
||||
"shortname": "Testnet",
|
||||
"longname": "s.altnet.rippletest.net (Testnet Public Cluster)"
|
||||
},
|
||||
{
|
||||
"id": "wstool-1-connection-devnet",
|
||||
"ws_url": "wss://s.devnet.rippletest.net:51233/",
|
||||
"jsonrpc_url": "https://s.devnet.rippletest.net:51234/",
|
||||
"shortname": "Devnet",
|
||||
"longname": "s.devnet.rippletest.net (Devnet Public Cluster)"
|
||||
},
|
||||
{
|
||||
"id": "wstool-1-connection-nftdevnet",
|
||||
"ws_url": "wss://xls20-sandbox.rippletest.net:51233/",
|
||||
"jsonrpc_url": "https://xls20-sandbox.rippletest.net:51234/",
|
||||
"shortname": "NFT-Devnet",
|
||||
"longname": "xls20-sandbox.rippletest.net (NFT-Devnet Cluster)"
|
||||
},
|
||||
{
|
||||
"id": "wstool-1-connection-ammdevnet",
|
||||
"ws_url": "wss://amm.devnet.rippletest.net:51233/",
|
||||
"jsonrpc_url": "https://amm.devnet.rippletest.net:51234/",
|
||||
"shortname": "AMM-Devnet",
|
||||
"longname": "amm.devnet.rippletest.net (XLS-30d AMM Devnet)"
|
||||
},
|
||||
{
|
||||
"id": "wstool-1-connection-localhost",
|
||||
"ws_url": "ws://localhost:6006/",
|
||||
"jsonrpc_url": "http://localhost:5005/",
|
||||
"shortname": "Local server",
|
||||
"longname": "localhost:6006 (Local <code>rippled</code> Server on port 6006) <br/>\n <small>(Requires that you <a href=\"install-rippled.html\">run <code>rippled</code></a> on this machine with default WebSocket settings)</small>"
|
||||
}
|
||||
] %}
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="wstool-1-connection" id="wstool-1-connection-s1" value="wss://s1.ripple.com/" data-jsonrpcurl="https://s1.ripple.com:51234/" data-shortname="Mainnet s1" checked>
|
||||
<label class="form-check-label" for="wstool-1-connection-s1">
|
||||
s1.ripple.com (Mainnet Public Cluster)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="wstool-1-connection" id="wstool-1-connection-xrplcluster" value="wss://xrplcluster.com/" data-jsonrpcurl="https://xrplcluster.com/" data-shortname="Mainnet xrplcluster">
|
||||
<label class="form-check-label" for="wstool-1-connection-xrplcluster">
|
||||
xrplcluster.com (Mainnet Full History Cluster)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="wstool-1-connection" id="wstool-1-connection-s2" value="wss://s2.ripple.com/" data-jsonrpcurl="https://s2.ripple.com:51234/" data-shortname="Mainnet s2">
|
||||
<label class="form-check-label" for="wstool-1-connection-s2">
|
||||
s2.ripple.com (Mainnet Full History Cluster)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="wstool-1-connection" id="wstool-1-connection-testnet" value="wss://s.altnet.rippletest.net:51233/" data-jsonrpcurl="https://s.altnet.rippletest.net:51234/" data-shortname="Testnet">
|
||||
<label class="form-check-label" for="wstool-1-connection-testnet">
|
||||
s.altnet.rippletest.net (Testnet Public Cluster)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="wstool-1-connection" id="wstool-1-connection-devnet" value="wss://s.devnet.rippletest.net:51233/" data-jsonrpcurl="https://s.devnet.rippletest.net:51234/" data-shortname="Devnet">
|
||||
<label class="form-check-label" for="wstool-1-connection-devnet">
|
||||
s.devnet.rippletest.net (Devnet Public Cluster)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="wstool-1-connection" id="wstool-1-connection-nftdevnet" value="wss://xls20-sandbox.rippletest.net:51233/" data-jsonrpcurl="https://xls20-sandbox.rippletest.net:51234/" data-shortname="NFT-Devnet">
|
||||
<label class="form-check-label" for="wstool-1-connection-nftdevnet">
|
||||
xls20-sandbox.rippletest.net (NFT-Devnet Cluster)
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="wstool-1-connection" id="wstool-1-connection-localhost" value="ws://localhost:6006/" data-jsonrpcurl="http://localhost:5005/" data-shortname="Local server">
|
||||
<label class="form-check-label" for="wstool-1-connection-localhost">
|
||||
localhost:6006 (Local <code>rippled</code> Server on port 6006) <br/>
|
||||
<small>(Requires that you <a href="install-rippled.html">run <code>rippled</code></a> on this machine with default WebSocket settings)</small>
|
||||
<input class="form-check-input" type="radio" name="wstool-1-connection" id="{{conn.id}}" value="{{conn.ws_url}}" data-jsonrpcurl="{{conn.jsonrpc_url}}" data-shortname="{{conn.shortname}}"{% if loop.index == 1 %} checked{% endif %}>
|
||||
<label class="form-check-label" for="{{conn.id}}">
|
||||
{{conn.longname}}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
Reference in New Issue
Block a user