Concepts
Everything Nenrin does fits on one page: an identity, a line, a loan, a tap, a record. This is the full set of rules the contract enforces.
Identity
An agent is an ERC-8004 identity: an NFT in the identity registry whose owner is the agent's wallet. The owner, or an operator it approved for all, controls the agent on Nenrin. Borrowed USDG always goes to the owner of the identity, so whoever controls the identity controls the money and carries the record.
Lines
A backer stakes USDG with stake(amount), then offers a line with offerLine(agentId, amount, rateBps, ttl). The amount is reserved from its free stake the moment the offer is made. The agent accepts with acceptLine(agentId, backer). An agent has one backer at a time and can switch only when nothing is borrowed.
- Reduce: the backer can shrink a line down to what is borrowed with
reduceLine. - Release: either side can end a line with nothing borrowed using
releaseLine. - Expiry: an offer lapses after its time to live, up to 30 days, and keeps its reservation until the backer cancels it.
Loans
The agent calls borrow(agentId, amount, term) for 1 to 30 days, within its line, with at most four loans open. The fee is fixed at that moment and rounded up:
fee = principal × rateBps × term / (30 days × 10 000) example: 10 USDG at 150 bps for 6 days fee = 10 × 0.015 × 6 / 30 = 0.03 USDG
Anyone can repay a loan with repay(loanId), paying principal plus fee. 90% of the fee goes to the backer, 10% to the reserve.
The record
The contract keeps a record per agent and every field can be rebuilt from its events.
| field | rule |
|---|---|
| rings | On-time repayment of a loan of at least 2 USDG held at least 24 hours. At most one per agent per 24 hours. |
| incomeRings | A ring whose repayment was paid by the agent's own tap. |
| thinRings | Repayment after the due date, during grace or before anyone marks the default. |
| loansRepaid | Every repayment, ring or not. |
| dollarDays | Principal times the time actually held, capped at the term. |
| scarred | Set forever by a default. |
Standing
standing(agentId) is a number from 0 to 1000 computed on chain from the record. It is zero for a scarred agent.
400 × min(rings, 120) / 120 + 300 × min(incomeRings, 60) / 60 + 200 × min(usdgDays, 3000) / 3000 + 100 × min(ageDays, 180) / 180 − 25 × thinRings (never below 0)
The tap
Every agent has a tap whose address is derived with CREATE2 from its id, so it is known before it is deployed. open(agentId) deploys it. The agent lists the tap as the payTo of what it sells.
A loan is ripe once it has been held a day, or is due within three hours, or is overdue. flow() can be called by anyone and never sends money anywhere but to Nenrin or to the agent's own wallet. Agents borrow for two days or more so that an early flow() cannot cost them a ring.
Elders
An agent's wallet binds itself to its identity with bindAgent(agentId). From then on the contract lets that wallet offer lines only while its agent is an elder (NotElder otherwise). People and other unbound addresses back freely. Each default among the agents an elder backs adds a scorch mark to its backer record.
Defaults
Three days after a due date anyone can call markDefault(loanId). The principal comes out of that loan's backer's stake, the line is released, and the agent is scarred: it can never borrow again and its wallet can never back anyone. Other open loans of the same agent keep their own clocks.
What the owner can do
The owner can pause new offers, acceptances and loans for at most 14 days at a time, set the reserve share up to 20%, lower the maximum line and withdraw the reserve. It cannot move a backer's stake, a loan, a tap or a record. Repayments, withdrawals and defaults are never paused.