rippled
Loading...
Searching...
No Matches
VaultDelete.cpp
1#include <xrpld/app/tx/detail/VaultDelete.h>
2
3#include <xrpl/ledger/View.h>
4#include <xrpl/protocol/Feature.h>
5#include <xrpl/protocol/MPTIssue.h>
6#include <xrpl/protocol/STNumber.h>
7#include <xrpl/protocol/STTakesAsset.h>
8#include <xrpl/protocol/TER.h>
9#include <xrpl/protocol/TxFlags.h>
10
11namespace xrpl {
12
15{
16 if (ctx.tx[sfVaultID] == beast::zero)
17 {
18 JLOG(ctx.j.debug()) << "VaultDelete: zero/empty vault ID.";
19 return temMALFORMED;
20 }
21
22 return tesSUCCESS;
23}
24
25TER
27{
28 auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
29 if (!vault)
30 return tecNO_ENTRY;
31
32 if (vault->at(sfOwner) != ctx.tx[sfAccount])
33 {
34 JLOG(ctx.j.debug()) << "VaultDelete: account is not an owner.";
35 return tecNO_PERMISSION;
36 }
37
38 if (vault->at(sfAssetsAvailable) != 0)
39 {
40 JLOG(ctx.j.debug()) << "VaultDelete: nonzero assets available.";
41 return tecHAS_OBLIGATIONS;
42 }
43
44 if (vault->at(sfAssetsTotal) != 0)
45 {
46 JLOG(ctx.j.debug()) << "VaultDelete: nonzero assets total.";
47 return tecHAS_OBLIGATIONS;
48 }
49
50 // Verify we can destroy MPTokenIssuance
51 auto const sleMPT = ctx.view.read(keylet::mptIssuance(vault->at(sfShareMPTID)));
52
53 if (!sleMPT)
54 {
55 // LCOV_EXCL_START
56 JLOG(ctx.j.error()) << "VaultDeposit: missing issuance of vault shares.";
58 // LCOV_EXCL_STOP
59 }
60
61 if (sleMPT->at(sfIssuer) != vault->getAccountID(sfAccount))
62 {
63 // LCOV_EXCL_START
64 JLOG(ctx.j.error()) << "VaultDeposit: invalid owner of vault shares.";
65 return tecNO_PERMISSION;
66 // LCOV_EXCL_STOP
67 }
68
69 if (sleMPT->at(sfOutstandingAmount) != 0)
70 {
71 JLOG(ctx.j.debug()) << "VaultDelete: nonzero outstanding shares.";
72 return tecHAS_OBLIGATIONS;
73 }
74
75 return tesSUCCESS;
76}
77
78TER
80{
81 auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
82 if (!vault)
83 return tefINTERNAL; // LCOV_EXCL_LINE
84
85 // Destroy the asset holding.
86 auto asset = vault->at(sfAsset);
87
88 if (auto ter = removeEmptyHolding(view(), vault->at(sfAccount), asset, j_); !isTesSuccess(ter))
89 return ter;
90
91 auto const& pseudoID = vault->at(sfAccount);
92 auto const pseudoAcct = view().peek(keylet::account(pseudoID));
93 if (!pseudoAcct)
94 {
95 // LCOV_EXCL_START
96 JLOG(j_.error()) << "VaultDelete: missing vault pseudo-account.";
97 return tefBAD_LEDGER;
98 // LCOV_EXCL_STOP
99 }
100
101 // Destroy the share issuance. Do not use MPTokenIssuanceDestroy for this,
102 // no special logic needed. First run few checks, duplicated from preclaim.
103 auto const shareMPTID = *vault->at(sfShareMPTID);
104 auto const mpt = view().peek(keylet::mptIssuance(shareMPTID));
105 if (!mpt)
106 {
107 // LCOV_EXCL_START
108 JLOG(j_.error()) << "VaultDelete: missing issuance of vault shares.";
109 return tefINTERNAL;
110 // LCOV_EXCL_STOP
111 }
112
113 // Try to remove MPToken for vault shares for the vault owner if it exists.
114 if (auto const mptoken = view().peek(keylet::mptoken(shareMPTID, account_)))
115 {
116 if (auto const ter = removeEmptyHolding(view(), account_, MPTIssue(shareMPTID), j_); !isTesSuccess(ter))
117 {
118 // LCOV_EXCL_START
119 JLOG(j_.error()) //
120 << "VaultDelete: failed to remove vault owner's MPToken"
121 << " MPTID=" << to_string(shareMPTID) //
122 << " account=" << toBase58(account_) //
123 << " with result: " << transToken(ter);
124 return ter;
125 // LCOV_EXCL_STOP
126 }
127 }
128
129 if (!view().dirRemove(keylet::ownerDir(pseudoID), (*mpt)[sfOwnerNode], mpt->key(), false))
130 {
131 // LCOV_EXCL_START
132 JLOG(j_.error()) << "VaultDelete: failed to delete issuance object.";
133 return tefBAD_LEDGER;
134 // LCOV_EXCL_STOP
135 }
136 adjustOwnerCount(view(), pseudoAcct, -1, j_);
137
138 view().erase(mpt);
139
140 // The pseudo-account's directory should have been deleted already.
141 if (view().peek(keylet::ownerDir(pseudoID)))
142 return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE
143
144 // Destroy the pseudo-account.
145 auto vaultPseudoSLE = view().peek(keylet::account(pseudoID));
146 if (!vaultPseudoSLE || vaultPseudoSLE->at(~sfVaultID) != vault->key())
147 return tefBAD_LEDGER; // LCOV_EXCL_LINE
148
149 // Making the payment and removing the empty holding should have deleted any
150 // obligations associated with the vault or vault pseudo-account.
151 if (*vaultPseudoSLE->at(sfBalance))
152 {
153 // LCOV_EXCL_START
154 JLOG(j_.error()) << "VaultDelete: pseudo-account has a balance";
155 return tecHAS_OBLIGATIONS;
156 // LCOV_EXCL_STOP
157 }
158 if (vaultPseudoSLE->at(sfOwnerCount) != 0)
159 {
160 // LCOV_EXCL_START
161 JLOG(j_.error()) << "VaultDelete: pseudo-account still owns objects";
162 return tecHAS_OBLIGATIONS;
163 // LCOV_EXCL_STOP
164 }
165 if (view().exists(keylet::ownerDir(pseudoID)))
166 {
167 // LCOV_EXCL_START
168 JLOG(j_.error()) << "VaultDelete: pseudo-account has a directory";
169 return tecHAS_OBLIGATIONS;
170 // LCOV_EXCL_STOP
171 }
172
173 view().erase(vaultPseudoSLE);
174
175 // Remove the vault from its owner's directory.
176 auto const ownerID = vault->at(sfOwner);
177 if (!view().dirRemove(keylet::ownerDir(ownerID), vault->at(sfOwnerNode), vault->key(), false))
178 {
179 // LCOV_EXCL_START
180 JLOG(j_.error()) << "VaultDelete: failed to delete vault object.";
181 return tefBAD_LEDGER;
182 // LCOV_EXCL_STOP
183 }
184
185 auto const owner = view().peek(keylet::account(ownerID));
186 if (!owner)
187 {
188 // LCOV_EXCL_START
189 JLOG(j_.error()) << "VaultDelete: missing vault owner account.";
190 return tefBAD_LEDGER;
191 // LCOV_EXCL_STOP
192 }
193
194 // We are destroying Vault and PseudoAccount, hence decrease by 2
195 adjustOwnerCount(view(), owner, -2, j_);
196
197 // Destroy the vault.
198 view().erase(vault);
199
200 associateAsset(*vault, asset);
201
202 return tesSUCCESS;
203}
204
205} // namespace xrpl
Stream error() const
Definition Journal.h:318
Stream debug() const
Definition Journal.h:300
STTx const & tx
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
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:112
beast::Journal const j_
Definition Transactor.h:110
ApplyView & view()
Definition Transactor.h:128
ApplyContext & ctx_
Definition Transactor.h:108
static TER preclaim(PreclaimContext const &ctx)
static NotTEC preflight(PreflightContext const &ctx)
TER doApply() override
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:325
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:462
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:492
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Definition Indexes.cpp:474
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:160
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
TER removeEmptyHolding(ApplyView &view, AccountID const &accountID, Issue const &issue, beast::Journal journal)
Definition View.cpp:1554
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:597
@ tefBAD_LEDGER
Definition TER.h:150
@ tefINTERNAL
Definition TER.h:153
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:92
std::string transToken(TER code)
Definition TER.cpp:243
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:941
@ temMALFORMED
Definition TER.h:67
bool isTesSuccess(TER x) noexcept
Definition TER.h:649
@ tecNO_ENTRY
Definition TER.h:287
@ tecOBJECT_NOT_FOUND
Definition TER.h:307
@ tecNO_PERMISSION
Definition TER.h:286
@ tecHAS_OBLIGATIONS
Definition TER.h:298
void associateAsset(STLedgerEntry &sle, Asset const &asset)
Associate an Asset with all sMD_NeedsAsset fields in a ledger entry.
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:580
@ tesSUCCESS
Definition TER.h:225
uint256 key
Definition Keylet.h:20
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:53
ReadView const & view
Definition Transactor.h:56
beast::Journal const j
Definition Transactor.h:61
State information when preflighting a tx.
Definition Transactor.h:15
beast::Journal const j
Definition Transactor.h:22