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/TER.h>
8#include <xrpl/protocol/TxFlags.h>
9
10namespace ripple {
11
14{
15 if (ctx.tx[sfVaultID] == beast::zero)
16 {
17 JLOG(ctx.j.debug()) << "VaultDelete: zero/empty vault ID.";
18 return temMALFORMED;
19 }
20
21 return tesSUCCESS;
22}
23
24TER
26{
27 auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
28 if (!vault)
29 return tecNO_ENTRY;
30
31 if (vault->at(sfOwner) != ctx.tx[sfAccount])
32 {
33 JLOG(ctx.j.debug()) << "VaultDelete: account is not an owner.";
34 return tecNO_PERMISSION;
35 }
36
37 if (vault->at(sfAssetsAvailable) != 0)
38 {
39 JLOG(ctx.j.debug()) << "VaultDelete: nonzero assets available.";
40 return tecHAS_OBLIGATIONS;
41 }
42
43 if (vault->at(sfAssetsTotal) != 0)
44 {
45 JLOG(ctx.j.debug()) << "VaultDelete: nonzero assets total.";
46 return tecHAS_OBLIGATIONS;
47 }
48
49 // Verify we can destroy MPTokenIssuance
50 auto const sleMPT =
51 ctx.view.read(keylet::mptIssuance(vault->at(sfShareMPTID)));
52
53 if (!sleMPT)
54 {
55 // LCOV_EXCL_START
56 JLOG(ctx.j.error())
57 << "VaultDeposit: missing issuance of vault shares.";
59 // LCOV_EXCL_STOP
60 }
61
62 if (sleMPT->at(sfIssuer) != vault->getAccountID(sfAccount))
63 {
64 // LCOV_EXCL_START
65 JLOG(ctx.j.error()) << "VaultDeposit: invalid owner of vault shares.";
66 return tecNO_PERMISSION;
67 // LCOV_EXCL_STOP
68 }
69
70 if (sleMPT->at(sfOutstandingAmount) != 0)
71 {
72 JLOG(ctx.j.debug()) << "VaultDelete: nonzero outstanding shares.";
73 return tecHAS_OBLIGATIONS;
74 }
75
76 return tesSUCCESS;
77}
78
79TER
81{
82 auto const vault = view().peek(keylet::vault(ctx_.tx[sfVaultID]));
83 if (!vault)
84 return tefINTERNAL; // LCOV_EXCL_LINE
85
86 // Destroy the asset holding.
87 auto asset = vault->at(sfAsset);
88 if (auto ter = removeEmptyHolding(view(), vault->at(sfAccount), asset, j_);
89 !isTesSuccess(ter))
90 return ter;
91
92 auto const& pseudoID = vault->at(sfAccount);
93 auto const pseudoAcct = view().peek(keylet::account(pseudoID));
94 if (!pseudoAcct)
95 {
96 // LCOV_EXCL_START
97 JLOG(j_.error()) << "VaultDelete: missing vault pseudo-account.";
98 return tefBAD_LEDGER;
99 // LCOV_EXCL_STOP
100 }
101
102 // Destroy the share issuance. Do not use MPTokenIssuanceDestroy for this,
103 // no special logic needed. First run few checks, duplicated from preclaim.
104 auto const shareMPTID = *vault->at(sfShareMPTID);
105 auto const mpt = view().peek(keylet::mptIssuance(shareMPTID));
106 if (!mpt)
107 {
108 // LCOV_EXCL_START
109 JLOG(j_.error()) << "VaultDelete: missing issuance of vault shares.";
110 return tefINTERNAL;
111 // LCOV_EXCL_STOP
112 }
113
114 // Try to remove MPToken for vault shares for the vault owner if it exists.
115 if (auto const mptoken = view().peek(keylet::mptoken(shareMPTID, account_)))
116 {
117 if (auto const ter =
118 removeEmptyHolding(view(), account_, MPTIssue(shareMPTID), j_);
119 !isTesSuccess(ter))
120 {
121 // LCOV_EXCL_START
122 JLOG(j_.error()) //
123 << "VaultDelete: failed to remove vault owner's MPToken"
124 << " MPTID=" << to_string(shareMPTID) //
125 << " account=" << toBase58(account_) //
126 << " with result: " << transToken(ter);
127 return ter;
128 // LCOV_EXCL_STOP
129 }
130 }
131
132 if (!view().dirRemove(
133 keylet::ownerDir(pseudoID), (*mpt)[sfOwnerNode], mpt->key(), false))
134 {
135 // LCOV_EXCL_START
136 JLOG(j_.error()) << "VaultDelete: failed to delete issuance object.";
137 return tefBAD_LEDGER;
138 // LCOV_EXCL_STOP
139 }
140 adjustOwnerCount(view(), pseudoAcct, -1, j_);
141
142 view().erase(mpt);
143
144 // The pseudo-account's directory should have been deleted already.
145 if (view().peek(keylet::ownerDir(pseudoID)))
146 return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE
147
148 // Destroy the pseudo-account.
149 view().erase(view().peek(keylet::account(pseudoID)));
150
151 // Remove the vault from its owner's directory.
152 auto const ownerID = vault->at(sfOwner);
153 if (!view().dirRemove(
154 keylet::ownerDir(ownerID),
155 vault->at(sfOwnerNode),
156 vault->key(),
157 false))
158 {
159 // LCOV_EXCL_START
160 JLOG(j_.error()) << "VaultDelete: failed to delete vault object.";
161 return tefBAD_LEDGER;
162 // LCOV_EXCL_STOP
163 }
164
165 auto const owner = view().peek(keylet::account(ownerID));
166 if (!owner)
167 {
168 // LCOV_EXCL_START
169 JLOG(j_.error()) << "VaultDelete: missing vault owner account.";
170 return tefBAD_LEDGER;
171 // LCOV_EXCL_STOP
172 }
173 adjustOwnerCount(view(), owner, -1, j_);
174
175 // Destroy the vault.
176 view().erase(vault);
177
178 return tesSUCCESS;
179}
180
181} // namespace ripple
Stream error() const
Definition Journal.h:327
Stream debug() const
Definition Journal.h:309
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:128
ApplyView & view()
Definition Transactor.h:144
beast::Journal const j_
Definition Transactor.h:126
ApplyContext & ctx_
Definition Transactor.h:124
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:521
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:507
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:545
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:165
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:355
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition AccountID.cpp:95
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:1013
@ tefBAD_LEDGER
Definition TER.h:151
@ tefINTERNAL
Definition TER.h:154
std::string transToken(TER code)
Definition TER.cpp:245
@ tecNO_ENTRY
Definition TER.h:288
@ tecOBJECT_NOT_FOUND
Definition TER.h:308
@ tecNO_PERMISSION
Definition TER.h:287
@ tecHAS_OBLIGATIONS
Definition TER.h:299
@ tesSUCCESS
Definition TER.h:226
bool isTesSuccess(TER x) noexcept
Definition TER.h:659
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
TER removeEmptyHolding(ApplyView &view, AccountID const &accountID, Issue const &issue, beast::Journal journal)
Definition View.cpp:1498
TERSubset< CanCvtToNotTEC > NotTEC
Definition TER.h:590
@ temMALFORMED
Definition TER.h:68
uint256 key
Definition Keylet.h:21
State information when determining if a tx is likely to claim a fee.
Definition Transactor.h:61
ReadView const & view
Definition Transactor.h:64
beast::Journal const j
Definition Transactor.h:69
State information when preflighting a tx.
Definition Transactor.h:16
beast::Journal const j
Definition Transactor.h:23