priors · priors.trade · credit pool · v0robinhood chain · usdg · erc-8004solidity 0.8.26 · 61 tests · fuzzed invariants

Unsecured USDG credit for AI agents.
Underwritten by sponsors who eat the loss. Scored by what got paid back.

repaid
loans
agents
lender losses
cast · reading the pool
$ 
sponsorvouched agentrepaid loandefaultthe grove · replaying the ledger
blockeventagentdetail
§ 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. Never takes principal loss: the waterfall below runs out of sponsor stake and the reserve before it reaches the pool.
root sponsorStakes at least $10 and vouches for agents out of that stake. Slashed first when a vouched agent defaults.
agentAn ERC-8004 identity. Borrows $5 to $500 for 1 to 30 days at 1% per 30 days. Earns its own capacity by repaying, up to $250, at most $25 per 7-day epoch, only after 1 day of seasoning, and only while the reserve covers all earned credit globally.
sub-sponsorAn agent with earned credit can vouch for other agents from that credit. If a child defaults, the sub-sponsor gets a recourse loan for the liable amount, due in 14 days. Losses flow up the tree, one level at a time.
reserveFirst-loss capital funded by 15% of fees and by $PRIORS creator fees. It is what makes earned credit safe to hand out: earned ≤ reserve, always.
§ 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)           // provably 0 while earned ≤ reserve
§ 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.solv0
score(r) = defaulted ? 0 :
    min(400, dollarDaysRepaid / $10)     // Σ principal × term over repaid loans
  + min(200, 20 · qualifiedRepaid)      // loans with term ≥ 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
worked example · live
dollar-days repaid
qualified loans
backing at risk
time enrolled
recourse honored
vouched defaulters
score() · matches cast call below
§ 04

Invariants

Checked on every state transition by a stateful fuzzer driving deposits, vouches, borrows, repayments, defaults and time. All hold.

I1 · solvency
badDebt ≤ totalEarned ≤ reserve
⇒ lenders never lose principal
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
61
tests
5
invariants
256 × 64
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. Its creator fees land in a treasury contract that does two things by rule: 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 any 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 (USDG)──▶ TreasurySponsor.sweep()      // anyone
                                     ├── 50% ─▶ CreditPool.fundReserve()   // first loss
                                     └── 50% ─▶ CreditPool.addStake(treasury)

firstLine(agent)   never-enrolled ERC-8004 id ─▶ vouch $5      // anyone, once per id
raise(agent)       3 qualified loans · 14 d · clean ─▶ line $50  // anyone
                    Σ vouched ≤ $100 per 7 d epoch                 // a sybil's ceiling

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
launchPons V2 factory, USDG pair, creator fee recipient = TreasurySponsor. 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 /score/:agentIdx402 · $0.001
verifyany RPC
§ 08

Addresses

Nothing on this page is stored anywhere but the chain. Add ?rpc=&pool= to render any deployment.