21 #include <test/jtx/Env.h>
22 #include <ripple/beast/utility/Journal.h>
23 #include <ripple/app/tx/apply.h>
24 #include <ripple/app/tx/impl/Transactor.h>
25 #include <ripple/app/tx/impl/ApplyContext.h>
26 #include <ripple/protocol/STLedgerEntry.h>
27 #include <boost/algorithm/string/predicate.hpp>
51 using namespace test::jtx;
56 env.fund (XRP (1000), A1, A2);
59 OpenView ov {*env.current()};
67 safe_cast<FeeUnit64>(env.current()->fees().units),
72 BEAST_EXPECT(precheck(A1, A2, ac));
75 if (! BEAST_EXPECT(ters.
size() == 2))
79 for (
TER const terExpect : ters)
81 terActual = ac.checkInvariants(terActual, fee);
82 BEAST_EXPECT(terExpect == terActual);
84 boost::starts_with(sink.messages().str(),
"Invariant failed:") ||
85 boost::starts_with(sink.messages().str(),
86 "Transaction caused an exception"));
89 for (
auto const& m : expect_logs)
91 BEAST_EXPECT(sink.messages().str().find(m) != std::string::npos);
99 using namespace test::jtx;
100 testcase <<
"XRP created";
102 {{
"XRP net change was positive: 500" }},
109 auto amt = sle->getFieldAmount (
sfBalance);
111 ac.view().update (sle);
119 using namespace test::jtx;
120 testcase <<
"account root removed";
124 {{
"an account root was deleted" }},
131 ac.view().erase (sle);
141 {{
"account deletion succeeded without deleting an account" }},
142 [](Account
const&, Account
const&,
ApplyContext& ac){
return true;},
149 {{
"account deletion succeeded but deleted multiple accounts" }},
150 [](Account
const& A1, Account
const& A2,
ApplyContext& ac)
157 ac.view().erase (sleA1);
158 ac.view().erase (sleA2);
168 using namespace test::jtx;
169 testcase <<
"ledger entry types don't match";
171 {{
"ledger entry type mismatch" },
172 {
"XRP net change of -1000000000 doesn't match fee 0" }},
179 auto sleNew = std::make_shared<SLE> (
ltTICKET, sle->key());
180 ac.rawView().rawReplace (sleNew);
185 {{
"invalid ledger entry type added" }},
195 auto sleNew = std::make_shared<SLE> (
198 ac.view().insert (sleNew);
206 using namespace test::jtx;
207 testcase <<
"trust lines with XRP not allowed";
209 {{
"an XRP trust line was created" }},
210 [](Account
const& A1, Account
const& A2,
ApplyContext& ac)
214 auto const sleNew = std::make_shared<SLE>(
216 ac.view().insert (sleNew);
224 using namespace test::jtx;
225 testcase <<
"XRP balance checks";
228 {{
"Cannot return non-native STAmount as XRPAmount" }},
229 [](Account
const& A1, Account
const& A2,
ApplyContext& ac)
236 sle->setFieldAmount (
sfBalance, nonNative);
237 ac.view().update (sle);
242 {{
"incorrect account XRP balance" },
243 {
"XRP net change was positive: 99999999000000001" }},
244 [
this](Account
const& A1, Account
const&,
ApplyContext& ac)
254 BEAST_EXPECT(!sle->getFieldAmount(
sfBalance).negative());
255 ac.view().update (sle);
260 {{
"incorrect account XRP balance" },
261 {
"XRP net change of -1000000001 doesn't match fee 0" }},
262 [
this](Account
const& A1, Account
const&,
ApplyContext& ac)
269 BEAST_EXPECT(sle->getFieldAmount(
sfBalance).negative());
270 ac.view().update (sle);
278 using namespace test::jtx;
279 using namespace std::string_literals;
280 testcase <<
"Transaction fee checks";
283 {{
"fee paid was negative: -1" },
284 {
"XRP net change of 0 doesn't match fee -1" }},
285 [](Account
const&, Account
const&,
ApplyContext&) {
return true; },
289 {{
"fee paid exceeds system limit: "s +
291 {
"XRP net change of 0 doesn't match fee "s +
293 [](Account
const&, Account
const&,
ApplyContext&) {
return true; },
297 {{
"fee paid is 20 exceeds fee specified in transaction."},
298 {
"XRP net change of 0 doesn't match fee 20"}},
299 [](Account
const&, Account
const&,
ApplyContext&) {
return true; },
309 using namespace test::jtx;
310 testcase <<
"no bad offers";
313 {{
"offer with a bad amount" }},
320 auto const offer_index =
322 auto sleNew = std::make_shared<SLE> (
ltOFFER, offer_index);
323 sleNew->setAccountID (
sfAccount, A1.id());
326 ac.view().insert (sleNew);
331 {{
"offer with a bad amount" }},
338 auto const offer_index =
340 auto sleNew = std::make_shared<SLE> (
ltOFFER, offer_index);
341 sleNew->setAccountID (
sfAccount, A1.id());
343 sleNew->setFieldAmount (
sfTakerPays, A1[
"USD"](10));
345 ac.view().insert (sleNew);
350 {{
"offer with a bad amount" }},
357 auto const offer_index =
359 auto sleNew = std::make_shared<SLE> (
ltOFFER, offer_index);
360 sleNew->setAccountID (
sfAccount, A1.id());
364 ac.view().insert (sleNew);
372 using namespace test::jtx;
373 testcase <<
"no zero escrow";
376 {{
"Cannot return non-native STAmount as XRPAmount" }},
377 [](Account
const& A1, Account
const& A2,
ApplyContext& ac)
383 auto sleNew = std::make_shared<SLE> (
386 sleNew->setFieldAmount (
sfAmount, nonNative);
387 ac.view().insert (sleNew);
392 {{
"XRP net change of -1000000 doesn't match fee 0"},
393 {
"escrow specifies invalid amount" }},
400 auto sleNew = std::make_shared<SLE> (
402 sleNew->setFieldAmount (
sfAmount, XRP(-1));
403 ac.view().insert (sleNew);
408 {{
"XRP net change was positive: 100000000000000001" },
409 {
"escrow specifies invalid amount" }},
416 auto sleNew = std::make_shared<SLE> (
422 ac.view().insert (sleNew);
430 using namespace test::jtx;
431 testcase <<
"valid new account root";
434 {{
"account root created by a non-Payment" }},
439 const Account A3 {
"A3"};
441 auto const sleNew = std::make_shared<SLE>(acctKeylet);
442 ac.view().insert (sleNew);
447 {{
"multiple accounts created in a single transaction" }},
452 const Account A3 {
"A3"};
454 auto const sleA3 = std::make_shared<SLE>(acctKeylet);
455 ac.view().insert (sleA3);
458 const Account A4 {
"A4"};
460 auto const sleA4 = std::make_shared<SLE>(acctKeylet);
461 ac.view().insert (sleA4);
467 {{
"account created with wrong starting sequence number" }},
471 const Account A3 {
"A3"};
473 auto const sleNew = std::make_shared<SLE>(acctKeylet);
474 sleNew->setFieldU32 (
sfSequence, ac.view().seq() + 1);
475 ac.view().insert (sleNew);