← Back to Transactors: Understanding the Lifecycle of a Transaction
Add a custom preflight or preclaim check to an existing transactor and verify it works correctly with unit tests.
For this exercise, you'll add a new validation rule to the CheckCreate transactor. The goal is to understand how validation logic is added and tested.
Imagine a new business rule: Checks cannot be created for amounts less than 1 XRP (1,000,000 drops).
This is a hypothetical requirement for learning purposes—it doesn't exist in the actual protocol.
Part 1: Identify Where to Add the Check
Open src/xrpld/app/tx/detail/CreateCheck.cpp
Determine whether this validation belongs in:
preflight() - stateless validation
preclaim() - ledger-state validation
Question: Which phase is appropriate and why?
Part 2: Implement the Validation
Add the following check to the appropriate phase:
Questions to consider:
Should this apply to non-XRP amounts?
What result code is most appropriate?
Should this be amendment-gated?
Part 3: Write a Unit Test
Create a test in src/test/app/Check_test.cpp (or a new test file):
Part 4: Compile and Run Tests
Verify your new test passes.
Part 5: Edge Cases
Add tests for edge cases:
Exactly 1 XRP: Should this succeed or fail?
Non-XRP amounts: Should the minimum apply?
Negative amounts: How is this handled? (Already validated elsewhere?)
Modified code: The validation check you added
Test code: Unit tests for the new validation
Test output: Results showing tests pass
Analysis document answering:
Why you chose preflight vs preclaim
Why you chose a particular result code
What edge cases you considered
Discussion Questions
If this were a real feature, should it be amendment-gated? Why?
What would happen if you returned tecBAD_AMOUNT instead of temBAD_AMOUNT?
Could this check ever pass in preflight but fail in doApply? Under what circumstances?
How would you test this check in a live (non-standalone) environment?
Bonus Challenge
Make the minimum amount configurable:
Only enforce the minimum when the amendment is enabled
Write tests for both enabled and disabled states
Important: After completing this exercise, revert your changes to avoid affecting the actual codebase: