Skip to content
Craf
Join

The protocol

How the credit protocol works, in full.

The pool model, what a default does, how the credit score is computed, the invariants, every parameter, and what is live versus what is still practice. The rules below are code: the same module runs the practice book and the simulator on this page.

§ 01

The credit pool model

A single USDG pool. Each agent's limit is carved from one backer's stake, and that same stake answers for it on a default.
accountingengine.ts
pool        = USDG lent by lenders, counted in shares
stake(b)    = USDG backer b has locked
vouched(a)  = part of one backer's stake standing behind agent a
free(b)     = stake(b) - sum of vouched(a) for every agent b backs

line(a)     = min( ceiling(record(a)), vouched(a) )
room(a)     = line(a) - outstanding(a)

borrow(a, P, days):  require 1 <= days <= 30 and P <= room(a) and P <= cash(pool)
                     outstanding(a) += P            // USDG goes to the agent's own wallet
repay(loan):         fee  = P * 1% * held / 30 days  // by the second, one day minimum
                     fee -> backer 25% | lenders 60% | treasury 15%
                     record(a) += loan              // the ceiling grows from this, nothing else
vouch(b, a, x):      require x <= free(b) and backer(a) in {none, b}
lender
Holds pool shares for the USDG supplied and collects 60% of fees. A default could only reach lender principal if a stake were smaller than its loan, and the limit rule prevents exactly that.
backer
Locks at least $10.00 and vouches lines out of it. Takes 25% of the fees its agents pay. Pays first when one of them defaults. Stake that backs nothing can leave at any time.
agent
An owner wallet with a name and a purpose. Takes $1.00 to $500.00 per loan, one to thirty days, priced at 1% per 30 days, never above what its backer signed for. Keeps its own wallet; nothing is held for it.
treasury
Takes 15% of every fee. Backs first lines for bonded agents out of its own stake, and receives forfeited bonds.

§ 02

A loan from borrow to default

Four states. The last one is the reason the backer exists.
Open

borrow(P, days)

Late

past the due date, inside 3 days of grace; repaying still works but costs a rung

Repaid

principal + accrued fee, any time before default

Defaulted

3 days past due, anyone marks it; the backer pays

defaultengine.ts · defaultWaterfall()
markDefault(loan):   require now > dueAt + 3 days      // anyone can call it
                     owed  = P + fee accrued to now
                     paid  = min(owed, stake(backer))   // the backer pays first
                     pool += principal part of paid     // lenders made whole up to the stake
                     loss  = P - principal part of paid // zero whenever the vouch covered P
                     record(a).defaulted = true         // score 0, no new line, ever
                     bond(a) -> treasury                // if the line came from a bond

Run one loan

Example
Outcome

Defaulted after 14 days plus 3 of grace. Owed: $50.283334.

Backer's stake pays
$50.00
Lenders lose
$0.00
Fee recovered (lenders / treasury)
$0.00 / $0.00
Backer stake left
$0.00

The stake covered everything. In Craf a line can never exceed what its backer vouched, so this is the normal case.

Computed in your browser by src/lib/credit/engine.ts, the same module the practice book runs on. 1 USDG = 1000000 units.

§ 03

Credit lines and the agent credit score

A line has a ceiling set by the record and a cap set by the backer. The score is a public summary of the same record; nobody sets it by hand.
RungCeiling7-day loans repaid on timeDays on the booksPrincipal returned
0$5.0000$0.00
1$10.0017$5.00
2$25.00314$20.00
3$50.00630$100.00
4$100.001045$400.00
5$250.001660$1,500.00
6$500.002490$5,000.00

A loan counts as week-long when it is held at least 7 days and repaid by its due date. Each late repayment drops the agent one rung.

Money held and returned

USDG × days held on repaid loans, one point per 10 USDG-days

up to 400

Loans held seven days or longer

20 points each

up to 200

A backer's money behind it

one point per $5 vouched

up to 150

Days on the books

two points a day

up to 150

Repaid by the due date

five points each

up to 100

Late repayments

and a default sets the score to zero for good

−50 each

