Every number here came off chain 2026-08-09. Nothing is extrapolated from a local Foundry gas report, and nothing is an estimate. Reproduce with:
cd relayer && npx tsx src/loadTest.ts --plan # price it, send nothing
cd relayer && npx tsx src/loadTest.ts # run the book
cd relayer && npx tsx src/loadTest.ts --burst=12 # concurrency
Raw output, including every transaction hash: load-report.json.
A complete factoring lifecycle is six transactions signed by three different parties.
| Leg | Signer | Gas |
|---|---|---|
confirmObligation |
obligor | 346,414 |
originate |
supplier | 564,780 |
approve (advance) |
financier | 71,677 |
fund |
financier | 731,057 |
approve (face) |
obligor | 71,665 |
settle |
obligor | 552,142 |
| Total | 2,337,735 |
At the 102 gwei observed, that is 0.238 MON per completed trade.
fund is the expensive leg, and the reason is the point of the project rather than an
inefficiency: it moves real Cleanverse cvaUSD, and that transfer runs the A-Token's own
compliance checks on both parties before any value moves. A stablecoin with no
transfer-time verification would be cheaper and would not be enforcing anything.
The cost does not move with the invoice. The book below spans 5,600 to 156,000
cvaUSD and every trade in it costs the same gas — face value is one uint256 written
once. Factoring economics are a percentage of face, so the margin on a Covenant trade
improves as the invoice grows, and the floor at which a trade is worth doing at all is
set by 0.238 MON, not by a percentage.
Monad testnet's block gas limit is 150,000,000. Divided by a full lifecycle:
~64 complete factoring lifecycles fit in a single block.
That is the useful capacity number, and it is the one an integrator should plan against — not a transactions-per-second figure that counts approvals.
Measured latency, submit to receipt, across the six legs of one trade:
| p50 | 246 ms |
| p95 | 249 ms |
| max | 249 ms |
Sequentially the client clears about 35 trades/minute, but that is a property of this script — it waits for each receipt before sending the next — and says nothing about the chain. So the same wallet signed ten confirmations up front with consecutive nonces and fired them without waiting:
| submitted | 10 transactions in 117 ms |
| mined in | one block — 52,235,358 |
| failures | 0 |
| all mined within | 1.30 s of the first send |
Nothing serialised, nothing was dropped, and no nonce gapped. All ten transaction
hashes are in load-report.json under burst, each independently
checkable against the chain.
The wall-clock figure is block cadence, not contention: the transactions were accepted in 117 ms and then waited together for the next block.
The desk's instrument register reads every note through one Multicall3 batch of 50
rather than one getNote per token:
27 notes, 2 RPC round trips, 97 ms.
Read cost is a function of ceil(notes / 50), not of note count, so the desk's load
time is flat until the book passes fifty and then steps once. Before this change the
register issued one request per note and stopped at a hard ceiling of 200.
The measurements are not synthetic traffic. They are a real book of varied trades run end to end against the deployed contracts with the four live demo wallets:
| notes on chain | 27 |
| distinct face values | 16 |
| distinct maturities | 9 |
| settled / funded / open | 16 / 6 / 5 |
| total face value | 2,018,230 cvaUSD |
Two advance rates appear because the two live obligors sit in different bands — subTier 90 prices at 9,700 bps and subTier 30 at 8,800 bps, exactly the curve the desk publishes.
Stated so the numbers above are not read as more than they are:
- One RPC endpoint, one client. This measures the chain and the contracts, not a production deployment's own throughput ceiling.
- Testnet. Monad mainnet's fee market will differ; the gas figures will not.
- Twelve concurrent transactions, not twelve thousand. It establishes that the lifecycle does not serialise. It does not establish a saturation point.
- The relayer is not in the hot path. A-Pass mirroring happens out of band, so its cost is not part of a trade and is not counted here.