Contracts / Testing

Testing an On-Chain Task/Reward Orchestrator with Foundry

ProofOrchestrator.sol moves money once a proof is attested. Eight tests, each named for the specific thing it refuses to let happen.

2026-09-01 · contracts/test/ProofOrchestrator.t.sol

The naming convention is deliberate: every test name states the specific guarantee, not just the function under test, so a failing test in CI output already tells you what broke without opening the file.

Test What it refuses to let happen
test_submitProof_
alwaysRevertsWithoutARealVerifier
Payment without a real verifier configured — the default state is "pays nothing," not "pays on faith."
test_paysOutOnlyAfterAttestationA prover collecting a reward before the attester has actually attested.
test_rejectsProofBytesThat
DontMatchTheAttestation
Submitting different proof bytes than the ones the attester actually attested to.
test_onlyAttesterCanAttestAnyone other than the configured attester address calling attest().
test_cannotDoubleFulfillClaiming the same reward twice for one task.
test_onlyTheClaimingProver
CanSubmit
A different address than the one that claimed the task submitting a proof for it.
test_cannotClaimAnAlready
ClaimedTask
Two provers racing to claim the same task and both succeeding.
test_cannotClaimOrSubmit
ForAnUnknownTask
Referencing a task ID that was never created.

Notice what's not in this list: nothing here tests that the STARK proof itself is valid, because the contract can't check that — see the trust-boundary post for why. These eight tests cover the access-control and state-machine surface of "who can trigger a payment, and when" — the part that is the contract's job — not the cryptography, which is zkvm-stark's job and is tested separately in Rust.

contracts/lib/forge-std is a git submodule, which is why CI checks it out with submodules: true before running forge test -vv — an easy step to forget when copying this CI job elsewhere, since a missing submodule fails with a confusing "file not found" rather than an obvious submodule error.
Related: why the verifier contract is named AttestedVerifier, and how these tests run in CI.