Dev log · from public records

Every release. With the details.

What shipped on Priors, newest first: contracts, x402 services, the SDK and packages, security. Every entry comes from public records (the open-source repository, the chain and npm) and links to them. Open details for addresses, parameters and tests.

securitypriors.trade/account

Your account goes by a name, not your email

The account pages no longer show the Google account you signed in with. Your Priors account gets a name of its own, drawn at random, and you can change it on your account page to any name no other account holds.

details
  • securityThe sign-in no longer hands your email to the pages: the header, the account page and the start and Stocks pages show the account's name instead, and a browser that kept the email from before no longer shows it.
  • newA name like mossy-cedar-417 the first time you sign in, the same on every device. Edit name on your account: 3 to 20 letters, digits, - or _, unique whatever the letter case. Only you see it.
  • fixSigning in with Google on the start page makes your wallet: it no longer stops at "Making your wallet…".
sdkmcp@priors/x402 0.2.0@priors/mcp 0.2.0

@priors/x402 and @priors/mcp 0.2.0: stock lines

The npm packages read the stock vault with no setup: the tokens it accepts, whether it lends on each right now, and the collateral behind an agent's stock line.

details
  • new@priors/mcp: stock_assets (the accepted tokens, their Chainlink value, their loan-to-value, any lending hold) and stock_position (an agent's deposit and what its line can draw now). credit_status shows a stock line's collateral, and what it can draw is capped at what the vault allows.
  • new@priors/x402: robinhood.stockVault is the live vault, so creditStatus carries a stock line's collateral and stockPosition() and stockAssets() work without an address.
  • fix@priors/mcp sends one JSON-RPC call per request. The public node answers a large batch with HTTP 429, so a tool that reads many things at once (stock_assets, credit_status on an agent with a long record) could wait for minutes; it now answers in about a second.
  • sourcenpm: @priors/x402 · npm: @priors/mcp · packages/
stockscontractsStockVault

Stock lines are live

An agent can now borrow against Robinhood stock tokens. Its owner deposits one of 35 accepted tokens and the stock vault backs a line against it, valued by Chainlink. Loans on it are ordinary pool loans: same fee, same terms, same default rules.

details
  • newStockVault at 0xbEcd…02B6, root #6424, behind a Transparent proxy whose admin is the 2-of-3 Safe. It is the one upgradeable Priors contract; what the Safe can and cannot do is in SECURITY-v2.
  • newEach stock lends at its own share of its value: 50% for index funds, T-bills and the largest names, 40%, 30% or 25% for the more volatile ones, with a cap on open lines per token (stock-ltv.4663.json). A line is at most $250.
  • newA better record needs less collateral: fees paid on treasury-backed loans add up to 15 points on a 50% stock, scaled down on riskier ones, never above 70%. Loans on the agent's own stock line never count toward it.
  • newEvery new loan is checked against the collateral's value at that moment. New credit waits during a lending hold: a sharp move against the last 14 days, a pending split or multiplier change, a paused or blocked token. Repaying and closing never wait.
  • newClosing gives every token back, at once with no loan open, otherwise with the last repayment. A default seizes the deposit.
  • newSDK: stockAssets(), openStockLine(), closeStockLine(), and the stock tokens in status(). On npm, @priors/mcp 0.2.0 has stock_assets and stock_position (see the release).
  • securityReviewed before deployment; findings SV-1 to SV-12 and their fixes are listed with their tests in SECURITY-v2.
  • sourcesrc/StockVault.sol, tests in test/StockVault.t.sol and StockVaultLtv.t.sol, the 35 tokens and their feeds in stock-assets.4663.json.
scorescore 2.0.1

Score v2 weights 2.0.1

A loan backed by the agent's own stock is the agent's own money, so it doesn't count as risk someone else took on it.

details
  • changedA loan the stock vault backs counts as the borrower's own money, not as risk someone else took. No weight changes. While the vault is live, v2 scores are published under 2.0.1 only.
  • sourcedocs/SCORE-v2.md.
scorex402score 2.0.0

Priors Score v2 is live

A second score beside the on-chain one. It counts only risk someone else took on an agent, and reads x402 income from the chain, whoever settled the payment. Every point comes with its reason.

details
  • newpriors.trade/api/score-v2: every agent's score, rung and components, each with the reason it counts, refreshed every few minutes. ?agent=<id> for one agent.
  • newOut of 1000: money others held at risk on the agent (300), week-long loans backed by someone else (200), backing by others (150), age (100), debts it covered for agents it vouched for (100), x402 income (150).
  • newx402 income: payments to the agent's wallets in the last 30 days, from payers that aren't its own and paid at least 1 USDG, capped per payer and weighted by the payer's own record. Money sent back doesn't count. A loan repaid from income counts up to 25% more.
  • newPayments are read on chain from block 71,702,460 (pool v2), through any facilitator, not only ours.
  • newShown on every agent's page, in the paid API's /v1/score and /v1/report, and by score_of on the hosted MCP and in @priors/mcp 0.1.7.
  • changedNothing on chain: the on-chain score in ScoreLib and CreditLensV2 is unchanged.
contractsSeatSizer

The seat vault sizes its own seats

SeatSizer now owns the seat vault. It keeps a $PRIORS seat worth about five lines on its own, from a day-long median, inside fixed bounds.

details
  • newSeatSizer 0xd24B…5E61, deployed at block 72,572,884. The Safe owns it, and it owns SeatVaultV3.
  • newIt records the $PRIORS pool on Uniswap V4 at most once every 29 minutes, and resizes from the median of the last 24 hours (at least 24 observations).
  • newA raise goes straight to the target. A cut at most halves the seat, once a day. The seat stays between 10,000 and 2,000,000 $PRIORS.
  • newIf the ceiling would leave a default's burn under 1.5 lines, seats pause.
  • securityIt can change the seat size and that pause, nothing else: the Safe reaches every other vault power through execute, and renouncing ownership reverts. Review findings SZ-1 to SZ-7 were fixed before deployment or are bounded: SECURITY-v2.md.
  • sourcesrc/SeatSizer.sol · test/SeatSizer.t.sol · test/SeatSizerFork.t.sol, which runs against live chain state
contractsSeatVaultV3

Seat vault v3

The vault's levers now reach seats that are already open, and a seat is bound to the owner who accepted it.

details
  • newSeatVaultV3 0x59D1…80a9, block 72,192,188. SeatVaultV2 is retired, empty and paused.
  • fixV-2: a pause, or a new seat size, burn or line, now reaches open seats. canBorrow refuses new loans on a seat below the current terms.
  • fixA seat is bound to the owner who accepted it: a sale stops lending, and anyone may close the seat, every token back to the staker.
  • newfreezeSeat lets the Safe close any seat, every token back, never a burn.
  • sourcesrc/SeatVaultV3.sol · test/SeatVaultV3V2Fixes.t.sol (V-2's three proofs of concept, each failing on V3) · 518 tests passing
contractsInviteBond

An automatic invite for a 5 USDG bond

Post a refundable 5 USDG bond from the wallet that owns the agent, prove you own it, and the invite bot signs a treasury invite on the spot.

details
  • newInviteBond 0x8BE4…3275, block 72,112,874, no admin. It replaced the first deployment the same day, so a new owner's bond replaces a stale one instead of being locked out.
  • newThe bond comes back after 3 qualified repayments with none open, or 4 days after it was posted if the agent never got a line. A default sends it to the Safe.
  • fixIB-1: the bot signs only while the bond cannot come back before the invite expires.
  • sourcesrc/InviteBond.sol · test/InviteBond.t.sol
mcpapimcp.priors.tradeapi.priors.trade

Hosted MCP and a paid API

Any AI agent can read a Priors record over MCP with no key, or buy it per call over x402.

details
  • newmcp.priors.trade/mcp: Streamable HTTP, read-only, no key. An agent's record and score, the pool's figures, recent loans, and services that take x402. claude mcp add --transport http priors https://mcp.priors.trade/mcp
  • newapi.priors.trade: /v1/score/{id} and /v1/report/{id}, x402 v2, 0.03 USDG a call, settled through facilitator.priors.trade. An unpaid call answers 402 with the terms in its PAYMENT-REQUIRED header.
  • securityBoth are in the bug bounty's scope.
x402facilitator.priors.trade

The Priors facilitator

An x402 facilitator for USDG on Robinhood Chain. Merchants sign up themselves at x402.priors.trade.

details
  • newPOST /verify and /settle with a merchant key; GET /health is open. It settles only to the merchant's registered payTo, from 0.01 USDG, never payer to self.
  • new20 free settles a UTC day per merchant, then 0.015 USDG a settle from a prepaid balance.
  • newA settlement whose receipt is late is answered pending, not failed, and one authorization is never submitted twice.
  • newPayments are EIP-3009 TransferWithAuthorization on USDG, 65-byte EOA signatures for now. It isn't the only facilitator on the chain: the merchant picks.
  • sourcedocs/FLOAT.md
sdk@priors/x402 0.1.3@priors/mcp 0.1.6

@priors/x402 and @priors/mcp on npm

Pay x402 in USDG from code, or run an MCP server that lets an agent pay, borrow and repay with its own wallet.

details
  • newFirst published at 12:31 UTC; @priors/x402 reached 0.1.3 and @priors/mcp 0.1.6 the same day. npm i @priors/x402 installs the payer (createPayer({ signer }).pay(url)); npx -y @priors/mcp runs the server.
  • securityhttps only: private and local addresses are refused before the request and again at connect time, and redirects are never followed.
  • securityMoney calls run one at a time, within session totals (PRIORS_MAX_SPEND_USD, PRIORS_MAX_BORROW_TOTAL_USD). A pending payment is resent, never signed twice.
  • fixRepay only pays loans of the agent the wallet controls (NOT_CONTROLLER).
  • changedOlder versions are deprecated on npm: @priors/mcp below 0.1.6, @priors/x402 below 0.1.3.
  • sourcenpm: @priors/x402 · npm: @priors/mcp · packages/ · findings P-1 to P-9 in SECURITY-v2.md
sdkpriors-v2

SDK and CLI on v2, with x402 float

A v2 client and CLI, and an x402 client that pays from the balance and borrows only the shortfall from the agent's line.

details
  • newnpx priors-v2 join | borrow | repay | status, with addresses from deployments/4663.v2.json.
  • newsdk/priors-v2.mjs for lenders, stakers, backers and agents: every write is simulated first, and consents are checked against the pool's own digest.
  • newsdk/float.mjs: pay(url, { agentId, maxBorrow }). Authorizations last at most 600 s, and a pending payment is resent, not signed again.
  • sourcedocs/FLOAT.md · docs/PARTICIPATE.md
securityBOUNTY.md

The bug bounty moves to v2

Critical $3,000, High $1,000, Medium $250, public credit below that. Every known v2 finding is listed with its test.

details
  • newIn scope: the v2 contracts at their live addresses, SeatVaultV3, InviteBond, the npm packages, the hosted MCP and the paid API.
  • newdocs/SECURITY-v2.md: each finding with its fix or what remains, and the test that shows it.
  • changedThe Safe lowered treasury v4's caps from their launch values of $100 and $50 to $25 of new lines per 7-day epoch and a $25 second line (tx 0x940d…8cb9).
  • sourceBOUNTY.md · report privately through GitHub's vulnerability reporting
contractsCreditPoolV2CreditLensV2

Pool v2 is live

Every credit line is 100% backed by a backer's locked pool shares. A default burns them, principal and fee, so lenders never take a loan loss.

details
  • newCreditPoolV2 0x2812…DE21 with PoolV2Lib, and CreditLensV2 0x9d70…3D9B for scores and reports, from block 71,702,460 (21:45 UTC).
  • newA line needs the agent owner's EIP-712 consent. With no loan open, an agent can move to another sponsor.
  • newThe owner is a 48-hour TimelockController 0x5d98…F87c; the Safe proposes and executes. The Safe is guardian: a pause lasts at most 14 days, and exits never pause.
  • newLoans of $5 to $500 for 1 to 30 days, with 3 days of grace. The fee is 1% per 30 days, pro rata, split 60% to lenders, 25% to the sponsor and 15% to the reserve; a sponsor may add a premium of up to 2% per 30 days.
  • fixBefore launch: N-1, a self-backing loop that took lender yield (a loan's fee is now locked in the backer's stake); N-2, a utilization-cap freeze (the cap is 100%); F-1, a farmable keeper bounty (set to 0).
  • changedEvery v1 repayment record was imported (importFromV1), and v1 is paused.
  • sourcesrc/CreditPoolV2.sol · test/CreditPoolV2Invariants.t.sol · 404 tests passing at release
contractsTreasurySponsorV4SeatVaultV2

Three ways onto the ledger

A treasury invite, a $PRIORS seat, or a backer who stakes USDG and vouches directly.

details
  • newTreasurySponsorV4 0x0c50…D573: $5 against an invite, a second line once seasoned (3 qualified loans, 14 days, a score of 100 or more), idle lines reclaimed after 30 days. Invites use EIP-712 domain "Priors Treasury", version 4.
  • newSeatVaultV2 0x6D93…6B5F: a staker's $PRIORS seat backs a $5 line, the agent needs 3 repaid loans, and half the seat burns on a default. Replaced by V3 the next day.
  • fixX-1: offers are bound to the agent's owner. X-2: idle seats expire after 30 days.
  • newAnyone can run a root with $10 or more of stake and vouch for an agent, with its consent.
  • sourcesrc/TreasurySponsorV4.sol · src/SeatVaultV2.sol
contractsTreasurySponsor v3

A first line needs an invite

Treasury v3 opens a first line only against an EIP-712 invite from a key the treasury's owner named. Registration stays permissionless.

details
  • newTreasurySponsor v3 0x59f2…77Df.
  • newfirstLine(id, expiry, invite): an invite names one agent and a deadline. NotInvited, InviteUsed and InviteExpired decode to sentences in the SDK, which gained signInvite() and parseInvite().
  • newscripts/verify-migration.mjs checks each deployed contract's runtime bytecode against the compiled artifact.
securityBOUNTY.md

A bug bounty

BOUNTY.md: rewards for valid findings in the live contracts.

contractssecurityCreditPool

The reviewed pool, with every record carried across

CreditPool isn't upgradeable, so the review's fixes shipped as a new pool, and every agent's repayment history came with it.

details
  • newCreditPool 0x0259…44e5 at block 68,593,823, with TreasurySponsor 0x9338…4daC and ReserveFunder 0x3234…B72d, owned by a 2-of-3 Safe.
  • fixunvouch is bounded by drawn principal; a dead root's earmarked stake is charged before the reserve; a settled, defaulted root can take its own stake back; duration parameters and importRecords are bounded.
  • fixAdopting an orphaned agent now requires it to owe nothing. An invariant at depth 400 found that one.
  • newAn early-exit fee: 0.5% inside 7 days, zero after. It is a constant, not a parameter, and the hold clock is share-weighted, so a dust deposit can't restart it.
  • securityAdvisory GHSA-4j38-23rc-qmv9, credited to llen, showed two of these defects in the previous pool's bytecode; they were already fixed in source. Its proposed invariant is now in the suite.
  • sourcetest/AuditHardening.t.sol · SECURITY.md · 123 tests passing
sdkpriors

Reverts that say what broke

The SDK asks the contract for fees, decodes all 34 custom errors, and simulates every write before it spends gas.

details
  • changedquote() calls the pool's quoteFee and reports withinTermLimits and withinSizeLimits.
  • newexplainRevert(); firstLine, raise, borrow, repay and register run a staticCall first.
  • fixGas estimates get 25% headroom; unused gas is refunded.
contractsCreditPool

Live on Robinhood Chain

The credit pool goes live on mainnet: ERC-8004 agents borrow USDG against their repayment record.

details
  • newCreditPool 0xd970…AC95 at block 67,729,526 (06:35 UTC), with a TreasurySponsor and a ReserveFunder.
  • fixThe same morning: a root's earned credit could be spent twice after a default. Whatever a root's stake cannot cover is now written off against what it earned, so the reserve backs it once.
  • changedThe fix shipped as a new pool, 0x4B9f…d122 at block 67,845,567. importRecords carried the repayment history across: reputation only, sealed on the first deposit.
  • fixmarkDefault consumes only the liable slice of backing for each loan.
  • sourcetest/ReviewPoC_RootEarnedDoubleSpend.t.sol · test/DefaultAccounting.t.sol
sdkpriors

Failover, and a broadcast sent once

RPC_URL takes a list of endpoints tried in order, and a transaction broadcast is never retried.

details
  • newEndpoints are tried in priority order, each attempt capped at 6 s. A node that refuses to serve moves on; a revert does not.
  • fixA broadcast is attempted exactly once, because a retry could pay twice.
  • fixregister() reads the agent id from the ERC-721 mint made to the caller.
securitySECURITY.md

A security policy, and CI on every push

Private vulnerability reporting on GitHub. Every push runs forge fmt, build and test, npm test and the publish guard.

contractssdkpriors 0.1.0

The repository goes public

Contracts, SDK, CLI and an agent skill. npm run quickstart walks a fresh agent through a loan and a score on a local chain.

details
  • newskills/priors: tell a coding agent "give my agent a credit history on Priors". AGENTS.md carries the same for other harnesses.
  • newScore v1 in ScoreLib: up to 400 points for dollar-days repaid, 200 for loans held 7 days or more, 150 for backing, 150 for age and 100 for recourse honored. An agent's own default is 0.
  • newA publish guard that fails the build on a tracked key or credential.
  • sourceREADME.md · src/libraries/ScoreLib.sol · skills/priors/SKILL.md