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 vault | Wrapper B, the Safe | |
|---|---|---|
| Who it is for | "give me a yield" | "manage it, but I keep custody" |
| Custody | pooled, you hold shares | your own account |
| Allocation | one posture for everyone | per user |
| Onboarding | one click | more steps |
| Constraint | every market must match the vault asset | none |
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.3and policy bound on-chain. Safe operations are signed as UserOperations, batched byDirectEntryPointTransportso 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)toselectVenueto the Net-Edge gate, thendecide(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 undercore/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 path | Safe path | |
|---|---|---|
| A refusal is | cap = 0, written on-chain | nothing happening |
| Evidence | the chain itself | a ledger entry is required |
| Takes effect | immediately, a cap decrease has no timelock | |
| An approval | waits out the timelock | immediate |
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
| Claim | Status |
|---|---|
| A decision replays from published inputs | yes, content addressed |
| It ran inside attested hardware | no. There is no enclave on this deployment |
| The log is complete | not 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 modules | Safe7579 is not deployed on GIWA. Measured, no bytecode, not one 7579 account on the chain |
| A self-hosted bundler | eth_supportedEntryPoints is not whitelisted, and one submitter is not a mempool |
| New Solidity this phase | none is deployed |
Chain-level facts live in Developers / GIWA.