§ 04

Invariants: what must always hold

Properties the math module is tested against. They are intended properties of the design, checked by unit tests today; the contracts will need the same checks as stateful fuzzing before they hold money.

I1

Split adds up

backer + lenders + treasury = fee, for every fee; rounding dust goes to lenders.

I2

No lender loss inside the vouch

while the backer's stake covers principal, lenderLoss = 0.

I3

Line never exceeds the vouch

room(a) ≤ vouched(a) − outstanding(a), and a defaulted agent's room is 0.

I4

Fees only grow with time

fee(P, t2) ≥ fee(P, t1) when t2 ≥ t1; one-day minimum.

I5

Conservation on default

paid by backer = principal recovered + fee recovered; principal recovered + loss = P.

I6

Shares are fair

a deposit at the current share price mints shares worth what was paid.

Run them yourself: npm test in the repository.

§ 05

Protocol parameters

The numbers the practice book runs on, and the defaults proposed for the contracts.
ParameterValueMeaning
minLoan / maxLoan$1.00 / $500.00size of one loan
term range1 d / 30 dhow long a loan can run
fee1% per 30 daccrued by the second on time held, one day minimum
split25 / 60 / 15backer / lenders / treasury
grace3 dafter the due date, before anyone can mark a default
minStake$10.00to count as a backer
bond$5.00refundable, for a treasury-backed first line
firstLine$5.00rung 0 ceiling
qualify7 da loan held this long and repaid on time counts toward the ladder

§ 06

$CRAF and the treasury

$CRAF goes live through Pons, the launch venue on Robinhood Chain. It is not required to borrow, lend or back.

The treasury earns 15% of every fee and receives forfeited bonds. It uses its own stake to back first lines for bonded agents, so a newcomer never has to find a stranger to vouch for a $5 line.

A proposal for after launch: holders could stake $CRAF as a seat behind an agent with a clean record, sharing the backer's 25% and losing part of the seat on a default. It needs a price oracle for the token and a deep enough market; it is not built and nothing on this site depends on it.

Fees in15% of every fee paid
Bondsforfeited bonds from defaulted agents
Outfirst-line stake for bonded agents
Seatsproposal; needs an oracle and an audit

§ 07

Contract interface, as designed

The calls an agent, a backer and a lender will make once the contracts exist. Today the practice book exposes the same verbs through signed messages.
deposit(uint256 assets) → shareslender
withdraw(uint256 assets)lender
stake(uint256 assets) · unstake(uint256 assets)backer
vouch(uint256 agentId, uint256 amount) · release(uint256 agentId)backer
register(string name) → agentIdagent owner
postBond(uint256 agentId)agent owner
borrow(uint256 agentId, uint256 amount, uint32 termDays, address to)agent owner or its key
repay(uint256 loanId)anyone
markDefault(uint256 loanId)anyone, after grace
score(uint256 agentId) · lineOf(uint256 agentId)view

§ 08

What is live and what is practice

So nobody has to guess.
USDG token facts (symbol, decimals, supply)read from the token contract every few secondslive
Your ETH and USDG balancesread from the chain for the connected walletlive
Block, gas, ETH pricechain RPC and OKX spotlive
Stock token pricesChainlink feeds on Robinhood Chainlive
Lend, back, register, bond, borrow, repay, defaultwallet-signed actions on a shared practice book; balances reset after 30 days of inactivitypractice
Fee math, line ladder, waterfall, scoresrc/lib/credit/engine.ts, with unit testspractice
Credit pool, backer vaults, agent registrycontract design written, not deployedplanned
$CRAF seatsproposal onlyplanned
Live from chainPractice · signed, not sent

§ 09

Contract and token addresses

On Robinhood Chain (id 4663). Only addresses that exist are listed as such.
USDG (Global Dollar)0x5fc5360D0400a0Fd4f2af552ADD042D716F1d1686 decimals, read on-chain
Craf credit pool—not deployed
Backer vaults—not deployed
Agent registry—not deployed
$CRAF—published at launch

Explorer: https://robinhoodchain.blockscout.com