# M12 Token Payment Contract — practical lab

## Bài toán
Emit indexed payment events and reject duplicate order identifiers; no private key custody in the backend.

## Vấn đề
Real crypto payments cross trust and transaction boundaries: chain RPC, EVM contracts, backend database, asynchronous events, and end-user balances.

## Giải pháp
Implement a small deterministic offline invariant first, then extend it to real PostgreSQL, Kafka and BSC Testnet in the capstone integration blueprint.

## Lý thuyết
- A blockchain transaction receipt is not identical to irreversible settlement.
- Use `(chain_id, tx_hash, log_index)` as an event identity, and verify contract address, event signature, token, recipient and amount.
- Track provisional versus finalized events and handle reorganization rollback.
- Never put private keys in git or environment examples with real values.

## Lab từng bước
1. Inspect `solution/ContractModelLab.java` and identify the invariant.
2. Run `cd solution && bash test.sh` (JDK 21 or compatible JDK required).
3. Change the failure case; verify assertions detect the regression.
4. Reimplement the flow in `starter/`.
5. Read `capstone/README.md` for real-service integration requirements.

## Expected output
See `expected-output.md`. PASS verifies **only** the offline scenario, not end-to-end integration.

## Exercises
Add tests for fee-on-transfer tokens; never assume received amount equals requested amount.

## Interview
- What is the trust boundary here?
- What if RPC returns success but the DB commit fails?
- What happens during a reorg?
- What can be retried safely and how do you enforce idempotency?
