Alerts Morpho vault depositors when a curator queues a timelocked change.
When you deposit into a Morpho vault, a curator decides which markets your funds are lent to and against which collateral. The curator can change those rules — raise a supply cap, accept a new collateral, remove a market, replace the guardian, or change the timelock itself.
They cannot do it instantly. Every such change is queued publicly and becomes executable only after the vault's timelock, typically 3 to 7 days. That delay exists for one reason: to give depositors time to withdraw if they disagree.
The queued action is public on-chain and exposed through the Morpho API. Nothing notifies the depositor. The protection window exists, and almost nobody watches it.
Scanning the 40 largest listed Ethereum vaults above $2M on 2026-07-19:
- 13 pending actions across 11 vaults
- 12 of them were already past their timelock, executable at any moment
- the oldest had been executable for 152 days (Gauntlet WETH Prime, a new supply cap on the weETH/WETH market)
- one became executable 5 hours before the scan (Gauntlet USDT Frontier, a $5M cap on PT-SIERRA-6AUG2026/USDT)
A pending action is not inherently bad — most are routine curation. The point is that the depositor is never told, so the notice period only protects those who happen to look.
Requires Node 22.6 or later. No runtime dependencies.
git clone https://github.com/Chad-Mufasax/morpho-watchtower
cd morpho-watchtower
npm install
npm run scan # one pass, prints every pending action
npm run watch # polls on an interval, alerts only on new ones
Without DISCORD_WEBHOOK_URL, findings are printed to stdout.
| Variable | Default | Meaning |
|---|---|---|
DISCORD_WEBHOOK_URL |
— | Discord webhook. Unset means stdout. |
CHAIN_IDS |
1 |
Comma-separated chain ids. |
VAULT_LIMIT |
100 |
Vaults to scan, largest first. |
MIN_VAULT_USD |
1000000 |
Skip vaults smaller than this. |
INTERVAL_MINUTES |
60 |
Poll interval in watch mode, clamped to 15–1440. |
STATE_PATH |
.watchtower/state.json |
Where seen actions are recorded. |
One GraphQL query against api.morpho.org/graphql pulls each vault's
state.pendingConfigs, whose decodedData union carries the typed payload of the queued
action. Each action is fingerprinted on vault, chain, function, execution time and target,
so a restart never re-alerts on something already reported. New actions are described in
plain language and pushed to Discord.
Severity weighs the type of action, the size of the vault, and whether the timelock has already elapsed. Guardian and timelock changes rank highest: they alter the protection mechanism itself.
The Morpho API allows 750 requests per minute and has no SLA. Exceeding roughly 20,000
requests per hour returns Retry-After: 604800 — a seven-day ban.
The client is built around that. A token bucket caps outbound traffic at 60 requests per
minute by default and is hard-limited to half the documented ceiling. Retry-After is
always honoured. Above one hour it is treated as a ban rather than a delay: the circuit
opens, the deadline is persisted to disk, and the process refuses to start again before it
expires. Retrying through a ban is what turns a short suspension into a long one.
A full scan of 100 vaults costs three requests.
- Reads the Morpho API only. If the API is down or wrong, so is this. It is not an independent view of chain state.
- Polling, not streaming. The API exposes no webhooks or subscriptions, so an action can be up to one interval old when reported.
- Vaults V1 shape. Vault V2 uses a different configuration model and is not covered yet.
- No opinion on whether a change is good or bad. It reports that one is queued and when it applies; judging it is the reader's job.
- Beta. Run it alongside your own checks, not instead of them.
MIT