Skip to main content
Building a conformance kit means reading a lot of real ledger data closely. These are the things that surprised us, each with the evidence behind it. Several became rules in the hardening guide.

About the ledger

On the fee-bump fixture, the fee-processing changes debit 46,340 stroops, but FeeCharged is 40,354. The difference is the Soroban refund, which settles after apply, later in the transaction’s meta. Anyone computing fees from balance deltas in fee processing alone over-reports by about 15% on this transaction. → Fees
The same testnet transaction’s meta differed between one node’s getTransaction and another’s getLedgers in a single value: a diagnostic invoke_time_nsecs (188,866 vs 126,592 ns). Whole testnet ledgers re-fetched hours later from the same endpoint hashed differently. Mainnet data-lake objects never did. → Consensus data only
A trustline created with the SAC’s trust() has no classic operation and no event. Its only record is a CREATED entry in the operation’s changes. An indexer keyed on operation types drops it silently. → SAC trustlines
Of 866 golden files at core v30.0.0, none contains an ed25519 signed-payload signer. The corpus covers it on testnet and on a generated network. → stellar-core goldens

About the tools

JavaScript, Go and Rust pass all 54 fixture checks and round-trip all 15,306 golden frames byte for byte. The risk isn’t in the SDKs’ decoding. It’s in what applications do with the values next. → SDK runners
SDF’s wallet-backend indexes all six fixtures correctly. The linter found one latent issue, an unvalidated memo helper that nothing calls yet. → wallet-backend pilot
A bare /manualclose can abort core on a timer assertion; the HTTP query server matches header names case-sensitively and closes every connection; the first Soroban settings upgrade is larger than the starting limit it’s stored under. All have workarounds. → Generating

About our own code

The first pilot driver passed wallet-backend’s JSON through JSON.parse and reported muxed IDs off by a few hundred. wallet-backend was right; our driver was rounding. Every 64-bit integer the kit emits is now a string. → 64-bit integers
The first IX003 flagged every Envelope.SourceAccount() call and produced two false positives in wallet-backend, both correct operation-source fallbacks. It now fires only in fee logic. → IX003