Add single asset vault (XLS-65d) (#5224)

- Specification: XRPLF/XRPL-Standards#239
- Amendment: `SingleAssetVault`
- Implements a vault feature used to store a fungible asset (XRP, IOU, or MPT, but not NFT) and to receive shares in the vault (an MPT) in exchange.
- A vault can be private or public.
- A private vault can use permissioned domains, subject to the `PermissionedDomains` amendment.
- Shares can be exchanged back into asset with `VaultWithdraw`.
- Permissions on the asset in the vault are transitively applied on shares in the vault.
- Issuer of the asset in the vault can clawback with `VaultClawback`.
- Extended `MPTokenIssuance` with `DomainID`, used by the permissioned domain on the vault shares.

Co-authored-by: John Freeman <jfreeman08@gmail.com>
This commit is contained in:
Bronek Kozicki
2025-05-20 19:06:41 +01:00
committed by GitHub
parent dd62cfcc22
commit e514de76ed
93 changed files with 7257 additions and 385 deletions

View File

@@ -83,6 +83,10 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
return tecHAS_OBLIGATIONS;
}
if (ctx.view.rules().enabled(featureSingleAssetVault) &&
sleMpt->isFlag(lsfMPTLocked))
return tecNO_PERMISSION;
return tesSUCCESS;
}
@@ -160,14 +164,14 @@ MPTokenAuthorize::authorize(
keylet::mptoken(args.mptIssuanceID, args.account);
auto const sleMpt = view.peek(mptokenKey);
if (!sleMpt || (*sleMpt)[sfMPTAmount] != 0)
return tecINTERNAL;
return tecINTERNAL; // LCOV_EXCL_LINE
if (!view.dirRemove(
keylet::ownerDir(args.account),
(*sleMpt)[sfOwnerNode],
sleMpt->key(),
false))
return tecINTERNAL;
return tecINTERNAL; // LCOV_EXCL_LINE
adjustOwnerCount(view, sleAcct, -1, journal);
@@ -194,20 +198,13 @@ MPTokenAuthorize::authorize(
auto const mptokenKey =
keylet::mptoken(args.mptIssuanceID, args.account);
auto const ownerNode = view.dirInsert(
keylet::ownerDir(args.account),
mptokenKey,
describeOwnerDir(args.account));
if (!ownerNode)
return tecDIR_FULL;
auto mptoken = std::make_shared<SLE>(mptokenKey);
if (auto ter = dirLink(view, args.account, mptoken))
return ter; // LCOV_EXCL_LINE
(*mptoken)[sfAccount] = args.account;
(*mptoken)[sfMPTokenIssuanceID] = args.mptIssuanceID;
(*mptoken)[sfFlags] = 0;
(*mptoken)[sfOwnerNode] = *ownerNode;
view.insert(mptoken);
// Update owner count.