- OrderForge is an original educational/reference protocol built to turn ABI encoding, hashing, signed-data, order, position, and invariant-testing concepts into one coherent engineering system rather than a collection of isolated Solidity examples.
- The repository is intentionally narrow: there is no protocol token, fee model, upgradeability, owner, privileged withdrawal path, or mainnet deployment claim.
- Version v1.0.0 was released only after the final hardening pass, green CI, adversarial regression coverage, stateful invariants, documented static-analysis policy, and repository protection were in place.
Protocol engineering · v1.0.0
OrderForge
A non-custodial EIP-712 signed limit-order settlement protocol with partial fills, ERC-1271 smart-wallet signatures, replay protection, and stateful Foundry invariants.
Verified engineering baseline
Proof at a glance
- Release
- v1.0.0
- Test suite
- 44 Forge tests: 35 unit, 4 fuzz, 5 invariants
- Property testing
- 4,096 fuzz runs per property
- Stateful testing
- 65,536 calls per invariant
- Coverage
- 100% production-contract lines, statements, branches, and functions
- Static analysis
- Slither: 0 results after documented narrow exclusions
Educational/reference protocol. OrderForge v1.0.0 has not undergone a professional smart-contract security audit and is not presented for real-funds use.
Overview
Signed-order protocol engineering where cryptographic intent, lifecycle state, settlement math, and adversarial testing all have to agree.
A non-custodial EIP-712 signed limit-order settlement protocol with partial fills, ERC-1271 smart-wallet signatures, replay protection, and stateful Foundry invariants.
The point is not feature count. OrderForge concentrates on one security-sensitive boundary—turning an off-chain maker signature into repeatable on-chain settlement—and makes the cryptography, lifecycle state, arithmetic, testing properties, and known assumptions inspectable together.
The protocol problem
Off-chain signed orders look simple until they are partially filled on-chain. The protocol must prove exactly what the maker authorized, prevent replay across contracts and chains, support both EOAs and smart-contract wallets, and keep cancellation and nonce state coherent across repeated fills.
Partial fills create a second class of risk: naive per-fill rounding can leak value or prevent exact completion. Token-transfer failures must also roll back lifecycle state atomically, otherwise an apparently failed settlement can corrupt the order's remaining capacity.
- Settlement must remain non-custodial: successful fills transfer payment directly from taker to maker and sold assets directly from maker to taker.
- Signed data must be unambiguous and domain-separated; unsafe packed encoding cannot define maker authorization.
- A maker nonce must not silently authorize two different live order lifecycles once partial execution begins.
- Accepted partial fills must never transfer sell tokens for zero economic payment and a completed order must settle to the exact signed buy amount.
- The reference implementation targets standard ERC-20 behaviour. Fee-on-transfer, rebasing, and intentionally malicious token semantics are explicitly unsupported rather than hidden behind optimistic claims.
My role and contribution
Smart Contract & Protocol Engineer
- Defined an EIP-712 Order type and domain that bind signatures to the chain ID and verifying contract.
- Used OpenZeppelin SignatureChecker so the same settlement path supports EOA signatures and ERC-1271 smart-contract wallets.
- Implemented first-fill nonce binding, explicit nonce invalidation, per-order maker cancellation, expiry, and optional allowed-taker restrictions.
- Implemented cumulative floor settlement math: each fill pays the difference between cumulative quoted payment before and after the new fill, so full completion reaches the exact signed buy amount without independent-rounding drift.
- Rejected partial fills below the buy token's economic resolution rather than allowing a taker to receive sell tokens for zero payment.
- Updated fill state before external token calls and used SafeERC20 plus ReentrancyGuard so token failures revert the complete transaction and restore lifecycle state atomically.
- Kept the settlement contract free of owner, admin, protocol-fee, custody, upgrade, and governance surfaces that were not required by the protocol model.
- Built separate ABI and identifier helpers to demonstrate abi.encode, abi.decode, abi.encodeCall, carefully-scoped abi.encodePacked, keccak256, and the collision risk of packed dynamic values.
- Added deterministic unit tests, high-run fuzz properties, a stateful handler with ghost accounting, Slither, coverage, build-size checks, and protected GitHub quality gates.
Architecture and trust boundaries
A maker signs a typed EIP-712 Order off-chain and distributes it without publishing protocol state. A taker submits the signed order and a sell-side fill amount to OrderForge. The contract validates the order structure, taker restriction, expiry, cancellation and nonce state, verifies the EOA or ERC-1271 signature, binds the maker nonce to the first executed order hash, and computes the incremental buy payment from cumulative fill state. It records the new fill before external calls, then settles ERC-20s directly between taker and maker. No settlement balance is intended to remain in OrderForge. Unit, fuzz, invariant, coverage, lint, size, and Slither gates verify the implementation and its documented assumptions.
- Typed EIP-712 Order
- Maker signature
- Chain-ID domain separation
- Verifying-contract binding
- EOA + ERC-1271 SignatureChecker
- Per-order cancellation
- Nonce binding and invalidation
- Expiry enforcement
- Cumulative floor accounting
- Partial and full fills
- SafeERC20 transfers
- Checks-effects-interactions
- 35 deterministic unit tests
- 4 fuzz properties × 4,096 runs
- 5 stateful invariants × 65,536 calls
- 100% production-contract coverage
Partial-fill correctness
Make cumulative settlement exact, not each fill independently
A partial-fill protocol cannot safely treat every fill as an isolated fraction and then round it independently. Rounding error accumulates. OrderForge instead derives the amount owed by comparing the cumulative quoted payment before and after the new fill.
buyBefore = floor(filledBefore × buyAmount / sellAmount)
buyAfter = floor(filledAfter × buyAmount / sellAmount)
buyFill = buyAfter - buyBeforeCumulative payment never exceeds the maker's signed buy amount, and a complete fill reaches that amount exactly.
If a proposed partial fill would produce zero incremental buy payment at token precision, it is rejected instead of transferring sell tokens for free.
Key protocol design decisions
- Context
- A maker signature is the protocol's primary authorization boundary. Ambiguous packed encoding or an unscoped digest can make two different messages indistinguishable or replayable in another domain.
- Choice
- Hash the structured Order with abi.encode and EIP-712, binding the final digest to both chain ID and the OrderForge verifying contract.
- Tradeoff
- Typed data is more verbose than a raw packed hash, but the authorization model becomes explicit, inspectable, wallet-friendly, and resistant to cross-domain replay.
- Context
- A maker can legitimately sign multiple candidate orders off-chain, but once one order using a nonce begins execution, another differently signed order with the same nonce must not become a second live lifecycle.
- Choice
- Bind maker + nonce to the first order hash that successfully fills, while preserving separate maker-controlled nonce invalidation.
- Tradeoff
- This deliberately limits nonce reuse after execution begins, trading some off-chain flexibility for a much clearer replay and cancellation model.
- Context
- Independent per-fill multiplication and rounding can accumulate error. Early ceil rounding can overcharge one filler, while small floor-rounded fills can otherwise settle for zero payment.
- Choice
- Compute buy payment as floor(new cumulative fill × price) minus floor(previous cumulative fill × price), and reject any accepted fill whose incremental payment is zero.
- Tradeoff
- Some very small fills are intentionally unfillable, but every accepted fill has non-zero economic payment and full completion settles exactly to the signed buy amount.
- Context
- The order contract does not need to warehouse user funds to exchange one approved ERC-20 for another.
- Choice
- Transfer buy token from taker to maker and sell token from maker to taker inside the same atomic fill transaction.
- Tradeoff
- Users must maintain balances and allowances at execution time, while the protocol avoids a custody balance, treasury, withdrawal path, and the additional trust surface those features would create.
Security model and explicit limitations
- EIP-712 signatures are bound to chain ID and verifying contract; mutated order data, another OrderForge instance, or another chain produces a different authorization digest.
- SignatureChecker supports both ordinary ECDSA accounts and ERC-1271 smart-contract wallets without separate privileged execution paths.
- Nonce binding, nonce invalidation, per-order cancellation, expiry, allowed-taker checks, fill bounds, and terminal order states constrain replay and lifecycle abuse.
- SafeERC20, state-before-transfer ordering, and ReentrancyGuard keep failed token operations atomic and block reentrant settlement paths.
- The contract exposes no owner, upgradeability, protocol fee, governance, rescue withdrawal, or administrative settlement override.
- Fee-on-transfer, rebasing, and intentionally malicious ERC-20 implementations are documented as unsupported rather than presented as safely handled.
- Foundry's block.timestamp lint warning is retained and documented because timestamp is used only at the maker-signed expiry boundary; it cannot alter tokens, price, recipient, or fill limits.
- OrderForge is educational/reference software. Automated testing and static analysis are not a professional security audit, and the protocol should not be used with meaningful funds without independent review.
Adversarial verification
Testing the properties, not just the happy path
- Thirty-five deterministic unit tests cover full and partial fills, restricted takers, expiry, malformed and mutated signatures, cross-contract and cross-chain domain separation, ERC-1271 acceptance and rejection, cancellation, nonce invalidation and binding, invalid order fields, ABI round-trips, typed calldata, packed-hash collision evidence, and token-failure rollback.
- Four Foundry fuzz properties run 4,096 cases each across partial-fill accounting, exact two-part settlement, ABI round-trip preservation, and market-ID symmetry.
- Five stateful invariants run 512 campaigns at depth 128: 65,536 handler calls per invariant with fill, cancel, and invalidateNonce sequences plus post-terminal fill attempts.
- The invariant suite checks no overfill, protocol/ghost accounting agreement, token conservation, zero intended protocol custody, exact cumulative pricing at completion, and permanent blocking after cancellation, invalidation, or completion.
- CI reports 100% line, statement, branch, and function coverage across every production contract under src/. Repository-wide coverage is lower because deployment and test helper code is included honestly in the aggregate.
- Slither 0.11.6 analyzes production contracts with 100 active detectors and reports zero results after two narrow, documented exclusions for intentional arbitrary ERC-20 settlement and signed-expiry timestamp use.
- GitHub Actions pins the toolchain, runs formatting, linting, build-size checks, the complete test suite, coverage, and Slither, while the main branch requires both Foundry and Slither status checks before merge.
Mutated and malformed signatures, cross-chain replay, wrong ERC-1271 signer, false-returning ERC-20 transfers, overfill attempts, conflicting orders sharing a nonce, zero-resolution partial fills, and fill attempts after cancellation, invalidation, or completion.
Release result and public proof
- Released OrderForge v1.0.0 as a public, reviewable protocol-engineering reference rather than a folder of isolated course examples.
- The final CI baseline passes 44 Forge tests with 4,096-run fuzzing, 65,536-call stateful invariants, full production-contract coverage, and zero Slither results after documented exclusions.
- The public repository includes architecture, ABI and hashing, testing, static-analysis, threat-model, learning-evidence, security, and contribution documentation.
- Repository metadata, topics, dependency update policy, squash-oriented maintenance, automatic branch cleanup, and an active main-branch ruleset make the engineering process visible as well as the Solidity code.
- The protocol contract remains deliberately small in scope: signed intent verification, order lifecycle, exact partial-fill accounting, and direct settlement are the product; unrelated DeFi features were intentionally not added.
Before
ABI encoding, hashing, order, position, and invariant-testing concepts demonstrated mostly as isolated educational examples.
After
A cohesive v1.0.0 signed-order protocol where cryptographic authorization, replay protection, partial-fill mathematics, atomic settlement, adversarial testing, static analysis, CI, and documentation reinforce one another.
Tradeoffs, learning, and next steps
Hardest part: Designing partial-fill and nonce semantics that remain mathematically exact and lifecycle-safe across arbitrary execution sequences, while keeping the settlement surface intentionally minimal.
Key learning: Protocol correctness is not just a collection of require statements: signed intent, state transitions, arithmetic, token behaviour, and terminal lifecycle rules need properties that can be stated clearly and attacked repeatedly with fuzzing and stateful invariants.
- Add a minimal off-chain TypeScript/viem reference that reproduces the Solidity EIP-712 digest and exercises a complete signing flow across languages.
- Explore formal verification of the cumulative settlement and lifecycle invariants without expanding the production feature surface.
- Commission an independent smart-contract security review before considering any real-funds deployment or production claim.