rippled
Loading...
Searching...
No Matches
VaultDelete.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2025 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/app/tx/detail/VaultDelete.h>
21
22#include <xrpl/ledger/View.h>
23#include <xrpl/protocol/Feature.h>
24#include <xrpl/protocol/MPTIssue.h>
25#include <xrpl/protocol/STNumber.h>
26#include <xrpl/protocol/TER.h>
27#include <xrpl/protocol/TxFlags.h>
28
29namespace ripple {
30
33{
34 if (ctx.tx[sfVaultID] == beast::zero)
35 {
36 JLOG(ctx.j.debug()) << "VaultDelete: zero/empty vault ID.";
37 return temMALFORMED;
38 }
39
40 return tesSUCCESS;
41}
42
43TER
45{
46 auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
47 if (!vault)
48 return tecNO_ENTRY;
49
50 if (vault->at(sfOwner) != ctx.tx[sfAccount])
51 {
52 JLOG(ctx.j.debug()) << "VaultDelete: account is not an owner.";
53 return tecNO_PERMISSION;
54 }
55
56 if (vault->at(sfAssetsAvailable) != 0)
57 {
58 JLOG(ctx.j.debug()) << "VaultDelete: nonzero assets available.";
59 return tecHAS_OBLIGATIONS;
60 }
61
62 if (vault->at(sfAssetsTotal) != 0)
63 {
64 JLOG(ctx.j.debug()) << "VaultDelete: nonzero assets total.";
65 return tecHAS_OBLIGATIONS;
66 }
67
68 // Verify we can destroy MPTokenIssuance
69 auto const sleMPT =
70 ctx.view.read(keylet::mptIssuance(vault->at(sfShareMPTID)));
71
72 if (!sleMPT)
73 {
74 // LCOV_EXCL_START
75 JLOG(ctx.j.error())
76 << "VaultDeposit: missing issuance of vault shares.";
78 // LCOV_EXCL_STOP
79 }
80
81 if (sleMPT->at(sfIssuer) != vault->getAccountID(sfAccount))
82 {
83 // LCOV_EXCL_START
84 JLOG(ctx.j.error()) << "VaultDeposit: invalid owner of vault shares.";
85 return tecNO_PERMISSION;
86 // LCOV_EXCL_STOP
87 }
88
89 if (sleMPT->at(sfOutstandingAmount) != 0)
90 {
91 JLOG(ctx.j.debug()) << "VaultDelete: nonzero outstanding shares.";
92 return tecHAS_OBLIGATIONS;
93 }
94
95 return tesSUCCESS;
96}
97
98TER
100{
101 auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
102 if (!vault)
103 return tefINTERNAL; // LCOV_EXCL_LINE
104
105 // Destroy the asset holding.
106 auto asset = vault->at(sfAsset);
107 if (auto ter = removeEmptyHolding(view(), vault->at(sfAccount), asset, j_);
108 !isTesSuccess(ter))
109 return ter;
110
111 auto const& pseudoID = vault->at(sfAccount);
112 auto const pseudoAcct = view().peek(keylet::account(pseudoID));
113 if (!pseudoAcct)
114 {
115 // LCOV_EXCL_START
116 JLOG(j_.error()) << "VaultDelete: missing vault pseudo-account.";
117 return tefBAD_LEDGER;
118 // LCOV_EXCL_STOP
119 }
120
121 // Destroy the share issuance. Do not use MPTokenIssuanceDestroy for this,
122 // no special logic needed. First run few checks, duplicated from preclaim.
123 auto const shareMPTID = *vault->at(sfShareMPTID);
124 auto const mpt = view().peek(keylet::mptIssuance(shareMPTID));
125 if (!mpt)
126 {
127 // LCOV_EXCL_START
128 JLOG(j_.error()) << "VaultDelete: missing issuance of vault shares.";
129 return tefINTERNAL;
130 // LCOV_EXCL_STOP
131 }
132
133 // Try to remove MPToken for vault shares for the vault owner if it exists.
134 if (auto const mptoken = view().peek(keylet::mptoken(shareMPTID, account_)))
135 {
136 if (auto const ter =
137 removeEmptyHolding(view(), account_, MPTIssue(shareMPTID), j_);
138 !isTesSuccess(ter))
139 {
140 // LCOV_EXCL_START
141 JLOG(j_.error()) //
142 << "VaultDelete: failed to remove vault owner's MPToken"
143 << " MPTID=" << to_string(shareMPTID) //
144 << " account=" << toBase58(account_) //
145 << " with result: " << transToken(ter);
146 return ter;
147 // LCOV_EXCL_STOP
148 }
149 }
150
151 if (!view().dirRemove(
152 keylet::ownerDir(pseudoID), (*mpt)[sfOwnerNode], mpt->key(), false))
153 {
154 // LCOV_EXCL_START
155 JLOG(j_.error()) << "VaultDelete: failed to delete issuance object.";
156 return tefBAD_LEDGER;
157 // LCOV_EXCL_STOP
158 }
159 adjustOwnerCount(view(), pseudoAcct, -1, j_);
160
161 view().erase(mpt);
162
163 // The pseudo-account's directory should have been deleted already.
164 if (view().peek(keylet::ownerDir(pseudoID)))
165 return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE
166
167 // Destroy the pseudo-account.
168 view().erase(view().peek(keylet::account(pseudoID)));
169
170 // Remove the vault from its owner's directory.
171 auto const ownerID = vault->at(sfOwner);
172 if (!view().dirRemove(
173 keylet::ownerDir(ownerID),
174 vault->at(sfOwnerNode),
175 vault->key(),
176 false))
177 {
178 // LCOV_EXCL_START
179 JLOG(j_.error()) << "VaultDelete: failed to delete vault object.";
180 return tefBAD_LEDGER;
181 // LCOV_EXCL_STOP
182 }
183
184 auto const owner = view().peek(keylet::account(ownerID));
185 if (!owner)
186 {
187 // LCOV_EXCL_START
188 JLOG(j_.error()) << "VaultDelete: missing vault owner account.";
189 return tefBAD_LEDGER;
190 // LCOV_EXCL_STOP
191 }
192 adjustOwnerCount(view(), owner, -1, j_);
193
194 // Destroy the vault.
195 view().erase(vault);
196
197 return tesSUCCESS;
198}
199
200} // namespace ripple
Stream error() const
Definition Journal.h:346
Stream debug() const
Definition Journal.h:328
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
AccountID const account_
Definition Transactor.h:147
ApplyView & view()
Definition Transactor.h:163
beast::Journal const j_
Definition Transactor.h:145
ApplyContext & ctx_
Definition Transactor.h:143
static NotTEC preflight(PreflightContext const &ctx)
static TER preclaim(PreclaimContext const &ctx)
TER doApply() override
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:540
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:526
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:564
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:184
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:374
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
void adjustOwnerCount(ApplyView &view, std::shared_ptr< SLE > const &sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
Definition View.cpp:1032
@ tefBAD_LEDGER
Definition TER.h:170
@ tefINTERNAL
Definition TER.h:173
std::string transToken(TER code)
Definition TER.cpp:264
@ tecNO_ENTRY
Definition TER.h:306
@ tecOBJECT_NOT_FOUND
Definition TER.h:326
@ tecNO_PERMISSION
Definition TER.h:305
@ tecHAS_OBLIGATIONS
Definition TER.h:317
@ tesSUCCESS
Definition TER.h:244
bool isTesSuccess(TER x) noexcept
Definition TER.h:674
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
TER removeEmptyHolding(ApplyView &view, AccountID const &accountID, Issue const &issue, beast::Journal journal)
Definition View.cpp:1511
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:605
@ temMALFORMED
Definition TER.h:87
uint256 key
Definition Keylet.h:40
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:80
ReadView const & view
Definition Transactor.h:83
beast::Journal const j
Definition Transactor.h:88
State information when preflighting a tx.
Definition Transactor.h:35
beast::Journal const j
Definition Transactor.h:42