Smart Contract Testing and Acceptance: What to Verify Before an Audit
Link each smart contract requirement to an expected result, evidence and reviewer. The escrow matrix covers permissions, terminal states, expiry, pause behavior, transfer failure and unpaid obligations.
Key takeaways 4
- Pending acceptance evidence is not a passed requirement
- Coverage does not establish correctness for all inputs
- Dependency state and test assumptions belong in the evidence package
- Fixes need results against the changed source revision
A passing test suite is useful evidence only when the tests check the agreed behavior. A contract can pass every test written for it while an important requirement has no test at all.
Start acceptance with a requirement/evidence matrix tied to one release candidate. For each rule, record the scenario, expected result, evidence location and reviewer. The filled escrow example below is a proposed test plan. No tests have been executed for this example and every result remains pending.
A requirement matrix the buyer can review
Assume one approved ERC-20 asset and escrow agreements with active, disputed and terminal states. In this example, only the payer can authorize an ordinary release. Anyone can trigger the payer's refund for an undisputed agreement at or after its expiry. A resolver can settle a dispute but cannot redirect an undisputed agreement. Funding and ordinary release stop during a pause. Eligible refunds and dispute resolution remain available.
These are fictional product rules chosen to make the matrix concrete. They are not a recommendation for every escrow system. Define deadlines, authorized recipients and dispute behavior before turning them into tests.
| ID and requirement | Scenario or property | Expected result | Evidence to retain | Review owner |
|---|---|---|---|---|
| ESC-01: authorized release | Payer and unrelated caller each request release on an active agreement before expiry | Payer can pay the agreed payee; unrelated caller cannot change funds or state | Positive and negative test results, balances and resulting state | Engineering reviewer |
| ESC-02: terminal state | Request payment again after a completed release or refund | No second payout and no second terminal transition | Regression test and state/balance assertions | Engineering reviewer |
| ESC-03: expiry boundary | Refund and release immediately before, exactly at and after expiry | Undisputed refund becomes available at expiry; ordinary release is unavailable from expiry | Boundary-case results using the specified timestamps | Product owner and reviewer |
| ESC-04: dispute authority | Resolver acts on disputed and undisputed agreements; another caller attempts settlement | Only the resolver can settle a disputed agreement to an allowed recipient | Role tests and permitted-recipient assertions | Security reviewer |
| ESC-05: pause policy | Attempt funding, release, eligible refund and disputed settlement while paused | Each operation follows the explicitly agreed pause policy | Operation-by-state matrix and results | Product owner |
| ESC-06: transfer failure | Approved-asset interaction fails in an exercised payout path | No successful settlement is recorded without its required transfer; liabilities remain consistent | Failure-case fixture and post-call assertions | Engineering reviewer |
| ESC-07: solvency | Generate admitted sequences of funding and settlement operations | Asset balance covers recorded unpaid obligations after each completed operation | Invariant definition, campaign configuration and failing inputs if any | Security reviewer |
| ESC-08: integration accounting | Execute a complete agreement through the supported application path | Displayed status and indexed events match the contract outcome | Transaction references and application reconciliation record | Integration owner |
ESC-06 needs to cover the failure forms admitted by the asset integration. ERC-20 requires callers to handle a false transfer result; assuming every unsuccessful token interaction reverts can leave a test plan incomplete. Support for other token behavior belongs in the asset specification, not in an unbounded claim to accept all ERC-20 tokens.
Attach actual result locations and statuses when testing the real candidate. The table records intended checks; a row whose evidence is pending has not passed acceptance.
Choose test methods for the rule being checked
Ethereum's testing documentation distinguishes unit, integration and property-based approaches. It also explains why code coverage and passing tests cannot guarantee that every input behaves correctly.
Use focused tests for a specific transition or permission check. Exercise components together when a payout depends on another contract or application. Generated inputs and operation sequences help explore arithmetic and state combinations, provided the campaign's allowed actions and assumptions are defined.
For ESC-07, write the unpaid-obligation calculation precisely. Include disputed obligations until they are validly settled. An asset balance greater than liabilities need not be an error: unsolicited token transfers can add assets without creating an agreement. An equality check would reject that situation even if no obligation was lost. This is a limitation of the proposed example, not a universal invariant for vaults, lending or fee-bearing products.
Keep the method linked to the requirement. A report listing a large number of fuzz runs says little about whether the generator ever opens disputes or exercises the expiry boundary. Ask which actors can call which operations and whether the model includes every relevant state.
External state must be reproducible
If a test depends on deployed contracts, record the network, block reference, external addresses and data assumptions. A fork-based test examines a selected state. It does not promise that a dependency will retain that behavior indefinitely, so identify what must be checked again near release.
An oracle-dependent product needs cases for its agreed freshness and failure rules. A cross-chain product needs a model of message delivery and replay behavior. Those cases are outside the escrow example, so its matrix should not be reused unchanged for either product.
Test the supported application path separately from contract permissions. A frontend can prevent a user from clicking release while the contract still permits a direct transaction. ESC-01 must check the contract rule without depending on the interface to enforce it.
Retain a release-specific evidence package
Package results so a receiving engineer can reproduce them without guessing which source revision or environment produced them.
| Artifact | Minimum content | What it lets the reviewer check |
|---|---|---|
| Candidate identity | Commit, dependency lockfiles, compiler and build configuration | Results refer to a defined input set |
| Requirement register | IDs, agreed behavior, owner and limitations | Business rules map to technical checks |
| Execution record | Commands, environment requirements, outcomes and campaign configuration | Another engineer can rerun the checks |
| Dependency record | External addresses, selected state and mocks with their assumptions | The tested environment is understood |
| Findings register | Issue, severity rationale, status, fix revision and rerun evidence | Unresolved items remain visible |
| Acceptance decision | Named approver, candidate version and accepted limitations | The decision applies to the reviewed scope |
Keep credentials out of shared logs and examples. Document how an authorized engineer obtains required access. Removing a secret should not remove the non-sensitive inputs needed to reproduce the run.
Reject a candidate when the evidence misses the requirement
Suppose all unit tests pass and the coverage report is high. The suite checks expiry before and after the deadline, but never exactly at it. The product specification says a refund becomes available at expiry. The implementation uses a strictly later comparison. The report cannot resolve that mismatch because the decisive input was never tested.
The acceptance action is to add the boundary case, correct whichever side conflicts with the approved product rule and rerun affected tests on the new revision. A green report from the old revision cannot accept the change. Keep the finding and its resolution linked to ESC-03.
An intentionally excluded behavior should receive an explicit limitation instead of a passing status. If the design supports only the approved settlement asset, accepting the project does not establish compatibility with a different token a user later supplies.
Handoff to independent review and deployment
Before independent review, agree the candidate version, audit scope and unresolved findings. Provide architecture and privileged-role documentation alongside test results. The smart contract audit overview covers the broader review context. A security audit engagement needs its own scope and reviewer, including an explicit independence boundary where the development provider is also involved in review.
Development acceptance and an independent audit answer different questions. Acceptance checks the agreed delivery. Review can uncover issues outside the current tests. New fixes need tests and a defined review path. Formal verification, if commissioned, also depends on the model and properties being proved.
For implementation, test design or agreed remediation, use Pharos smart contract development with the requirement matrix attached. Once the candidate is accepted for release, carry its identity and limitations into the deployment runbook. The release approver should see the exact revision, any unresolved finding and the evidence attached to each acceptance condition.
I work with startup founders who need a dedicated software development team but don’t want to gamble on hiring, random outsourcing, or opaque delivery.
Most founders face the same problem sooner or later.
Early technical and team decisions lock the product into tech debt, slow delivery, missed milestones and constant re-hiring. By the time this becomes visible, fixing it is already expensive.As a CTO and software architect, I help founders design, build and run dedicated development teams that work as a true extension of the startup. Not as a black-box vendor.
My focus is on complex products where mistakes are costly:
- Web3 and blockchain platforms
- FinTech and regulated products
- High-load startup systems
- MVP → scale transitions
We don’t do body-shopping.
We don’t sell generic outsourcing.Instead, we help founders:
- build the right team structure from day one
- keep technical ownership and transparency
- scale delivery without losing control
- avoid vendor lock-in and hidden risks
Teams are aligned with the product roadmap, business goals and long-term architecture. Not just short-term velocity.