Caliber Factor
Advance against escrow, not promises — the methodology.
by PokoBlue · @PokoBlue99 · September 2026 Version: v1.1 · PROVISIONAL PARAMETERS · published ahead of the Arc mainnet release; the parameters below become operative only when the proving period closes — see §Provisional Parameters and the Proving Period Sibling to, and consumer of, Caliber Rating v2.1.0 Derived from the Caliber Coverage v1.1 internal draft (May 2026), narrowed to committed, escrowed receivables. Coverage remains a separate future methodology — see §Future Work.
TL;DR
Caliber Rating tells you whether an agent delivers. Caliber Factor tells a capital provider one narrower thing: how much of this agent's escrowed, confirmed work is safe to advance against — and gives both sides the on-chain controls that make the advance repay itself as those jobs settle.
Factor never advances against a forecast. It advances only against USDC a client has already locked in ERC-8183 escrow, only for jobs that pass a counterparty-independence graph test, discounted by a dispute haircut and a client-diversification weight, and always less than the client locked. Repayment is skimmed from those same jobs' settlements. A refundable bond and an earned reserve backstop the residual.
Caliber publishes the eligibility decision, the advanceable backlog, a signed FactorAttestation, and the control primitives. It does not lend, price, or decide the advance. The capital provider owns the credit decision, the pricing, and any recourse; Caliber owns the signal and the controls. Caliber holds no advance, bears no credit loss, performs no KYC.
Everything is computed from public ERC-8004 + ERC-8183 events. Same house rule as the Rating: if you can read the tables below, you can audit any number we publish.
Why This Exists
Under ERC-8183 the client escrows USDC before work is delivered. An agent with confirmed jobs therefore holds something rare in credit: receivables where the payer's money is already locked on-chain. Traditional factoring advances against invoices and hopes the debtor pays; Factor advances against escrow that cryptographically cannot be spent elsewhere. Structurally safer than the off-chain original — the collection risk is reduced to dispute risk.
This is deliberately not lending against future earning power. That harder question — projecting settlement velocity, coverage ratios, breach covenants — belongs to the separate Caliber Coverage methodology, which remains future work. Factor is the narrow, conservative slice: committed backlog only. If the money isn't already locked, it doesn't count. That single restriction is what makes every downstream number in this document verifiable rather than forecast.
Where Caliber Stops and the Capital Provider Begins
Factor is neutral, permissionless infrastructure. It measures, attests, and provides on-chain control primitives. It is not the lender.
| Caliber owns — permissionless, on-chain | The capital provider owns — their risk |
|---|---|
| Eligibility decision (the graph test), per job | The capital — and the credit loss |
| Advanceable backlog: haircut δ, diversification weight w | Whether and how much to actually advance |
| The signed FactorAttestation | The advance rate (within the published cap) |
| Control primitives: skim splitter, earned reserve, bond, routing-away default mark | Pricing / fees |
| Guarded-launch caps (published, event-logged) | Any KYC, legal contract, or off-chain recourse |
| The reproducible calculation method | Any PD / loss model derived from Caliber's measurements |
Provider disclosure — state this to anyone consuming Factor. Caliber measures and controls on-chain risk and provides no legal recourse. The escrow, bond, and reserve bound only the loss that code and economic deterrence cover. A provider advancing beyond those bounds carries the tail itself and mitigates it by its own means — contracts, KYC, or pricing. That is a provider decision, never a Caliber guarantee.
What Factor Measures (The Core Table)
Items marked [reused] come from Caliber Rating v2.1.0; [new] are introduced here.
| Input | What it is | Source | Status |
|---|---|---|---|
Job state (Open/Funded/Submitted/terminal) | Which jobs are confirmed and escrowed | ERC-8183 | [new use] |
funded_backlog | USDC locked in this agent's confirmed, unsettled jobs | ERC-8183 escrow | [new] |
| Counterparty graph | Who funds whom; ownership and funding links between wallets | ERC-8004/8183 | [new] |
dispute_rate (credibility-weighted) | How often this agent's work is rejected | Rating §2.1 | [reused] |
counterparty_hhi over eligible clients | Concentration of the repayment source | derived | [adapted] |
self_deal_share, sybil / concentration flags | Wash-activity signals | Rating §2.3 | [reused as gates] |
| Client identity age, prior settled jobs | Fresh-counterparty test inputs | ERC-8004/8183 | [new] |
| Caliber tier + flags | Agent-side quality gate | Rating | [reused] |
Advance terms (advance_rate, fee) | Chosen by the provider within published caps | provider-supplied | — |
outstanding | Advance + fee not yet repaid | advance contract | [new] |
Honest notes: only escrowed money counts — no off-chain income, no self-reported pipeline, no velocity extrapolation. Eligibility is per job, then aggregated per agent. Factor requires confirmed escrow to exist; an agent with an empty backlog has an advanceable amount of zero, correctly.
Step 1 — The Eligibility Gates (binary, per job)
A job contributes to the advance base only if every gate passes. Fail one, and the job counts $0 — however large. Exclusion may deter activity; it is never counted as collateral.
Gate 1 — Confirmed and escrowed. Job state is Funded or Submitted
(work delivered, awaiting acceptance), and the job is not past its
expiredAt. Open jobs never count — nothing is locked. A job past its
expiry does not count either: on Arc's AgenticCommerce, claimRefund() may
be called by anyone once expiredAt has passed and returns the escrow to the
client, so that money is the client's to take back at any moment. Jobs in dispute are excluded entirely; δ (below) prices the risk of
future disputes on clean jobs, not the fact of a live one.
On Arc that dispute exclusion is presently vacuous, and saying so is better
than implying a control that does not run. Arc's AgenticCommerce has no
Disputed job state — the indexed vocabulary is
Open / Funded / Submitted / Completed / Rejected / Expired — and the one
dispute signal the index holds, the validations table, carries no job_id,
so no job-level dispute can be excluded even in principle. The practical
consequence: a Submitted job whose validation came back FAILED contributes
its full escrow to the advance base. A dispute becomes observable only once
the job leaves Submitted, at which point Gate 1 excludes it as a terminal
state. Linking validations to jobs is the fix and it is a Rating-side schema
change, not a Factor one.
Gate 2 — Not self-dealt, directly or through a cycle. The client must not be the agent's owner or operator — through the agent's identity addresses or its registered payout address, since funding one's own splitter is self-dealing just as plainly — and there must be no funding path connecting client and agent within the counterparty graph (multi-hop cycle detection, reference depth ≤ 3). Nor may the job's ERC-8183 evaluator be the agent's own side — its wallet, its operator or its splitter — because the evaluator alone decides whether funded work completes, and an agent that evaluates itself confirms its own escrow. Where the client is the evaluator, as on most Arc jobs, acceptance is discretionary but not self-dealt: that is priced as a weight, not excluded. This is the full graph-cycle test the Rating's sybil section listed as future work; Factor v1.0 delivers it. The Rating's sybil and concentration flags additionally act as hard agent-side gates.
The traversed edge set is funding only. An edge exists where a client has funded a provider; ownership edges — two agents sharing a beneficial owner — are not traversed, because beneficial ownership is not observable on-chain beyond the NFT owner already folded into the agent's addresses. Earlier drafts of this section said "ownership-or-funding", which overstated it. Entity clustering would strengthen this and is not in v1.0.
The edge set is a materialized view refreshed on the daily snapshot, so a funding cycle constructed after the last refresh is invisible to this gate for up to 24 hours. Staleness is conservative in one direction only — a missing edge cannot invent a path, but it can hide one — which is the wrong direction for an anti-fraud gate, and is stated here rather than left to be discovered.
Gate 3 — No fresh single-use counterparties. The funding client must have an identity older than the reference age (14 days) and at least one prior settled job with an unrelated counterparty. A wallet minted yesterday that has only ever funded this agent is not evidence of demand; it is the setup for manufactured collateral.
Identity age is measured on chain time — the block its first job was created in, converted by interpolating between the nearest real block timestamps we hold, and not on when Caliber's indexer happened to write the row. The interpolation is deliberately local: a chain's block rate is not a constant, and on Arc a single straight line fitted across all history implies 5.6 blocks/sec against a current rate near 1, which misdates a week-old block by four days. The two differ by months across any backfilled range, and reading the gate off insert time would make every client on the chain read as newly minted after a re-backfill. On Arc a plain EOA emits no registration event, so first on-chain activity remains the only observable proxy for identity age; measuring it on chain time is what makes it a property of the client rather than of us.
Gate 4 — Agent-side quality. The agent holds a quality tier (Bronze or above) with no active risk flag. Watch-tier agents have an advanceable amount of zero for as long as the flag stands.
The eligible set E is everything that survives all four gates.
The unit of aggregation — payout address, not agent id
Eligibility is decided per job. It is then aggregated per payout address, not per agent id, and the distinction is load-bearing.
An ERC-8004 registration is an NFT. One wallet may hold many, and on Arc the
agent's payout address is its owner, because agentWallet/operator is
unpopulated. Escrow is therefore held against the address, while the Rating is
computed per agent id. Measured on Arc on 2026-09-01: one wallet
(0xafe6dd95…0549) held 143 agent registrations over $51.25 of live
escrow, and the next held 100. Summed per agent id the qualified population
showed $5,609.25 of advanceable escrow; de-duplicated by payout address it
was $41.55 — the same pot counted 135 times.
This matters because per-attestation safety does not compose. Each of those
attestations would be individually truthful and would each satisfy
advance < escrow locked; together they would authorise 135 advances against
one pot. An invariant that holds on every document and fails on the set is not
an invariant.
Two rules follow, and both are part of the eligibility decision Caliber owns:
-
Aggregate to the payout address. Eligible escrow, the advanceable backlog, and any outstanding advance are quantities of an address. An attestation names the agent id it was requested for and the payout address it is computed over; a consumer holding two attestations that share a payout address is holding one claim twice.
The payout address is the agent's registered splitter, and it is not the same set as the agent's identity. Under ERC-8183
provideris fixed atcreateJob, so escrow created against the agent's own wallet can never be skimmed — counting it would size an advance against collateral the repayment rail cannot reach. An agent with no registered splitter therefore has an advanceable backlog of zero, whatever its wallet holds, and Caliber refuses to attest rather than issuing a truthful-looking number that no advance could be repaid from. Identity addresses remain what Gate 2 and the sibling union are evaluated over: who the agent is, versus where it is paid. -
Gate 4 evaluates the union of siblings. Where several registrations share a payout address, the address inherits the worst tier and the union of active flags among them. Without this, Gate 4 is trivially bypassable: the wallet above spans Silver and Watch, because
feedback_eventsare keyed by agent id while jobs resolve by address, so an operator could attest through whichever registration happens to be clean while the flagged sibling sits at the same address, drawing on the same escrow.
Both rules are implemented, not aspirational. The union is applied in
rating/engine/factor/gates.ts (unionSiblingQuality), which takes the
maximum tier ordinal — ordinals ascend as quality descends, so the worst
tier is the largest number — and the bitwise OR of active flags, across every
registration resolving to the payout address. The attestation route refuses
outright when the union fails Gate 4, and names the sibling that bound the
decision, so a refusal is explainable rather than asserted.
One honest limit: a sibling that has never been rated contributes neither a
tier nor an absence of one. It is counted and reported (siblings_without_rating),
because an unrated sibling is absence of evidence, not evidence of cleanliness —
and inventing a tier for it would be the same species of overclaim the union
exists to prevent. Its flags, where it has any, still count.
Enforcement is deliberately duplicated rather than trusted to the attestation
alone: the advance contract keys outstanding by payout address, so a second
advance against the same address is refused on-chain however many attestations
exist. Same discipline as §Defense in Depth — two independent layers, neither
asked to be perfect alone.
Step 2 — The Advanceable Backlog
Two published discounts turn eligible escrow into the advanceable backlog — the dispute haircut and the client-diversification weight — and, from v1.1, a third mechanism that is published but set to 1.0:
The client-evaluator weight. On most Arc jobs the client paying for the work
is also its ERC-8183 evaluator, and decides alone whether it is accepted; the
job contract has no appeal step. Escrow on such a job counts at weight
CLIENT_EVALUATOR_WEIGHT. It is 1.0, so today it changes no number: the
reference parameters are fitted on mainnet, not invented on testnet, and the
risk is disclosed to providers instead of priced by a guess. The mechanism is
published now so that setting it later is a parameter change under this
version, not a new methodology.
δ — the dispute haircut, per agent. The share of confirmed work that history says may still be rejected. Derived from the Rating's credibility-weighted dispute rate, floored:
δ = max( δ_min , dispute_rate_credibility_weighted ) δ_min = 5% (reference)
An agent whose smoothed rejection rate is 18% gets δ = 0.18; a clean agent with thin history is pulled toward the population floor rather than flattered by a small sample — the same credibility discipline the Rating uses everywhere.
What dispute_rate_credibility_weighted is, exactly. It is
1 − completion_rate_smoothed from the Rating (rating/engine/rating.ts), and
three properties of that number matter enough to state rather than leave to the
reader:
- The window is 30 days, not lifetime. δ prices what this agent's recent conduct implies, which is the right horizon for escrow that will settle in weeks — but it does mean an agent's δ can move without any new dispute, simply as old jobs age out of the window.
- The denominator is resolved jobs, and "unresolved badly" counts.
Rejected,Expired,Disputed,CancelledandRefundedall count against completion. That is broader than the word "dispute" suggests: an expired job is not a dispute, but it is confirmed work that did not turn into a settlement, which is precisely the risk δ exists to price. Stated plainly because the alternative — a narrow literal dispute count — would understate the haircut on exactly the agents that deserve it. - It is credibility-blended toward the population mean, per chain, so a thin history is pulled toward the floor rather than reading as perfect.
This is a defensible proxy rather than a literal reading of the phrase "credibility-weighted dispute rate", and it is written down here so a provider reproducing δ from the public rating response gets our number and not a different one.
w — the client-diversification weight, over the eligible set. In factoring, concentration is repayment-source risk: if 80% of the eligible escrow comes from one client, one dispute or one walk-away impairs most of the repayment path. So:
w = clamp( 1 − HHI_eligible_clients , w_min , 1 ) w_min = 0.30 (reference)
A disclosed refinement vs. the Coverage draft: Coverage's quality factor q
multiplied (1 − self_deal_share) into the weight and deliberately did not
haircut backlog. Factor differs on both, for stated reasons: self-dealt jobs
are already excluded at Gate 2 (a binary gate beats a discount), and in
Factor the backlog is the repayment source, so its concentration must be
priced. Different product, different treatment — disclosed here so the
divergence is auditable.
The advanceable backlog:
advanceable_backlog = ( Σ_{jobs ∈ E} escrow_i ) × (1 − δ) × w
Worked example. Eligible escrow $10,000; agent's smoothed dispute rate 18%, so δ = 0.18. Shares are stated so every figure is reproducible:
| Client shares | HHI | w | ×(1−δ) | Advanceable | Provider @ 55% | |
|---|---|---|---|---|---|---|
| Diversified | 4 × $2,500 | 0.25 | 0.75 | 0.82 | 6,150 | ≈ 3,383 |
| One dominant client | $8,500 + 3 × $500 | 0.73 | 0.30 (floored) | 0.82 | 2,460 | ≈ 1,353 |
Same locked money, well under half the safe advance — because most of the
repayment path hangs on one counterparty's behaviour. Note the second row hits
w_min: raw 1 − HHI is 0.27, and the floor is what stops concentration from
driving the backlog to zero.
Worth reading carefully: w = 1.0 is unreachable with a finite client list.
1 − HHI approaches 1 only as the number of equally-weighted clients grows
without bound; four equal clients cap out at 0.75, ten at 0.90. An earlier
draft of this example asserted w ≈ 1.00 for four clients, which contradicted
the formula directly above it — corrected in 1.0-draft2.
Step 3 — The Advance and Its Caps
The provider chooses the advance rate; Caliber publishes the bounds.
advance ≤ advance_rate × advanceable_backlog advance_rate: provider-chosen
advance < Σ escrow_i (always less than the client locked — hard invariant)
The fee. The factoring fee is flat and one-time, charged at acceptance, and provider-set within a published range — reference 2.40% of the advance at the pilot tenor. It is a factoring discount fee in the classic sense, not a time-accruing charge: there is no due date to accrue against, and an advance that clears in three days costs exactly what one clearing in thirty costs.
Three consequences, all intended. The agent sees one fixed repaid in total figure at acceptance, and it never moves. Reconciliation is a subtraction rather than an accrual schedule. And the vocabulary stays on factoring fee — nothing in this document accrues with time or reads as interest.
The fee is part of outstanding, so the skim captures it on the same waterfall
as the principal. The advance is not clear until both are.
Reference advance rate: 0.55. During the guarded launch, additional published caps apply — a per-agent USDC maximum, a global outstanding maximum, and an allowlist of agents and providers — all admin-set, event-logged, and governed like the bond table (changes take effect when published). Caps are a launch-safety instrument, not a credit judgment.
The FactorAttestation
Every eligibility decision ships as a signed EIP-712 FactorAttestation
that any contract can verify — the same primitive pattern as the
RatingAttestation, on its own verifier.
Carried fields (pinned at FactorVerifier deployment): chain id · agent id ·
agent address · eligible escrow (USDC) · advanceable backlog (post-δ, post-w) ·
eligible job count · δ and w as applied · Factor methodology version ·
freshness window · replay nonce. Issued through a paid x402 nanopayment
route (HTTP 402, pay-per-attestation), verified on-chain by a dedicated
FactorVerifier; the deployed RatingVerifier is unchanged. A provider that
verifies the signature against the published Caliber signer key knows the
claim is current, complete, and untampered — and sizes the advance from it.
δ and w are carried as applied, rounded to basis points, so a consumer can
recompute advanceable_backlog = eligible_escrow × (1−δ) × w rather than take
it on trust. Because the engine computes the backlog from the full-precision
values and the attestation carries the rounded ones, an honest attestation
can miss exact equality by up to roughly one basis point of the backlog.
FactorVerifier.checkBacklogArithmetic therefore takes a tolerance, and the
published minimum safe value is toleranceBps = 1. A consumer calling it
with toleranceBps = 0 — the natural "check it exactly" choice — can reject a
correct attestation, so the tolerance is stated here rather than left to be
discovered against a live advance.
Nonce consumption on requireAdvanceWithinBounds is restricted to consumers
Caliber has allowlisted, and the authorisation event names the consumer that
burned the nonce. An attestation is public calldata once broadcast, so an
unrestricted gate let any observer burn a valid attestation's nonce and force
it to be re-purchased. The allowlist narrows that to an accountable set; it
does not bind one attestation to one provider, which would require a
provider field in the signed struct and therefore a version change.
Repayment — The Skim Splitter
Read together with §Security. The splitter is the preferred repayment rail for a cooperative agent — not an enforcement mechanism.
The agent registers a Caliber payout splitter as its payment address at onboarding. Settlements of advance-encumbered (factored) jobs route through it and split by a fixed waterfall:
on settlement(amount) of a factored job:
repay = min(amount × skim_rate, outstanding)
reserve = min(amount × reserve_rate, reserve_target − reserve_balance)
transfer(repay, provider) # repayment first, code-enforced
transfer(reserve, earned_reserve) # then the reserve slice
transfer(remainder, agent) # agent keeps the rest
if outstanding == 0: release() # splitter releases; bond returns
Reference default: skim_rate = 80%. With reserve_rate = 5%
(§The Earned Reserve), the agent retains 15% of each factored settlement while
the advance is outstanding.
Seniority is fixed and unconditional: repayment → reserve → agent. If the two published slices would ever exceed the settlement, the reserve gives way and the provider is paid in full — never the reverse.
That seniority imposes a condition the reference parameters must respect:
skim_rate + reserve_rate ≤ 100% — the condition for the reserve to accrue
Above it, repayment consumes the settlement and the reserve slice is zero by
construction. skim_rate = 100% remains a permitted provider choice, and
under it the reserve is dormant by design. That configuration is not
unsafe: at a full skim the reserve is redundant, because provider exposure
(outstanding − bond − reserve) is identical whether a dollar reduces the
outstanding or is retained as seizable collateral. It simply cannot exercise a
reserve — which is why it is not the reference.
An earlier draft published skim_rate = 100% as the reference alongside a 5%
reserve rate. The two are arithmetically incompatible; see §Change History,
1.0-draft3.
The published sizing rule is unchanged — at the chosen rate the advance must clear from the eligible backlog alone:
skim_rate ≥ ( advance + fee ) / advanceable_backlog
At the reference advance rate and fee this binds well below the reference skim: 0.55 × 1.024 ≈ 0.56 ≤ 0.80, leaving margin for a provider pricing above the reference fee or sizing above the reference rate.
Two properties define this design: repayment is code-enforced for every settlement that passes the splitter, and there is no fixed due date — the advance clears exactly as fast as the underlying jobs settle. What is not enforced is the agent's choice to keep routing here. That is the next two sections.
The Earned Reserve
A published slice of each factored settlement (reference reserve_rate = 5%,
target = 10% of the original advance) accumulates in an on-chain earned
reserve — the agent's own money, held as additional cushion.
What it is for. The reserve is the mechanism that makes partial-skim configurations safe. Below a full skim the agent keeps cash on every settlement while an advance is still outstanding; the reserve forces part of that retained cash into a bucket the provider can seize. It converts the agent's own liquidity into collateral at precisely the moment the agent begins keeping some. Where there is no retained cash — a 100% skim — there is nothing to divert, and the reserve is correspondingly dormant (§Repayment).
Release rules: the reserve returns to the agent in full, automatically, on full repayment of the advance. On a routing-away default (below) it is seizable to the provider alongside the bond, in waterfall order: reserve first, bond second. The reserve is a commitment device funded by the agent's own earnings — it exists so that the closer an agent gets to repaid, the more of its own money walking away would burn.
The Bond
The agent posts a refundable USDC bond on Factor's own tier-stepped schedule, as a percentage of the advance:
| Agent tier | Bond |
|---|---|
| Gold | 3% of advance |
| Silver | 4% of advance |
| Bronze | 5% of advance |
| Pending · Watch · Dormant | not eligible — excluded at Gate 4 |
Floor: 25 USDC, so a small advance still posts a bond that costs something to abandon.
Why the advance, and not the backlog. A bond must be a fixed, known amount at the moment it is posted. The advanceable backlog moves with every settlement, every newly-escrowed job and every recomputation of δ and w; the advance does not. Sizing against a moving quantity would mean a bond that is either re-collateralised continuously or wrong the instant it is posted.
Why not the existing CaliberEscrow schedule. That table is bps of a single job budget and exists to gate per-job counterparty risk — a different quantity and a different failure. Its rates (50–1500 bps) are calibrated for that job; 150 bps of an advance is far too small to deter routing away from one. Factor therefore governs its own table, under the same rule as everything else here: a change takes effect when it is published.
The schedule above is the one FactorBond.requiredBond() implements on-chain
and rating/engine/factor/params.ts bondForAdvance() implements off-chain;
the two are asserted against each other in both test suites. At a $100 advance
the 25 USDC floor binds and the tier rate does not — worth knowing before
sizing a demonstration, since a bond many times the advance it backs is
arithmetically correct and rhetorically useless.
Future work (v1.1): size the bond against the largest single factored settlement rather than the advance — the quantity actually at risk in one routing-away event.
Two automatic transitions, both required and both on-chain:
- Automatic release following repayment —
outstanding == 0releases the bond to the agent without any party's discretion. - Slashing following routing-away default — see next section.
The bond is not a rating signal; it is downside the agent's own wallet feels.
Routing-Away Default — Factor's Default Definition
Distinct from the Rating's performance-default (work rejected — a property of work quality), Factor defines exactly one default: routing-away — a property of the advance.
Definition: while an advance is outstanding, a factored job settles to an address other than the registered splitter, or the agent re-points its payout address away from the splitter. Both are provable on-chain: the settlement event names its recipient, and Caliber indexes every job under the agent's identity. This is the self-punishing leakage case — cheating under the borrowing identity leaves cryptographic evidence attached to that identity.
Detection and consequence: an off-chain keeper marks the breach with the settlement evidence; a cure window (reference 24 h) lets the agent remit the skimmed amount and clear the mark; past the window, slashing is permissionless — anyone may execute it. Waterfall: earned reserve, then bond, to the provider, capped at outstanding.
The mark's cure deadline is fixed when the mark is made, not recomputed from the current cure-window setting, so shortening the window cannot collapse a cure period already running against an agent. A change to the window governs future marks only.
What evidence is, exactly. It is a citation, not a proof. A mark must
carry a non-empty reference to the offending settlement, and an empty one is
refused — but nothing on-chain verifies that the reference resolves to a real
settlement, and nothing can: the breach is the absence of a settlement at
the splitter, and a contract cannot observe an absence. That is the whole
reason detection is keeper-gated rather than permissionless. So the mark is
auditable — the citation is public, indexed, and checkable by anyone against
the chain — without being self-proving. Earlier drafts implied a stronger
check than exists.
"Permissionless" covers both legs, and has to. The reserve is seized first
and the bond second, so an owner-gated reserve seizure would leave the
permissionless bond slash unreachable and a provider's recovery would depend on
Caliber choosing to act — the exact dependency this clause exists to remove.
CaliberSplitterFactory.seizeReserve() therefore opens to any caller the
moment FactorBond.slashable() reports an uncured mark past the window, and not
one block earlier: before that it stays owner-only, so a permissionless first
leg never becomes a way to take an honest agent's reserve on demand.
Deployment caveat, and it matters because the argument above is an
all-or-nothing one. That two-leg permissionless waterfall ships in the
contract source and is covered by tests. It is not on the factory
currently deployed to Arc Testnet, which predates the change and holds no
reference to FactorBond at all — so on testnet today the first leg is
owner-only, and by this section's own reasoning that makes the permissionless
second leg unreachable. Redeploying the factory would re-key the CREATE2
splitter clones that already-seeded jobs name as their ERC-8183 provider,
so the testnet deployment is deliberately left as it is and this clause reads
as mainnet-only until the factory is redeployed. An independent review on
2026-09-07 found this paper asserting it as current fact; that was wrong, and
this paragraph is the correction. The Rating is not altered by a
routing-away default directly — but the mark is public, and a provider (or the
Rating's own adverse-evidence factor, where a signed breach observation
exists) can consume it. Performance stays the Rating's axis; repayment conduct
is Factor's.
Sustained/debounced discipline applies to detection infrastructure faults, not to the breach itself: one provable leaked settlement is one breach.
Defense in Depth Against Self-Financing
The primary defense is exclusion: self-dealt and circular escrow counts $0
at Gate 2, so manufactured backlog buys no advance. The escrow arithmetic is
not a second layer against collusion, and this paper previously said it was.
The invariant advance < escrow locked protects a provider only if that escrow
settles to the splitter. A disguised self-hirer controls the other side of the
job: its confederate client — or its confederate evaluator — can reject the
work, or let it expire, and ERC-8183 refunds the escrow to that client. Nothing
settles, nothing is routed away, no default can be marked, and neither reserve
nor bond is seized. The self-hirer keeps the advance, forfeits a bond that is
frozen rather than paid out, and nets advance − bond. What stands between the
book and collusion is therefore the independence gates and the size of the
bond, not the arithmetic. For an agent that is not colluding the arithmetic
still matters: walking away forfeits its own customers' escrow, which is
usually worth far more to it than the advance.
Where the arithmetic layer is enforced, at v1.0. FactorVerifier .requireAdvanceWithinBounds implements both published bounds — advance ≤ advance_rate × advanceable_backlog and advance < Σ escrow_i — and refuses
the amounts they forbid. But a provider must choose to route its advance
through it: CaliberSplitterFactory.openAdvance, the function that records an
advance, takes the skim rate and the principal as parameters and does not
itself consult the verifier. So at v1.0 the arithmetic layer is a check a
provider performs, not a property the advance path enforces. An independent
review on 2026-09-07 found this paper describing it as structural, and it was
not; the sentence you are reading is the correction.
The exclusion layer is unaffected — it runs off-chain in the eligibility
engine before any attestation is signed, which is where it always ran. What
changes is only the claim about the second layer: it is available and
published, it is not automatic. Making openAdvance consume a
FactorAttestation is the mainnet design and is deliberately not being
retrofitted to the testnet deployment, because redeploying the factory
re-keys the CREATE2 splitter clones that already-seeded jobs name as their
ERC-8183 provider.
What This Is / Is Not
It is: a neutral, permissionless eligibility-and-control layer for advances against escrowed ERC-8183 receivables; deterministic and reproducible given its inputs; a consumer of Caliber Rating v2.1.0 attestations.
It is not: the lender (no capital, no sizing decision) · a credit-line or pricing recommendation · a credit rating or PD/LGD model · legal recourse or KYC · a forecast of future earnings (that is Coverage, unshipped) · financial advice.
The Honest Disclaimers
- ⚖️ No legal recourse. On-chain controls only; the provider disclosure above applies in full.
- 🧪 Not calibrated, and testnet cannot calibrate it. Every value in this document is an editorial starting point, not fitted to resolved-advance data — none exists yet. Nor can testnet supply it: the only Arc population with enough eligible escrow to fit against is a cohort we provisioned ourselves, and fitting a parameter to activity we constructed is circular, not calibration. The parameters stay provisional until the proving period below closes on live mainnet outcomes. Until then the guarded-launch caps, not the parameters, are what bound the downside.
- 🔌 The splitter is a rail, not a lock. A sovereign agent can re-route or respawn. Routing-away is made provable and costly, abandonment is made irrational by the advance cap, reserve, and bond — not impossible. The fuller willingness-to-pay framework (franchise value, loan-to-franchise sizing) lives in Coverage, unshipped. Providers should treat the whole advance as the loss bound: the bond and the reserve are paid out only after a routing-away default is marked and left uncured, and when the financed jobs are rejected or expire their escrow is refunded to the client and no default can be marked at all.
- 🎯 Evaluator noise is inherited. If a lenient client accepts bad work, the escrow settles and the haircut never sees it — Factor inherits the Rating's evaluator-quality gap.
- 📉 Dispute risk is priced, not eliminated. δ is a haircut on history, not a guarantee about the next job.
- 🤝 Garbage in, garbage out. Every limitation of the underlying ERC-8183 event data flows through.
Provisional Parameters and the Proving Period
None of these values is signed off, and none is operative on its own. They are published so the calculation is reproducible and so the eventual recalibration has a stated starting point — not because they are calibrated.
The proving period runs from the Arc mainnet deployment until
resolved-advance data exists to review them against: advances that have been
funded and have either fully repaid or defaulted. During it, every attestation
carries the provisional marker, the guarded-launch caps are held at their
conservative setting, and the participating agents and providers are
allowlisted. Sign-off at the end is a dated, event-logged act that closes the
period and moves the version from 1.1.0-provisional to 1.1.0 — not an
assumption made by anyone's silence. Should the review move a value, that is a
material change: it is published, and it takes effect when it is published. An
advance already open keeps the terms it was opened under.
| Parameter | Provisional value | Owner | Read from |
|---|---|---|---|
| δ_min — dispute-haircut floor | 5% | Caliber, published | engine |
| w_min — diversification-weight floor | 0.30 | Caliber, published | engine |
| Cycle-detection depth | 3 hops | Caliber, published | engine |
| Fresh-counterparty age / history | 14 days / ≥1 unrelated settled job | Caliber, published | engine |
| Agent quality gate | Bronze+ tier, no active flag | Caliber, published | engine |
| Advance rate | 0.55 reference | Provider, within caps | engine |
| Factoring fee | 2.40% of advance — flat, one-time, at acceptance | Provider, within published range | engine |
| skim_rate | 80% of factored settlements | Provider, ≥ sizing rule; ≤ 100% − reserve_rate for the reserve to accrue | engine |
| reserve_rate / target | 5% / 10% of advance | Caliber, published | engine |
| Bond | 3% / 4% / 5% of advance (Gold / Silver / Bronze), floor 25 USDC | Caliber, published | engine |
| Cure window | 24 h | Caliber, published | contract |
| Guarded-launch caps (per-agent, global, allowlist) | published at deploy | Caliber, event-logged | deploy config |
| Aggregation unit | payout address, siblings unioned | Caliber, published | engine |
Rows marked engine are read at render time from the eligibility engine’s own parameter module, not transcribed into this document — so the published number and the computed number cannot drift apart. Attestations issued while these values are provisional carry the methodology version 1.7.0-provisional; closing the proving period is what removes the marker.
Relationship, Versioning, Provenance
Own version line: Caliber Factor v1.x. Not Rating v3.0 (nothing in the
performance rating changes — attestation bytes, tiers, weights, deployed
RatingVerifier all untouched) and not Coverage v1.x (a different object:
Factor measures committed escrow; Coverage would measure loans against
projected cash flow). Factor adopts the Rating's governance wholesale:
published versions, a change log, and a dedicated on-chain version pointer in
FactorVerifier. A published change takes effect when it is published. The
dual-version acceptance that follows a version bump is a property of the
contract, not a notice period: FactorVerifier accepts the current version and
the immediately-previous one, and the previous one stops verifying when the next
bump displaces it.
Consumes Rating v2.1.0 (not v2.0.1 — older Factor materials citing 2.0.1 are superseded). Supersedes the Coverage draft's disclaimer that "full counterparty-graph cycle detection is future work": v1.0 ships it as Gate 2.
Provenance. Factor is the disciplined subset of the Caliber Coverage v1.1 draft (May 2026): the neutrality boundary, δ, the diversification logic, the skim rail, the bond, and the routing-away breach concept are inherited; the velocity forecast (v̂), CFADS/DSCR ratios, breach state machine, margin calls, mark-to-market franchise, and credit-line sizing are deliberately excluded — they underwrite lending, not factoring, and the data to calibrate them does not yet exist. The same instinct that retired the v1.0 credit-rating framing applies: ship only what the evidence supports.
Future Work: Caliber Coverage
Everything fenced out above has a home. Caliber Coverage — continuous cash-flow coverage for agent loans (live DSCR, dual-trigger covenants, franchise-bounded sizing) — remains a designed-but-unshipped sibling on its own future version line. It is explicitly not part of the Factor release and nothing in a Factor deployment depends on it.
Change History
| Version | Date | Changes |
|---|---|---|
| 1.1 | 2026-09-23 | Gate 2 excludes a job whose ERC-8183 evaluator is the agent's own side — its wallet, operator or splitter — because the evaluator alone decides whether funded work completes, and an agent that evaluates itself confirms its own escrow. Measured on Arc before the change: 1.4% of funded jobs, which completed at 19.6%. Gate 2's text never named the evaluator, so this is a change to a gate and a new minor version, not a correction. And a client-evaluator weight, published and set to 1.0 (§Step 2): 73.5% of funded Arc jobs are evaluated by the client paying for them; the risk is disclosed rather than priced until mainnet data can fit it. No other gate, weight, rate or attestation field changes. Attestations issued from publication cite 1.1.0-provisional; FactorVerifier accepts it and the immediately-previous 1.0.0-provisional, so an attestation issued under v1.0 still verifies. v1.0 stays readable at its own URL, marked superseded. |
| 1.0 · corrections | 2026-09-23 | Three sentences promised providers protection the contracts do not deliver, and Gate 1 counted escrow the client could already take back. (1) §Defense in Depth called the escrow arithmetic a second layer — "down before it even defaults, with reserve and bond seized on top", under a slogan this row does not repeat. On a rejected or expired job ERC-8183 refunds the escrow to the client, no routing-away default exists to mark, and nothing is seized; a colluding self-hirer nets advance − bond. Rewritten. (2) §Known Limitations told providers to treat the bond and reserve together as their loss bound; the loss bound is the whole advance. (3) Gate 1 now excludes a Funded/Submitted job past its expiredAt: claimRefund() is callable by anyone from that moment and returns the escrow to the client, and the index does not record the refund, so such jobs were being counted as confirmed escrow — measured 23 Sep, of 5,298 jobs the index listed as in flight, 5,077 were past expiry and 90 already refunded. No weight, rate, cap or attestation field changes. Ops ruled on 23 Sep that (3) is a correction, not a gate change: Gate 1 already justifies itself by what is locked, and escrow anyone can refund is not locked. Gate 1's text now carries the expiry clause explicitly. REQUEST-033 §1 and §3. |
| 1.0 · corrections | 2026-09-19 | The 30-day notice rule was withdrawn on 19 September 2026. Operator decision. Changes to prices, the bond table, caps, reference parameters and methodology versions now take effect when they are published. No parameter, gate, formula or attestation field changes, so neither the document version nor the 1.0.0-provisional stamp moves — this is a corrections revision of v1.0 in place, at the same URL, on the same reasoning as the 2026-09-07 entry below: a version bump would falsely signal a methodology change. What was not withdrawn: an advance opened before a change keeps the terms it was opened under. Dual-version acceptance also survives, because it was never the notice rule — FactorVerifier accepts the current version and the immediately-previous one, and the previous stops verifying when the next bump displaces it, with no expiry date. |
| 1.0 · corrections | 2026-09-07 | Six places where this paper claimed more than the deployment delivers. No parameter, gate, formula or attestation-field changes, so neither the document version nor the 1.0.0-provisional version stamped on attestations moves, and no 30-day notice is owed. This is a corrections revision of v1.0 in place, at the same URL, recorded here rather than issued as a new version: a version bump would falsely signal a methodology change and open a dual-version acceptance window for nothing. Every edit below narrows a claim to what is true, in the same commit as the code it describes. Prompted by an independent review of the Factor rail (docs/seoul/reports/REVIEW-2026-09-07.md) which was given the published spec and the deployed artifacts and told to find where they disagree. (1) The arithmetic layer is a provider check, not a contract guarantee, at v1.0. FactorVerifier.requireAdvanceWithinBounds implements both published advance bounds correctly and nothing on the advance path calls it — CaliberSplitterFactory.openAdvance takes the principal and skim rate as free parameters. §Defense in Depth said "structural"; it is available and published, not automatic. On-chain consumption is the mainnet design and is deliberately not retrofitted, because redeploying the factory re-keys the CREATE2 clones that seeded jobs name as provider. (2) The permissionless two-leg seizure is mainnet-only until the factory is redeployed. draft4(5) asserted it as current fact; the deployed testnet factory predates that change and holds no FactorBond reference at all, which by this paper's own all-or-nothing argument makes the permissionless second leg unreachable there. (3) Gate 2 traverses funding edges only. The text said "ownership-or-funding path"; ownership edges are not traversed, because beneficial ownership is not observable on-chain beyond the NFT owner already folded into the agent's addresses. Also now states that the edge set is a materialized view refreshed daily, so a cycle constructed after the last refresh is invisible for up to 24 h — staleness hides paths, it cannot invent them, which is the wrong direction for an anti-fraud gate and is better said than found. (4) Gate 1's dispute exclusion is vacuous on Arc. AgenticCommerce has no Disputed state and validations carries no job_id, so no job-level dispute exclusion is possible even in principle; a Submitted job whose validation came back FAILED contributes its full escrow. The fix is a Rating-side schema link. (5) A default mark's evidence is a citation, not a proof — non-empty is now enforced, but nothing on-chain can verify the reference resolves, because the breach is the absence of a settlement and a contract cannot observe an absence. Also: a mark's cure deadline is now fixed when the mark is made, so shortening the window cannot collapse a cure period already running. (6) The attestation's bps rounding has a published tolerance. δ and w are carried rounded while the backlog is computed from full precision, so an honest attestation can miss exact equality by ~1 bp; toleranceBps = 1 is the published minimum and 0 can reject a correct attestation. Nonce consumption is additionally restricted to allowlisted consumers. |
| 1.0-draft5 | 2026-09-07 | The engine was measuring the wrong pot of money. No parameter changes. (1) Eligible escrow is now gathered from the agent's payout address — its registered splitter — not from its identity addresses. ERC-8183 fixes provider at createJob, so escrow naming the agent's own wallet can never be skimmed; the engine had been computing the advanceable backlog over exactly the escrow a repayment rail cannot reach, and on the seeded cohort both pots happened to hold 1.00 USDC, so the arithmetic looked correct while describing unreachable collateral. An agent with no splitter now has a backlog of zero and the attestation route refuses (no_repayment_rail) rather than signing a number no advance could repay from. Gate 2 additionally treats the payout address as the agent's own, since funding one's own splitter is the shape a manufactured advance base would actually take. (2) Gate 3's block→time conversion is now local interpolation between the nearest real block timestamps rather than one line fitted across all history: on Arc the global fit implies 5.63 blocks/sec against a current ~1/sec and misdated 1 Sep as 5 Sep — safe in direction, but it would have moved the seeded cohort's Gate 3 from 15 Sep to ~19 Sep. Both fallbacks err toward reporting a client as younger, because for an anti-fraud gate over-rejecting is the survivable error. |
| 1.0-draft4 | 2026-09-06 | Five places where the paper described a control the code did not have. No parameter changes; every edit here brings the document into line with what now ships, in the same commit as the code. (1) The sibling union is implemented, not merely specified. draft2 announced that Gate 4 evaluates the worst tier and the union of flags across registrations sharing a payout address; the engine reported the siblings and evaluated the gate per agent id anyway, leaving the exact bypass the paper names — attest through the clean sibling while the flagged one draws on the same escrow — open. unionSiblingQuality() now takes the maximum tier ordinal and the OR of flags, the attestation route refuses on it and names the binding sibling, and an unrated sibling is counted rather than assumed clean. (2) δ's derivation is written down. It is 1 − completion_rate_smoothed: a 30-day window, credibility-blended toward the per-chain population mean, over a denominator that counts Expired, Cancelled and Refunded alongside Rejected. That is a defensible proxy for "credibility-weighted dispute rate" and a broader one than the phrase implies, so it is stated rather than left to be rediscovered by anyone reproducing δ. (3) Gate 3's identity age is measured on chain time, via a block→timestamp fit, not on the indexer's insert timestamp — which differs by months across any backfilled range and would have made every client on the chain read as newly minted after a re-backfill. (4) The bond schedule is Factor's own on chain. draft3 moved the published table to 3/4/5% of the advance with a 25 USDC floor, but FactorBond still read CaliberEscrow.requiredBond() — bps of a job budget — and answered $0.50 for a $100 advance against a published floor of $25. The contract now implements the published table, asserted against params.ts in both test suites. (5) Permissionless slashing covers both legs. The reserve is seized before the bond, and reserve seizure was owner-only, so the permissionless bond slash was unreachable and a provider's recovery depended on Caliber acting. seizeReserve() now opens to any caller the moment FactorBond.slashable() reports an uncured mark past the cure window, and stays owner-only before it. |
| 1.0-draft3 | 2026-09-06 | Skim/reserve compatibility, Factor's own bond schedule, and the fee's shape. Three operator-signed parameter changes, all from designing the surfaces that render them. (1) The reference skim_rate moves from 100% to 80%. At 100%, skim + reserve = 105% of a settlement, so under the waterfall's repayment-first seniority the reserve slice is zero by construction — the paper described a mechanism its own default configuration could never exercise, and an end-to-end demonstration of the earned reserve requires one that actually accrues and releases. The seniority rule and the skim_rate + reserve_rate ≤ 100% accrual condition are now stated explicitly; a 100% skim stays a permitted provider choice, documented as dormant by design and shown to be safe (at a full skim the reserve is redundant, since provider exposure is unchanged whether a dollar repays or is retained as seizable collateral). The reserve's purpose is restated honestly: it is what makes partial-skim configurations safe, by forcing part of the agent's retained cash into a seizable bucket. (2) The bond leaves the CaliberEscrow per-job schedule for Factor's own tier-stepped table — 3% / 4% / 5% of the advance for Gold / Silver / Bronze, floor 25 USDC. The escrow table is bps of a job budget, a different quantity gating a different failure, and 150 bps of an advance does not deter routing away from it. The base is the advance rather than the backlog because a bond must be a fixed known amount at posting and the backlog moves with every settlement. (3) The factoring fee is specified for the first time: flat, one-time, charged at acceptance, provider-set within a published range, 2.40% reference at the pilot tenor, and part of outstanding so the skim captures it. Gates, δ, w, the caps, the attestation fields, the cure window and the slash waterfall are unchanged. |
| 1.0-draft2 | 2026-09-01 | Provisional-parameter regime and the payout-address aggregation unit. Three changes, all from building the engine against live data. (1) Parameters are restated as provisional and non-operative rather than "reference values pending sign-off", with a defined proving period that closes only on resolved-advance outcomes from mainnet; the disclaimer now states plainly that testnet cannot calibrate Factor, because the only population with enough eligible escrow is one we provisioned ourselves. (2) Aggregation moves from per-agent-id to per payout address: one Arc wallet holds 143 registrations over $51.25 of escrow, so summing per agent id reported $5,609.25 advanceable where $41.55 exists. (3) Gate 4 now evaluates the union of siblings (worst tier, OR-ed flags) — the same wallet spans Silver and Watch, so a per-agent-id gate was bypassable by attesting through a clean sibling. Also corrects the Step 2 worked example, which asserted w ≈ 1.00 for four equal clients while the formula immediately above it gives 1 − HHI = 0.75; the formula was right and the example wrong, so the table is restated with explicit client shares and the w_min floor shown doing its job. Gate definitions, δ, w, caps, the attestation fields and the waterfall are unchanged. |
| 1.0-draft | 2026-09-01 | First Factor methodology, extracted and narrowed from Coverage v1.1 draft. Adds: four binary eligibility gates (incl. multi-hop cycle detection), per-agent δ from credibility-weighted dispute rate, w over the eligible set (self-deal term dropped — excluded upstream; divergence from Coverage disclosed), advance-rate cap structure, FactorAttestation struct, splitter waterfall with reserve accrual/release rules, routing-away default with cure window and permissionless slash, guarded-launch cap governance, reference-parameter table. Removes (to Coverage): v̂, CFADS, DSCR, breach state machine, franchise mark-to-market, credit-line sizing. |
| 1.0 | 2026-09-07 | Publication. The drafting sequence closes and the document is published at a stable, versioned URL, so an on-chain FactorAttestation cites a public specification rather than a repository file. No change to any gate, parameter, formula or control since 1.0-draft5 — publication is not a content change, and saying so is the point of a change history. Parameters remain provisional and non-operative: they are re-stated against the mainnet deployment and become operative only when the proving period closes on resolved-advance outcomes. |
Caliber Factor v1.1 · September 2026 · Bangkok 🇹🇭 Neutral eligibility & control layer. The capital provider owns the credit decision. Standards-native, open methodology — improves by getting punched.