The protocol

How the pool works, in full.

The model, the default waterfall, the score, the invariants and every parameter, read live from the contracts on Robinhood Chain. Nothing on this page is a promise the code doesn't keep.

§ 01

Model

One pool of USDG. Every agent has a capacity, most of it lent to it by a sponsor. What a sponsor lends out, it can lose. That is the entire trust mechanism.

accountingCreditPool.sol
capacity(a)   = stake(a) + earned(a) + delegatedIn(a)   // delegatedIn only while sponsor(a) is alive
available(a)  = capacity(a) − principalOut(a) − delegatedOut(a)

vouch(s → a, x):  require x ≤ available(s)
                   delegatedOut(s) += x ;  delegatedIn(a) += x
                   // a non-root sponsor may only delegate from earned(s)

borrow(a, P):     require minLoan ≤ P ≤ available(a)
                   principalOut(a) += P ;  fee = P · feeBps · term / 30d

repay(a, P+fee): fee → lenders 60% · sponsor(a) 25% · reserve 15%
                   earned(a) += min(P · growthBps, epochRoom, maxEarned − earned(a))
lenderDeposits USDG, holds shares, earns 60% of every fee. Sponsor stake and the reserve are intended to absorb defaults before lender principal. Experimental contracts still require launch validation; capital is at risk.
root sponsorStakes and vouches for agents out of that stake. Slashed first when a vouched agent defaults. Anyone can become one: the minimum stake is set in the parameters below, and a stake can be withdrawn whenever it is not backing a line.
agentAn ERC-8004 identity. Borrows $5 to $500 for 1 to 30 days at 1% per 30 days, within the line its sponsor vouched. The contract can also grant earned credit for repaying; on mainnet that is switched off (maxEarned is $0), so every line has a sponsor's stake in front of it.
sub-sponsorIn the contract, an agent with earned credit can vouch for others from it, and pays a recourse loan if a child defaults. With earned credit off on mainnet, no agent is a sub-sponsor today.
reserveFirst-loss capital funded by 15% of fees and, once the creator fee is routed here, by $PRIORS creator fees. It is what makes earned credit safe to hand out: the intended reserve bound is earned ≤ reserve.
§ 02

Loan lifecycle and the default waterfall

Four transitions. The last one is the one that gives the score its meaning.

state machineloan.status
default waterfall_onDefault()
liable   = min(P, delegatedIn(a))          // sponsor is on the hook up to what it pledged

if sponsor(a) is root:
    slash  = min(liable, stake(sponsor))
    stake(sponsor) −= slash ;  poolLiquidity += slash
else if sponsor(a) is alive:
    issue recourse loan(sponsor, liable, 14d)     // its own default if unpaid
    score(sponsor) −= 75 per vouched defaulter
else:
    liable = 0                                    // dead sponsor, nothing to take

uncovered = P − liable
reserve  −= min(uncovered, reserve)               // first-loss capital pays next
badDebt  += max(0, uncovered − reserve)           // live on robinhood chain, checked by the invariant suite on every push
§ 03

Score

Six terms over the on-chain record, 0 to 1000. A pure function of creditReport(agent). No oracle, no committee, no review. The two big terms are dollar-days and week-long loans, so the cheapest way to a high score is to hold real money for real time and give it back.

ScoreLib.solv1
score(r) = defaulted ? 0 :
    min(400, dollarDaysRepaid / $10)     // Σ principal × actual holding time, capped at term
  + min(200, 20 · qualifiedRepaid)      // loans held for ≥ 7 d
  + min(150, delegatedIn / $5)          // someone's money at risk for you
  + min(150, 2 · daysEnrolled)
  + min(100, 50 · recourseHonored)      // paid for a child's default
  − 75 · childrenDefaulted
// one-day loans churned for cents move nothing; capital held for weeks does
recorded score inputs—
dollar-days repaid —
qualified loans —
backing at risk —
time enrolled —
recourse honored —
vouched defaulters —
score(—) · recorded contract score—
§ 04

Invariants

Checked on every state transition by a stateful fuzzer driving deposits, vouches, borrows, repayments, defaults and time. These are intended properties, not a guarantee of safety. Additional default scenarios are under review.

I1 · solvency
badDebt ≤ totalEarned ≤ reserve
⇒ intended lender protection; validation pending
I2 · cash
balance(USDG) =
  poolLiquidity + totalStake
  + reserve + unclaimedSponsorFees
I3 · exposure
∀a: principalOut(a) + delegatedOut(a)
      ≤ capacity(a)
no one lends what they don't hold
Live
on Robinhood Chain
5
invariants
256 × 400
fuzz runs × depth
—
lender loss to date
§ 05

Parameters

Read from getParams() on the deployed pool. Owner-adjustable within bounds; every change emits ParamsUpdated.

paramvaluemeaning
§ 06

$PRIORS is a sponsor

Launched on Pons, Robinhood Chain's launchpad, paired with USDG. During the beta the creator fee is not yet routed here — the treasury is topped up by hand, by sending it USDG and calling sweep(), which anyone can do. What the contract does with whatever it receives is by rule and unchanged: half to the first-loss reserve, half staked under the treasury's own ERC-8004 identity as a root sponsor. From that stake it gives each invited new agent its first $5 line and raises clean records to $50, capped per epoch. Its agents' sponsor fees go to the buyback wallet. Its stake gets slashed when they default. Its tree is in the grove, next to everyone else's.

fee pathReserveFunder.sol
Pons escrow ──creator fees──▶ TreasurySponsor.sweep()    // testing
you ────────── send USDG ───▶ TreasurySponsor.sweep()    // beta: by hand
                              ├── 50% ─▶ pool.fundReserve()  // first loss
                              └── 50% ─▶ pool.addStake(id)   // stake

firstLine(agent)  new ERC-8004 id ─▶ vouch $5             // once per id
raise(agent)      3 qualified · 14 d · clean ─▶ line $50   // anyone
                   Σ vouched ≤ $100 per 7 d epoch          // sybil cap

collect()         25% of its agents' fees ─▶ buyback wallet
default            stake slashed · branch burns · in public
from token— swept so far, half reserve, half treasury stake
reserve— first-loss capital today
earned credit— of unpledged lines it currently backs
paid for defaults— covered after sponsors, lenders untouched
contractnot launched yet
launchPons, USDG pair. The creator-fee recipient has not been pointed at the TreasurySponsor yet — only the token's creator can do that. Until then the fee accrues to the creator's Pons escrow, not to the treasury, and the treasury is topped up by hand. ponsfamily.com/launchpad
§ 07

Interface

Everything an agent, a sponsor or a lender can do. The score is one view call; the API in the repo serves the same number over x402, and sdk/priors.mjs wraps the lot in six methods.

deposit(uint256 assets) → shareslender
withdraw(uint256 shares) → assetslender
enrollRoot(uint256 agentId, uint256 stake)sponsor
vouch(uint256 sponsor, uint256 agentId, uint256 amount)sponsor
borrow(uint256 agentId, uint256 principal, uint64 term)agent
repay(uint256 loanId)agent
markDefault(uint256 loanId)anyone
claimSponsorFees(uint256 agentId)sponsor
score(uint256 agentId) → uint256view
creditReport(uint256 agentId) → Reportview
treasury.firstLine(uint256 agentId)anyone
treasury.raise(uint256 agentId)anyone
treasury.sweep() · collect()anyone
GET /v1/score/:agentIdoptional x402
verifyany RPC
§ 08

Addresses

These are the contracts this page reads, on Robinhood Chain (chain id 4663). The light in the top bar shows the block it last read.