xrpld
Loading...
Searching...
No Matches
SetFeeTests.cpp
1// Auto-generated unit tests for transaction SetFee
2
3
4#include <gtest/gtest.h>
5
6#include <protocol_autogen/TestHelpers.h>
7
8#include <xrpl/protocol/SecretKey.h>
9#include <xrpl/protocol/Seed.h>
10#include <xrpl/protocol/STTx.h>
11#include <xrpl/protocol_autogen/transactions/SetFee.h>
12#include <xrpl/protocol_autogen/transactions/AccountSet.h>
13
14#include <string>
15
16namespace xrpl::transactions {
17
18// 1 & 4) Set fields via builder setters, build, then read them back via
19// wrapper getters. After build(), validate() should succeed.
20TEST(TransactionsSetFeeTests, BuilderSettersRoundTrip)
21{
22 // Generate a deterministic keypair for signing
23 auto const [publicKey, secretKey] =
25
26 // Common transaction fields
27 auto const accountValue = calcAccountID(publicKey);
28 std::uint32_t const sequenceValue = 1;
29 auto const feeValue = canonical_AMOUNT();
30
31 // Transaction-specific field values
32 auto const ledgerSequenceValue = canonical_UINT32();
33 auto const baseFeeValue = canonical_UINT64();
34 auto const referenceFeeUnitsValue = canonical_UINT32();
35 auto const reserveBaseValue = canonical_UINT32();
36 auto const reserveIncrementValue = canonical_UINT32();
37 auto const baseFeeDropsValue = canonical_AMOUNT();
38 auto const reserveBaseDropsValue = canonical_AMOUNT();
39 auto const reserveIncrementDropsValue = canonical_AMOUNT();
40 auto const gasLimitValue = canonical_UINT32();
41 auto const bytecodeSizeLimitValue = canonical_UINT32();
42 auto const gasPriceValue = canonical_UINT32();
43
44 SetFeeBuilder builder{
45 accountValue,
46 sequenceValue,
47 feeValue
48 };
49
50 // Set optional fields
51 builder.setLedgerSequence(ledgerSequenceValue);
52 builder.setBaseFee(baseFeeValue);
53 builder.setReferenceFeeUnits(referenceFeeUnitsValue);
54 builder.setReserveBase(reserveBaseValue);
55 builder.setReserveIncrement(reserveIncrementValue);
56 builder.setBaseFeeDrops(baseFeeDropsValue);
57 builder.setReserveBaseDrops(reserveBaseDropsValue);
58 builder.setReserveIncrementDrops(reserveIncrementDropsValue);
59 builder.setGasLimit(gasLimitValue);
60 builder.setBytecodeSizeLimit(bytecodeSizeLimitValue);
61 builder.setGasPrice(gasPriceValue);
62
63 auto tx = builder.build(publicKey, secretKey);
64
65 std::string reason;
66 EXPECT_TRUE(tx.validate(reason)) << reason;
67
68 // Verify signing was applied
69 EXPECT_FALSE(tx.getSigningPubKey().empty());
70 EXPECT_TRUE(tx.hasTxnSignature());
71
72 // Verify common fields
73 EXPECT_EQ(tx.getAccount(), accountValue);
74 EXPECT_EQ(tx.getSequence(), sequenceValue);
75 EXPECT_EQ(tx.getFee(), feeValue);
76
77 // Verify required fields
78 // Verify optional fields
79 {
80 auto const& expected = ledgerSequenceValue;
81 auto const actualOpt = tx.getLedgerSequence();
82 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfLedgerSequence should be present";
83 expectEqualField(expected, *actualOpt, "sfLedgerSequence");
84 EXPECT_TRUE(tx.hasLedgerSequence());
85 }
86
87 {
88 auto const& expected = baseFeeValue;
89 auto const actualOpt = tx.getBaseFee();
90 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBaseFee should be present";
91 expectEqualField(expected, *actualOpt, "sfBaseFee");
92 EXPECT_TRUE(tx.hasBaseFee());
93 }
94
95 {
96 auto const& expected = referenceFeeUnitsValue;
97 auto const actualOpt = tx.getReferenceFeeUnits();
98 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReferenceFeeUnits should be present";
99 expectEqualField(expected, *actualOpt, "sfReferenceFeeUnits");
100 EXPECT_TRUE(tx.hasReferenceFeeUnits());
101 }
102
103 {
104 auto const& expected = reserveBaseValue;
105 auto const actualOpt = tx.getReserveBase();
106 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveBase should be present";
107 expectEqualField(expected, *actualOpt, "sfReserveBase");
108 EXPECT_TRUE(tx.hasReserveBase());
109 }
110
111 {
112 auto const& expected = reserveIncrementValue;
113 auto const actualOpt = tx.getReserveIncrement();
114 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveIncrement should be present";
115 expectEqualField(expected, *actualOpt, "sfReserveIncrement");
116 EXPECT_TRUE(tx.hasReserveIncrement());
117 }
118
119 {
120 auto const& expected = baseFeeDropsValue;
121 auto const actualOpt = tx.getBaseFeeDrops();
122 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBaseFeeDrops should be present";
123 expectEqualField(expected, *actualOpt, "sfBaseFeeDrops");
124 EXPECT_TRUE(tx.hasBaseFeeDrops());
125 }
126
127 {
128 auto const& expected = reserveBaseDropsValue;
129 auto const actualOpt = tx.getReserveBaseDrops();
130 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveBaseDrops should be present";
131 expectEqualField(expected, *actualOpt, "sfReserveBaseDrops");
132 EXPECT_TRUE(tx.hasReserveBaseDrops());
133 }
134
135 {
136 auto const& expected = reserveIncrementDropsValue;
137 auto const actualOpt = tx.getReserveIncrementDrops();
138 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveIncrementDrops should be present";
139 expectEqualField(expected, *actualOpt, "sfReserveIncrementDrops");
140 EXPECT_TRUE(tx.hasReserveIncrementDrops());
141 }
142
143 {
144 auto const& expected = gasLimitValue;
145 auto const actualOpt = tx.getGasLimit();
146 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfGasLimit should be present";
147 expectEqualField(expected, *actualOpt, "sfGasLimit");
148 EXPECT_TRUE(tx.hasGasLimit());
149 }
150
151 {
152 auto const& expected = bytecodeSizeLimitValue;
153 auto const actualOpt = tx.getBytecodeSizeLimit();
154 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBytecodeSizeLimit should be present";
155 expectEqualField(expected, *actualOpt, "sfBytecodeSizeLimit");
156 EXPECT_TRUE(tx.hasBytecodeSizeLimit());
157 }
158
159 {
160 auto const& expected = gasPriceValue;
161 auto const actualOpt = tx.getGasPrice();
162 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfGasPrice should be present";
163 expectEqualField(expected, *actualOpt, "sfGasPrice");
164 EXPECT_TRUE(tx.hasGasPrice());
165 }
166
167}
168
169// 2 & 4) Start from an STTx, construct a builder from it, build a new wrapper,
170// and verify all fields match.
171TEST(TransactionsSetFeeTests, BuilderFromStTxRoundTrip)
172{
173 // Generate a deterministic keypair for signing
174 auto const [publicKey, secretKey] =
175 generateKeyPair(KeyType::Secp256k1, generateSeed("testSetFeeFromTx"));
176
177 // Common transaction fields
178 auto const accountValue = calcAccountID(publicKey);
179 std::uint32_t const sequenceValue = 2;
180 auto const feeValue = canonical_AMOUNT();
181
182 // Transaction-specific field values
183 auto const ledgerSequenceValue = canonical_UINT32();
184 auto const baseFeeValue = canonical_UINT64();
185 auto const referenceFeeUnitsValue = canonical_UINT32();
186 auto const reserveBaseValue = canonical_UINT32();
187 auto const reserveIncrementValue = canonical_UINT32();
188 auto const baseFeeDropsValue = canonical_AMOUNT();
189 auto const reserveBaseDropsValue = canonical_AMOUNT();
190 auto const reserveIncrementDropsValue = canonical_AMOUNT();
191 auto const gasLimitValue = canonical_UINT32();
192 auto const bytecodeSizeLimitValue = canonical_UINT32();
193 auto const gasPriceValue = canonical_UINT32();
194
195 // Build an initial transaction
196 SetFeeBuilder initialBuilder{
197 accountValue,
198 sequenceValue,
199 feeValue
200 };
201
202 initialBuilder.setLedgerSequence(ledgerSequenceValue);
203 initialBuilder.setBaseFee(baseFeeValue);
204 initialBuilder.setReferenceFeeUnits(referenceFeeUnitsValue);
205 initialBuilder.setReserveBase(reserveBaseValue);
206 initialBuilder.setReserveIncrement(reserveIncrementValue);
207 initialBuilder.setBaseFeeDrops(baseFeeDropsValue);
208 initialBuilder.setReserveBaseDrops(reserveBaseDropsValue);
209 initialBuilder.setReserveIncrementDrops(reserveIncrementDropsValue);
210 initialBuilder.setGasLimit(gasLimitValue);
211 initialBuilder.setBytecodeSizeLimit(bytecodeSizeLimitValue);
212 initialBuilder.setGasPrice(gasPriceValue);
213
214 auto initialTx = initialBuilder.build(publicKey, secretKey);
215
216 // Create builder from existing STTx
217 SetFeeBuilder builderFromTx{initialTx.getSTTx()};
218
219 auto rebuiltTx = builderFromTx.build(publicKey, secretKey);
220
221 std::string reason;
222 EXPECT_TRUE(rebuiltTx.validate(reason)) << reason;
223
224 // Verify common fields
225 EXPECT_EQ(rebuiltTx.getAccount(), accountValue);
226 EXPECT_EQ(rebuiltTx.getSequence(), sequenceValue);
227 EXPECT_EQ(rebuiltTx.getFee(), feeValue);
228
229 // Verify required fields
230 // Verify optional fields
231 {
232 auto const& expected = ledgerSequenceValue;
233 auto const actualOpt = rebuiltTx.getLedgerSequence();
234 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfLedgerSequence should be present";
235 expectEqualField(expected, *actualOpt, "sfLedgerSequence");
236 }
237
238 {
239 auto const& expected = baseFeeValue;
240 auto const actualOpt = rebuiltTx.getBaseFee();
241 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBaseFee should be present";
242 expectEqualField(expected, *actualOpt, "sfBaseFee");
243 }
244
245 {
246 auto const& expected = referenceFeeUnitsValue;
247 auto const actualOpt = rebuiltTx.getReferenceFeeUnits();
248 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReferenceFeeUnits should be present";
249 expectEqualField(expected, *actualOpt, "sfReferenceFeeUnits");
250 }
251
252 {
253 auto const& expected = reserveBaseValue;
254 auto const actualOpt = rebuiltTx.getReserveBase();
255 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveBase should be present";
256 expectEqualField(expected, *actualOpt, "sfReserveBase");
257 }
258
259 {
260 auto const& expected = reserveIncrementValue;
261 auto const actualOpt = rebuiltTx.getReserveIncrement();
262 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveIncrement should be present";
263 expectEqualField(expected, *actualOpt, "sfReserveIncrement");
264 }
265
266 {
267 auto const& expected = baseFeeDropsValue;
268 auto const actualOpt = rebuiltTx.getBaseFeeDrops();
269 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBaseFeeDrops should be present";
270 expectEqualField(expected, *actualOpt, "sfBaseFeeDrops");
271 }
272
273 {
274 auto const& expected = reserveBaseDropsValue;
275 auto const actualOpt = rebuiltTx.getReserveBaseDrops();
276 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveBaseDrops should be present";
277 expectEqualField(expected, *actualOpt, "sfReserveBaseDrops");
278 }
279
280 {
281 auto const& expected = reserveIncrementDropsValue;
282 auto const actualOpt = rebuiltTx.getReserveIncrementDrops();
283 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfReserveIncrementDrops should be present";
284 expectEqualField(expected, *actualOpt, "sfReserveIncrementDrops");
285 }
286
287 {
288 auto const& expected = gasLimitValue;
289 auto const actualOpt = rebuiltTx.getGasLimit();
290 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfGasLimit should be present";
291 expectEqualField(expected, *actualOpt, "sfGasLimit");
292 }
293
294 {
295 auto const& expected = bytecodeSizeLimitValue;
296 auto const actualOpt = rebuiltTx.getBytecodeSizeLimit();
297 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfBytecodeSizeLimit should be present";
298 expectEqualField(expected, *actualOpt, "sfBytecodeSizeLimit");
299 }
300
301 {
302 auto const& expected = gasPriceValue;
303 auto const actualOpt = rebuiltTx.getGasPrice();
304 ASSERT_TRUE(actualOpt.has_value()) << "Optional field sfGasPrice should be present";
305 expectEqualField(expected, *actualOpt, "sfGasPrice");
306 }
307
308}
309
310// 3) Verify wrapper throws when constructed from wrong transaction type.
311TEST(TransactionsSetFeeTests, WrapperThrowsOnWrongTxType)
312{
313 // Build a valid transaction of a different type
314 auto const [pk, sk] =
316 auto const account = calcAccountID(pk);
317
318 AccountSetBuilder wrongBuilder{account, 1, canonical_AMOUNT()};
319 auto wrongTx = wrongBuilder.build(pk, sk);
320
321 EXPECT_THROW(SetFee{wrongTx.getSTTx()}, std::runtime_error);
322}
323
324// 4) Verify builder throws when constructed from wrong transaction type.
325TEST(TransactionsSetFeeTests, BuilderThrowsOnWrongTxType)
326{
327 // Build a valid transaction of a different type
328 auto const [pk, sk] =
329 generateKeyPair(KeyType::Secp256k1, generateSeed("testWrongTypeBuilder"));
330 auto const account = calcAccountID(pk);
331
332 AccountSetBuilder wrongBuilder{account, 1, canonical_AMOUNT()};
333 auto wrongTx = wrongBuilder.build(pk, sk);
334
335 EXPECT_THROW(SetFeeBuilder{wrongTx.getSTTx()}, std::runtime_error);
336}
337
338// 5) Build with only required fields and verify optional fields return nullopt.
339TEST(TransactionsSetFeeTests, OptionalFieldsReturnNullopt)
340{
341 // Generate a deterministic keypair for signing
342 auto const [publicKey, secretKey] =
343 generateKeyPair(KeyType::Secp256k1, generateSeed("testSetFeeNullopt"));
344
345 // Common transaction fields
346 auto const accountValue = calcAccountID(publicKey);
347 std::uint32_t const sequenceValue = 3;
348 auto const feeValue = canonical_AMOUNT();
349
350 // Transaction-specific required field values
351
352 SetFeeBuilder builder{
353 accountValue,
354 sequenceValue,
355 feeValue
356 };
357
358 // Do NOT set optional fields
359
360 auto tx = builder.build(publicKey, secretKey);
361
362 // Verify optional fields are not present
363 EXPECT_FALSE(tx.hasLedgerSequence());
364 EXPECT_FALSE(tx.getLedgerSequence().has_value());
365 EXPECT_FALSE(tx.hasBaseFee());
366 EXPECT_FALSE(tx.getBaseFee().has_value());
367 EXPECT_FALSE(tx.hasReferenceFeeUnits());
368 EXPECT_FALSE(tx.getReferenceFeeUnits().has_value());
369 EXPECT_FALSE(tx.hasReserveBase());
370 EXPECT_FALSE(tx.getReserveBase().has_value());
371 EXPECT_FALSE(tx.hasReserveIncrement());
372 EXPECT_FALSE(tx.getReserveIncrement().has_value());
373 EXPECT_FALSE(tx.hasBaseFeeDrops());
374 EXPECT_FALSE(tx.getBaseFeeDrops().has_value());
375 EXPECT_FALSE(tx.hasReserveBaseDrops());
376 EXPECT_FALSE(tx.getReserveBaseDrops().has_value());
377 EXPECT_FALSE(tx.hasReserveIncrementDrops());
378 EXPECT_FALSE(tx.getReserveIncrementDrops().has_value());
379 EXPECT_FALSE(tx.hasGasLimit());
380 EXPECT_FALSE(tx.getGasLimit().has_value());
381 EXPECT_FALSE(tx.hasBytecodeSizeLimit());
382 EXPECT_FALSE(tx.getBytecodeSizeLimit().has_value());
383 EXPECT_FALSE(tx.hasGasPrice());
384 EXPECT_FALSE(tx.getGasPrice().has_value());
385}
386
387}
AccountSet build(PublicKey const &publicKey, SecretKey const &secretKey)
Build and return the AccountSet wrapper.
Builder for SetFee transactions.
Definition SetFee.h:345
SetFeeBuilder & setReserveIncrementDrops(std::decay_t< typename SF_AMOUNT::type::value_type > const &value)
Set sfReserveIncrementDrops (SoeOptional).
Definition SetFee.h:461
SetFeeBuilder & setBaseFeeDrops(std::decay_t< typename SF_AMOUNT::type::value_type > const &value)
Set sfBaseFeeDrops (SoeOptional).
Definition SetFee.h:439
SetFeeBuilder & setReserveIncrement(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfReserveIncrement (SoeOptional).
Definition SetFee.h:428
SetFeeBuilder & setReserveBaseDrops(std::decay_t< typename SF_AMOUNT::type::value_type > const &value)
Set sfReserveBaseDrops (SoeOptional).
Definition SetFee.h:450
SetFeeBuilder & setReserveBase(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfReserveBase (SoeOptional).
Definition SetFee.h:417
SetFeeBuilder & setLedgerSequence(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Transaction-specific field setters.
Definition SetFee.h:384
SetFeeBuilder & setGasPrice(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfGasPrice (SoeOptional).
Definition SetFee.h:494
SetFeeBuilder & setGasLimit(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfGasLimit (SoeOptional).
Definition SetFee.h:472
SetFeeBuilder & setReferenceFeeUnits(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfReferenceFeeUnits (SoeOptional).
Definition SetFee.h:406
SetFeeBuilder & setBytecodeSizeLimit(std::decay_t< typename SF_UINT32::type::value_type > const &value)
Set sfBytecodeSizeLimit (SoeOptional).
Definition SetFee.h:483
SetFee build(PublicKey const &publicKey, SecretKey const &secretKey)
Build and return the SetFee wrapper.
Definition SetFee.h:507
SetFeeBuilder & setBaseFee(std::decay_t< typename SF_UINT64::type::value_type > const &value)
Set sfBaseFee (SoeOptional).
Definition SetFee.h:395
Transaction: SetFee.
Definition SetFee.h:30
TEST(TransactionsAccountDeleteTests, BuilderSettersRoundTrip)
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition Seed.cpp:58
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
AccountID calcAccountID(PublicKey const &pk)
void expectEqualField(T const &expected, T const &actual, char const *fieldName)