How it works
One signature, five calls, the rule inside the contract that keeps every loan at or under 40%, recording an existing loan, and the guard that watches it afterwards.
When you pay a bill from bitcoin, your wallet signs one transaction. That transaction runs five calls in order, all of them as you. If any one of them fails, the whole transaction is undone and nothing happened.
A company paying a run of supplier bills signs the same way: up to 10 bills in one transaction, grouped by currency, each paid through its own Memo call with the supplier's invoice number, and the contract's 40% check still applied to every payment that adds debt. A company that pays from its Safe gets the same bills in one Safe transaction instead: see Safe payments.
The one-signature batch
These are the five calls, in the order the app builds them. P is the pledge, A the bill amount, C the bill's currency (USDC or EURC), N the bill number and R the invoice reference.
cirBTC.approve(Morpho, P): let Morpho take exactly the pledge.Morpho.supplyCollateral(params, P, payer, 0x): pledge the bitcoin. It stays pledged in your name, never sold.Morpho.borrow(params, A, 0, payer, payer): borrow exactly the bill, to your own wallet.C.approve(AdagBills, A): let Adag move exactly that amount.Memo.memo(AdagBills, payData(N), memoId(N), R): pay billNthrough Memo, with the reference attached.
A few rules hold for every batch the app builds:
- Every call targets an address fixed when the app was built: AdagBills, AdagGuard, Morpho, Memo, Multicall3From or one of the three tokens. Nothing in a link or an RPC answer can change a target, a receiver or an amount.
- Approvals go only to the contract that uses them, for exactly the amount that batch uses.
- Every call is marked "must succeed". There is no partial success.
- Market details fetched from the chain must hash to the fixed market id before they go into a call, so a lying RPC cannot swap in a different market.
If your existing pledge already covers the loan, steps 1 and 2 are left out. Paying from a USDC or EURC balance is just steps 4 and 5. Several bills can go in one signature, grouped by currency, up to 10 bills per batch.
The pledge the app proposes is what the contract's own collateralNeeded view asks for, plus a 5% margin to absorb a price move before the block lands. If the margin is not enough, the transaction reverts with LtvAboveLimit. It never over-borrows.
Memo and Multicall3From
Two small contracts that ship with Arc make the single signature possible.
Multicall3From (0x522fAf9A91c41c443c66765030741e4AaCe147D0) takes a list of calls and runs them through Arc's CallFrom precompile. The effect is that every call reaches its target with your wallet as the sender. Morpho sees you pledging and borrowing for yourself, so it needs no extra permission. The tokens see you approving. AdagBills sees you paying.
Memo (0x5294E9927c3306DcBaDb03fe70b92e01cCede505) wraps the payment call and emits a Memo event carrying the bill number and your reference, so the supplier's invoice number travels with the money.
A Memo event on its own proves nothing, because anyone can emit one with any bill number. Adag's app treats a bill as paid only when that bill's own AdagBills says so in storage, or when there is a BillPaid event from that contract's address, tied to a transaction hash and log index.
Why this only works on Arc
- Batches that act as your wallet. CallFrom lets one signed transaction run several calls as the signer, from a plain wallet. On most chains you would need a smart-contract wallet, or several signatures, and the lending market would see a batching contract as the borrower instead of you.
- A native memo. Attaching an invoice reference to a payment is a first-class Arc feature, not a custom log format.
- Fees in USDC. Gas is paid in USDC, the same currency as the bill. A bitcoin-backed payment costs about 0.008 USDC in fees.
- Morpho Blue with cirBTC markets. Arc has live Morpho markets lending USDC and EURC against cirBTC, with Chainlink price feeds. Adag is fixed to those two markets.
The new-debt rule
The 40% check lives inside AdagBills' pay function, so it applies however the transaction was built: by this app, by a Safe, by a script, or by hand.
On every payment, for both markets, Adag compares your live Morpho position with the last one it recorded for you. The check runs whenever you have debt and your position has become riskier by your own action since then: more borrow shares, or less pledged collateral. When it runs:
- Debt is your borrow shares converted to assets, rounded up, after interest is brought up to date in the same transaction.
- Collateral value is your pledged cirBTC times the oracle price, rounded down.
- The payment reverts unless debt is at or under 40% of that value, read from live Morpho and oracle state. Nothing you pass in can stand in for it.
- A new loan also needs a fresh price: the BTC/USD feed no older than 26 hours, and EUR/USD no older than 96 hours for the euro market.
A payment from your balance that adds no new debt is never blocked by a price drop. The rule only guards new borrowing.
The first version of this rule compared borrow shares only. A separate review found it could be skipped: pay once, close the loan outside Adag, then re-open it with exactly the recorded share count against far less bitcoin. The rule now records both shares and collateral, and a randomised invariant test that includes that exact attack fails within 5 calls if the old rule is put back. See Audit status.
Recording an existing loan
A wallet that Adag has never seen has a recorded position of zero, so any loan it already holds counts as new debt at its first payment. If that loan is above 40%, the payment is refused, even one paid from cash.
enrol() fixes that. It takes no arguments and records the caller's own Morpho position in both markets, exactly as Morpho reports it in that block. No money moves, and nobody can record a position for someone else. From then on Adag judges only what you borrow after the record: a cash payment that adds no debt goes through, and borrowing more, or taking collateral away, is checked against the 40% line as before.
Recording and paying in the same block is refused (EnrolledThisBlock), so new debt cannot be borrowed, recorded and spent in one batch. The promise is that a payment through Adag is never the action that takes a position above 40%.
This was proven on 26 September 2026 on a real borrower's wallet at 70.26%, simulated on live state because only that borrower could sign: a cash payment was refused before recording; after recording, borrowing more in the paying batch was refused, and the same bill paid from cash went through. A Safe records its loan in a Safe transaction of its own: see Safe payments.
After the payment: the loan guard
Adag checks the 40% line at the moment you pay. After that, AdagGuard can watch the loan: you set a trigger and a target and approve an amount of the loan's currency, and once the loan passes the trigger anyone may call protect, which repays only what brings the loan back to your target, from your own wallet. Adag's keeper calls it when Chainlink's price updates, and Telegram alerts tell you when a loan gets close. Before a bitcoin payment that takes your loan to or past your own trigger, the pay screen says how much the guard will then repay. A payment from your balance keeps aside what the guard is about to repay and says so under the button, and if the guard cannot be read, the pay screens do not pay.
Diagrams
System overview
Multicall3From and Memo reach their targets through Arc's CallFrom precompile, which is why the wallet, not the batch contract, is the sender Morpho, the tokens, AdagBills and AdagGuard see. The keeper's wallet holds gas only and can send one thing: protect.
One bitcoin-backed payment, end to end
Contract and module dependencies
Solid arrows are code dependencies. Dotted arrows are calls to deployed contracts.
Overview
Pay your suppliers in dollars or euros from bitcoin you pledge instead of sell. What Adag is, who it is for, and what is live today.
Getting started
Pay a run of supplier bills from a company treasury or its Safe, pay a single bill, record an existing loan, protect a loan, or write a bill and get paid in USDC or EURC.