xls: 82 title: MPT Integration into DEX description: Adds Multi-Purpose Token (MPT) support for XRPL DEX author: Gregory Tsipenyukproposal-from: https://github.com/XRPLF/XRPL-Standards/discussions/231 status: Draft category: Amendment requires: XLS-33, XLS-30 created: 2024-09-19 updated: 2026-02-10
- MPT Integration into DEX
- Abstract
- 1. Overview
- 2. Transaction: AMMCreate
- 3. Transaction: AMMDeposit
- 4. Transaction: AMMWithdraw
- 5. Transaction: AMMDelete
- 6. Transaction: AMMClawback
- 7. Transaction: CheckCreate
- 8. Transaction: CheckCash
- 9. Transaction: OfferCreate
- 10. Transaction: Payment
- 11. RPC: path_find
- 12. RPC: ripple_path_find
- 13. RPC: amm_info
- 14. RPC: book_offers
- 15. Rationale
- 16. Security
- Appendix
MPT Integration into DEX¶
Abstract¶
This proposal introduces a new amendment MPTVersion2 as an extension to XLS-33 Multi-Purpose Tokens. MPTVersion2 amendment enables Multi-purpose token (MPT) support on the XRPL DEX, including offers, cross-currency payments, checks, and AMM.
1. Overview¶
The integration of Multi-Purpose Tokens (MPT) into the XRP Ledger Decentralized Exchange (DEX) focuses on extending the functional reach of existing trading mechanisms without introducing new on-ledger objects or modifying core state structures. By leveraging the existing ledger primitives, this update enables standard DEX transactions to natively support MPTs as a valid asset class. This specification outlines the necessary schema updates for transaction requests and provides comprehensive JSON examples to illustrate the interoperability between MPTs, XRP, and standard IOUs. Furthermore, this document details the expanded set of failure scenarios and transaction result codes specific to MPT trading, ensuring robust error handling for cross-asset liquidity paths and order-matching logic. For a comprehensive description of all transactions refer to XRPL documentation
Current transactions, which interact with XRPL DEX are:
AMMCreate: Create a new Automated Market Maker (AMM) instance for trading a pair of assets (fungible tokens or XRP).AMMDeposit: Deposit funds into an AMM instance and receive the AMM's liquidity provider tokens (LP Tokens) in exchange.AMMWithdraw: Withdraw assets from an AMM instance by returning the AMM's liquidity provider tokens (LP Tokens).AMMClawback: Enable token issuers to claw back tokens from wallets that have deposited into AMM pools.AMMDelete: Delete an empty AMM instance that could not be fully deleted automatically.CheckCreate: Create a Check object in the ledger, which is a deferred payment that can be cashed by its intended destination.CheckCash: Attempts to redeem a Check object in the ledger to receive up to the amount authorized by the corresponding CheckCreate transaction.OfferCreate: An OfferCreate transaction places an Offer in the decentralized exchange.Payment: A Payment transaction represents a transfer of value from one account to another.
MPT supports all of the above transactions. MPT can be combined with IOU and XRP tokens in the transactions. For instance, a Payment could be a cross-token payment from MPT token to IOU token; AMM can be created for XRP and MPT token-pair; an order book offer can be created to buy some MPT token and to sell another MPT token. MPT doesn't modify the transactions fields, flags, and functionality. However, the JSON of the MPT amount field differs from the JSON of the IOU amount field. Instead of currency and issuer, MPT is identified by mpt_issuance_id. MPT amount value is INT or UINT, which must be less or equal to $63^2 - 1$. Below are the examples of JSON MPT amount and JSON MPT asset:
{
"Amount": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308",
"value": "110"
},
"Asset": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308"
}
}
Any transaction with MPT Amount or Asset have to use JSON format as described above. For any transaction, which uses MPT token, the token has to be created first by an issuer with MPTokenIssuanceCreate transaction and in most cases, except for AMMCreate, AMMWithdraw, AMMClawback, CheckCash, and OfferCreate, the token has to be authorized by the holder account with MPTokenAuthorize transaction as described in XLS-33d. MPTokenAuthorize creates MPToken object, owned by a holder account. In addition, MPTokenIssuanceCreate must have the following flags set:
lsfMPTCanTrade, in order for individual holders to trade their balances using the XRP Ledger DEX or AMM.lsfMPTCanTransfer, in order for the tokens held by non-issuers to be transferred to other accounts.
2. Transaction: AMMCreate¶
Any token or both tokens in AMMCreate transaction can be MPT. I.e., in addition to the current combination of XRP/IOU and IOU/IOU token pair, AMMCreate can have XRP/MPT, IOU/MPT, and MPT/MPT token pair. Each MPT in the pair is identified by mpt_issuance_id. If both tokens are MPT then each token must have a unique mpt_issuance_id. In case of AMMCreate the token pair is identified by Amount and Amount2.
2.1. Fields¶
We do not introduce new fields.
2.2. Failure Conditions¶
We extend the AMMCreate with the following failure conditions, where MPTokenIssuance refers to the ledger object defining the specific MPT type identified in the transaction's Amount or Amount2 fields; MPToken refers to the ledger object representing the specific MPT balance of the account executing the transaction (if that account is not the issuer); and flags refer to those set on the MPTokenIssuance object unless explicitly stated as being set on the individual MPToken object:
AmountorAmount2hold MPT andfeatureMPTokensV2amendment is not enabled, fail withtemDISABLED.MPTokenIssuanceobject doesn't exist, fail withtecOBJECT_NOT_FOUND.MPTokenobject doesn't exist and AMM creator is not the issuer of MPT, fail withtecNO_AUTH.MPTLockflag is set onMPTokenIssuance, fail for issuer and holder withtecFROZEN.MPTLockflag is set onMPToken, fail for holder withtecFROZEN.MPTRequireAuthflag is set and AMM creator is not authorized, fail withtecNO_AUTH.MPTCanTransferflag is not set and AMM creator is not the issuer of MPT, withtecNO_PERMISSION.MPTCanTradeflag is not set, fail withtecNO_PERMISSION.
2.3. State Changes¶
On success AMMCreate creates and authorizes an MPToken object for each MPT token for the AMM pseudo-account.
2.4. MPToken Ledger Object¶
MPToken object is created for each asset representing MPToken as follows:
| Field Name | JSON Type | Internal Type | Description |
|---|---|---|---|
Account |
String | ACCOUNTID | (Required) AMM Pseudo-account. |
MPTAmount |
String | UINT64 | (Required) AMM pool amount. |
Flags |
String | UINT32 | (Required) lsfMPTAMM(0x00000004). If MPTokenIssuance requires explicit authorization then also lsfMPTAuthorized(0x00000002). |
2.5. Example JSON¶
{
"Account": "rffMEZLzDQPNU6VYbWNkgQBtMz6gCYnMAG",
"Amount": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308",
"value": "1000"
},
"Amount2": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308",
"value": "1000"
},
"Fee": "2000000",
"Flags": 0,
"TradingFee": "0",
"TransactionType": "AMMCreate"
}
3. Transaction: AMMDeposit¶
AMMDeposit is identified by Asset and Asset2 with the token type corresponding to Amount and Amount2 of AMMCreate. Asset and Asset2 are STIssue type, which represents a token by currency and issuer. If STIssue type represents MPT then mpt_issuance_id must be used instead. AMMDeposit has optional fields Amount and Amount2, which if present must match the type of Asset and Asset2 respectively.
3.1. Fields¶
We do not introduce new fields.
3.2. Failure Conditions¶
We extend the AMMDeposit with the following failure conditions, where MPTokenIssuance refers to the ledger object defining the specific MPT type identified in the transaction's Amount or Amount2 fields; MPToken refers to the ledger object representing the specific MPT balance of the account executing the transaction (if that account is not the issuer); and flags refer to those set on the MPTokenIssuance object unless explicitly stated as being set on the individual MPToken object:
Asset,Asset2,Amount, orAmount2hold MPT andfeatureMPTokensV2amendment is not enabled, fail withtemDISABLED.MPTokenIssuanceobject doesn't exist, fail withterNO_AMM.MPTokenobject doesn't exist and the account is not the issuer of MPT, fail withtecNO_AUTH.MPTLockflag is set onMPTokenIssuance, fail for issuer and holder withtecFROZEN.MPTLockflag is set onMPToken, fail for holder withtecFROZEN.MPTRequireAuthflag is set and the account is not authorized, fail withtecNO_AUTH.MPTCanTransferflag is not set and the account is not the issuer of MPT, fail withtecNO_PERMISSION.MPTCanTradeflag is not set, fail withtecNO_PERMISSION.
3.3. State Changes¶
We do not introduce new state changes.
3.4. Example JSON¶
{
"Account": "rffMEZLzDQPNU6VYbWNkgQBtMz6gCYnMAG",
"Amount": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308",
"value": "100"
},
"Amount2": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308",
"value": "100"
},
"Asset": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308"
},
"Asset2": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308"
},
"Fee": "10",
"Flags": 524288,
"TransactionType": "AMMDeposit"
}
4. Transaction: AMMWithdraw¶
AMMWithdraw is identified by Asset and Asset2 with the token type corresponding to Amount and Amount2 of AMMCreate. Asset and Asset2 are STIssue type, which represents a token by currency and issuer. If STIssue type represents MPT then mpt_issuance_id must be used instead. AMMWithdraw has optional fields Amount and Amount2, which if present must match the type of Asset and Asset2 respectively.
4.1. Fields¶
We do not introduce new fields.
4.2. Failure Conditions¶
We extend the AMMWithdraw with the following failure conditions, where MPTokenIssuance refers to the ledger object defining the specific MPT type identified in the transaction's Amount or Amount2 fields; MPToken refers to the ledger object representing the specific MPT balance of the account executing the transaction (if that account is not the issuer); and flags refer to those set on the MPTokenIssuance object unless explicitly stated as being set on the individual MPToken object:
Asset,Asset2,Amount, orAmount2hold MPT andfeatureMPTokensV2amendment is not enabled, fail withtemDISABLED.MPTokenIssuanceobject doesn't exist, fail withterNO_AMM.MPTLockflag is set onMPTokenIssuance, fail for issuer and holder withtecFROZEN. Can withdraw another asset.MPTLockflag is set onMPToken, fail for holder withtecFROZEN. Can withdraw another asset.MPTRequireAuthflag is set and the account is not authorized, fail withtecNO_AUTH. Can withdraw another asset.MPTCanTransferflag is not set and the account is not the issuer of MPT, fail withtecNO_PERMISSION. Can withdraw another asset.MPTCanTradeflag is not set, fail withtecNO_PERMISSION.
4.3. State Changes¶
On success AMMWithdraw creates and authorizes MPToken object if Liquidity Provider doesn't own MPToken object for a withdrawn token.
4.4. MPToken Ledger Object¶
MPToken object is created as follows:
| Field Name | JSON Type | Internal Type | Description |
|---|---|---|---|
Account |
String | ACCOUNTID | (Required) Liquidity Provider account. |
MPTAmount |
String | UINT64 | (Required) Withdrawn amount. |
Flags |
String | UINT32 | (Required) 0. |
4.5. Example JSON¶
{
"Account": "rffMEZLzDQPNU6VYbWNkgQBtMz6gCYnMAG",
"Amount": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308",
"value": "100"
},
"Amount2": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308",
"value": "100"
},
"Asset": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308"
},
"Asset2": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308"
},
"Fee": "10",
"Flags": 1048576,
"TransactionType": "AMMWithdraw"
}
5. Transaction: AMMDelete¶
AMMDelete is identified by Asset and Asset2 with the token type corresponding to Amount and Amount2 of AMMCreate. Asset and Asset2 are STIssue type, which represents a token by currency and issuer. If STIssue type represents MPT then mpt_issuance_id must be used instead.
5.1. Fields¶
We do not introduce new fields.
5.2. Failure Conditions¶
We extend the AMMDelete transaction with the following failure conditions:
AssetorAsset2hold MPT andfeatureMPTokensV2amendment is not enabled, fail withtemDISABLED.
5.3. State Changes¶
We do not introduce new state changes.
5.4. Example JSON¶
{
"Account": "rJVUeRqDFNs2xqA7ncVE6ZoAhPUoaJJSQm",
"Asset": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308"
},
"Asset2": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308"
},
"Fee": "10",
"Flags": 0,
"Sequence": 9,
"TransactionType": "AMMDelete"
}
6. Transaction: AMMClawback¶
AMMClawback is identified by Asset and Asset2 with the token type corresponding to Amount and Amount2 of AMMCreate. Asset and Asset2 are STIssue type, which represents a token by currency and issuer. If STIssue type represents MPT then mpt_issuance_id must be used instead. AMMClawback has optional field Amount, which if present must match the type of Asset.
6.1. Fields¶
We do not introduce new fields.
6.2. Failure Conditions¶
We extend the AMMClawback transaction with the following failure conditions, where MPTokenIssuance refers to the ledger object defining the specific MPT type identified in the transaction's Amount:
Asset,Asset2, orAmounthold MPT andfeatureMPTokensV2amendment is not enabled, fail withtemDISABLED.MPTokenIssuanceobject doesn't exist, fail withterNO_AMM.lsfMPTCanClawbackflag is not set onMPTokenIssuance, fail withtecNO_PERMISSION.
6.3. State Changes¶
On success AMMClawback creates and authorizes MPToken object if Liquidity Provider doesn't own MPToken object for a clawbacked token.
6.4. MPToken Ledger Object¶
MPToken object is created as follows:
| Field Name | JSON Type | Internal Type | Description |
|---|---|---|---|
Account |
String | ACCOUNTID | (Required) Liquidity Provider account. |
MPTAmount |
String | UINT64 | (Required) Clawbacked amount. |
Flags |
String | UINT32 | (Required) 0. |
6.5. Example JSON¶
{
"TransactionType": "AMMClawback",
"Account": "rPdYxU9dNkbzC5Y2h4jLbVJ3rMRrk7WVRL",
"Holder": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"Asset": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308"
},
"Asset2": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308"
},
"Amount": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308",
"value": "1000"
},
"Flags": 1
}
7. Transaction: CheckCreate¶
If SendMax field is MPT then it is identified by mpt_issuance_id.
7.1. Fields¶
We do not introduce new fields.
7.2. Failure Conditions¶
We extend the CheckCreate with the following failure conditions, where MPTokenIssuance refers to the ledger object defining the specific MPT type identified in the transaction's SendMax; and flags refer to those set on the MPTokenIssuance object unless explicitly stated as being set on the individual MPToken object:
SendMaxholds MPT andfeatureMPTokensV2amendment is not enabled, fail withtemDISABLED.MPTokenIssuanceobject doesn't exist, fail withtecOBJECT_NO_FOUND.MPTLockflag is set onMPTokenIssuance, fail for issuer and holder withtecFROZEN.MPTLockflag is set onMPToken, fail for holder as source and destination withtecFROZEN.MPTCanTradeflag is not set, fail withtecNO_PERMISSION.
7.3. State Changes¶
We do not introduce new state changes.
7.4. Example JSON¶
{
"TransactionType": "CheckCreate",
"Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo",
"Destination": "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
"SendMax": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308",
"value": "100"
},
"Expiration": 570113521,
"InvoiceID": "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B",
"DestinationTag": 1,
"Fee": "12"
}
8. Transaction: CheckCash¶
If Amount or DeliverMin fields are MPT then they are identified by mpt_issuance_id. mpt_issuance_id of DeliverMin and Amount must match.
8.1. Fields¶
We do not introduce new fields.
8.2. Failure Conditions¶
We extend the CheckCash with the following failure conditions, where MPTokenIssuance refers to the ledger object defining the specific MPT type identified in the transaction's Amount or DeliverMin fields; MPToken refers to the ledger object representing the specific MPT balance of the account executing the transaction (if that account is not the issuer); and flags refer to those set on the MPTokenIssuance object unless explicitly stated as being set on the individual MPToken object:
MPTokenIssuanceobject doesn't exist, fail withtecNO_ENTRY.MPTokenobject doesn't exist and the account is not the issuer of MPT, fail withtecPATH_PARTIAL.MPTLockflag is set onMPTokenIssuance, fail withtecPATH_PARTIALif source and destination are holders. Fail withtecFROZENif source is issuer and destination is holder.MPTLockflag is set onMPToken, fail for issuer and holder as destination withtecPATH_PARTIAL. Fail for holder as source withtecFROZEN.MPTRequireAuthflag is set and the account is not authorized, fail withtecNO_AUTH.MPTCanTransferflag is not set and the account is not the issuer of MPT, fail withtecPATH_PARTIAL.MPTCanTradeflag is not set, fail withtecNO_PERMISSION.
8.3. State Changes¶
On success CheckCash creates and authorizes MPToken object if the account doesn't own MPToken object.
8.4. MPToken Ledger Object¶
MPToken object is created as follows:
| Field Name | JSON Type | Internal Type | Description |
|---|---|---|---|
Account |
String | ACCOUNTID | (Required) Destination account. |
MPTAmount |
String | UINT64 | (Required) Cashed amount. |
Flags |
String | UINT32 | (Required) 0. |
8.5. Example JSON¶
{
"Account": "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy",
"TransactionType": "CheckCash",
"Amount": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308",
"value": "100"
},
"CheckID": "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334",
"Fee": "12"
}
9. Transaction: OfferCreate¶
OfferCreate can have any token combination of TakerGets and TakerPays. I.e., in addition to the current combination of XRP/IOU and IOU/IOU tokens, OfferCreate can have XRP/MPT, IOU/MPT, and MPT/MPT tokens. If TakerPays or TakerGets fields are MPT then they are identified by mpt_issuance_id.
To ensure asset transfer consistency on offer crossing, the following logic is applied to the offer's assets transfer between the accounts.
TakerGets asset is transferred if:
MPTCanTransferis set- The offer's owner is the issuer
- The asset is the delivered asset and the destination account is the issuer
TakerPays is transferred if:
MPTCanTransferis set- The offer's owner is the issuer
- The asset is the source asset and the source account is the issuer
- The offer's
TakerPaysandTakerGetsare not the source and destination assets
MPT tokens are not adjusted for TickSize in the offers.
9.1. Fields¶
We do not introduce new fields.
9.2. Failure Conditions¶
We extend the OfferCreate with the following failure conditions, where MPTokenIssuance refers to the ledger object defining the specific MPT type identified in the transaction's TakerPays or TakerGets fields; MPToken refers to the ledger object representing the specific MPT balance of the account executing the transaction (if that account is not the issuer); and flags refer to those set on the MPTokenIssuance object unless explicitly stated as being set on the individual MPToken object:
MPTokenIssuanceobject doesn't exist, fail withtecOBJECT_NOT_FOUNDforTakerPaysandtecUNFUNDED_OFFERforTakerGets.MPTokenobject doesn't exist and the account is not the issuer of MPT, fail withtecUNFUNDED_OFFERforTakerGets.MPTLockflag is set and the account is not the issuer of MPT, fail withtecUNFUNDED_OFFERforTakerGets. Create but not cross the offer forTakerPays.MPTRequireAuthflag is set and the account is not authorized, fail withtecUNFUNDED_OFFER.MPTCanTransferflag is not set and the account is not the issuer of MPT.OfferCreatesucceeds but doesn't cross other offers owned by holders. It crosses offers owned by an issuer. IfMPTCanTransferis cleared after an offer is created then this offer is removed from the order book on offer crossing or cross-currency payment.MPTCanTradeflag is not set, fail withtecNO_PERMISSION. IfMPTCanTradeis cleared after an offer is created then this offer is removed from the order book on offer crossing or cross-currency payment.
9.3. State Changes¶
On success OfferCreate creates and authorizes MPToken object for the offer's owner account if the offer is consumed, the offer's owner is not MPToken issuer, and MPToken object doesn't exist for TakerPays's mpt_issuance_id.
9.4. MPToken Ledger Object¶
MPToken object is created as follows:
| Field Name | JSON Type | Internal Type | Description |
|---|---|---|---|
Account |
String | ACCOUNTID | (Required) Offer's owner account. |
MPTAmount |
String | UINT64 | (Required) Buy amount. |
Flags |
String | UINT32 | (Required) 0. |
9.5. Example JSON¶
{
"Account": "rMTysmc799PzTvK228jNaua6w3b6VgYUjw",
"Fee": "10",
"Flags": 0,
"TakerGets": {
"mpt_issuance_id": "00000003430427B80BD2D09D36B70B969E12801065F22308",
"value": "100"
},
"TakerPays": {
"mpt_issuance_id": "00000002430427B80BD2D09D36B70B969E12801065F22308",
"value": "100"
},
"TransactionType": "OfferCreate"
}
10. Transaction: Payment¶
Payment can have any cross-token payment combination. I.e., in addition to the current combination of XRP/IOU and IOU/IOU cross-token payment, Payment can have XRP/MPT, IOU/MPT, and MPT/MPT cross-token payment. MPT can be used to specify Paths, in which case mpt_issuance_id should be used instead of currency and issuer as shown in the JSON example below. MPT doesn't support payment rippling. mpt_issuance_id identifies a unique MPT. It's impossible to reference the same MPT with different issuer. If Amount, DeliverMax, DeliverMin, or SendMax fields are MPT then they are identified by mpt_issuance_id.
10.1. Fields¶
We do not introduce new fields.
10.2. Failure Conditions¶
We extend the Payment with the following failure conditions, where MPTokenIssuance refers to the ledger object defining the specific MPT type identified in the transaction's Amount or SendMax fields; MPToken refers to the ledger object representing the specific MPT balance of the account executing the transaction (if that account is not the issuer); and flags refer to those set on the MPTokenIssuance object unless explicitly stated as being set on the individual MPToken object:
MPTokenIssuanceobject doesn't exist, fail withtecOBJECT_NO_FOUND.MPTokenobject doesn't exist and the account is not the issuer of MPT, fail withtecNO_AUTH.MPTLockflag is set onMPTokenIssuance, fail withtecPATH_DRY.MPTLockflag is set onMPToken, fail withtecPATH_DRY.MPTRequireAuthflag is set and the account is not authorized. Any transfer between unauthorized accounts fail withtecNO_AUTH.MPTCanTransferflag is not set. Any transfer between unauthorized accounts fail withtecPATH_PARTIAL.MPTCanTradeis not set, fail withtecPATH_DRY.
10.3 State Changes¶
We do not introduce new state changes.
10.4. Example JSON¶
{
"Account": "rJ85Mok8YRNxSo7NnxKGrPuk29uAeZQqwZ",
"DeliverMax": {
"mpt_issuance_id": "00000010A407AF5856CCF3C42619DAA925813FC955C72983",
"value": "100"
},
"DeliverMin": {
"mpt_issuance_id": "00000010A407AF5856CCF3C42619DAA925813FC955C72983",
"value": "90"
},
"Destination": "rHKBGB4vhnnVFmfrj4sUx3F9riz2CiHgCK",
"Fee": "10",
"Flags": 131072,
"Paths": [
[
{
"mpt_issuance_id": "00000004A407AF5856CCF3C42619DAA925813FC955C72983"
},
{
"mpt_issuance_id": "0000000AA407AF5856CCF3C42619DAA925813FC955C72983"
},
{
"mpt_issuance_id": "00000010A407AF5856CCF3C42619DAA925813FC955C72983"
}
]
],
"SendMax": "100000000"
}
11. RPC: path_find¶
11.1. Request Fields¶
We do not introduce new fields.
mpt_issuance_id subfield replaces currency and issuer subfields in MPT amount fields.
11.2 Response Fields¶
We do not introduce new fields.
mpt_issuance_id subfield replaces currency and issuer subfields in MPT amount fields, and currency subfield in paths_computed field.
11.3 Example Request¶
{
"command": "path_find",
"subcommand": "create",
"destination_account": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
"destination_amount": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "-1"
},
"send_max": "100000000000000",
"source_account": "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn"
}
11.4 Example Response¶
{
"alternatives": [
{
"destination_amount": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "100"
},
"paths_canonical": [],
"paths_computed": [
[
{
"issuer": "r9QxhA9RghPZBbUchA9HkrmLKaWvkLXU29",
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"type": 96
}
]
],
"source_amount": "100000000"
}
],
"destination_account": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
"destination_amount": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "-1"
},
"destination_currencies": [
"000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"XRP"
],
"full_reply": true,
"ledger_current_index": 8,
"source_account": "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn",
"validated": false
}
11.5. Failure Conditions¶
There is no new failure conditions.
12. RPC: ripple_path_find¶
12.1. Request Fields¶
We do not introduce new fields.
mpt_issuance_id subfield replaces currency and issuer subfields in MPT amount fields.
12.2 Response Fields¶
We do not introduce new fields.
mpt_issuance_id subfield replaces currency and issuer subfields in MPT amount fields, and currency subfield in paths_computed field.
12.3 Example Request¶
{
"command": "ripple_path_find",
"destination_account": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
"destination_amount": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "-1"
},
"send_max": "100000000000000",
"source_account": "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn"
}
12.4 Example Response¶
{
"alternatives": [
{
"destination_amount": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "100"
},
"paths_canonical": [],
"paths_computed": [
[
{
"issuer": "r9QxhA9RghPZBbUchA9HkrmLKaWvkLXU29",
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"type": 96
}
]
],
"source_amount": "100000000"
}
],
"destination_account": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
"destination_amount": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "-1"
},
"destination_currencies": [
"000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"XRP"
],
"full_reply": true,
"ledger_current_index": 8,
"source_account": "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn",
"validated": false
}
12.5. Failure Conditions¶
There is no new failure conditions.
13. RPC: amm_info¶
13.1. Request Fields¶
We do not introduce new fields.
mpt_issuance_id subfield replaces currency and issuer subfields in asset fields.
13.2 Response Fields¶
We do not introduce new fields.
mpt_issuance_id subfield replaces currency and issuer subfields in MPT amount fields.
13.3 Example Request¶
{
"command": "amm_info",
"asset": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83"
},
"asset2": {
"mpt_issuance_id": "000000055C488AAC5813270850685FFD89F4A4A8F4CD4C83"
}
}
13.4 Example Response¶
{
"result": {
"amm": {
"account": "rKM4AJ3JkgmdhKkJLpBcRUSZo7Prq13BYS",
"amount": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "100"
},
"amount2": {
"mpt_issuance_id": "000000055C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "100"
},
"asset2_frozen": false,
"asset_frozen": false,
"auction_slot": {
"account": "r9QxhA9RghPZBbUchA9HkrmLKaWvkLXU29",
"discounted_fee": 0,
"expiration": "2000-01-02T00:00:40+0000",
"price": {
"currency": "033EE62589A944E08A96DC309D6ADBD2FBCFBD11",
"issuer": "rKM4AJ3JkgmdhKkJLpBcRUSZo7Prq13BYS",
"value": "0"
},
"time_interval": 0
},
"lp_token": {
"currency": "033EE62589A944E08A96DC309D6ADBD2FBCFBD11",
"issuer": "rKM4AJ3JkgmdhKkJLpBcRUSZo7Prq13BYS",
"value": "100"
},
"trading_fee": 0,
"vote_slots": [
{
"account": "r9QxhA9RghPZBbUchA9HkrmLKaWvkLXU29",
"trading_fee": 0,
"vote_weight": 100000
}
]
},
"ledger_current_index": 8,
"status": "success",
"validated": false
}
}
13.5. Failure Conditions¶
There is no new failure conditions.
14. RPC: book_offers¶
14.1. Request Fields¶
We do not introduce new fields.
mpt_issuance_id subfield replaces currency and issuer subfields in taker_gets and taker_pays fields.
14.2 Response Fields¶
We do not introduce new fields.
mpt_issuance_id subfield replaces currency and issuer subfields in TakerGets and TakerPays fields.
14.3 Example Request¶
{
"command": "book_offers",
"ledger_index": "current",
"taker": "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn",
"taker_gets": {
"mpt_issuance_id": "000000065C488AAC5813270850685FFD89F4A4A8F4CD4C83"
},
"taker_pays": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83"
}
}
14.4 Example Response¶
{
"result": {
"ledger_current_index": 12,
"offers": [
{
"Account": "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn",
"BookDirectory": "55795BD0628C360A24D3163A2A1EDD66AA9F715E94E9C1D954232CE5E5C6B16D",
"BookNode": "0",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "0",
"PreviousTxnID": "1177EC0BC778D39306481F6D2E33C267DB783800A58EE2F90C91AE38F1B023AD",
"PreviousTxnLgrSeq": 11,
"Sequence": 6,
"TakerGets": {
"mpt_issuance_id": "000000065C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "101"
},
"TakerPays": {
"mpt_issuance_id": "000000045C488AAC5813270850685FFD89F4A4A8F4CD4C83",
"value": "100"
},
"index": "F4715C7C5957FE81246F259315494C671AF12C8B180BB32398DE5148B82ADD93",
"owner_funds": "1000",
"quality": "0.9900990099009901"
}
],
"status": "success",
"validated": false
}
}
14.5. Failure Conditions¶
There is no new failure conditions.
15. Rationale¶
The primary motivation for integrating Multi-Purpose Tokens (MPTs) into the XRPL’s Decentralized Exchange (DEX) is to ensure that the ledger’s next-generation token standard is not siloed from its existing liquidity ecosystem. While MPTs were designed to offer a more compact, scalable, and compliant alternative to traditional Trust Line-based tokens (IOUs), their utility is fundamentally capped if they cannot interact with Automated Market Makers (AMMs) or order books. By enabling MPTs as native trading assets, the ledger provides institutional issuers with a high-performance "Version 2" fungible token that retains the XRPL's core value proposition: atomic, cross-currency settlement. Unlike other blockchains that rely on smart contract standards like ERC-20, where DEX integration requires a wrapper or a complex external contract audit, the XRPL MPT/DEX integration is embedded at the protocol level. This ensures that compliance features—such as individual locks, global freezes, and clawbacks—are automatically enforced during trading without adding the latency or security risks associated with application-layer logic.
A cornerstone of this design is the high degree of transparency and parity between MPT and traditional IOU interactions within the DEX. Rather than introducing a disparate trading engine, the specification extends existing transaction types—such as OfferCreate, AMMCreate, and Payment—to support MPTs natively. This decision was driven by the need for ease of integration; by mirroring the behavior of the "Version 1" token standard, developers can leverage familiar design patterns and existing codebases. For the end user, the experience is intended to be virtually indistinguishable: an MPT functions as a first-class trading asset that can be paired with XRP or any other issued currency. This "plug-and-play" compatibility ensures that the transition to MPTs does not require a steep learning curve for the community or a costly overhaul of the ecosystem’s middleware.
Furthermore, the design prioritizes a unified liquidity model where the ledger's pathfinding logic treats MPTs and IOUs as functionally equivalent nodes. While MPTs use a unique mpt_issuance_id for technical precision, the underlying economic logic—such as cross-currency payments and order book mechanics—remains consistent. This prevents a fragmented developer experience where two different "flavors" of trading would need to be maintained. By choosing to wrap the new functionality within the ledger’s battle-tested DEX primitives, the XLS provides a robust and secure migration path, allowing institutions to adopt the more efficient MPT standard without losing access to the global liquidity and mature tooling that the XRP Ledger has cultivated over the past decade.
16. Security¶
While Multipurpose Tokens (MPT) inherit the core security model of the XRPL (including issuer-controlled freezes and authorization), this integration acknowledges the architectural shift from RippleState to MPT objects. Security is maintained by performing real-time verification of MPT-specific flags and ensuring that DEX quality calculations account for MPT-specific decimal scaling to prevent rounding exploits. Furthermore, the DEX engine treats MPT-specific freezes as immediate execution barriers, mirroring the existing IOU freeze behavior.
Appendix¶
A: STIssue serialization¶
STIssue type is extended to support MPT as follows:
- Break down
mpt_issuance_idinto its sequence number and account. - The account is serialized in the first 160 bits, followed by a dedicated black hole account in the next 160 bits.
- Finally, the sequence number (32 bits) is serialized last.
- Deserialization method reads 320-bit
currencyandaccount. Ifaccountis the black hole account then additional 32 bits have to be read and deserialized into a sequence number. - This method maintains backward compatibility, doesn’t require a separate amendment, but adds 32 extra bits compared to the current format, or adds 160 bits compared to 192 bits required for serializing
mpt_issuance_id.
| 160 bits MPT issuer account | 160 bits black-hole account | 32 bits sequence |
|---|---|---|