Architecture

Architecture

Heron is one decision core serving two kinds of customer, feeding a record that a separate agent checks without ever asking Heron anything.

The diagram is the whole system. Drag to pan, Ctrl or Cmd and scroll to zoom, or press Full for the readable version.

Everything below explains one part of it. Each section opens in plain language and closes with an Under the hood note carrying the real module and the check that holds it in place, so a depositor can read the first half and stop, and an auditor can read both.

Two customers, so two wrappers

The two paths exist because a retail depositor and a treasury cannot share one.

Wrapper A, the vaultWrapper B, the Safe
Who it is for"give me a yield""manage it, but I keep custody"
Custodypooled, you hold sharesyour own account
Allocationone posture for everyoneper user
Onboardingone clickmore steps
Constraintevery market must match the vault assetnone

Choosing between them is the one decision worth making slowly, and Getting started walks through it.

Under the hood. Wrapper A is a Heron-curated MetaMorpho vault, ERC-4626, with Heron as CURATOR. Wrapper B is a per-user Safe 1.4.1 with Safe4337Module v0.3 and policy bound on-chain. Safe operations are signed as UserOperations, batched by DirectEntryPointTransport so N users land in one transaction, and settled through EntryPoint v0.7, which is deployed on GIWA.

One core, blind to both

The core reads markets, subtracts every cost, and returns a verdict with the numbers behind it. It is not told which wrapper asked.

That reads like tidiness. It is the load-bearing rule. Heron ships two custody models, and the moment the decision can tell them apart, the two drift, and "Heron decided X" stops being one sentence with one explanation. It becomes two, and nobody outside can tell which one they were given.

Under the hood. snapshot(block) to selectVenue to the Net-Edge gate, then decide(candidate, snapshots, costs, block) to (verdict, receipt). The core imports nothing from either wrapper, and an import-graph test enforces it by reading every file under core/decide/ and asserting no import specifier matches /wrapper|safe|metamorpho|vault/i.

The accepting half is asserted beside it, that the wrappers do import the core. Without that, the rule is satisfied by a core nobody uses, and the test is green for the wrong reason.

A refusal is not the same thing on both sides

Vault pathSafe path
A refusal iscap = 0, written on-chainnothing happening
Evidencethe chain itselfa ledger entry is required
Takes effectimmediately, a cap decrease has no timelock
An approvalwaits out the timelockimmediate

On the Safe path, doing nothing looks exactly like being switched off. That single asymmetry is why the ledger is load-bearing rather than a nice extra.

Where the yield actually comes from

Morpho Blue is the only place yield is born here. Borrowers pay interest per second, and Heron's job is to work out whether entering a market pays more than entering it costs.

Some markets look attractive and are not. A market untouched for months can carry a high headline rate that no borrower is actually paying, which is why staleness is a refusal reason rather than a footnote.

Under the hood. DemandAgent creates the borrow demand, runs from a separate wallet, never the keeper, and commits its schedule hash before the run. Committing first is what stops the schedule being tuned afterwards to flatter the result.

The record, and the agent that checks it

Every decision is published at the time it is made, refusals included.

Then a separate process, on a separate RPC, re-derives the whole thing from the chain: the APY, the curve, realised yield, the decisions including refusals, the counterfactual, and one more.

The sixth check is completeness: did Heron stay silent on a candidate it should have ruled on? That is the failure a tamper-evident log cannot catch by itself, because a log can only be honest about entries that exist.

Under the hood. VDL passes the verification agent a claim and a block number, and nothing comes back. The one-way arrow is the point: an agent that could ask Heron for anything would be checking Heron's work against Heron's own answers. The AI in that agent explains findings and hunts anomalies. It never does the arithmetic.

What this shape does not give you

ClaimStatus
A decision replays from published inputsyes, content addressed
It ran inside attested hardwareno. There is no enclave on this deployment
The log is completenot established

Content addressing proves these bytes hash to X. It does not prevent omission, never publishing record N, since no auditor can prove an absence. Nor equivocation, serving two auditors different chains that are each internally consistent. Heron runs the mirror, so publishing more of it fixes neither. Independent witnesses co-signing would, and a witness Heron recruits, funds and instructs answers "did somebody other than Heron press the button" and nothing else.

An older version of these docs described an AWS Nitro enclave attesting to each decision. It does not exist here, and the code says so in its own comment.

Deliberately out of scope

Why
ERC-7579 modulesSafe7579 is not deployed on GIWA. Measured, no bytecode, not one 7579 account on the chain
A self-hosted bundlereth_supportedEntryPoints is not whitelisted, and one submitter is not a mempool
New Solidity this phasenone is deployed

Chain-level facts live in Developers / GIWA.