Repo context. accensa-contracts holds the on-chain half of Accensa: ReceiptAnchor
(Merkle batch anchoring so an agent can verify it was charged correctly without trusting
the seller's API) and RefundVault (policy-bounded refunds without the merchant becoming
a custodian). Both are deployed on testnet. soroban-sdk 27.0.4, MIT. Read README.md,
docs/SECURITY_MODEL.md and DEPLOYMENTS.md before starting.
Problem
refund-vault has contracts/refund-vault/tests/integration_test.rs — a real tests/
directory, compiled as a separate crate against the public API. receipt-anchor has no tests/
directory at all. Its coverage is entirely src/test.rs and src/fuzz_test.rs, both declared as
private modules inside the crate.
The difference matters more than it looks. An in-crate test can reach private items and
pub(crate) internals, so it can pass while the public contract interface — the one a client
actually calls through ReceiptAnchorClient — is broken or awkward. An integration test can only
use what a real integrator can use, which is the whole point of having one.
Concretely, there is no test that exercises ReceiptAnchor the way accensa-app's indexer does:
register the contract, anchor several batches, read them back through the generated client, and
verify a receipt against a root produced outside the contract.
What to do
- Create
contracts/receipt-anchor/tests/integration_test.rs.
- Drive the contract exclusively through the generated
ReceiptAnchorClient — no use of
private items from the crate.
- Cover at minimum: initialize then anchor a batch and read it back; anchor several batches and
check get_batch_count; verify a receipt against a root computed in the test rather than by
the contract; the BatchNotFound path; and a prune_batches round trip.
- Reuse the shared vectors in
src/vectors.rs if that is convenient, but note they are currently
wired in via #[path] from src/test.rs — an integration crate may need its own include.
Acceptance criteria
contracts/receipt-anchor/tests/integration_test.rs exists and passes.
- Nothing in it touches a private item.
- It fails if
verify_receipt starts returning the wrong answer for a known-good proof.
cargo test in CI runs it without extra flags.
Problem
refund-vaulthascontracts/refund-vault/tests/integration_test.rs— a realtests/directory, compiled as a separate crate against the public API.
receipt-anchorhas notests/directory at all. Its coverage is entirely
src/test.rsandsrc/fuzz_test.rs, both declared asprivate modules inside the crate.
The difference matters more than it looks. An in-crate test can reach private items and
pub(crate)internals, so it can pass while the public contract interface — the one a clientactually calls through
ReceiptAnchorClient— is broken or awkward. An integration test can onlyuse what a real integrator can use, which is the whole point of having one.
Concretely, there is no test that exercises
ReceiptAnchorthe wayaccensa-app's indexer does:register the contract, anchor several batches, read them back through the generated client, and
verify a receipt against a root produced outside the contract.
What to do
contracts/receipt-anchor/tests/integration_test.rs.ReceiptAnchorClient— nouseofprivate items from the crate.
check
get_batch_count; verify a receipt against a root computed in the test rather than bythe contract; the
BatchNotFoundpath; and aprune_batchesround trip.src/vectors.rsif that is convenient, but note they are currentlywired in via
#[path]fromsrc/test.rs— an integration crate may need its own include.Acceptance criteria
contracts/receipt-anchor/tests/integration_test.rsexists and passes.verify_receiptstarts returning the wrong answer for a known-good proof.cargo testin CI runs it without extra flags.