Search projects, hackathons, sponsors and tech

    ← All projects

    ArcAsset

    Agents that service tokenized private credit on Arc and sell the repayment data they generate.

    Demo

    About

    Private credit is large, illiquid, and serviced by hand. A small originator who wants to fund a receivable on-chain hits three walls. Issuance is bespoke: every note is a one-off legal and technical artifact. Servicing is manual, and at small ticket sizes that labour costs more than the spread. And the repayment behaviour that would let the next lender price the next note stays trapped inside whoever serviced the last one. ArcAsset is three things stacked. A note primitive. A verified-human issuer mints a note with a principal, a coupon rate and a period schedule. Lenders fund it in native USDC. Repayments land in a vault and are claimable pro-rata; the note itself is an ERC-20, so one token is one unit of principal contributed and transfers move future claims with it. An autonomous servicing agent. For every note it has been delegated, the agent advances periods, marks missed payments delinquent past their grace window, triggers distributions, and posts every action on-chain. It is paid a servicing fee in basis points out of each repayment it processes. It runs unattended — the demo shows a period settling with nobody touching anything. An intelligence storefront. Everything the agent learns doing that job — repayment punctuality per issuer, cohort delinquency curves, cure rates, and whether a missed payment was cured by the issuer or by somebody else — is sold per query, settled in USDC on Arc. The third piece is the point. The agent's job produces a dataset as a byproduct, and the dataset is the durable asset. Servicing pays for itself; the data compounds. World Selfie Check gates issuance, not lending. Repayment history is worthless without an identity anchor: without one, an issuer defaults, walks away, and reappears at a fresh address with a clean record, and past behaviour predicts nothing about a one-transaction-old address. One human, one issuing identity. Out of scope and we say so: no secondary market, no multi-tranche waterfalls, no legal wrapper, no collateral liquidation. A default is recorded, not enforced.

    How it's made

    Contracts are Solidity 0.8.24 on Foundry: IssuerRegistry, NoteFactory, RWANote, RepaymentVault and ServicingRelay. Arc. Notes settle in Arc's native currency, which is USDC at 18 decimals. Settling natively removes the ERC-20 approve step entirely — funding and repayment are one transaction, not two — and it reduces the paid-API payment check to a single value field on a receipt, instead of parsing a Transfer log that a hostile token contract could spoof. The cost is that every payout now hands control to the recipient, so payouts use call{value:} rather than transfer, because transfer's 2300-gas stipend would break any lender that is itself a contract; checks-effects-interactions became load-bearing rather than stylistic; and the vault's own accounting is authoritative rather than address(this).balance, which can be inflated by a force-send via selfdestruct. Cheap settlement is also what makes a $0.50 per-query price viable at all — that is why the data product is on Arc and not behind a Stripe page. The Graph. The subgraph is not a reporting layer bolted on at the end; it is the agent's decision surface. The agent keeps no database. It queries the subgraph, decides, and acts — so if the agent dies, state is intact on-chain and a replacement holding the same delegation resumes from the same index. The same subgraph is the read path for the web UI and the source for the paid API: one index, three consumers. Delinquency counts, punctuality and cohort rollups are maintained incrementally in handlers, so no query needs a full scan of the repayment history to answer. World. Selfie Check gates issuance and nothing else. Lending stays permissionless — adding friction to the capital side to fix a problem on the issuance side would be a straightforward mistake. A nullifier verifies at most one address, ever, and is deliberately not reassignable: a "move my verification to a new wallet" path is precisely how a defaulting issuer would escape their own history. It is not KYC and we do not describe it as such; it proves a live human, not an identity. The agent is Bun and Hono. Its decision function is pure — period state and clock in, action out — so it is unit tested with no chain and no network. The rails around it exist because the key is hot: actions are bounded per tick, so a subgraph bug cannot produce ten thousand transactions before a human notices; every action is idempotent by contract rather than by memory, since settling an already-settled period reverts and local state is lost on restart; and it confirms by transaction receipt, never by the subgraph, because the indexer lags and polling it to learn whether your own transaction landed is how you double-send. It skips a tick entirely when the indexer is more than 200 blocks behind rather than acting on stale data. ServicingRelay is written so a fully compromised agent key can grief but not steal: the servicing fee goes to a recipient fixed at issuance, never to msg.sender, and the relay cannot mint, change terms, or move funds to an arbitrary address. The intel API is HTTP 402. A request without payment returns a quote; the buyer sends native USDC with the quote id in calldata and re-requests with the transaction hash. Hashes are single-use and quotes expire. No accounts, no API keys — payment is the auth. One detail worth flagging because it is easy to get wrong and quietly misleading: cohort delinquency curves divide by the number of notes that actually reached each period, not by the original cohort size. That denominator shrinks, and dividing by the original count would understate late-period delinquency. Buckets with fewer than five notes return null instead of a rate, because three notes do not make a rate. Frontend is Next.js 16 App Router with wagmi and viem. Money is bigint integer math end to end and truncates rather than rounds — at 18 decimals a single USDC exceeds 2^53, so a float anywhere in a money path is a correctness bug, not a rounding one. Every view handles loading, empty, error and stale explicitly, and a banner shows indexer lag rather than silently serving old data.