Documentation
Prove the history. Keep the collateral.
Meritr is an autonomous credit protocol on Creditcoin. It reads a borrower's real repayment history from another chain through Attestcoin, scores it into portable credit, and when a position falls into distress it restructures the debt instead of liquidating it. The borrower keeps every unit of their collateral.
Every credit fact in the system arrived as a proof the Creditcoin runtime itself validated. There is no oracle operator, no multisig relayer and no trusted price poster anywhere in that path - not as a design goal, but as a property you can test in one command.
What Meritr is
Onchain credit is amnesiac and brutal, and Meritr answers both halves.
Amnesiac: a borrower with three years of flawless Aave repayments on Ethereum arrives on a new chain as a stranger. Their history is real and public, but no contract on the destination chain can verify it without trusting somebody to report it faithfully.
Brutal: every major lending market answers distress with exactly one action - liquidation. A temporary drawdown ends the borrower's equity, dumps collateral into a falling market and pays a bonus to a bot. Traditional finance restructures distressed debt every day. DeFi seizes it.
How it works
Ethereum mainnet Creditcoin testnet (102031)
──────────────── ───────────────────────────────
Aave V3 repayment ──proof──▶ Attestcoin precompile 0x…0FD2
Aave V3 supply │ verifies inclusion
Aave V3 liquidation ▼ and continuity
MeritrAttestor ──▶ credit memory
│
▼
MeritrVault ◀── agent triggers
│ restructuring
▼
MeritrPassport (soulbound)A relayer watches Aave V3 on Ethereum, asks Creditcoin's proof-builder for a proof of each relevant transaction, and submits it to MeritrAttestor. The contract hands the proof to the precompile, and only what the precompile accepts becomes a credit fact.
Where everything lives
- Network
- Creditcoin CC3 testnet, chain id
102031 - MeritrAttestor
0xB462C2772b8003e3c511C373dDC5715642B34D4c- MeritrVault
0x233D2aE279230fBFFbe61e6dF2A9DC6bF6ff3e84- MeritrPassport
0xAdd2C477A101250C8A3e6Fe26a642143F610A601- BlockProver precompile
0x0000000000000000000000000000000000000FD2- ChainInfo precompile
0x0000000000000000000000000000000000000FD3- Proof-builder
https://proof-gen-api.cc3-testnet.creditcoin.network- Source chain
- Ethereum mainnet, Aave V3 -
chainKey 3 - Live console
- /app
- Source
- mrnetwork0001/Meritr
- Project deck
- deck.pdf
- Creditcoin docs
- docs.creditcoin.org
- Source verification
- every contract above is source-verified on Blockscout - the links open the code, not the bytecode
Attestcoin integration
Attestcoin is Creditcoin's decentralised oracle: attesters watch a source chain, reach quorum, and submit attestations to an attestation chain. A smart contract can then hand a proof to the BlockProver precompile and trust the fields it decodes. Creditcoin calls this half of the protocol readability, and it is what Meritr uses.
MeritrAttestor inherits ASCBase from @gluwa/asc-contracts. Ingestion sets the active chain key, then self-calls execute so that a direct call to the inherited entry point reverts with DirectExecuteForbidden - the contract will not process a payload that did not come through its own front door.
Which logs count is not hardcoded. An onchain schema registry keyed by (chainKey, emitter, topic0) decides whether a log is a repayment, a collateral supply, a borrow or a liquidation, so a new market can be registered without redeploying the contract.
Chain keys
A chainKey is not an EVM chain id, and its value differs per Creditcoin network. This is the single easiest way to get an Attestcoin integration silently wrong: a mismatched key fails no assertion, it simply means no proof ever matches a schema and the credit history stays empty forever.
- Ethereum mainnet, on Creditcoin testnet
chainKey 3- Sepolia, on Creditcoin testnet
chainKey 1- Ethereum mainnet, on Creditcoin mainnet
chainKey 1- Base, Solana, anything else
- not registered - Attestcoin cannot prove it
Meritr does not trust its own table. scripts/verifyChainKeys.js reads the ChainInfo precompile at 0x…0FD3 and compares it against the catalogue, and deployment aborts on a mismatch.
Credit scoring
Proven facts fold into a 300-900 score through CreditMath.sol, across five weighted components: repayment volume, repayment count, collateral history, wallet maturity and liquidation penalty. The weights sum to basis-point precision so no component can silently dominate.
The score sets the borrower's interest rate band and borrowing capacity. It is recomputed onchain from attested facts, never supplied as an argument.
Vault & restructuring
The load-bearing design decision in the entire protocol is this signature:
function restructure(address borrower)
external
returns (uint256, uint256, uint256);No rate. No amount. No score. No signature over off-chain numbers. The vault re-reads the score from MeritrAttestor - whose every input carries an Attestcoin proof - and recomputes each term through the same library the agent used. The agent decides whether and whom. The chain decides how much.
Restructuring cuts the rate, extends the term and retires debt from a protocol reserve toward a health factor of 1.35 - drawing at most 25% of the reserve in one event, and nothing at all when the reserve is empty, in which case it degrades to rate relief and a term extension. It has no code path that moves collateral at all; seizure exists only in the separate liquidation backstop, which activates below a health factor of 1.
Credit passport
MeritrPassport is a soulbound ERC-721: transfers revert in the _update hook, and approve and setApprovalForAll revert outright. Artwork is generated fully onchain as SVG, so the token depends on no external host.
What the agent decides
The DeAI risk agent watches every open position, ranks them by expected loss averted, and triggers restructuring on the position where intervention is worth the most. That ranking is the entire scope of its discretion.
Its arithmetic is checked against the chain's. agents/scoring.py mirrors CreditMath.sol exactly, including integer truncation, and a parity suite runs vectors generated from the deployed library asserting every component of every score matches. A one-wei divergence fails the build.
Safety model
- A compromised agent key can
- trigger restructurings the protocol would already have approved
- It cannot
- invent a score, grant itself a rate, choose an amount, or drain the reserve
- If the agent goes offline
- anyone may trigger the identical restructuring after a 6-hour grace period
- Per-loan limits
- a cooldown between interventions and a hard cap on their number
- Deployer key
- never placed on the server that runs the agent
Borrower protection does not hinge on a server staying up, and the agent is not a liveness dependency for the protocol.
Run it yourself
git clone https://github.com/mrnetwork0001/Meritr cd Meritr && npm install python3 -m venv .venv && .venv/bin/pip install -r requirements.txt npx hardhat test # 50 Solidity tests .venv/bin/pytest -q # 39 Python tests, incl. score parity npm run backend # risk API npm run dev # console
Verify the proofs
The claim that no key can insert a credit fact is worth exactly what the precompile's refusal is worth, so you can make it refuse on demand. This fetches a real Aave repayment proof, asks the live precompile to judge it, flips a single byte inside the proven transaction, and asks again:
npm run verify:proof genuine proof -> ACCEPTED one byte altered -> REJECTED (Merkle proof validation failed)
verify is a view function, so this costs no gas and needs no funded account. Every fact in MeritrAttestor cleared that same gate.
What is real
Creditcoin testnet has no canonical stablecoin, so the lending market trades a demo pair Meritr deployed itself. Both tokens have an open mint and are worth nothing. That is disclosed rather than papered over - and it does not reach the credit data.
- Credit facts
- proof-verified - nobody can create one without the precompile
- Borrowed asset (mUSD)
- synthetic, ungated mint, price pinned at $1.00
- Collateral (mWETH)
- synthetic unit, marked with a live Chainlink ETH/USD feed
The separation is checkable in one command:
grep -ci 'vault' contracts/MeritrAttestor.sol contracts/MeritrPassport.sol # → 0
The credit layer holds no reference to the market layer. Swapping the demo market for real assets would leave every score unchanged.
Limitations
Stated because a credit protocol that hides its assumptions is not one anyone should use.
- Collateral pricing is governance-fed
- the single trusted input in the risk path; production needs a real feed
- Source timestamps are approximated
- the prover exposes a verified height, not a verified timestamp
- The contracts are unaudited
- treat any mainnet deployment accordingly
- The demo market tokens are freely mintable
- and immutable in the vault, so swapping them needs a new deployment
- “ZK-Credit” is a commitment scheme
- not a SNARK, today