# Governance risk

> Who can unilaterally change a pool, a market, a token or a vault - and how that is classified and scored.

Source: https://docs.1delta.io/risk/governance/

---

Every governance screen answers one question: **can a single key unilaterally
change this contract and harm users?** The same classifier is applied to lending
pools, isolated markets, tokens and vaults, so the tiers mean the same thing
everywhere.

The bar:

> The contract must not be upgradeable by a single EOA. Prefer a real multisig
> (ideally with a timelock) or a DAO.

---

## The classifier

Given any governance root address, resolve what it actually is and map it to a
tier:

| Root resolves to | Tier |
| --- | --- |
| EOA, or a timelock whose admin is an EOA | **high** |
| Safe with threshold below 3, or fewer than 5 owners | **medium** |
| Safe of at least 3-of-5, or a timelock fronted by such a Safe | **low** |
| DAO governor, or a cross-chain governance system (executor plus payload controller) | **low** |
| `address(0)` — governance renounced, contract finalised | **low** (safest) |
| Unclassifiable contract, or the read failed | **unknown** |

Two details matter more than the table:

**The owner chain is walked, not read once.** A `CUSTOM` owner is not a dead end.
Aave's pool admin is an executor owned by a delayed payload controller which owns
the executor back and carries the guardian Safe; naive classification reports
"custom, manual review" while the honest answer is a DAO with a delay. Cycles are
detected, and cross-chain setups (a timelock whose admin is an omnichain executor)
resolve to governance rather than unknown.

**Infrastructure errors are never answers.** A rate-limited Safe read is retried,
not recorded as `CUSTOM`. A throttled proxy-slot read is retried, not recorded as
"immutable". A revert is a real answer; a 429 is not. Reads rotate across RPC
endpoints with backoff, and a sweep that could not resolve a market re-probes only
the unresolved ones on the next run.

---

## Pooled lenders

For Aave-style and Compound-style forks, the governance root is the pool
administrator, resolved per deployment:

| Family | Root |
| --- | --- |
| Aave V2/V3 forks | `pool -> AddressesProvider.owner()` |
| Compound V2 forks | Comptroller `admin()`, else `owner()`, else the EIP-1967 proxy admin |
| Compound V3 (Comet) | `Comet.governor()` |

Compound V2 and V3 are architecturally unrelated and are kept in separate data
sets; a lender belongs to exactly one. The resulting tier feeds the protocol
score as described in [Protocol risk](https://docs.1delta.io/risk/lending-protocols/).

---

## Isolated markets: three trust vectors

On Euler, Silo, Fluid and similar protocols, one tier per protocol is the wrong
model. Each market is screened on three separate surfaces:

| Component | What it controls | Euler V2 | Silo |
| --- | --- | --- | --- |
| **market / vault** | the lending vault itself | eVault `governorAdmin()`, `0x0` = finalised | the silo contract |
| **config** | LTVs, caps, parameters | eVault params (same governor) | `siloConfig` (immutable) |
| **oracle** | the price the market liquidates on | `EulerRouter.governor()` | solvency-oracle owner |

The market's tier is the **worst of the three** — they are separate ways to lose
the same deposit. In practice the oracle operator is the highest-yield lever: an
EOA that can re-point a router can price collateral at anything it likes, which
puts every deposit in that market at risk regardless of how sound the vault
itself is.

Markets are keyed by the app's `marketUid`, so governance joins one-to-one with
oracle ratings and collateral data. Because isolated-market protocols usually
share one central root (every vault of a family resolving to the same factory
owner), roots are memoised per chain.

Morpho Blue is intentionally excluded: the singleton is immutable, and its
per-market risk is curation and oracle choice, not governance.

---

## Token governance

Tokens are screened on two dimensions and rated worst-of:

**Upgradeability** — detect EIP-1967 (transparent, UUPS, beacon) and legacy
slots; no slot means immutable. Resolve the upgrade authority (transparent to the
admin slot, hopping an OZ `ProxyAdmin` to its owner; UUPS to `owner()`; beacon to
the beacon owner) and classify it.

**Mint authority** — enumerate `MINTER_ROLE` holders *and* the role admin who can
grant it, plus `masterMinter()` and bare `minter()`. An EOA minter and an EOA
role-admin are the same risk: one key can inflate supply.

| Situation | Score | Level |
| --- | --- | --- |
| Immutable, no proxy | 1 | green |
| Upgradeable, admin tier low (timelock or strong multisig) | 2 | green |
| Upgradeable, admin tier medium (small multisig) | 3 | yellow |
| Upgradeable, admin unclassified | 4 | red |
| Upgradeable by an EOA | 5 | red |
| Could not be probed | not merged | unknown |

A **capability floor** applies on top: a token whose admin can blacklist, pause
or seize is floored at 3 (yellow) even when the code is otherwise well governed —
the admin can act on your balance directly.

Tokens that could not be probed are left out entirely rather than merged with a
guess, so a transient RPC outage never fabricates a rating. Exotic proxies
(Aragon, diamond, custom) and governor-contract admins are handled by curated
overrides.

---

## Vault governance

A vault depositor is exposed to two governance surfaces, rated on the same 1-5
ladder and combined worst-of:

- **Its own timelock** — the notice period before a curator can change caps, add
  a market or swap the allocator. At least 3 days scores 2; at least 1 day scores
  3; under a day, including zero, scores 4. A vault with no timelock can be
  pointed at a new market in a single transaction with no window to withdraw.
  Only providers where the timelock is a real parameter are scored — absence of
  the concept is not a timelock of zero.
- **The governance of the markets it lends into**, taken over positions that are
  material (at least 5% weight). A sound vault over markets whose oracle an EOA
  can swap is not sound.

Vault governance raises the reported level but stays out of the weighted mean —
see [Vault risk](https://docs.1delta.io/risk/vaults/).
