# Staking Rewards API Documentation
> Documentation for the Staking Rewards APIs — accurate, up-to-date staking data and ratings covering 60+ assets and hundreds of providers. Includes the Staking Data API (GraphQL), the Ratings API (REST), and billing/subscription management.
Full documentation contents are inlined below, grouped by section. Each page is preceded by its source URL.
---
# Overview
## Welcome
Source: https://docs.stakingrewards.com/
# Staking Rewards API Documentation
The Staking Rewards APIs provide access to accurate and up-to-date staking data, covering over 60 Assets and hundreds of Providers.
## Choose Your Path
## Our APIs
## Shared Infrastructure
Both APIs use the same **API keys** and **credit-based billing**. See [Billing](/billing/subscriptions-and-credits) for details.
---
# Getting Started
## Quick Start Guide
Source: https://docs.stakingrewards.com/get-started/quick-start-guide
## What We Offer
Our API provides access to comprehensive staking data for developers, staking enthusiasts, data analysts, and anyone interested in gaining a deeper understanding of digital assets, staking providers, validator nodes, and more.
The API requires an API Key for access and uses a GraphQL endpoint returning JSON responses. It's designed for both experienced developers and beginners.
## Getting an API Key
We believe that the best tools aren't exclusive, but accessible to everyone, regardless of their circumstances.
**Free Tier Available** — We offer a free tier for hobbyists, enthusiasts, students, and startups.
Request your API key at: [https://www.stakingrewards.com/data-api](https://www.stakingrewards.com/data-api)
We also offer four paid tiers: **Standard**, **Startup**, **Advanced**, and **Professional**.
## Prerequisites
To use the API, you'll need:
1. **GraphQL client** — Examples: Apollo Client (JavaScript), Relay (JavaScript), Graphene (Python)
2. **GraphQL knowledge** — Basic understanding recommended; resources available at [graphql.org/learn](https://graphql.org/learn/)
## API Endpoint
```
POST https://api.stakingrewards.com/public/query
```
All requests are `POST` requests with the following headers:
| Header | Value |
| -------------- | ------------------ |
| `Content-Type` | `application/json` |
| `X-API-KEY` | `YOUR_API_KEY` |
## Implementation Examples
```javascript
const endpoint = "https://api.stakingrewards.com/public/query";
const query = `
{
assets(where: {symbols: ["ETH"]}, limit: 1) {
name
slug
description
symbol
}
}
`;
fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": "YOUR_API_KEY",
},
body: JSON.stringify({ query }),
})
.then((response) => response.json())
.then((data) => console.log(data.data));
```
```python
import requests
endpoint = "https://api.stakingrewards.com/public/query"
query = """
query {
assets(where: {symbols: ["ETH"]}, limit: 1) {
name
slug
description
symbol
}
}
"""
headers = {
"Content-Type": "application/json",
"X-API-KEY": "YOUR_API_KEY",
}
data = {"query": query}
response = requests.post(endpoint, json=data, headers=headers)
if response.status_code == 200:
print(response.json())
else:
print("Error occurred:", response.status_code)
```
## Sample Response
```json title="Sample response"
{
"data": {
"assets": [
{
"name": "Ethereum",
"slug": "ethereum-2-0",
"description": "the worlds largest and most decentralised Layer1 blockchain...",
"symbol": "ETH"
}
]
}
}
```
Your API key is a secret credential. Never commit it to version control, expose it in client-side code, or share it publicly. Use environment variables to manage your key securely.
## Next Steps
- **[Hands-On for Beginners](/get-started/hands-on-for-beginners)** — New to GraphQL? Walk through the fundamentals with our interactive playground.
- **[API Reference](/staking-data-api/schema-and-objects)** — Explore the full schema, types, and available queries.
## Hands-On for Beginners
Source: https://docs.stakingrewards.com/get-started/hands-on-for-beginners
The power of the Staking Data API lies before you. If terms like JSON or GraphQL seem intimidating, don't worry — this guide will walk you through the labyrinth of tech speak.
The Playground contains seven progressive steps from novice to expert. Each step builds complexity.
## Step 1: Query Assets
Query 10 assets with their IDs, slugs, logos, and reward rates.
```graphql
{
assets(limit: 10) {
id
slug
logoUrl
metrics(where: { metricKeys: ["reward_rate"] }, limit: 1) {
defaultValue
}
}
}
```
**Key concepts:**
- `limit` parameter is required on every query level
- `isActive` defaults to `true` (only active assets are returned)
- `showAll` for metrics defaults to `false`
## Step 2: Historical Reward Rates
Query a specific asset (Polkadot) with historical reward rate metrics, filtered by creation date and ordered chronologically.
```graphql
{
assets(where: { slugs: ["polkadot"] }, limit: 1) {
name
metrics(
where: { metricKeys: ["reward_rate"], createdAt_lt: "2023-06-01" }
order: { createdAt: asc }
limit: 10
) {
defaultValue
createdAt
}
}
}
```
This introduces:
- `slugs` parameter for filtering specific assets
- Historical data queries with `createdAt_lt` (created at less than)
- Ordering results with `order` parameter
## Step 3: Query Providers
Query providers instead of assets, fetching assets under management metrics.
```graphql
{
providers(limit: 10) {
name
logoUrl
metrics(where: { metricKeys: ["assets_under_management"] }, limit: 1) {
defaultValue
}
}
}
```
**Key terms:**
- **Provider** = entity offering one or more reward options
- **Reward Option** = strategy/mechanism for locking tokens to earn rewards (example: delegating ATOM to a validator)
## Step 4: Verified Staking Providers
Query verified staking providers for Cosmos with highest AUM, including nested reward option metrics.
```graphql
{
providers(
where: { isVerified: true }
order: { metricKey_desc: "assets_under_management" }
limit: 10
) {
name
metrics(where: { metricKeys: ["assets_under_management"] }, limit: 1) {
defaultValue
}
rewardOptions(
where: { inputAsset: { slugs: ["cosmos"] } }
limit: 5
) {
metrics(where: { metricKeys: ["staked_tokens"] }, limit: 1) {
defaultValue
}
}
}
}
```
The VSP (Verified Staking Provider) program covers over 50 Providers with combined over $10 Billion in Assets under Management.
## Step 5: Liquid Staking Reward Options
Query liquid-staking reward options for Ethereum 2.0, retrieving provider details and multiple metrics.
```graphql
{
rewardOptions(
where: {
inputAsset: { slugs: ["ethereum-2-0"] }
typeKeys: ["liquid-staking"]
}
limit: 10
) {
providers(limit: 1) {
name
}
metrics(
where: {
metricKeys: [
"commission"
"staking_wallets"
"staked_tokens"
"reward_rate"
"staking_share"
"net_staking_flow_7d"
]
}
limit: 10
) {
metricKey
defaultValue
}
}
}
```
**Input vs Output Assets:**
- `inputAsset` = token deposited (e.g., ETH)
- `outputAsset` = proof of deposit received (e.g., stETH)
## Step 6: Provider Reward Options with Validators
Query a specific provider's reward options with associated validators and their comprehensive metrics.
```graphql
{
providers(where: { slugs: ["allnodes"] }, limit: 1) {
name
rewardOptions(limit: 10) {
inputAssets(limit: 1) {
name
}
validators(limit: 5) {
address
metrics(
where: { metricKeys: ["staked_tokens", "commission"] }
limit: 5
) {
metricKey
defaultValue
}
}
}
}
}
```
**Slug** is a unique identifier for assets and providers, visible in website URLs. For example, in `stakingrewards.com/earn/ethereum-2-0`, the slug is `ethereum-2-0`.
## Step 7a: Global Metrics
Query global metrics directly without filtering by specific entities.
```graphql
{
metrics(
where: {
asset: null
provider: null
rewardOption: null
validator: null
metricKeys: ["marketcap"]
}
limit: 20
) {
metricKey
defaultValue
changePercentages
}
}
```
**Global Metrics** are ecosystem-wide measurements like combined market cap of PoS assets or total staked value across all networks.
## Step 7b: Historical Global Metrics
Retrieve historical global metrics (example: net staking flow 7-day) with time-based filtering.
```graphql
{
metrics(
where: {
asset: null
provider: null
rewardOption: null
validator: null
metricKeys: ["net_staking_flow_7d"]
createdAt_gt: "2023-01-01"
}
order: { createdAt: asc }
limit: 100
) {
metricKey
defaultValue
createdAt
}
}
```
## Key Takeaways
- Always include a `limit` parameter at every level of your query
- `isActive` is `true` by default — you only get active items unless you specify otherwise
- Use `slugs` to filter specific assets or providers
- Use `metricKeys` to request specific metrics
- The `defaultValue` field contains the current/latest metric value
- For historical data, use `createdAt_gt` or `createdAt_lt` with date strings
## Next Steps
Now that you've walked through the basics, explore the full API:
- **[Schema](/staking-data-api/schema-and-objects)** — Understand how all objects relate to each other
- **[Objects](/staking-data-api/schema-and-objects#assets)** — Deep dive into Assets, Providers, Validators, and more
- **[Queries](/staking-data-api/querying-data#simple-queries)** — Learn advanced query techniques
## Use with AI Agents
Source: https://docs.stakingrewards.com/get-started/use-with-ai
Give your AI coding assistant full knowledge of the Staking Rewards API by adding a single skill file. The agent will be able to query staking data, fetch ratings, and help you write integration code — no manual API docs reading required.
## What is SKILL.md?
A `SKILL.md` file is a structured reference document that teaches AI agents how to use an API. It contains endpoints, authentication details, query patterns, and common pitfalls — everything the agent needs to make correct API calls on your behalf.
## Supported Tools
The skill follows the [Agent Skills](https://agentskills.io) open standard and works with any compatible agent:
- **Claude Code** — native skill support
- **Claude.ai** — enable via [Settings → Capabilities](https://claude.ai/settings/capabilities) (Pro/Max/Team/Enterprise)
- **Gemini CLI** — native skill support
- **OpenAI Codex** — native skill support
- **Cursor** — add as project rules
- **Windsurf** — add as project rules
- **GitHub Copilot** — add as repository instructions
## Setup
### Get your API key
If you don't have one yet, [get an API key](https://www.stakingrewards.com/data-api).
Set it as an environment variable:
```bash
export STAKING_REWARDS_API_KEY=your_key_here
```
### Install the skill
The fastest way to install is via [skills.sh](https://skills.sh/stakingrewards/skills/staking-rewards-api):
```bash
npx skills add stakingrewards/skills --skill staking-rewards-api
```
This automatically downloads and places the skill file for your AI tool.
**Manual installation from GitHub**
The skill includes `SKILL.md` and a `references/` folder with additional context files. Clone the repository at [github.com/stakingrewards/skills](https://github.com/stakingrewards/skills) to get everything:
```bash
git clone https://github.com/stakingrewards/skills.git
```
Then follow the tool-specific steps below to place the files in the right location.
### Configure your AI tool
If you used `npx skills add`, the skill is already installed.
For manual installation from the cloned repo:
```bash
# Install skill globally for Claude Code
mkdir -p ~/.claude/skills/staking-rewards-api
cp -r skills/ ~/.claude/skills/staking-rewards-api/
```
To scope it to a single project instead, install into the project's skills directory:
```bash
mkdir -p .claude/skills/staking-rewards-api
cp -r skills/ .claude/skills/staking-rewards-api/
```
If you used `npx skills add`, the skill is already installed.
For manual installation using the native Gemini CLI command:
```bash
gemini skills install https://github.com/stakingrewards/skills
```
Or copy from the cloned repo:
```bash
# Install globally
mkdir -p ~/.gemini/skills/staking-rewards-api
cp -r skills/ ~/.gemini/skills/staking-rewards-api/
# Or scope to a single project
mkdir -p .gemini/skills/staking-rewards-api
cp -r skills/ .gemini/skills/staking-rewards-api/
```
If you used `npx skills add`, the skill is already installed.
For manual installation using the native Codex command:
```bash
$skill-installer stakingrewards/skills
```
Or copy from the cloned repo:
```bash
# Install globally
mkdir -p ~/.agents/skills/staking-rewards-api
cp -r skills/ ~/.agents/skills/staking-rewards-api/
# Or scope to a single project
mkdir -p .agents/skills/staking-rewards-api
cp -r skills/ .agents/skills/staking-rewards-api/
```
Add the skill as a Cursor rule:
```bash
mkdir -p .cursor/rules
cp skills/SKILL.md .cursor/rules/staking-rewards-api.mdc
```
Alternatively, paste the contents of `SKILL.md` under **Cursor Settings → Rules**.
Add the skill as a Windsurf rule:
```bash
mkdir -p .windsurf/rules
cp skills/SKILL.md .windsurf/rules/staking-rewards-api.md
```
Alternatively, paste the contents of `SKILL.md` under **Windsurf Settings → Rules**.
Add as repository instructions:
```bash
mkdir -p .github
cp skills/SKILL.md .github/copilot-instructions.md
```
### Start querying
Ask your AI assistant natural language questions:
- *"Get the current reward rate for Ethereum"*
- *"Show me the top 10 staking providers by AUM"*
- *"What are the best-rated DeFi protocols?"*
- *"Fetch historical staking data for Cosmos over the last 30 days"*
- *"Compare validator commission rates for Polkadot"*
The agent will construct the correct API calls, handle authentication, and format the results.
## What the Agent Can Do
With the skill file, your AI agent knows how to:
- **Query staking data** — assets, providers, validators, reward options, and metrics via GraphQL
- **Fetch ratings** — DeFi and infrastructure ratings via REST endpoints
- **Filter and sort** — by metric values, date ranges, asset types, and more
- **Handle historical data** — with date filters and interval aggregation
- **Write integration code** — generate JavaScript, Python, or any language for your use case
- **Debug errors** — recognizes common error codes and suggests fixes
## Example Session
```
You: What's the current reward rate for ETH?
Agent: Let me query the Staking Rewards API for that.
The current ETH reward rate is 3.42%.
Data from Staking Rewards.
```
```
You: Show me the top 5 DeFi protocols by rating
Agent: Here are the top-rated DeFi protocols:
| Protocol | Provider | Rating | TVL | APY |
|-------------------|-------------|--------|----------|-------|
| Aave v3 WETH | Aave | A | $5.99B | 2.18% |
| Rocket Pool rETH | Rocket Pool | BB | $813M | 2.13% |
| ... | ... | ... | ... | ... |
```
Need help? Contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) or via Telegram [@berlincrypto](https://t.me/berlincrypto).
---
# Staking Data API
## Schema & Objects
Source: https://docs.stakingrewards.com/staking-data-api/schema-and-objects
The Staking Rewards API is built on GraphQL, providing a strongly-typed schema that defines all available types, fields, and relationships. This page covers the core object types, their fields, and how they relate to each other.
## Object Relationships
### Reward Options (Core Concept)
Reward Options are the core and center of the API. Each Reward Option connects to an Asset, Validator, Chain, and Provider.
Examples of Reward Options:
- Depositing ETH into Lido yields stETH
- Staking stETH in Curve produces CRV rewards
- Converting ETH to WETH via smart contract
### How Objects Connect
- **Metrics** are connected to Assets, Reward Options, Providers, and Validators for storing individual object data. This allows you to query performance metrics, staking data, and historical information for any entity.
- **Assets** are only connected to Reward Options, Metrics, and other Assets — not directly to Validators or Providers. To access provider or validator information for an asset, you must go through Reward Options.
- **Validators** are connected only to Reward Options and Metrics. They are relevant through Provider relationships, as providers operate validators across different networks.
- **Providers** are connected to Reward Options, their own Reward Option Types, and Metrics. They represent the entities that offer staking services.
### Relationship Diagram
```
Assets
^
|
Providers <-- Reward Options --> Validators
| | |
v v v
Metrics Metrics Metrics
```
You can also explore the schema interactively in the [GraphQL Playground](/playground) — the Docs panel lets you browse all types and fields.
## Schema Explorer
Browse all types, fields, and arguments. Click any type name to navigate to its definition. Use the search bar to find specific types or fields.
## Querying Data
Source: https://docs.stakingrewards.com/staking-data-api/querying-data
The Staking Data API uses GraphQL. You send queries via `POST` to the API endpoint, selecting exactly the fields you need. Every query — at every nesting level — requires a `limit` argument.
## Essentials
### The Limit Property
Every level of the query requires a limit value. If you don't define a limit, your query won't work. A limit is required, even if it's obvious the output will only be one element!
The API uses limit properties to enhance speed and efficiency through four mechanisms:
1. **Performance optimization** — Restricting returned data volume improves speed, particularly for large datasets, by reducing transmission requirements.
2. **User-controlled data** — The limit field enables users to manage data quantity and prevent information overload.
3. **Bandwidth optimization** — Mobile and low-bandwidth scenarios benefit from reduced data transmission, improving API performance and user data usage.
4. **Pagination and offset** — Combining limit with offset enables pagination, allowing large datasets to be divided into manageable sections.
```graphql title="Limit at every query level"
{
rewardOptions(
where: { inputAsset: { symbols: ["ETH"] }, typeKeys: ["pos"] }
limit: 1
) {
metrics(
where: { metricKeys: ["reward_rate"], createdAt_lt: "2023-01-01" }
limit: 5
) {
metricKey
defaultValue
changePercentages
createdAt
}
}
}
```
### The isActive Flag
The API employs an `isActive` flag to exclude inactive Assets, Reward Options, Providers, and Validators.
| Value | Description |
|-------|-------------|
| `True` | Only return active items (default) |
| `False` | Only return inactive items |
| `Any` | Return all items regardless of active status |
`isActive` is set to `True` by default. This means explicitly including `where: {isActive: True}` in queries is unnecessary.
```graphql title="Using isActive: Any"
{
assets(where: { slugs: ["ethereum"], isActive: Any }, limit: 1) {
metrics(limit: 10) {
defaultValue
createdAt
id
}
}
}
```
This query retrieves metrics for Ethereum regardless of its active status by using `isActive: Any`.
## Simple Queries
You can fetch a single data entry using a simple object query. Any argument has to be an array (except booleans).
```graphql
{
assets(where: { symbols: ["ETH"] }, limit: 1) {
id
name
slug
description
symbol
}
}
```
```json
{
"data": {
"assets": [
{
"id": "asset-id",
"name": "Ethereum",
"slug": "ethereum-2-0",
"description": "the worlds largest and most decentralised Layer1 blockchain...",
"symbol": "ETH"
}
]
}
}
```
### Response Structure
The response contains a top-level `data` field with nested results. The `assets` field contains an array of asset objects with the requested fields like id, name, slug, description, and symbol.
### Accessing Response Data
**Using forEach loop:**
```javascript title="Iterate over results"
data.assets.forEach(asset => {
console.log(asset.name, asset.symbol);
});
```
**Using array destructuring:**
```javascript title="Destructure first result"
const [ethereum] = data.assets;
console.log(ethereum.name); // "Ethereum"
```
Remember that `limit` is required for all queries, even when you expect only one result.
## Filtering Results
The `where` clause lets you narrow down results by matching fields against specific values. Every filterable field accepts an array of values (except booleans like `isActive`), and the API returns entries that match any of the provided values.
### How Filters Work
Filters are passed as key-value pairs inside the `where` argument. You can filter on top-level fields (like `symbols`, `slugs`, or `ids`) as well as on nested relationships (like `inputAsset`). When you provide multiple keys inside a single `where`, they combine with AND logic — every condition must be satisfied for an item to be returned.
For array-valued filters (e.g., `symbols: ["ETH", "SOL"]`), the API uses OR logic within that array — it returns items matching any of the listed values.
### Common Filter Fields
| Entity | Common Filters |
|--------|---------------|
| `assets` | `symbols`, `slugs`, `ids`, `isActive` |
| `rewardOptions` | `inputAsset: { symbols }`, `typeKeys`, `isActive` |
| `providers` | `names`, `slugs`, `isActive` |
| `metrics` | `metricKeys`, `createdAt_gt`, `createdAt_lt` |
| `validators` | `addresses`, `isActive` |
### Example
```graphql title="Filter by metric keys"
{
assets(where: {symbols: ["ETH"]}, limit: 1) {
id
name
slug
symbol
metrics(where: {metricKeys: ["price", "staking_marketcap"]}, limit: 2) {
metricKey
unit
defaultValue
changePercentages
}
}
}
```
This query filters assets to only Ethereum (`symbols: ["ETH"]`) and then further filters its metrics to return only the `price` and `staking_marketcap` metric keys, limiting the result to 2 metrics.
Filters on nested objects (like `metrics` within `assets`) work independently — each level has its own `where` clause and `limit`.
## Sorting Results
The `order` argument organizes results based on specified values. Sort direction options include `ascending (asc)` or `descending (desc)`, using the format `{field_name: order}`. Execution sequence determines prioritization — earlier values take precedence.
### Basic Sorting
```graphql title="Sort by launch status and name"
{
assets(order: { isLaunched: desc, name: asc }, limit: 10) {
name
symbol
slug
isLaunched
}
}
```
This demonstrates sorting assets alphabetically by name, with launched assets appearing first.
### Advanced Sorting with Metrics
Ordering supports `changePercentagesKey` or `changeAbsolutesKey` combined with `metricKey_asc` or `metricKey_desc`, where direction derives from metricKey.
```graphql title="Rank by 30-day staking marketcap"
{
assets(
order: { metricKey_desc: "staking_marketcap", changePercentagesKey: _30d }
limit: 10
) {
id
name
slug
description
symbol
metrics(where: { metricKeys: ["staking_marketcap"] }, limit: 10) {
metricKey
defaultValue
changePercentages
}
}
}
```
This demonstrates ranking the top 10 assets by staking marketcap using 30-day percentage changes.
### Sort Options
| Field | Description |
|-------|-------------|
| `metricKey_asc` | Sort by metric value ascending |
| `metricKey_desc` | Sort by metric value descending |
| `changePercentagesKey` | Sort by percentage change over a period |
| `changeAbsolutesKey` | Sort by absolute change over a period |
| `name` | Sort alphabetically by name |
| `address` | Sort by address (validators) |
| `createdAt` | Sort by creation date |
### Time Periods for Change Sorting
When using `changePercentagesKey` or `changeAbsolutesKey`:
| Period | Duration |
|--------|----------|
| `_24h` | 24 hours |
| `_7d` | 7 days |
| `_30d` | 30 days |
| `_90d` | 90 days |
| `_1y` | 1 year |
## Nested Queries
Nested queries let you traverse relationships between objects in a single request, building hierarchical structures that follow the data model.
The maximum nesting depth is 2.
Fetch the Allnodes provider with its associated reward options and validators:
```graphql title="Nested provider query"
{
providers(where: { names: ["Allnodes"] }, limit: 1) {
id
name
slug
rewardOptions(where: { typeKeys: ["pos"] }, limit: 10) {
id
inputAssets(limit: 10) {
name
}
validators(limit: 10) {
id
address
}
}
}
}
```
### How It Works
1. The query starts at the `providers` level, filtering for "Allnodes"
2. Within each provider, it retrieves `rewardOptions` filtered by type
3. For each reward option, it fetches `inputAssets` and `validators`
This nested structure allows you to get related data in a single request instead of making multiple API calls.
Always specify `limit` at each level of nesting to control the amount of data returned and optimize performance.
## Combining Multiple Arguments
You can combine multiple filters and arguments in a single query to retrieve precisely the data you need. This query retrieves reward options with multiple filters — specific input assets and type keys — while returning details about the type, metrics, input assets, and providers.
```graphql title="Combined filters and arguments"
{
rewardOptions(where: {inputAsset: {symbols: ["ETH"]}, typeKeys: ["solo-staking", "pos"]}, limit: 10) {
type {
key
label
}
metrics(limit: 10) {
metricKey
defaultValue
}
inputAssets(limit: 1) {
name
symbol
}
providers(limit: 5) {
name
country
}
}
}
```
This query demonstrates:
- Filtering by input asset symbol (`ETH`)
- Filtering by multiple type keys (`solo-staking` and `pos`)
- Limiting results at each nesting level
- Retrieving related objects (type, metrics, inputAssets, providers)
## Multiple Queries in One Request
You can combine multiple queries into one request to maximize efficiency. Both queries execute in parallel and the response contains separate data for each.
```graphql title="Batch assets and global metrics"
{
assets(order: { name: asc }, limit: 10) {
name
symbol
slug
}
metrics(
where: {
asset: null
provider: null
rewardOption: null
validator: null
metricKeys: ["marketcap"]
}
limit: 1
) {
defaultValue
changeAbsolutes
changePercentages
createdAt
}
}
```
This request contains two distinct queries:
1. **First query** — Retrieves 10 assets sorted by name (ascending), returning name, symbol, and slug fields
2. **Second query** — Fetches global metrics with specific filters (null parameters for asset, provider, rewardOption, validator) and metricKeys of `["marketcap"]`, returning defaultValue, changeAbsolutes, changePercentages, and createdAt
## Historical Data
For historical data, the `createdAt_gt` filter is needed. Without it, you only get the latest value. The required date format is `YYYY-MM-DD`.
### Credit Cost for Historical Queries
Historical data queries incur a flat **5,000-credit surcharge** in addition to the normal per-field cost (3 credits per `metrics` leaf). This reflects the higher value of historical data. The fields `changePercentages` and `changeAbsolutes` are not available for historical queries — including them returns a 400 error.
### Reward Rate History
Retrieve historical reward rate data for Ethereum:
```graphql title="Historical ETH reward rates"
{
rewardOptions(where: {inputAsset: {symbols: ["ETH"]}, typeKeys: ["solo-staking", "pos"]}, limit: 10) {
metrics(where: { metricKeys: ["reward_rate"], createdAt_lt: "2023-01-01" }, limit: 10) {
metricKey
defaultValue
createdAt
}
}
}
```
### Daily Interval Data
Query daily historical data for ETH reward rates starting from a specific date:
```graphql title="Daily interval reward rates"
{
rewardOptions(where: {inputAsset: {symbols: ["ETH"]}}, limit: 1) {
metrics(where: { metricKeys: ["reward_rate"], createdAt_gt: "2023-01-01" }, interval: day, limit: 500) {
metricKey
defaultValue
createdAt
}
}
}
```
### Weekly Asset Metrics
Query weekly price metrics for an asset between specific dates:
```graphql title="Weekly price with date range"
{
assets(where: {ids: ["60a27c3d4d60300008d25ecf"]}, limit: 1){
slug
metrics(limit:500, where:{metricKeys: ["price"], createdAt_gt: "2023-01-01", createdAt_lt: "2023-09-07"}, order: {createdAt: desc}, interval: week, pickItem: last) {
metricKey
defaultValue
createdAt
}
}
}
```
### Technical Limitations
- Interval queries work only for single resources
- Results are capped at 500 data points globally
- Supported intervals: `hour`, `day`, `week`, `month`, `quarter`
### Using Variables
You can use GraphQL variables to parameterize your queries:
**Variables:**
```json title="Query variables"
{
"slugs": ["ethereum-2-0"],
"limit": 100,
"offset": 0,
"metricKeys": ["reward_rate"],
"timeStart": "2023-01-01"
}
```
**Query:**
```graphql title="Parameterized historical query"
query getHistoricalMetrics($slugs: [String!], $limit: Int, $offset: Int, $metricKeys: [String!], $timeStart: Date) {
assets(where: {slugs: $slugs}, limit: 1) {
metrics(where: {metricKeys: $metricKeys, createdAt_gt: $timeStart}, limit: $limit, offset: $offset, order: {createdAt: asc}) {
defaultValue
createdAt
id
}
}
}
```
### Date Filters
| Filter | Description |
|--------|-------------|
| `createdAt_gt` | Greater than (after) the specified date |
| `createdAt_lt` | Less than (before) the specified date |
| `createdAt_gte` | Greater than or equal to the specified date |
| `createdAt_lte` | Less than or equal to the specified date |
### Interval Options
| Interval | Description |
|----------|-------------|
| `hour` | Hourly data points |
| `day` | Daily data points |
| `week` | Weekly data points |
| `month` | Monthly data points |
| `quarter` | Quarterly data points |
## Methodology
Source: https://docs.stakingrewards.com/staking-data-api/methodology
Understanding how metrics are calculated helps you interpret the data correctly. Each entity type has its own set of metrics with specific calculation methodologies.
## Asset Metrics
The following table provides a detailed overview of the metrics methodology used to track and measure the performance of a particular asset. To get more information about the object/class itself, please refer to the [Assets](/staking-data-api/schema-and-objects#assets) section.
| Key | Description |
|-----|-------------|
| `active_validators` | Number of Validators in the Active Set. |
| `annualized_rewards_usd` | Average native reward_rate multiplied by staked_tokens multiplied by the price of the asset. |
| `block_reward` | On-chain block Reward parameter if available, otherwise, number of tokens paid out per block to stakers averaged over the last 30 days. |
| `block_time` | The average block_time for this asset over the last 30 days. block_time_24h and block_time_30d may exist. |
| `circulating_percentage` | Circulating Supply divided by Total Supply. |
| `circulating_supply` | The supply of this asset that can be freely moved. |
| `daily_trading_volume` | The aggregate trading volume of all trading pairs for the asset over the past 24 hours. This metric provides insights into the level of market activity and liquidity for a given asset, and can be used to identify trends in trading activity and investor sentiment. |
| `delegated_tokens` | Number of tokens delegated to validators. |
| `inflation_rate` | The annualized monetary expansion of an asset, based on its current token reward payout, reward accrual interval, and total supply change. This metric can provide insights into the long-term supply dynamics of an asset. Higher inflation rates may lead to greater token supply growth and dilution of existing token holders' holdings, while lower inflation rates may contribute to greater scarcity and price appreciation over time. |
| `marketcap` | The theoretical value of this asset calculated by multiplying the current price by the current circulating supply. A key indicator of an asset's size and significance in the market. Keep in mind, a higher market cap often implies more stability, but not always! |
| `net_staking_flow_7d` | The number of tokens staked in the last 7 days minus the number of tokens unstaked in the last 7 days, multiplied by the current price of the asset. A positive net staking flow indicates an increase in staked tokens, while a negative net staking flow indicates a decrease. As this metric is displayed in USD, it can easily be compared between assets. |
| `price` | The current market value of 1 unit of an asset in USD. It is the average of the price buyers are willing to pay, and the price sellers are willing to sell at current point in time. The price of an asset can fluctuate based on supply and demand and market conditions. |
| `real_reward_rate` | The nominal reward rate of the network adjusted for inflation. This metric can provide insights into the actual, inflation-adjusted return that stakers or delegators can expect to receive for participating in the network, and can help investors understand the potential long-term value of their token holdings. Higher real reward rates generally indicate greater potential returns for stakers or delegators, while lower real reward rates may indicate lower expected returns or potentially negative real yields in some cases. |
| `reward_rate` | The current annualized average reward rate across the network. This is the rate at which stakers can earn rewards for participating in network consensus and/or governance. |
| `staked_tokens` | The total number of tokens that are currently being staked across the network. The amount of staked tokens can give an indication of the level of participation and interest in staking among network participants. |
| `staking_marketcap` | The total value of staked tokens across the network. This is calculated by multiplying the staked tokens with the current price. This metric can give an indication of the overall market size and long-term confidence in the network. |
| `staking_ratio` | The percentage of eligible tokens that are currently being staked or delegated to the network. This metric can provide insights into the level of network participation among token holders, as well as the overall health and security of the network. A higher staking ratio generally indicates a more committed community of token holders, as well as a more secure and decentralized network, while a lower staking ratio may indicate lower levels of engagement, and potentially greater network centralization or security risks. |
| `total_staking_wallets` | The total number of unique wallet addresses that are actively staking or delegating tokens to the network. This metric can provide insights into the level of network participation and decentralization, as well as the distribution of staking rewards among network participants. Higher numbers of staking wallets may indicate a greater degree of decentralization and network security, as well as a more engaged and active community of token holders. |
| `total_validators` | Number of Total Validators. |
You can get the data of a particular asset by running the following query, filtered by the asset's symbol. If you need more information about the asset, you can use the `assets` query with the `metrics` field. This will return all the metrics available for the asset (you can also add `variations`, `changeAbsolutes` and `changePercentages`).
- `changeAbsolutes` is the absolute change in the metric value within the last `24h`, `7d`, `30d`, `90d` or `1y`.
- `changePercentages` is the percentage change in the metric value within the last `24h`, `7d`, `30d`, `90d` or `1y`.
Refer to the [Global Metrics](#global-metrics) section for more information.
### Get active validators of Ethereum
To get the active validators (which is a [Metric](/staking-data-api/schema-and-objects#metrics)) and base data of Ethereum, you can run the following query.
```graphql
{
assets(where: { symbols: ["ETH"] }, limit: 1) {
id
name
slug
description
symbol
metrics(where: { metricKeys: ["active_validators"] }, limit: 1) {
metricKey
label
defaultValue
}
}
}
```
```json
{
"data": {
"assets": [
{
"id": "ID",
"name": "Ethereum",
"slug": "ethereum-2-0",
"description": "the world's largest and most decentralised Layer1 blockchain. The network is used for building dApps, holding assets, transacting and communicating without being controlled by a central authority. The Ethereum vision is to build a digital future on a global scale, that is powerful enough to help all of humanity",
"symbol": "ETH",
"metrics": [
{
"metricKey": "active_validators",
"label": "Active Validators",
"defaultValue": 123456789
}
]
}
]
}
}
```
## Provider Metrics
The following table provides a detailed overview of the methodology of a provider.
| Key | Description |
|-----|-------------|
| `assets_under_management` | This metric reflects the cumulative worth of all the assets entrusted to the provider's management, encompassing various forms of staking and delegation activities. AUM offers insights into the provider's size, performance, and overall reach in the staking and crypto ecosystems. A higher AUM suggests substantial user trust, while a lower AUM might indicate a more specialized or selective approach. This metric is essential for evaluating the provider's prominence and potential impact in the staking and cryptocurrency realms. |
| `commission` | This provider's balance-weighted average commission rate is calculated across all tracked reward options from various networks within the staking rewards ecosystem. It's important to note that this metric has limitations when comparing providers operating across networks with differing fee structures. Networks with inherently higher or lower fees can influence the overall average commission rate, potentially making direct provider-to-provider comparisons challenging. Despite this limitation, the balance-weighted approach offers insights into the provider's fee strategy, accounting for the influence of network-specific fee dynamics. |
| `provider_aum_change_7d` | The absolute monetary difference in the total value of assets managed by a provider over the past seven days. This metric reflects the change in the value of assets under management between the current day and the same day of the previous week, measured in USD. Provider AUM Change 7d provides insights into the recent performance and growth trajectory of the provider's managed assets. A positive change indicates an increase in the total value of assets managed, which could be due to successful investment strategies, market gains, or inflows of capital. Conversely, a negative change suggests a decline in AUM, which might be attributed to factors such as market downturns or client withdrawals. |
| `staking_wallets` | This metric shows the number of addresses that have chosen the provider for staking or delegation. It indicates the provider's presence and reputation within various ecosystems. A higher count suggests a larger user base, while a lower count may indicate specialization. It is crucial for evaluating the provider's influence and potential across diverse networks. |
### Sample Query
```graphql title="Provider metrics and reward options"
{
providers(limit: 10) {
name
logoUrl
country
rewardOptions(limit: 5) {
id
type {
key
label
}
metrics(limit: 10) {
metricKey
defaultValue
}
}
}
}
```
## Validator Metrics
The following table provides a detailed overview of the methodology used to track and measure the performance of validators.
| Key | Description |
|-----|-------------|
| `commission` | On-Chain commission rate. |
| `delegated_tokens` | On-chain number of tokens delegated to this validator. |
| `reward_rate` | Best assumption of the reward rate using on-chain data. Variations will take other metrics' variations into account. |
| `self_staked_tokens` | On-chain number of tokens self-staked by this validator. |
| `staked_tokens` | Total Tokens staked with this validator (delegated + self staked, active or inactive). |
| `staking_share` | validator.balance / asset.staked_tokens |
| `staking_wallets` | Number of unique addresses delegating to this validator on-chain. |
### Sample Query
```graphql title="Validator metrics by address"
{
validators(order: { address: asc }, limit: 5) {
id
address
metrics(limit: 20) {
metricKey
defaultValue
}
}
}
```
## Reward Option Metrics
The following table provides a detailed overview of the methodology of Reward Options.
| Key | Description |
|-----|-------------|
| `commission` | The Fee metric represents the commission charged by the provider on your earnings. It's an important factor to consider when projecting your net returns. The Reward Rate displayed already accounts for this fee, meaning it reflects what you'll earn after the fee deduction. Be cautious of providers offering 0 or unusually low fees, as it could be a strategy to attract more volume and they may drastically increase fees once they have gained enough traction. Remember, higher fees don't always mean lower net returns, as they might be associated with higher-performing reward options. |
| `delegated_tokens` | On-chain number of tokens delegated to this reward option (if PoS). |
| `net_staking_flow_7d` | Net Staking Flow 7D indicates the net change in staked tokens over the past 7 days, converted into USD using the current asset price. It's calculated by subtracting the number of unstaked tokens from the number of staked tokens. A positive value signifies an increase in staked tokens, suggesting growing interest in the reward option. Conversely, a negative value might indicate a decrease in confidence or interest. Since this metric is expressed in USD, it allows for easy comparison between different assets. This metric is especially useful for spotting short-term trends. Significant changes could be a signal to restake with a different provider, delegate to this provider, or completely unstake, depending on the magnitude and direction of the change. However, while it's a valuable tool for detecting shifts, it should be used in conjunction with longer-term metrics and other indicators for a comprehensive investment strategy. |
| `reward_rate` | Use the Reward Rate to gauge your potential returns over the next year. This metric provides a theoretical annual percentage rate (APR) based on the current market metrics. Comparing Reward Rates between different reward options can help you optimize your investment strategy. However, please note that this is a theoretical rate, and actual returns can vary due to market fluctuations and changes in reward values. |
| `self_staked_tokens` | Self Staked Tokens represents the amount a provider has directly staked on-chain. This metric can give you an idea of how much 'skin in the game' the provider has, indicating their level of commitment and confidence in their own service. However, it doesn't account for potential indirect stakes the provider may have, such as delegations from other wallets they control, or delegations they've made to other providers for diversification. Therefore, while a high value in Self Staked Tokens can show significant investment by the provider, a low value doesn't necessarily indicate a lack of investment or commitment, as they could be using other strategies. |
| `staked_tokens` | Staked Tokens represent the total number of tokens currently staked or locked with this reward option. This metric can give you an insight into the level of trust other users have in this provider and its overall market traction. If you're seeking to promote decentralization, you could use this data to diversify your investment away from heavily staked providers. However, large quantities of staked tokens could also indicate a well-established and trusted provider. Keep in mind that the popularity of a provider doesn't guarantee their performance. |
| `staking_share` | Network Control shows what percentage of all staked tokens are delegated to this reward option. It offers a broader perspective of the provider's influence and popularity in the overall network. A high Network Control may indicate a trusted and established provider, but it may also limit decentralization. If you aim to promote decentralization, consider delegating your tokens to providers with lower Network Control. Remember, a high Network Control doesn't necessarily guarantee superior returns or stability. |
| `staking_wallets` | Stakers represents the number of unique wallet addresses that are staking or delegating with this reward option. Similar to Staked Tokens and Network Control, it can provide insights into the provider's popularity and trust level. A high number of Stakers indicates a wider user base, which can be a positive signal. However, if you notice a high Staked Tokens value coupled with a low number of Stakers, this could suggest that a large portion of the stake is controlled by a few, potentially professional entities, like a centralized entity, a 'whale', or another protocol. This could signify a more professional operation, but it could also limit decentralization. |
### Sample Query
This sample query will return the first 10 reward options that have ETH as an input asset, and the first 5 active validators for each reward option.
```graphql title="ETH reward options with validators"
{
rewardOptions(
where: { inputAsset: { symbols: ["ETH"] } }
limit: 10
) {
id
inputAssets(limit: 100) {
slug
}
validators(limit: 5) {
id
}
}
}
```
## Global Metrics
The following table provides a detailed overview of the global metrics methodology. To get more information about metrics, please refer to the [Objects/Metrics](/staking-data-api/schema-and-objects#metrics) section.
| Key | Description |
|-----|-------------|
| `benchmark_staking_ratio` | This metric can help you gauge how much interest there is in staking across the whole ecosystem. It's calculated by taking the balance weighted average of the staking ratios of all assets. |
| `annualized_rewards_usd` | This metric helps you understand how much value is being created in the market by staking by showing how much total rewards are paid out to stakers. The calculation involves summing up the rewards given out in USD across all assets. It's important to note that this total may be influenced by the volatility of the market and the value of the reward tokens. |
| `staking_marketcap` | This metric should be the main metric you keep your eye on over the long term as it will highlight any major changes in the ecosystem. This represents the total USD value of all tokens that have been staked and are being tracked by Staking Rewards. It's calculated by summing the USD value of all staked tokens. However, the value may fluctuate due to changes in the market prices of the tokens. |
| `benchmark_reward_rate` | This metric provides an average reward rate across all staking opportunities tracked by Staking Rewards, balanced by the amount staked. It's determined by calculating the balance weighted average reward rate across all opportunities. It's worth noting that this average rate may be affected by assets offering high APRs through high inflation rates or by assets with low APRs but deflationary tokenomics. |
| `marketcap` | This metric indicates the total USD value of the circulating supply of all crypto assets. It's calculated by multiplying the current price of each asset by its circulating supply. This value can fluctuate based on market conditions and the prices of individual assets. |
| `pos_flippening_pow` | This is a ratio of the market capitalization of all PoS assets to that of all PoW assets. It's calculated by dividing the PoS assets market cap by the PoW assets market cap. This metric can provide an interesting perspective on the relative growth of PoS and PoW, but it should be noted that market cap alone doesn't define the success or utility of a blockchain model. |
| `pos_assets_marketcap` | This metric represents the total market capitalization of all Proof of Stake (PoS) assets tracked by Staking Rewards. It's determined by summing up the market capitalizations of all PoS assets. Remember, it may not fully represent the entire PoS market, as it only includes the assets tracked by Staking Rewards. |
| `pow_assets_marketcap` | This metric shows the total market capitalization of all Proof of Work (PoW) assets. It's calculated by summing up the market capitalizations of all PoW assets. |
| `staking_wallets` | This metric indicates the total number of unique staking addresses across all assets. It's derived by summing up the number of unique staking addresses for each asset. This can give a sense of the spread and participation of staking, but it might not indicate the distribution of assets among stakers. |
| `crypto_gdp` | This refers to the total revenue of all assets tracked by Staking Rewards. It's calculated by summing up the revenue generated by all these assets. Keep in mind that this figure may not fully represent the "GDP" of the entire crypto market, as it only includes the assets tracked by Staking Rewards. |
| `net_staking_flow_7d` | This metric can be used as an indicator of the general trend in the Staking ecosystem over the past week. It shows the net value of all assets staked or unstaked over the last week. It's calculated by summing up the value of all assets staked and subtracting the value of all assets unstaked. |
| `total_vsp_aum` | This metric indicates the value of assets under management for all the verified staking providers, in USD. It is calculated by adding up the staked assets, multiplied by price, for all verified staking providers. |
| `total_vsp_wallets` | This metric indicates the number of unique wallets staking for verified staking providers. It's derived by summing up the number of unique staking addresses for each provider. |
| `total_vsps` | This metric indicates the current number of verified staking providers. |
To query global metrics, make sure to apply a filter that excludes any asset, provider, reward option, or validator relation:
### Sample Query
```graphql title="Global marketcap metric"
{
metrics(
where: {
asset: null
provider: null
rewardOption: null
validator: null
metricKeys: ["marketcap"]
}
limit: 1
) {
defaultValue
changeAbsolutes
changePercentages
createdAt
}
}
```
## Best Practices
Source: https://docs.stakingrewards.com/staking-data-api/resources/best-practices
This is not a complete list of all the best practices, but it is a good starting point.
## Limits and Efficiency
- Reduce API calls for improved efficiency and lower latency
- Use the `limit` property strategically to transfer only necessary data
- Leverage pagination with mandatory `limit` and optional `offset` parameters
- Prefer higher `limit` values with `offset` iteration over multiple lower-limit requests
- Cache data locally when feasible
- Apply appropriate filters and parameters to optimize requests
- Adhere to rate limiting guidelines
- Design applications to handle errors gracefully (timeouts, server issues)
## Featuring Data in Publications and Websites
When publishing API data, proper attribution is essential. Recommended format:
```html
Source: Stakingrewards.com
```
This should appear on each page featuring the data.
## Security
- Secure API key storage using environment variables or encrypted solutions
- Avoid hardcoding endpoint URLs; use dynamic construction instead
- Maintain current software and operating system updates
## Data Integrity
- Validate retrieved data against standards before processing
- Confirm proper formatting and presence of all required fields
## Terms of Service, Updating and Maintenance
- Follow API terms of service guidelines
- Stay current with API versions and changes
## Practical Query Samples
Source: https://docs.stakingrewards.com/staking-data-api/resources/practical-query-samples
This page provides developers with GraphQL query examples for the Staking Rewards API, demonstrating how to retrieve staking metrics for various blockchain assets.
Refer to the [Quick Start Guide](/get-started/quick-start-guide) for initial setup instructions with JavaScript and Python.
## Get Reward Rate for Ethereum
Retrieve the reward_rate metric for Ethereum:
```graphql
{
assets(where: { symbols: ["ETH"] }, limit: 1) {
name
symbol
slug
logoUrl
metrics(where: { metricKeys: ["reward_rate"] }, limit: 1) {
metricKey
defaultValue
}
}
}
```
## Get staked_tokens Metric for Ethereum
Query the staked_tokens metric including change metrics:
```graphql
{
assets(where: { slugs: ["ethereum-2-0"] }, limit: 1) {
slug
id
metrics(where: { metricKeys: ["staked_tokens"] }, limit: 1) {
metricKey
defaultValue
changeAbsolutes
changePercentages
}
}
}
```
## Get staked_tokens of Validators for Cosmos
Filter by asset (Cosmos), type (pos/proof-of-stake), and retrieve validator addresses, statuses, and staked token metrics:
```graphql
{
rewardOptions(
where: {
inputAsset: { slugs: ["cosmos"] }
typeKeys: ["pos"]
}
limit: 10
offset: 0
) {
providers(limit: 1) {
slug
}
validators(limit: 100) {
address
status {
label
}
metrics(where: { metricKeys: ["staked_tokens"] }, limit: 1) {
metricKey
defaultValue
}
}
}
}
```
## Get reward_rate with Providers and Validators
Fetch reward rates from providers and validators, ordered by staked_tokens:
```graphql
{
rewardOptions(
where: {
inputAsset: { slugs: ["cosmos"] }
typeKeys: ["pos"]
}
order: { metricKey_desc: "staked_tokens" }
limit: 10
offset: 0
) {
providers(limit: 1) {
slug
}
metrics(where: { metricKeys: ["reward_rate"] }, limit: 1) {
metricKey
defaultValue
}
validators(limit: 100, offset: 0) {
address
status {
label
}
metrics(where: { metricKeys: ["reward_rate"] }, limit: 1) {
metricKey
defaultValue
}
}
}
}
```
## Get ID for an Asset
Obtain an asset's unique identifier:
```graphql
{
assets(where: { slugs: ["ethereum-2-0"] }, limit: 1) {
slug
id
}
}
```
## Retrieving Historical Metrics
Retrieve three different metrics with date filtering from 2023-01-01 onward:
```graphql
{
stakingmcap: metrics(
where: {
asset: { id: "ASSET_ID" }
metricKeys: ["staking_marketcap"]
createdAt_gt: "2023-01-01"
}
limit: 3
order: { createdAt: desc }
) {
...histData
}
rewardRate: metrics(
where: {
asset: { id: "ASSET_ID" }
metricKeys: ["reward_rate"]
createdAt_gt: "2023-01-01"
}
limit: 2
order: { createdAt: desc }
) {
...histData
}
stakedTokens: metrics(
where: {
asset: { id: "ASSET_ID" }
metricKeys: ["staked_tokens"]
createdAt_gt: "2023-01-01"
}
limit: 2
order: { createdAt: desc }
) {
...histData
}
}
fragment histData on Metric {
defaultValue
createdAt
}
```
## Error Codes
Source: https://docs.stakingrewards.com/staking-data-api/resources/error-codes
When making a request to our API, there may be times when an error is returned. If you are unable to resolve the issue, please contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) or via Telegram [@berlincrypto](https://t.me/berlincrypto).
## Not Authorized (401)
**Message:** `you should be authenticated to do this request`
**Resolution:** Requires valid `X-API-KEY` header authentication. Check for token expiration or permission issues.
## User Not Found (401)
**Message:** `user not found`
**Resolution:** Invalid or unknown API key. Check account status via [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com).
## Missing Limit Parameter (400)
**Message:** `unable to parse paging argument: limit field is required`
**Resolution:** The `limit` parameter is mandatory for list-returning queries.
## Exceeding Maximum Limit (400)
**Message:** `unable to parse paging argument: max limit is 500`
**Resolution:** The `limit` parameter cannot exceed 500.
## Invalid Argument (GRAPHQL_VALIDATION_FAILED)
**Example:** Typo detection like "metricss" vs "metrics"
**Resolution:** Check the suggestions provided for correct field names.
## Variable Type Mismatch (GRAPHQL_VALIDATION_FAILED)
**Example:** `Int cannot represent non-integer value: "1"`
**Resolution:** Variables must match expected argument types.
## Maximum Query Depth Exceeded (400)
**Message:** `query path is too long. Max depth is 2`
**Resolution:** Nested fields are limited to 2 levels.
## Operation Not Found
**Message:** `operation not found`
**Resolution:** Occurs when request body lacks a valid query.
## Field Conflict (GRAPHQL_VALIDATION_FAILED)
**Description:** Multiple fields with identical names but different arguments.
**Resolution:** Use aliases to differentiate fields with the same name.
```graphql
{
assets(where: { symbols: ["ETH"] }, limit: 1) {
rewardRate: metrics(where: { metricKeys: ["reward_rate"] }, limit: 1) {
defaultValue
}
price: metrics(where: { metricKeys: ["price"] }, limit: 1) {
defaultValue
}
}
}
```
If you encounter an error not listed here, please contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) with the full error message and your query.
## FAQs
Source: https://docs.stakingrewards.com/staking-data-api/resources/faqs
Welcome to the FAQ section. If your question is not answered below, please contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) or via Telegram [@berlincrypto](https://t.me/berlincrypto).
## What is this API and what can it do?
The API is a tool that allows users to retrieve information about various objects related to staking and digital assets. Retrievable objects include Assets, Providers, Validators, Reward Options, and Metrics. The API uses GraphQL implementation and requires authentication.
## How do I get started with this API?
Refer to the [Quick Start Guide](/get-started/quick-start-guide) for account setup and making your first API request.
## What authentication methods does this API support?
The API uses auth key authentication via the `X-API-KEY` header. See the [Quick Start Guide](/get-started/quick-start-guide) for details.
## Can I use this API to access data from multiple datasets?
Yes. The API provides access to recent and historical data across Asset, Provider, RewardOption, and Validator object types with their associated properties.
## What is the maximum number of API requests I can make per day?
Request limits depend on your subscription plan. See the [Subscriptions & Credits](/billing/subscriptions-and-credits) section for plan-specific limits, or contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com).
## How often is the staking data updated in the API?
Data is updated periodically on an automated basis. Update frequency varies by asset and metric type. Contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) for specific update frequency questions.
## Is there a way to get historical staking data through the API?
Yes. Historical data retrieval is possible using date filters. See the [Historical Data](/staking-data-api/querying-data#historical-data) documentation page for details.
## How do I report an issue or bug with the API?
Contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) or via Telegram [@berlincrypto](https://t.me/berlincrypto). Please provide:
- Detailed problem description
- Error messages received
- Query that caused the issue
- Any relevant log files
For support, email [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) or message [@berlincrypto](https://t.me/berlincrypto) on Telegram.
---
# Ratings API
## Overview
Source: https://docs.stakingrewards.com/ratings-api/overview
The Ratings API provides access to ratings data through a simple REST interface with GET endpoints. It covers two distinct rating categories: **DeFi** and **Infrastructure**.
## DeFi Ratings
DeFi ratings evaluate the risk of DeFi products across categories like operations, security, and strategy. Each product receives a letter grade from AAA (best) to D (worst).
The scoring model assesses products based on publicly available data and, for fully rated protocols, additional information gathered through a team review process. For details on how scores are calculated, see the [Scoring Model documentation](https://docs.stakingrewards.com/defi-ratings/rating-methodology/scoring-model).
For more information on DeFi ratings, see the [DeFi Ratings documentation](https://docs.stakingrewards.com/defi-ratings).
### Endpoints
- **List DeFi Ratings** — Returns all DeFi product ratings across all platforms. Supports filtering by type, chain, TVL, APY, and more.
- **List DeFi Platform Ratings** — Returns DeFi product ratings for a specific platform (by slug).
- **Get DeFi Product Rating** — Returns the rating for a single DeFi product (by platform slug and contract address).
### Preview vs. Full Ratings
DeFi ratings come in two variants:
- **Preview ratings** have a version suffixed with `-preview` (e.g. `v0.1-alpha-preview`). These ratings rely solely on publicly available information and do not go through the full rating process including team review. Preview ratings include both a **known score** (based on publicly verifiable information) and a **potential score** (the rating that could be achieved if the protocol undergoes a full rating, including improvements suggested by the Staking Rewards team). Preview ratings do not have a risk report available for purchase on the Staking Rewards platform.
- **Full ratings** go through the complete rating process including team review. They do not have a potential score. Fully rated protocols will have a risk report available to purchase on the Staking Rewards platform.
## Infrastructure Ratings
Infrastructure ratings evaluate staking infrastructure providers (validators, node operators) across business operations, reliability, and security setup. Each provider receives a letter grade from AAA (best) to D (worst).
For more information, see the [Verified Provider Program documentation](https://docs.stakingrewards.com/verified-provider-program).
### Endpoints
- **List Infrastructure Ratings** — Returns all infrastructure provider ratings. Supports filtering by rating grade, date ranges, and version.
- **Get Infrastructure Rating** — Returns the rating for a specific infrastructure provider (by slug).
## Monitored Protocols & Events
Source: https://docs.stakingrewards.com/ratings-api/monitored-protocols
DeFi alerts returned by the [List DeFi Alerts](/ratings-api/endpoints/defi/listDefiAlerts)
endpoint are generated by on-chain monitors that watch governance- and
risk-relevant contracts for each rated protocol. This page is the human-readable
inventory of what is covered: which protocols and contracts are watched, which
on-chain events trigger an alert, and the incident type and severity each maps
to.
This page is maintained by hand alongside the monitors. If a protocol or event
appears in an alert but not here, treat this page as lagging — the monitors are
the source of truth.
## Incident types
Every alert is classified into exactly one of seven incident types. The
`incident_type` filter on the alerts endpoint matches these values.
| Incident type | What it tracks |
|---|---|
| `ContractUpgrade` | Proxy upgrades, implementation changes, version updates, upgrade proposals/cancellations |
| `TimelockChange` | Timelock delay changes, call scheduling/execution/cancellation |
| `AdminChange` | Owner transfers, admin updates, pending-owner set/accepted, authority changes |
| `MultisigChange` | Safe owner add/remove, threshold changes, module/guard/fallback-handler updates |
| `RoleChange` | Role grants/revocations, role-admin changes, minter/pauser/oracle role assignments |
| `ProtocolParameterChange` | Fee changes, reserve configs, rate limits, caps, cooldown durations |
| `EmergencyAction` | Pause/unpause, bunker mode, staking halt, seizure, emergency shutdown, reserve freeze |
## Severity levels
| Severity | Meaning |
|---|---|
| `CRITICAL` | Funds-at-risk or protocol-halting events (pauses, seizures, emergency shutdown) |
| `ERROR` | High-impact governance/upgrade events (implementation upgrades, admin transfers, timelock delay decreases) |
| `WARNING` | Notable governance/parameter changes (role grants, fee changes, multisig membership) |
| `INFO` | Routine or low-impact updates (minor parameter tweaks, proposal scheduling) |
The `severity` filter matches these values (case-insensitive).
## Coverage summary
| Protocol | Chain | Products |
|---|---|---|
| Aave | Ethereum | protocol-wide + per-reserve |
| BlackRock | Ethereum | `buidl` |
| Coinbase | Ethereum | `cbeth` |
| Compound | Ethereum | `usdt` + protocol-wide |
| Ethena | Ethereum | `susde` |
| EtherFi | Ethereum | `eeth`, `weeth`, `liquid-eth` |
| HyperLend | HyperEVM | protocol-wide + per-asset |
| Kelp | Ethereum | `rseth` |
| Lido (earnETH) | Ethereum | `earneth` |
| Lido (earnUSD) | Ethereum | `earnusd` |
| Lido (stETH) | Ethereum | `steth` |
| Lido (strETH) | Ethereum | `streth` |
| Lombard | Ethereum | `lbtc` |
| Looping Collective | Ethereum | `lcbtc` |
| Maple | Ethereum | `syrupusdc`, `syrupusdt` |
| Moonwell Flagship ETH | Base | `moonwell-flagship-eth` |
| Morpho | Ethereum | per-vault |
| Ondo | Ethereum | `usdy`, `ousg` |
| Puffer | Ethereum | `pufeth` |
| Rocket Pool | Ethereum | `reth` |
| Sky | Ethereum | `susds` |
| Spark | Ethereum | `spweth`, `spusdc`, `spusdt` + per-reserve |
| Stader | Ethereum | `ethx` |
| StakeWise | Ethereum | `oseth` |
| USD.ai | Arbitrum One | `susdai`, `usdai` |
| Valantis (stHYPE) | HyperEVM | `sthype` |
---
## Aave (`aave`)
- **Chain(s):** Ethereum
- **Products:** the rated Aave Ethereum Core Market assets — `weth`, `usdc`, `wbtc`, `eurc`, `usdt`, `wsteth`, `cbbtc`, `weeth`, `usde`. Protocol-wide events (governance/admin/oracle/upgrades) apply to all of them; asset-scoped events only page for the rated assets (changes on other reserves are tracked on the dashboard at INFO)
- **Contracts monitored:**
- `Pool` — `0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2`
- `PoolConfigurator` — `0x64b761D848206f447Fe2dd461b0c635Ec39EbB27`
- `PoolAddressesProvider` — `0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e`
- `ACLManager` — `0xc2aaCf6553D20d1e9d78E365AAba8032af9c85b0`
- `ExecutorLvl1` — `0x5300A1a15135EA4dc7aD5a167152C01EFc9b192A`
- `ExecutorLvl2` — `0x17Dd33Ed0e3dD2a80E37489B8A63063161BE6957`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| RoleGranted (ACLManager — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the root access-control key that can administer every other role — effectively whole-protocol control. This is the highest-trust change Aave can make, so it pages at top urgency. |
| RoleGranted (ACLManager — POOL_ADMIN / EMERGENCY_ADMIN / ASSET_LISTING_ADMIN) | RoleChange | ERROR | A new address gains a powerful privileged role: pool administration (including upgrading the tokens that hold user funds), the ability to pause the protocol, or control over which price oracles are used. Each can materially affect funds or availability, so granting it pages. |
| RoleGranted (ACLManager — RISK_ADMIN / BRIDGE) | RoleChange | WARNING | A new address gains a bounded operational role — tuning risk parameters within limits, or bridge minting capped by configuration. Expected governance activity, so it is recorded for visibility but does not page. |
| RoleGranted (ACLManager — FLASH_BORROWER) | RoleChange | INFO | A new address is exempted from flash-loan premiums. This carries no governance power and cannot affect other users, so it is logged for completeness only. |
| RoleGranted (ACLManager — unrecognized role) | RoleChange | ERROR | A role the monitor cannot map to a known name is granted. Because an unmapped or custom role could be powerful, it is treated as potentially dangerous and paged ("fail loud") rather than silently ignored. |
| RoleRevoked (ACLManager — DEFAULT_ADMIN / EMERGENCY_ADMIN / POOL_ADMIN) | RoleChange | ERROR | A role whose *loss* is dangerous is removed — the root key (removal can lock out governance), the emergency-pause ability (losing it removes the protocol's exploit brake), or pool administration. Worth paging even though revocations usually reduce risk, because these can also signal a hostile takeover or an operational mistake. |
| RoleRevoked (ACLManager — other roles) | RoleChange | WARNING | A lower-impact role (e.g. risk admin, flash borrower) is removed. Reducing privilege is generally safe, so it is recorded but does not page. |
| RoleAdminChanged (ACLManager) | RoleChange | CRITICAL | The rule for *who may grant or revoke* a role is rewired — a structural change to the access-control graph itself, not just who holds a role. This is meta-authority over the entire permission system: changing the admin of a powerful role (e.g. POOL_ADMIN or the root DEFAULT_ADMIN) is a direct privilege-escalation / takeover vector. This is not part of Aave's normal operations, so any occurrence is maximally anomalous (a classic way an attacker entrenches control) — paged at the highest severity, same tier as a root-authority or oracle swap. |
| OwnershipTransferred (Executor) | AdminChange | CRITICAL | Ownership of a governance executor moves to a new address. The executor is where Aave's power actually resides — it holds pool-admin and root access-control rights and owns the AddressesProvider — and its owner can make it execute an arbitrary call from that privileged address (upgrade the fund-bearing token contracts, grant any role, swap the oracle). Owning the executor is therefore total control of the protocol. The legitimate owner is the governance payload-controller, never a person; ownership moves only as part of a governance migration, so any other occurrence is a top-urgency, funds-at-risk event. |
| ACLAdminUpdated | AdminChange | ERROR | Changes which address is registered as the ACL admin — the account tied to the ACLManager's root DEFAULT_ADMIN role that ultimately grants and revokes every other role. A root-of-trust change, so it always pages. |
| ACLManagerUpdated | ContractUpgrade | CRITICAL | Repoints the protocol at a different ACLManager contract. Because permission checks resolve the manager at runtime, a swap immediately changes the authority behind every privileged action — a malicious manager could make anyone a pool admin and drain funds. Outside the protocol's initial setup this is not a normal operation, so any occurrence is a top-urgency, funds-at-risk event. |
| PoolUpdated | ContractUpgrade | ERROR | Upgrades the implementation behind the core Pool proxy — replacing the code of Aave's main lending contract while funds and storage stay in the unchanged proxy. Governance-gated and routine, but because it ships new code for the contract at the heart of the protocol, every upgrade pages so it can be matched to a known governance proposal. |
| PoolConfiguratorUpdated | ContractUpgrade | ERROR | Upgrades the implementation behind the PoolConfigurator proxy — the privileged contract that sets every reserve's risk parameters (caps, collateral config, freeze/pause). Governance-gated; each upgrade pages so the new code can be matched to a known governance proposal. |
| PriceOracleUpdated | ContractUpgrade | CRITICAL | Swaps the protocol's entire price-oracle contract. Pricing is resolved at runtime, so a swap instantly repoints all collateral valuation and liquidations — a malicious or buggy oracle is one of the fastest ways to drain a lending pool. Outside initial setup this is not a normal operation; any occurrence is a top-urgency, funds-at-risk event. (Routine per-asset feed changes use a different event.) |
| PriceOracleSentinelUpdated | ContractUpgrade | ERROR | Sets the PriceOracleSentinel — L2 machinery that blocks borrows/liquidations during sequencer downtime. This monitor covers only Aave's Ethereum-mainnet deployment, which has no sequencer, so the sentinel is inert here and is not set on this deployment; an occurrence is anomalous and pages. (On Aave's L2 markets the sentinel is live safety infrastructure; those deployments are outside this monitor's current scope.) Worst case if misconfigured is freezing liquidations — a slow solvency risk, not an instant drain. |
| PoolDataProviderUpdated | ContractUpgrade | WARNING | Swaps the PoolDataProvider, a read-only view/aggregation helper UIs and integrators call to read reserve data. It holds no funds, grants no privileges, and isn't used in any state-changing path, so a swap can at most return wrong data to off-chain readers — dashboard-only. |
| OwnershipTransferred (AddressesProvider) | AdminChange | CRITICAL | Ownership of the PoolAddressesProvider — the market's master registry — moves to a new address. Its owner is the single key that can swap the Pool, the PoolConfigurator, the ACLManager, and the price oracle, i.e. it can trigger every one of the funds-at-risk events above. Transferring it is the protocol's top root-of-trust change. Ownership moves only as part of a governance migration (the legitimate owner is the governance executor), so any other occurrence is a top-urgency, funds-at-risk event. |
| ProxyCreated | ContractUpgrade | INFO | The AddressesProvider deploys a brand-new proxy for a registry slot. This fires only the first time a proxied component (the Pool, the PoolConfigurator, etc.) is registered, and always co-fires with the meaningful event for that component (PoolUpdated, AddressSetAsProxy) — which carries the real severity. On its own it grants no privileges and moves no funds, so it is recorded for completeness only. It fires only when proxied components are first registered, at protocol setup. |
| AddressSetAsProxy | ContractUpgrade | ERROR | Upgrades the implementation behind a registered proxy via the generic registry path — the same mechanism as PoolUpdated, but for a registry slot that doesn't have its own dedicated setter. It swaps the executing code of a governance-controlled proxy, so it carries the same risk class as a Pool/Configurator upgrade and pages, to be matched against a known governance proposal. It fires only at protocol setup to register a proxied component, and is not part of routine operations. |
| AddressSet | ContractUpgrade | ERROR | The owner edits one entry in the market's address registry (its "phone book") for an id that has no dedicated setter — the dangerous core pointers (oracle, ACL manager, ACL admin, data provider) have their own events and do not flow through here. The risk is indirection: contracts resolve components by id at runtime, so a poisoned entry can redirect a trusted integration to an attacker's contract. Impact depends on who reads that id — e.g. the UMBRELLA entry wires in Aave's safety module that covers reserve bad debt. Owner-only and rare, so each occurrence pages to be matched against a known proposal. |
| ReserveFactorChanged (≤50%) | ProtocolParameterChange | INFO | The reserve factor — the share of borrow interest diverted to the protocol treasury rather than to suppliers — is changed for an asset. A routine, frequently-adjusted economic knob the risk stewards tune; it does not touch fund custody, collateral safety, or solvency. Normal values sit in a 5–50% band, so changes within it are tracked on the dashboard, not paged. |
| ReserveFactorChanged (>50%) | ProtocolParameterChange | WARNING | The new reserve factor exceeds 50%, outside the normal operating band. The only values this high on record are Aave's GHO stablecoin at 100% (by design) and an asset being offboarded (SNX at 95%) — legitimate but unusual, so the change is surfaced for confirmation that it is an intended offboarding or special-asset setting. It does not page. |
| FlashloanPremiumTotalUpdated (≤1%) | ProtocolParameterChange | INFO | The total flash-loan premium (the fee on a flash loan) is changed. This is the lowest-stakes fee on the protocol — it cannot reach funds or solvency (a high premium just makes flash loans expensive, a zero premium just makes them free; the loan must still be repaid in the same transaction). Historically it has only ever been 5–9 bps, so normal changes are tracked on the dashboard, not paged. |
| FlashloanPremiumTotalUpdated (>1%) | ProtocolParameterChange | WARNING | The new flash-loan premium exceeds 1% — roughly a tenfold jump over the 5–9 bps norm. There is no legitimate reason for such a value, so it is surfaced as a likely misconfiguration or tampering signal. It does not page. |
| FlashloanPremiumToProtocolUpdated | ProtocolParameterChange | INFO | Changes how the flash-loan premium is split between the protocol treasury and the liquidity suppliers (a bounded 0–100% share). The borrower's total fee is unchanged — only who receives it moves — so no setting carries fund or solvency risk, and 100% (all premium to treasury) is a legitimate endpoint governance has used. Tracked on the dashboard, not paged. |
| BridgeProtocolFeeUpdated | ProtocolParameterChange | WARNING | Changes the protocol's cut of the fee on Aave's Portal feature (cross-chain "unbacked" minting). The fee itself is harmless, but the Portal subsystem is dormant on Ethereum mainnet — this fee and the bridge role are unused here — and it is higher-risk if activated. Any change is therefore treated as a canary that someone is configuring Portal on mainnet and is surfaced for review (correlate with a bridge-role grant). It does not page. |
| LiquidationProtocolFeeChanged (≤30%) | ProtocolParameterChange | INFO | The protocol's cut of the liquidation bonus for an asset is changed. The liquidation bonus is what pays liquidators to keep the protocol solvent; the standard cut is 10% (historical band 0–20%), so changes within range are tracked on the dashboard, not paged. |
| LiquidationProtocolFeeChanged (>30%) | ProtocolParameterChange | WARNING | The new fee exceeds 30% — well outside the historical 0–20% band. Taking too large a share of the liquidation bonus erodes the liquidator's margin, which can slow or stall liquidations and lead to bad debt, so the change is surfaced for review. The risk is gradual and the parameter is bounded, so it does not page. |
| ATokenUpgraded | ContractUpgrade | ERROR | Upgrades the implementation of an asset's aToken — the contract that custodies user deposits for that reserve. A fund-bearing code swap (a malicious implementation could drain the reserve), so it pages, same as a core Pool upgrade. Routine via governance — protocol-wide migrations upgrade every reserve in a single transaction — so each migration should map to a known proposal. |
| VariableDebtTokenUpgraded | ContractUpgrade | ERROR | Upgrades the implementation of an asset's variable-debt token — the contract that accounts for that reserve's borrows. Same risk class as the aToken upgrade: a code swap on core reserve accounting, so it pages and each upgrade should map to a known governance proposal. |
| ReserveInterestRateStrategyChanged | ProtocolParameterChange | INFO | Swaps the interest-rate-strategy contract a reserve uses (the contract that computes borrow and supply rates from utilization). It affects only rates, not custody — a bad strategy could grief with extreme rates but cannot move funds, and it is fully recoverable. A routine, historically high-volume risk-steward action (largely superseded from V3.2 by interest-rate data changes), so it is tracked on the dashboard, not paged. |
| ReserveInterestRateDataChanged | ProtocolParameterChange | INFO | The V3.2+ routine way to retune a reserve's interest-rate curve — a risk steward writes new rate data (optimal usage ratio, base rate, and the two utilization slopes) onto a shared strategy contract, rather than deploying a new strategy. Purely economic: it moves borrow and supply rates, never touches custody or solvency, and is fully recoverable. The highest-volume reserve event, so it is tracked on the dashboard, not paged. |
| ReservePaused (rated asset, paused) | EmergencyAction | CRITICAL | Emergency halt of a monitored reserve — pausing blocks every interaction with the asset including withdrawals and liquidations, so the product goes fully dark and user funds are locked in place. Strictly more severe than a freeze (which still lets users exit). No monitored asset has ever been paused on Aave's Ethereum market (the few pauses to date were on non-monitored assets), so a pause on a monitored product is exceptional and paged immediately, whether it is protective incident response or hostile. Non-monitored assets are tracked on the dashboard at INFO. |
| ReservePaused (rated asset, unpaused) | EmergencyAction | WARNING | A monitored reserve is taken out of pause and restored to normal operation — the recovery / all-clear signal. Tracked on the dashboard rather than paged. |
| ReserveFrozen (rated asset, frozen) | EmergencyAction | ERROR | A monitored reserve is frozen — new supply and borrow are blocked, but users can still repay, withdraw, and be liquidated, so funds are not locked. This is Aave's graceful asset-offboarding tool, one tier below a pause; freezing a monitored product is material enough to page but, because exits stay open, is not treated as critical. Non-monitored assets are tracked on the dashboard at INFO. |
| ReserveFrozen (rated asset, unfrozen) | EmergencyAction | WARNING | A monitored reserve is unfrozen and re-enabled for new supply and borrow — the recovery signal. Tracked on the dashboard rather than paged. |
| CollateralConfigurationChanged (rated asset, LTV→0 or liquidation-threshold cut ≥5%) | ProtocolParameterChange | ERROR | The solvency-critical collateral parameters of a monitored reserve — loan-to-value (LTV), liquidation threshold (LT), and liquidation bonus. Two cases page: (1) a drop in the liquidation threshold, which makes existing positions immediately liquidatable and can trigger a wave of forced liquidations and bad debt — the genuinely dangerous direction; (2) LTV set to 0, which disables the asset as new collateral (a protective de-risking / wind-down signal). Evaluated against the previous on-chain value, so only a real transition pages. |
| CollateralConfigurationChanged (rated asset, other change) | ProtocolParameterChange | WARNING | Routine collateral re-parameterisation of a monitored reserve — raising LTV/threshold, small ±1% adjustments, or liquidation-bonus tweaks. Material enough to record but not dangerous to existing positions, so it is tracked on the dashboard rather than paged. Changes on non-monitored reserves are INFO. |
| BorrowCapChanged (rated asset, disabled) | ProtocolParameterChange | WARNING | The borrow cap of a monitored reserve is cut to the "disabled" sentinel (a cap of 1 token), which effectively stops new borrowing of the asset — a wind-down / de-risking signal. Surfaced on the dashboard for prominence (it correlates with freezes and collateral de-risking), but not paged: the borrow cap only limits new borrowing and never affects existing positions or funds. |
| BorrowCapChanged (other) | ProtocolParameterChange | INFO | Routine adjustment of how much of an asset can be borrowed (raising/lowering the cap as the market grows or de-risks). It cannot affect existing positions or cause loss, so it is tracked on the dashboard, not paged. |
| SupplyCapChanged (rated asset, disabled) | ProtocolParameterChange | WARNING | The supply cap of a monitored reserve is cut to the "disabled" sentinel (a cap of 1 token), effectively stopping new deposits of the asset — a wind-down signal. Surfaced on the dashboard for prominence, but not paged: the supply cap only limits new deposits and never affects existing positions or funds. |
| SupplyCapChanged (other) | ProtocolParameterChange | INFO | Routine adjustment of how much of an asset can be supplied (raising/lowering the cap as the pool grows or de-risks). It cannot affect existing positions or cause loss, so it is tracked on the dashboard, not paged. |
| DebtCeilingChanged (rated asset, isolation-mode transition) | ProtocolParameterChange | WARNING | A monitored asset enters or exits **isolation mode** — Aave's sandbox for riskier collateral, where the asset can only be used alone (not combined with other collateral), can only borrow stablecoins, and has a capped total debt (the debt ceiling, in USD). Entering isolation is a restricted/de-risk listing; exiting (ceiling set to 0) promotes it to normal collateral. This is a genuine risk-posture change, so it is surfaced on the dashboard — but not paged, since the ceiling only limits exposure and never affects existing positions. |
| DebtCeilingChanged (other) | ProtocolParameterChange | INFO | Routine adjustment of an isolated asset's debt ceiling (raising/lowering the capped total debt while it stays in isolation mode), or a listing-time no-op. It cannot affect existing positions or cause loss, so it is tracked on the dashboard, not paged. |
| SiloedBorrowingChanged (rated asset, toggled) | ProtocolParameterChange | WARNING | A monitored asset is switched into or out of **siloed borrowing** — a siloed asset can only be borrowed on its own (you can't borrow anything else against it in the same account), a containment control for assets with manipulable or thin-liquidity prices. Turning it on signals a price-manipulation concern; turning it off relaxes that. A risk-posture change surfaced on the dashboard, but not paged: it constrains borrowing behaviour only and never affects existing positions. |
| SiloedBorrowingChanged (other) | ProtocolParameterChange | INFO | A listing-time no-op (siloed status set to its default at reserve init) or a change on a non-monitored asset. Tracked on the dashboard, not paged. |
| LiquidationGracePeriodChanged (rated asset) | ProtocolParameterChange | WARNING | When a paused reserve is reopened, a grace period can keep liquidations blocked for a short window so borrowers can react before liquidations resume. This sets that window for a monitored asset. Surfaced on the dashboard as context for the reserve pause/unpause that triggered it (the pause itself is the page); not paged on its own. Non-monitored assets are INFO. |
| LiquidationGracePeriodDisabled (rated asset) | ProtocolParameterChange | WARNING | Cancels an active liquidation grace period on a monitored asset, re-enabling liquidations immediately. Dashboard context for the pause/unpause lifecycle; not paged on its own. Non-monitored assets are INFO. |
| PendingLtvChanged | ProtocolParameterChange | INFO | Bookkeeping for the freeze mechanism: when a reserve is frozen its current LTV is cached here (and effective LTV set to 0), then restored on unfreeze. It always accompanies a reserve freeze and the related collateral-config change, both of which already carry the alert, so this is tracked on the dashboard at INFO to avoid double-counting the same incident. |
| EModeCategoryAdded | ProtocolParameterChange | ERROR (rated-holding category, LT drop ≥500bps) / INFO | Defines/updates an efficiency-mode category's LTV & liquidation threshold; for a position in the category the category LT is the binding constraint. Aave v3.2 e-mode is high-churn (~40 categories, many ephemeral PT-token expiry categories, LTs tuned upward almost daily), so only a genuine ≥500bps LT *drop* on a category holding a rated asset pages — everything else is dashboard INFO. Stateful. 353 on-chain; **0** ≥500bps drops on rated categories → clean trip-wire (a flat WARNING tier would have been 95 rows of noise). |
| AssetCollateralInEModeChanged | ProtocolParameterChange | INFO | Enables/disables an asset as collateral in an e-mode category. High-churn in v3.2 (assets move between categories — `collateral=false` is routine restructuring, not a removal), so dashboard-only; used to maintain which categories hold a rated asset for the LT-drop rule above. Only rated-asset changes are recorded. (A naive "disabled → ERROR" rule would have mis-paged 20× on restructuring.) |
| AssetLtvzeroInEModeChanged | ProtocolParameterChange | ERROR (rated asset, ltvzero=true) / INFO | Forces (or restores) a rated asset's e-mode LTV to 0 — disabling it as e-mode borrowing power, a real de-risk/disable signal → ERROR; restoring → INFO. 1 on-chain on a rated asset (WETH cat 1 forced to 0, later restored). |
| Upgraded (Pool) | ContractUpgrade | ERROR | The main Pool contract's implementation is upgraded — this replaces the core money-market logic for the entire market (every monitored product and reserve), so it is always paged. It is kept at ERROR rather than the top severity because Pool upgrades are a routine, recurring governance migration (a few per year); the page exists so the upgrade can be confirmed against a known Aave governance proposal. |
## BlackRock (`blackrock`)
- **Chain(s):** Ethereum
- **Products:** `buidl`
- **Contracts monitored:**
- `BUIDL` — `0x7712c34205737192402172409a8f7ccef8aa2aec`
- `BUIDL-I` — `0x6a9da2d710bb9b700acde7cb81f10f1ff8c89041`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| ProxyTargetSet | ContractUpgrade | ERROR | BUIDL proxy target changed to new implementation |
| ProxyOwnerChanged | AdminChange | ERROR | BUIDL proxy owner changed |
| OwnershipTransferred | AdminChange | ERROR | DSToken ownership transferred |
| DSServiceSet | RoleChange | WARNING | Securitize infrastructure service address changed |
| WalletAdded | RoleChange | INFO | Wallet added to BUIDL whitelist |
| WalletRemoved | RoleChange | INFO | Wallet removed from BUIDL whitelist |
| Seize | EmergencyAction | CRITICAL | Token seizure (regulatory) executed |
| OmnibusSeize | EmergencyAction | CRITICAL | Omnibus account seizure executed |
| Pause | EmergencyAction | CRITICAL | Protocol paused |
| Unpause | EmergencyAction | CRITICAL | Protocol unpaused |
| Upgraded (BUIDL-I) | ContractUpgrade | ERROR | BUIDL-I proxy upgraded to new implementation |
## Coinbase (`coinbase`)
- **Chain(s):** Ethereum
- **Products:** `cbeth`
- **Contracts monitored:**
- `cbETH` — `0xbe9895146f7af43049ca1c1ae358b0541ea49704`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| Upgraded | ContractUpgrade | ERROR | cbETH proxy upgraded to new implementation |
| AdminChanged | AdminChange | ERROR | cbETH proxy admin changed |
| OwnershipTransferred | AdminChange | ERROR | Ownership transferred |
| MasterMinterChanged | RoleChange | WARNING | MasterMinter (controls who can mint) changed |
| MinterConfigured | RoleChange | WARNING | Minter added/updated with allowance |
| MinterRemoved | RoleChange | WARNING | Minter removed |
| PauserChanged | RoleChange | WARNING | Pauser role changed |
| BlacklisterChanged | RoleChange | WARNING | Blacklister role changed |
| RescuerChanged | RoleChange | WARNING | Rescuer role changed |
| OracleUpdated | RoleChange | WARNING | Oracle (exchange-rate updater) address updated |
| Pause | EmergencyAction | CRITICAL | Protocol paused |
| Unpause | EmergencyAction | CRITICAL | Protocol unpaused |
## Compound (`compound`)
- **Chain(s):** Ethereum
- **Products:** `usdt` (Comet market events); protocol-wide for governance/admin/multisig
- **Contracts monitored:**
- `cUSDTv3 (Comet)` — `0x3afdc9bca9213a35503b077a6072f3d0d5ab0840`
- `CometProxyAdmin` — `0x1ec63b5883c3481134fd50d5daebc83ecd2e8779`
- `Timelock` — `0x6d903f6003cca6255d85cca4d3b5e5146dc33925`
- `GovernorBravo` — `0xc0da02939e1441f497fd74f78ce7decb17b66529`
- `Community MultiSig (Pause Guardian)` — `0xbbf3f1421d886e9b2c5d716b5192ac998af2012c`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| PauseAction | EmergencyAction | ERROR | Market operations paused/unpaused |
| WithdrawReserves | ProtocolParameterChange | WARNING | Protocol reserves withdrawn to treasury |
| OwnershipTransferred (ProxyAdmin) | AdminChange | ERROR | CometProxyAdmin ownership transferred |
| NewDelay | TimelockChange | ERROR | Timelock delay changed |
| QueueTransaction | TimelockChange | INFO | Governance action queued |
| ExecuteTransaction | TimelockChange | INFO | Governance action executed |
| CancelTransaction | TimelockChange | INFO | Governance action cancelled |
| NewAdmin (Timelock) | AdminChange | ERROR | Timelock admin changed |
| NewPendingAdmin (Timelock) | AdminChange | WARNING | Timelock pending admin set |
| NewImplementation (Governor) | ContractUpgrade | ERROR | Governor implementation upgraded |
| VotingDelaySet | ProtocolParameterChange | WARNING | Voting delay changed |
| VotingPeriodSet | ProtocolParameterChange | WARNING | Voting period changed |
| ProposalThresholdSet | ProtocolParameterChange | WARNING | Proposal threshold changed |
| NewAdmin (Governor) | AdminChange | ERROR | Governor admin changed |
| NewPendingAdmin (Governor) | AdminChange | WARNING | Governor pending admin set |
| AddedOwner | MultisigChange | WARNING | Signer added to Pause Guardian multisig |
| RemovedOwner | MultisigChange | WARNING | Signer removed from Pause Guardian multisig |
| ChangedThreshold | MultisigChange | WARNING | Pause Guardian multisig threshold changed |
| EnabledModule | MultisigChange | WARNING | Module enabled on multisig |
| DisabledModule | MultisigChange | WARNING | Module disabled on multisig |
| ChangedGuard | MultisigChange | WARNING | Guard contract changed on multisig |
| ChangedFallbackHandler | MultisigChange | WARNING | Fallback handler changed on multisig |
## Ethena (`ethena`)
- **Chain(s):** Ethereum
- **Products:** `susde`
- **Contracts monitored:**
- `StakedUSDeV2 (sUSDe)` — `0x9D39A5DE30e57443BfF2A8307A4256c8797A3497`
- `USDe Token` — `0x4c9EDD5852cd905f086C759E8383e09bff1E68B3`
- `EthenaMinting` — `0xe3490297a08d6fC8Da46Edb7B6142E4F461b62D3`
- `StakingRewardsDistributor` — `0xf2fa332bd83149c66b09b45670bce64746c6b439`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| CooldownDurationUpdated (decreased) | ProtocolParameterChange | ERROR | sUSDe unstaking cooldown shortened — smaller defensive window before redemptions |
| CooldownDurationUpdated (increased) | ProtocolParameterChange | WARNING | sUSDe unstaking cooldown lengthened |
| AdminTransferRequested (sUSDe) | AdminChange | WARNING | sUSDe admin transfer requested (two-step step 1; pages on completion) |
| AdminTransferred (sUSDe) | AdminChange | CRITICAL | sUSDe root admin transferred — root-of-trust takeover of the staked vault |
| RoleGranted (sUSDe, BLACKLIST_MANAGER_ROLE) | RoleChange | ERROR | Freeze-power role granted (can restrict/blacklist stakers) |
| RoleGranted (sUSDe, REWARDER_ROLE) | RoleChange | WARNING | Rewarder role granted |
| RoleGranted (sUSDe, other/unlabeled role) | RoleChange | ERROR | Unknown or unexpected role granted (fail-loud). DEFAULT_ADMIN_ROLE and restricted-staker roles are suppressed as echo/compliance noise |
| RoleRevoked (sUSDe, BLACKLIST_MANAGER_ROLE) | RoleChange | ERROR | Freeze-power role revoked |
| RoleRevoked (sUSDe, other role) | RoleChange | WARNING | Non-freeze role revoked (risk-reducing) |
| RoleAdminChanged (sUSDe) | RoleChange | CRITICAL | sUSDe role-admin rewired — meta-authority over the permission system |
| LockedAmountRedistributed | EmergencyAction | CRITICAL | sUSDe locked stake seized/redistributed from restricted stakers |
| MaxMintPerBlockChanged (set to 0) | EmergencyAction | ERROR | USDe minting halted — per-block mint limit dropped to 0 |
| MaxMintPerBlockChanged (re-enabled from 0) | EmergencyAction | WARNING | USDe minting re-enabled — mint limit raised off 0 |
| MaxMintPerBlockChanged (other change) | ProtocolParameterChange | WARNING | Max mint per block changed |
| MaxRedeemPerBlockChanged (set to 0) | EmergencyAction | ERROR | USDe redemption halted — per-block redeem limit dropped to 0 |
| MaxRedeemPerBlockChanged (re-enabled from 0) | EmergencyAction | WARNING | USDe redemption re-enabled — redeem limit raised off 0 |
| MaxRedeemPerBlockChanged (other change) | ProtocolParameterChange | WARNING | Max redeem per block changed |
| AssetAdded | ProtocolParameterChange | ERROR | New collateral asset added to USDe backing — needs eyeball ("is this asset legit?") |
| AssetRemoved | ProtocolParameterChange | WARNING | Collateral asset removed (de-risking) |
| TokenTypeSet | ProtocolParameterChange | ERROR | Collateral token classification changed (e.g. stable-bucket treatment) |
| CustodianAddressAdded | AdminChange | ERROR | New custodian destination authorized — collateral can be sent off-chain to it |
| CustodianAddressRemoved | AdminChange | WARNING | Custodian destination removed (de-risking) |
| USDeSet | ContractUpgrade | ERROR | EthenaMinting USDe address changed |
| DelegatedSignerAdded | RoleChange | WARNING | Benefactor delegated its own signing authority (counterparty-level) |
| DelegatedSignerRemoved | RoleChange | WARNING | Benefactor removed a delegated signer |
| AdminTransferRequested (EthenaMinting) | AdminChange | WARNING | EthenaMinting admin transfer requested (two-step step 1; pages on completion) |
| AdminTransferred (EthenaMinting) | AdminChange | CRITICAL | EthenaMinting root admin transferred — controls mint, redeem and collateral custody |
| RoleGranted (EthenaMinting, MINTER/REDEEMER/COLLATERAL_MANAGER_ROLE) | RoleChange | ERROR | Fund- or supply-affecting role granted (mint USDe, release collateral, move backing to custody) |
| RoleGranted (EthenaMinting, GATEKEEPER_ROLE) | RoleChange | WARNING | Defensive circuit-breaker role granted (can halt, not steal) |
| RoleGranted (EthenaMinting, other/unlabeled role) | RoleChange | ERROR | Unknown or unexpected role granted (fail-loud). DEFAULT_ADMIN_ROLE suppressed (echo of AdminTransferred) |
| RoleRevoked (EthenaMinting) | RoleChange | WARNING | Any EthenaMinting role revoked (de-risking); DEFAULT_ADMIN_ROLE suppressed |
| RoleAdminChanged (EthenaMinting) | RoleChange | CRITICAL | EthenaMinting role-admin rewired — meta-authority over the permission system |
| MinterUpdated (USDe) | RoleChange | CRITICAL | USDe minter changed — sole authority to mint the synthetic dollar |
| OwnershipTransferred (USDe) | AdminChange | ERROR | USDe ownership transferred |
| OwnershipTransferStarted (USDe) | AdminChange | WARNING | USDe ownership transfer started (two-step step 1; pages on completion) |
| OperatorUpdated (StakingRewardsDistributor) | RoleChange | WARNING | StakingRewardsDistributor operator updated |
| MintingContractUpdated | ContractUpgrade | ERROR | StakingRewardsDistributor minting contract updated |
| OwnershipTransferred (StakingRewardsDistributor) | AdminChange | ERROR | StakingRewardsDistributor ownership transferred |
| OwnershipTransferStarted (StakingRewardsDistributor) | AdminChange | WARNING | StakingRewardsDistributor ownership transfer started (two-step step 1; pages on completion) |
| TokensRescued (StakingRewardsDistributor) | EmergencyAction | CRITICAL | Arbitrary ERC-20 swept out of the rewards distributor via rescueTokens — always warrants review |
## EtherFi (`etherfi`)
- **Chain(s):** Ethereum
- **Products:** `eeth`, `weeth`, `liquid-eth`, plus protocol-wide for governance/admin contracts
- **Contracts monitored:**
- `eETH` — `0x35fA164735182de50811E8e2E824cFb9B6118ac2`
- `weETH` — `0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee`
- `LiquidityPool` — `0x308861A430be4cce5502d0A12724771Fc6DaF216`
- `WithdrawRequestNFT` — `0x7d5706f6ef3F89B3951E23e557CDFBC3239D4E2c`
- `MembershipManager` — `0x3d320286E014C3e1ce99Af6d6B00f0C1D63E3000`
- `EtherFiAdmin` — `0x0EF8fa4760Db8f5Cd4d993f3e3416f30f942D705`
- `EtherFiTimelock` — `0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761`
- `Treasury` — `0x6329004E903B7F420245E7aF3f355186f2432466`
- `BoringVault (Liquid ETH)` — `0xf0bb20865277aBd641a307eCe5ee04E79073416C`
- `Teller (Liquid ETH)` — `0x9AA79C84b79816ab920bBcE20f8f74557B514734`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| Upgraded (LiquidityPool) | ContractUpgrade | ERROR | LiquidityPool implementation upgraded |
| OwnershipTransferred (LiquidityPool) | AdminChange | ERROR | LiquidityPool ownership transferred |
| AdminChanged (LiquidityPool) | AdminChange | ERROR | LiquidityPool proxy admin changed |
| Paused (LiquidityPool) | EmergencyAction | ERROR | LiquidityPool paused |
| Unpaused (LiquidityPool) | EmergencyAction | ERROR | LiquidityPool unpaused |
| UpdatedFeeRecipient (LiquidityPool) | ProtocolParameterChange | WARNING | LiquidityPool fee recipient updated |
| UpdatedTreasury (LiquidityPool) | ProtocolParameterChange | WARNING | LiquidityPool treasury address updated |
| Upgraded (WithdrawRequestNFT) | ContractUpgrade | ERROR | WithdrawRequestNFT upgraded |
| OwnershipTransferred (WithdrawRequestNFT) | AdminChange | ERROR | WithdrawRequestNFT ownership transferred |
| Paused (WithdrawRequestNFT) | EmergencyAction | ERROR | WithdrawRequestNFT paused |
| Unpaused (WithdrawRequestNFT) | EmergencyAction | ERROR | WithdrawRequestNFT unpaused |
| MinDelayChange (Timelock, decreased) | TimelockChange | ERROR | Timelock min delay decreased (higher risk) |
| MinDelayChange (Timelock, increased) | TimelockChange | WARNING | Timelock min delay increased/unchanged |
| RoleGranted (Timelock) | RoleChange | WARNING | Timelock role granted |
| RoleRevoked (Timelock) | RoleChange | WARNING | Timelock role revoked |
| RoleAdminChanged (Timelock) | RoleChange | ERROR | Timelock role admin changed |
| CallScheduled (Timelock) | TimelockChange | INFO | Timelock call scheduled |
| CallExecuted (Timelock) | TimelockChange | INFO | Timelock call executed |
| Cancelled (Timelock) | TimelockChange | INFO | Timelock call cancelled |
| AdminUpdated (EtherFiAdmin) | AdminChange | ERROR | EtherFiAdmin admin added/removed |
| Upgraded (EtherFiAdmin) | ContractUpgrade | ERROR | EtherFiAdmin upgraded |
| OwnershipTransferred (EtherFiAdmin) | AdminChange | ERROR | EtherFiAdmin ownership transferred |
| Upgraded (eETH) | ContractUpgrade | ERROR | eETH token contract upgraded |
| OwnershipTransferred (eETH) | AdminChange | ERROR | eETH token ownership transferred |
| Upgraded (weETH) | ContractUpgrade | ERROR | weETH token contract upgraded |
| OwnershipTransferred (weETH) | AdminChange | ERROR | weETH token ownership transferred |
| Upgraded (MembershipManager) | ContractUpgrade | ERROR | MembershipManager upgraded |
| OwnershipTransferred (MembershipManager) | AdminChange | ERROR | MembershipManager ownership transferred |
| Paused (MembershipManager) | EmergencyAction | ERROR | MembershipManager paused |
| Unpaused (MembershipManager) | EmergencyAction | ERROR | MembershipManager unpaused |
| OwnershipTransferred (Treasury) | AdminChange | ERROR | Treasury ownership transferred |
| AuthorityUpdated (BoringVault) | AdminChange | ERROR | BoringVault authority updated |
| OwnershipTransferred (BoringVault) | AdminChange | ERROR | BoringVault ownership transferred |
| AssetDataUpdated (Teller) | ProtocolParameterChange | INFO | Teller asset data updated |
| Paused (Teller) | EmergencyAction | ERROR | Teller paused |
| Unpaused (Teller) | EmergencyAction | ERROR | Teller unpaused |
| AuthorityUpdated (Teller) | AdminChange | ERROR | Teller authority updated |
| OwnershipTransferred (Teller) | AdminChange | ERROR | Teller ownership transferred |
## HyperLend (`hyperlend`)
- **Chain(s):** HyperEVM
- **Products:** rated as a single product — the **HYPE Core Market** (product `hype`, the WHYPE reserve `0x5555…5555`). Most incidents are protocol-wide (`product: ""`); only events on the rated HYPE reserve escalate above INFO and carry `product: hype`. The exchange-rate series (`getReserveNormalizedIncome`, the HYPE supply liquidity index) is polled for `hype`.
- **Contracts monitored:**
- `Pool` — `0x00A89d7a5A02160f20150EbEA7a2b5E4879A1A8b`
- `PoolConfigurator` — `0x8CB4310dD38F6fD59388C9DE225f328092bdC379`
- `PoolAddressesProvider` — `0x72c98246a98bFe64022a3190e7710E157497170C`
- `ACLManager` — `0x10914Ee2C2dd3F3dEF9EFFB75906CA067700a04A`
- `ProxyAdmin` — `0xdb3Bf3e22380780F75D7F57C772e71fCa7EBA027`
- `TimelockA` — `0xaAaaaAAAa810beD1EDA93A18FEC940857ED17879`
- `TimelockB` — `0xbbBBbbBB81e9B92918AA51e0CDfB3B53f7D72432`
- `TimelockC` — `0xCCcCCcCCC4B6CD09594E7c5bF108695F79313115`
- `GovernanceMultisig` — `0x2110E7B8e925C387A88259CEac9bd82c47868E9C`
- `TreasuryMultisig` — `0xCBF400610DBF462fE316D8A7db6Ba78d57E43d7b`
- `EmergencyAdminMultisig` — `0xC2A0F2c78dd7E37C82aA3A8e37fc712a3ddb7cAc`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| RoleGranted (ACLManager — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the root access-control key that can administer every other role — effectively whole-protocol control. The highest-trust change the protocol can make, so it pages at top urgency. |
| RoleGranted (ACLManager — POOL_ADMIN / EMERGENCY_ADMIN / ASSET_LISTING_ADMIN) | RoleChange | ERROR | A new address gains a powerful privileged role: pool administration (including upgrading the tokens that hold user funds), the ability to pause the protocol, or control over which price oracles are used. Each can materially affect funds or availability, so granting it pages. |
| RoleGranted (ACLManager — RISK_ADMIN / BRIDGE) | RoleChange | WARNING | A new address gains a bounded operational role — tuning risk parameters within limits, or bridge minting capped by configuration. Expected governance activity, recorded for visibility but does not page. |
| RoleGranted (ACLManager — FLASH_BORROWER) | RoleChange | INFO | A new address is exempted from flash-loan premiums. Carries no governance power and cannot affect other users, logged for completeness only. |
| RoleGranted (ACLManager — unrecognized role) | RoleChange | ERROR | A role the monitor cannot map to a known name is granted. An unmapped or custom role could be powerful, so it is treated as potentially dangerous and paged ("fail loud"). |
| RoleRevoked (ACLManager — DEFAULT_ADMIN / EMERGENCY_ADMIN / POOL_ADMIN) | RoleChange | ERROR | A role whose *loss* is dangerous is removed — the root key (removal can lock out governance), the emergency-pause ability (losing it removes the protocol's exploit brake), or pool administration. Worth paging even though revocations usually reduce risk, because these can also signal a hostile takeover or an operational mistake. |
| RoleRevoked (ACLManager — other roles) | RoleChange | WARNING | A lower-impact role (e.g. risk admin, asset-listing admin) is removed. Reducing privilege is generally safe, so it is recorded but does not page. |
| RoleAdminChanged (ACLManager) | RoleChange | CRITICAL | The rule for *who may grant or revoke* a role is rewired — a structural change to the access-control graph itself, not just who holds a role. This is meta-authority over the entire permission system: changing the admin of a powerful role (e.g. POOL_ADMIN or the root DEFAULT_ADMIN) is a direct privilege-escalation / takeover vector. It is not part of normal operations, so any occurrence is maximally anomalous — paged at the highest severity, same tier as a root-authority or oracle swap. |
| MinDelayChange (Timelock, decrease) | TimelockChange | ERROR | Timelock delay decreased |
| MinDelayChange (Timelock, increase) | TimelockChange | WARNING | Timelock delay increased |
| RoleGranted (Timelock — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the timelock's own admin role — it can grant itself proposer and executor and bypass the delay entirely, i.e. full control of the governance queue. Pages at top urgency. |
| RoleGranted (Timelock — PROPOSER / CANCELLER) | RoleChange | ERROR | A new address gains the ability to schedule arbitrary privileged operations into the timelock queue (proposer), or to cancel a pending operation before it executes (canceller — can block an emergency governance action). Each is a governance-integrity change worth paging. |
| RoleGranted (Timelock — EXECUTOR) | RoleChange | WARNING | A new address may execute operations that are already scheduled and past their delay — it cannot introduce new actions, so it is recorded but does not page. |
| RoleGranted (Timelock — unrecognized role) | RoleChange | ERROR | A role the monitor cannot map to a known name is granted; treated as potentially powerful and paged ("fail loud"). |
| RoleRevoked (Timelock — DEFAULT_ADMIN / CANCELLER) | RoleChange | ERROR | A capability whose *loss* is dangerous is removed — the timelock admin (removal can lock out / brick governance) or the canceller (removes the brake that can stop a malicious pending operation). Worth paging. |
| RoleRevoked (Timelock — PROPOSER / EXECUTOR) | RoleChange | WARNING | A lower-impact timelock role is removed. Reducing privilege is generally safe and recoverable, so it is recorded but does not page. |
| ACLAdminUpdated | AdminChange | ERROR | Changes which address is registered as the ACL admin — the account tied to the ACLManager's root DEFAULT_ADMIN role that ultimately grants and revokes every other role. A root-of-trust change, so it always pages. Unlike ACLManagerUpdated, this updates a stored pointer rather than swapping the live authority contract, so it is ERROR rather than CRITICAL. |
| ACLManagerUpdated | ContractUpgrade | CRITICAL | Repoints the protocol at a different ACLManager contract. Because permission checks resolve the manager at runtime, a swap immediately changes the authority behind every privileged action — a malicious manager could make anyone a pool admin and drain funds. Outside initial setup this is not a normal operation, so any occurrence is a top-urgency, funds-at-risk event. |
| PoolUpdated | ContractUpgrade | ERROR | Upgrades the implementation behind the core Pool proxy — replacing the code of the main lending contract while funds and storage stay in the unchanged proxy. Governance-gated and routine, but because it ships new code for the contract at the heart of the protocol, every upgrade pages so it can be matched to a known governance proposal. (Co-fires with the Pool-proxy Upgraded event.) |
| PoolConfiguratorUpdated | ContractUpgrade | ERROR | Upgrades the implementation behind the PoolConfigurator proxy — the privileged contract that sets every reserve's risk parameters (caps, collateral config, freeze/pause). A malicious configurator could mis-set parameters market-wide, but it does not custody funds; each upgrade pages so the new code can be matched to a known governance proposal. |
| PriceOracleUpdated | ContractUpgrade | CRITICAL | Swaps the protocol's entire price-oracle contract. Pricing is resolved at runtime, so a swap instantly repoints all collateral valuation and liquidations — a malicious or buggy oracle is one of the fastest ways to drain a lending pool. Outside initial setup this is not a normal operation; any occurrence is a top-urgency, funds-at-risk event. (Routine per-asset feed changes use a different event.) |
| OwnershipTransferred (AddressesProvider) | AdminChange | CRITICAL | Ownership of the PoolAddressesProvider — the market's master registry — moves to a new address. Its owner is the single key that can swap the Pool, the PoolConfigurator, the ACLManager, and the price oracle, i.e. it can trigger every one of the funds-at-risk events above. Transferring it is the protocol's top root-of-trust change. Ownership moves only as part of a governance migration (the legitimate owner is the governance pipeline), so any other occurrence is a top-urgency, funds-at-risk event. |
| ProxyCreated | ContractUpgrade | INFO | The AddressesProvider deploys a brand-new proxy for a registry slot. Fires only the first time a proxied component is registered, and co-fires with the meaningful event for that component (PoolUpdated / AddressSetAsProxy) which carries the real severity. On its own it grants no privileges and moves no funds, so it is recorded for completeness only. |
| AddressSetAsProxy | ContractUpgrade | ERROR | Upgrades the implementation behind a registered proxy via the generic registry path — the same mechanism as PoolUpdated, but for a registry slot without its own dedicated setter. It swaps the executing code of a governance-controlled proxy, so it carries the same risk class as a Pool/Configurator upgrade and pages, to be matched against a known governance proposal. |
| ReserveFactorChanged (≤50%) | ProtocolParameterChange | INFO | The reserve factor — the share of borrow interest diverted to the treasury rather than to suppliers — is changed for an asset. A routine economic knob with no fund-custody, collateral, or solvency reach. Normal values sit in a ~5–50% band, so changes within it are dashboard-only. |
| ReserveFactorChanged (>50%) | ProtocolParameterChange | WARNING | The new reserve factor exceeds 50%, outside the normal operating band — typically an asset being offboarded or a special-asset setting. Surfaced for confirmation that it is intended; it does not page. |
| FlashloanPremiumTotalUpdated (≤1%) | ProtocolParameterChange | INFO | The total flash-loan premium (the fee on a flash loan) is changed. The lowest-stakes fee — it cannot reach funds or solvency (a high premium just makes flash loans expensive, a zero premium just makes them free; the loan must still be repaid in the same transaction). Normal values are a few bps, so changes within range are dashboard-only. |
| FlashloanPremiumTotalUpdated (>1%) | ProtocolParameterChange | WARNING | The new flash-loan premium exceeds 1% — roughly a tenfold jump over the 5–9 bps norm. There is no legitimate reason for such a value, so it is surfaced as a likely misconfiguration or tampering signal. It does not page. |
| FlashloanPremiumToProtocolUpdated | ProtocolParameterChange | INFO | Changes how the flash-loan premium is split between the treasury and suppliers (0–100%). The borrower's total fee is unchanged — only who receives it — so there is no fund or solvency reach. Recorded for completeness. |
| BridgeProtocolFeeUpdated | ProtocolParameterChange | WARNING | The bridge protocol fee is changed. The fee itself is a harmless bounded split, but it belongs to the dormant Portal / unbacked-mint subsystem, which has never been used on HyperLend. Any change is a canary that someone is configuring Portal, so it is surfaced — dashboard-only, never pages. |
| LiquidationProtocolFeeChanged (≤30%) | ProtocolParameterChange | INFO | The protocol's cut *of* the liquidation bonus for an asset is changed, within the normal band. Routine; recorded dashboard-only. |
| LiquidationProtocolFeeChanged (>30%) | ProtocolParameterChange | WARNING | The new cut exceeds 30% — high enough to erode the liquidator's margin, which can stall liquidations and create bad-debt / solvency risk. Surfaced for review; the risk is gradual (not instant loss) and the parameter is bounded, so it is dashboard-only and does not page. |
| ATokenUpgraded | ContractUpgrade | ERROR | Upgrades the aToken implementation for a reserve — the contract that custodies suppliers' deposits. A fund-bearing code swap, so it pages to be matched against a known governance proposal. Not CRITICAL (routine per-asset migration). The HYPE reserve tags product `hype`; other reserves are protocol-wide. |
| VariableDebtTokenUpgraded | ContractUpgrade | ERROR | Upgrades the variable-debt-token implementation for a reserve — the contract that tracks borrowers' debt. Same fund-bearing risk class as the aToken upgrade; pages to be matched against a known governance proposal. |
| ReserveInterestRateStrategyChanged | ProtocolParameterChange | INFO | Points a reserve at a different interest-rate-strategy contract (the contract that computes borrow/supply rates from utilization). Affects only rates, not custody — a bad curve could grief with extreme rates but cannot move funds and is fully recoverable. On HyperLend (Aave v3.0.2) this is the sole rate-model-change signal; there is no V3.2 interest-rate-data event. Tracked on the dashboard, not paged. |
| ReservePaused (HYPE, paused) | EmergencyAction | CRITICAL | Emergency halt of the HYPE reserve — pausing blocks every interaction with the asset including withdrawals and liquidations, so the rated product goes fully dark and user funds are locked in place. Strictly more severe than a freeze (which still lets users exit). Paged immediately whether it is protective incident response or hostile. Never fired on HyperLend to date. |
| ReservePaused (HYPE, unpaused) | EmergencyAction | WARNING | The HYPE reserve is taken out of pause and restored to normal operation — the recovery / all-clear signal. Dashboard, not paged. |
| ReservePaused (other reserves) | EmergencyAction | INFO | A non-rated reserve in the market is paused/unpaused. Tracked on the dashboard only. |
| ReserveFrozen (HYPE, frozen) | EmergencyAction | ERROR | The HYPE reserve is frozen — new supply and borrow are blocked, but users can still repay, withdraw, and be liquidated, so funds are not locked. The graceful asset-offboarding tool, one tier below a pause; material enough to page, but not critical because exits stay open. |
| ReserveFrozen (HYPE, unfrozen) | EmergencyAction | WARNING | The HYPE reserve is unfrozen and re-enabled for new supply and borrow — the recovery signal. Dashboard, not paged. |
| ReserveFrozen (other reserves) | EmergencyAction | INFO | A non-rated reserve is frozen/unfrozen. Tracked on the dashboard only (the freezes to date were all on non-rated reserves). |
| CollateralConfigurationChanged (HYPE, LTV→0 or liquidation-threshold cut ≥5%) | ProtocolParameterChange | ERROR | The solvency-critical collateral parameters of the HYPE reserve — loan-to-value (LTV), liquidation threshold (LT), and liquidation bonus. Two cases page: (1) a drop in the liquidation threshold, which makes existing positions immediately liquidatable and can trigger a wave of forced liquidations and bad debt — the genuinely dangerous direction; (2) LTV set to 0, which disables HYPE as new collateral (a protective de-risking signal). Evaluated against the previous on-chain value, so only a real transition pages. |
| CollateralConfigurationChanged (HYPE, other change) | ProtocolParameterChange | WARNING | Routine re-parameterisation of HYPE collateral — raising LTV/threshold, small adjustments, or liquidation-bonus tweaks. Material enough to record but not dangerous to existing positions, so it is tracked on the dashboard rather than paged. |
| CollateralConfigurationChanged (other reserves) | ProtocolParameterChange | INFO | Collateral config change on a non-rated reserve. Dashboard only. |
| BorrowCapChanged (HYPE, disabled) | ProtocolParameterChange | WARNING | The HYPE borrow cap is cut to the "disabled" sentinel (a cap of 1 token), effectively stopping new borrowing of the asset — a wind-down / de-risking signal. Surfaced on the dashboard for prominence (it correlates with freezes and collateral de-risking), but not paged: the cap only limits new borrowing and never affects existing positions or funds. |
| BorrowCapChanged (other) | ProtocolParameterChange | INFO | Routine borrow-cap adjustment, or any change on a non-rated reserve. Cannot affect existing positions or cause loss, so it is tracked on the dashboard, not paged. |
| SupplyCapChanged (HYPE, disabled) | ProtocolParameterChange | WARNING | The HYPE supply cap is cut to the "disabled" sentinel (a cap of 1 token), effectively stopping new deposits — a wind-down signal. Surfaced on the dashboard for prominence, but not paged: the cap only limits new deposits and never affects existing positions or funds. |
| SupplyCapChanged (other) | ProtocolParameterChange | INFO | Routine supply-cap adjustment, or any change on a non-rated reserve. Cannot affect existing positions or cause loss, so it is tracked on the dashboard, not paged. |
| OwnershipTransferred (ProxyAdmin) | AdminChange | CRITICAL | Ownership of the ProxyAdmin — the contract that owns the transparent proxies and can upgrade their implementations — moves to a new address. Whoever owns it can swap the fund-bearing proxy code, i.e. upgrade the protocol; it is HyperLend's root upgrade key (the structural equivalent of Aave's governance executor). The legitimate owner is the governance pipeline; ownership moves only during a governance migration, so any other occurrence is a top-urgency, funds-at-risk event. |
| Upgraded (Pool) | ContractUpgrade | ERROR | The implementation behind the main Pool proxy is swapped. The Pool holds all core lending logic (supply, borrow, liquidate, interest accrual), so a logic swap can change every accounting rule in the market — the single most powerful upgrade in the protocol. Twins with PoolUpdated from the PoolAddressesProvider (the registry-side announcement of the same swap). Pages at ERROR; CRITICAL is reserved for unstoppable-takeover changes (Safe threshold/module). Seen 4 times — all legitimate Aave-fork version upgrades. |
| AddedOwner (Safe) | MultisigChange | ERROR | A new signer is added to one of HyperLend's admin Safes (Governance / Treasury / EmergencyAdmin), which sit atop the governance pipeline. Changing who can authorize the multisig's actions alters the protocol's trust set, so it pages to be confirmed against a known governance decision. Not CRITICAL: adding a signer without also lowering the threshold does not grant unilateral control. |
| RemovedOwner (Safe) | MultisigChange | ERROR | A signer is removed from one of HyperLend's admin Safes (Governance / Treasury / EmergencyAdmin). The mirror of AddedOwner — it alters who controls the multisig (rotating out a compromised key, or a hostile actor pruning honest signers). Pages to be confirmed against a known governance decision; not CRITICAL on its own unless paired with a threshold drop (which pages CRITICAL separately). |
| ChangedThreshold (Safe) | MultisigChange | CRITICAL | Changes how many signer approvals (M of N) the Safe requires. The threshold *is* the multisig's security — lowering it, especially to 1, collapses the Safe to effectively single-signer control, so one key (compromised, malicious, or coerced) can unilaterally execute anything it controls (here, the whole governance pipeline). An instant takeover-class change, so it pages at the top tier on any threshold change. |
| EnabledModule (Safe) | MultisigChange | CRITICAL | A Safe module is enabled. Modules can execute transactions *through* the Safe bypassing the M-of-N signature check entirely — so a malicious or buggy module can move funds and drive the governance pipeline with zero signer approvals, regardless of the threshold. The most dangerous Safe change there is; never used on HyperLend, so a first-ever occurrence is highly anomalous and paged at the top tier. |
| DisabledModule (Safe) | MultisigChange | ERROR | A previously-enabled Safe module is removed. Generally risk-reducing (it removes a signature-bypass path), so a tier below enabling one — but still an execution-surface change worth a look, since it could be benign cleanup or the hostile removal of a legitimate safety/recovery module. Never used on HyperLend. |
| ChangedGuard (Safe) | MultisigChange | ERROR | A transaction guard is set, replaced, or removed on a HyperLend Safe. A guard hooks every Safe transaction (pre/post execution) and can revert any of them, so a malicious guard can freeze the multisig (DoS) and removing one strips a protective check — an execution-control change paged at ERROR. Never used on HyperLend. |
| ChangedFallbackHandler (Safe) | MultisigChange | ERROR | The fallback handler on a HyperLend Safe is set or replaced. The handler runs in the Safe's context for calls that match none of its own functions and can expand the Safe's callable surface — e.g. forging EIP-1271 "valid signature" responses so other contracts accept the Safe's approval without a real multisig vote. Quieter than a guard/module change and can't move funds itself, but still a callable-surface change paged at ERROR. Never used on HyperLend. |
## Kelp (`kelp`)
- **Chain(s):** Ethereum
- **Products:** `rseth`, plus protocol-wide for Timelock/Safe governance contracts
- **Contracts monitored:**
- `rsETH Token` — `0xA1290d69c65A6Fe4DF752f95823fae25cB99e5A7`
- `LRTDepositPool` — `0x036676389e48133B63a802f8635AD39E752D375D`
- `LRTOracle` — `0x349A73444b1a310BAe67ef67973022020d70020d`
- `TimelockController` — `0x49bD9989E31aD35B0A62c20BE86335196A3135B1`
- `External Admin Safe (6/8)` — `0xb3696a817D01C8623E66D156B6798291fa10a46d`
- `ProxyAdmin` — `0xb61e0E39b6d4030C36A176f576aaBE44BF59Dc78`
- `LRTWithdrawalManager` — `0x62De59c08eB5dAE4b7E6F7a8cAd3006d6965ec16`
- `LRTUnstakingVault` — `0xc66830e2667bc740c0bed9a71f18b14b8c8184ba`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| Paused (rsETH) | EmergencyAction | CRITICAL | rsETH token paused |
| Unpaused (rsETH) | EmergencyAction | CRITICAL | rsETH token unpaused |
| CustodyAddressUpdated (rsETH) | AdminChange | ERROR | rsETH custody address updated |
| UpdatedLRTConfig (rsETH) | AdminChange | ERROR | rsETH LRT config updated |
| FrozenFundsRecovered (rsETH) | EmergencyAction | CRITICAL | Frozen funds recovered from/to addresses |
| UserTransfersBlocked (rsETH) | EmergencyAction | ERROR | User transfers blocked until timestamp |
| MaxMintAmountPerDayUpdated (rsETH) | ProtocolParameterChange | WARNING | rsETH max mint amount per day updated |
| Paused (LRTDepositPool) | EmergencyAction | CRITICAL | LRTDepositPool paused |
| Unpaused (LRTDepositPool) | EmergencyAction | CRITICAL | LRTDepositPool unpaused |
| MinAmountToDepositUpdated | ProtocolParameterChange | INFO | Min amount to deposit updated |
| MaxNodeDelegatorLimitUpdated | ProtocolParameterChange | WARNING | Max node delegator limit updated |
| NodeDelegatorAddedinQueue | AdminChange | WARNING | Node delegator added to queue |
| NodeDelegatorRemovedFromQueue | AdminChange | WARNING | Node delegator removed from queue |
| UpdatedLRTConfig (LRTDepositPool) | AdminChange | ERROR | LRTDepositPool LRT config updated |
| RsETHPriceDecrease (LRTOracle) | EmergencyAction | ERROR | rsETH price decreased |
| RsETHPriceBelowPeak (LRTOracle) | EmergencyAction | WARNING | rsETH price below peak |
| AssetPriceOracleUpdate (LRTOracle) | ProtocolParameterChange | WARNING | Asset price oracle updated |
| PricePercentageLimitUpdate (LRTOracle) | ProtocolParameterChange | WARNING | Price percentage limit updated |
| MaxFeeMintAmountPerDayUpdated (LRTOracle) | ProtocolParameterChange | WARNING | Max fee mint amount per day updated |
| Paused (LRTOracle) | EmergencyAction | CRITICAL | LRTOracle paused |
| Unpaused (LRTOracle) | EmergencyAction | CRITICAL | LRTOracle unpaused |
| UpdatedLRTConfig (LRTOracle) | AdminChange | ERROR | LRTOracle LRT config updated |
| Paused (LRTWithdrawalManager) | EmergencyAction | CRITICAL | LRTWithdrawalManager paused |
| Unpaused (LRTWithdrawalManager) | EmergencyAction | CRITICAL | LRTWithdrawalManager unpaused |
| EmergencyWithdrawFromAave | EmergencyAction | CRITICAL | Emergency withdrawal from Aave |
| InstantWithdrawalFeeUpdated | ProtocolParameterChange | WARNING | Instant withdrawal fee updated |
| InstantWithdrawalFeeRecipientUpdated | ProtocolParameterChange | WARNING | Instant withdrawal fee recipient updated |
| InstantWithdrawalEnabledUpdated | ProtocolParameterChange | WARNING | Instant withdrawal enabled/disabled for asset |
| WithdrawalDelayBlocksUpdated | ProtocolParameterChange | WARNING | Withdrawal delay blocks updated |
| MinAmountToWithdrawUpdated | ProtocolParameterChange | INFO | Min amount to withdraw updated |
| AaveIntegrationConfigured | ProtocolParameterChange | WARNING | Aave integration configured |
| AaveIntegrationEnabled | ProtocolParameterChange | WARNING | Aave integration enabled/disabled |
| UpdatedLRTConfig (LRTWithdrawalManager) | AdminChange | ERROR | LRTWithdrawalManager LRT config updated |
| Paused (LRTUnstakingVault) | EmergencyAction | ERROR | LRTUnstakingVault paused |
| Unpaused (LRTUnstakingVault) | EmergencyAction | ERROR | LRTUnstakingVault unpaused |
| MaxUncompletedWithdrawalCountSet | ProtocolParameterChange | WARNING | Max uncompleted withdrawal count set |
| QueuedWithdrawalsBufferUpdated | ProtocolParameterChange | INFO | Queued withdrawals buffer updated |
| UpdatedLRTConfig (LRTUnstakingVault) | AdminChange | ERROR | LRTUnstakingVault LRT config updated |
| MinDelayChange (Timelock, decreased) | TimelockChange | ERROR | Timelock min delay decreased (higher risk) |
| MinDelayChange (Timelock, increased) | TimelockChange | WARNING | Timelock min delay increased/unchanged |
| RoleGranted (Timelock) | RoleChange | WARNING | Timelock role granted |
| RoleRevoked (Timelock) | RoleChange | WARNING | Timelock role revoked |
| RoleAdminChanged (Timelock) | RoleChange | ERROR | Timelock role admin changed |
| CallScheduled (Timelock) | TimelockChange | INFO | Timelock call scheduled |
| CallExecuted (Timelock) | TimelockChange | INFO | Timelock call executed |
| Cancelled (Timelock) | TimelockChange | INFO | Timelock call cancelled |
| AddedOwner (Safe) | MultisigChange | WARNING | Owner added to External Admin Safe |
| RemovedOwner (Safe) | MultisigChange | WARNING | Owner removed from External Admin Safe |
| ChangedThreshold (Safe) | MultisigChange | WARNING | External Admin Safe threshold changed |
| EnabledModule (Safe) | MultisigChange | WARNING | Module enabled on External Admin Safe |
| DisabledModule (Safe) | MultisigChange | WARNING | Module disabled on External Admin Safe |
| ChangedGuard (Safe) | MultisigChange | WARNING | Guard changed on External Admin Safe |
| ChangedFallbackHandler (Safe) | MultisigChange | WARNING | Fallback handler changed on External Admin Safe |
## Lido — earnETH (`lido-finance`)
- **Chain(s):** Ethereum
- **Products:** `earneth`. The Mellow-global Factories and the seven governing Safes are shared with earnUSD, so their events are emitted protocol-wide (`product: ""`) and appear in both Lido Earn sections
- **Contracts monitored:**
- `Vault` — `0x6a37725ca7f4CE81c004c955f7280d5C704a249e`
- `ShareManager (earnETH share token)` — `0xBBFC8683C8fE8cF73777feDE7ab9574935fea0A4`
- `Oracle` — `0xAda1f4c24603aB2fe5aBd35BCD12370e98A20358`
- `OracleSubmitter` — `0xFbD83f7C531D35D99392a5A20bb5F1e75E97076e`
- `FeeManager` — `0xed4Fac879eE86F3aB0101993A3713e7cAA0488E1`
- `RiskManager` — `0xa2a4C4ecE27229aF51c546844AB752824Ccb557e`
- `TimelockController` — `0x363Ba8843d06BA5968f55C26aB055162eDd62189`
- Verifiers (the curator's permission set):
- `Verifier 0` — `0xBc46B79d79fCac1F4232D4Da1BA31aCED0AABFE0`
- `Verifier 1` — `0xc0FC0B74923A80Af21B1E49633cAA309f432140F`
- Redemption queues:
- `RedeemQueue (wstETH)` — `0x095bFAca9f1c6F2B063Cd67C6d6bfcd0c3aaB7b4`
- `SyncRedeemQueue (wstETH)` — `0xB5984D87d21C4375d18972fd546b688BD4Fc1f0A`
- Instant-deposit queues:
- `SyncDepositQueue (ETH)` — `0xb99394f8b95d426Cb2F013B857C74aCC924b20D5`
- `SyncDepositQueue (WETH)` — `0xCe6C2505fEF74d2dE10FCF1d534cB73eCc837976`
- `SyncDepositQueue (wstETH)` — `0xECD2Bfe725fa14f5Ed86e9bDcc0eA4b34A4ed522`
- `SyncDepositQueue (GG)` — `0x2792004b709E3E88b8FCCb06c3C5e1A6dff0EC2B`
- `SyncDepositQueue (strETH)` — `0xA4F23f56442C01a478af20fe06b9F5f8f05aDD96`
- `SyncDepositQueue (DVstETH)` — `0xA80f247b92C79740b0610b754403D5cb0bf216b5`
- Subvaults and async deposit queues (monitored for proxy upgrades and upgrade-authority changes only):
- `Subvault 0` — `0xC5901C2481ca9C26398A9Da258b13717894bfebF`
- `Subvault 1` — `0x7F515C80fA4C1FCFF34F0329141A9C3b20468FE5`
- `DepositQueue (ETH)` — `0x1db7094Ef0D994B0b62f6Cd67dB801ad194999A8`
- `DepositQueue (WETH)` — `0x3Fc48660d02e59fBedD0a5Cc18a5580D1f8dD6A4`
- `DepositQueue (wstETH)` — `0xe39EED9A454C4918F8d0682062777cB251cd513F`
- `DepositQueue (GG)` — `0x411172F1E5310d03b38128F2a294F2e33c691B30`
- `DepositQueue (strETH)` — `0x268ea1cc674cdaE200c4609E7b09d03Dc618E663`
- `DepositQueue (DVstETH)` — `0x4bDd2Ea1E20acb13f2758190c92a84175107A86f`
- Shared Earn governance (also covers earnUSD) — Mellow-global Factories:
- `DepositQueue Factory` — `0xBB92A7B9695750e1234BaB18F83b73686dd09854`
- `RedeemQueue Factory` — `0xfe76b5fd238553D65Ce6dd0A572C0fda629F8421`
- `Subvault Factory` — `0x75FE0d73d3C64cdC1C6449D9F977Be6857c4d011`
- `Verifier Factory` — `0x04B30b1e98950e6A13550d84e991bE0d734C2c61`
- Shared Earn governance (also covers earnUSD) — Safes:
- `Mellow Upgrade Authority (Safe)` — `0x81698f87C6482bF1ce9bFcfC0F103C4A0Adf0Af0`
- `LazyVaultAdmin (Safe)` — `0x0Dd73341d6158a72b4D224541f1094188f57076E`
- `Curator (Safe)` — `0xe5abcc40196174Ae0d12153dE286F0D8E401769d`
- `OracleUpdater (Safe)` — `0x93a797643d74fC81e7A51F3f84a9D78F930435D1`
- `Lido Pauser (Safe)` — `0xA916fD5252160A7E56A6405741De76dc0Da5A0Cd`
- `Mellow Pauser (Safe)` — `0x6E887aF318c6b29CEE42Ea28953Bd0BAdb3cE638`
- `ActiveVaultAdmin (Safe)` — `0x982aB69785f5329BB59c36B19CBd4865353fEf10`
- Every proxy listed above also has its own dedicated OpenZeppelin v5 `ProxyAdmin` contract, each monitored for ownership transfer — 43 across both Earn products and the four Factories, all currently owned by the Mellow Upgrade Authority Safe
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| RoleGranted (Vault — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the root access-control key of the Vault. The Vault is the single access-control registry for the whole earnETH stack — the share token, oracle, risk manager, verifiers and every queue all check permissions against it — so this key can hand out every other privilege in the product. |
| RoleGranted (Vault — pause / oracle / queue-composition roles) | RoleChange | ERROR | A new address gains one of the roles that can freeze the share token, blacklist accounts, pause a queue, replace a verifier's permission root, set a hook, create a queue or subvault, write oracle prices, or loosen the oracle's price checks. |
| RoleGranted (Vault — other roles) | RoleChange | WARNING | A new address gains a bounded operational role — deposit/subvault caps, balance accounting, or moving assets between the vault and its subvaults. |
| RoleRevoked (Vault — DEFAULT_ADMIN) | RoleChange | CRITICAL | A root admin is removed from the Vault registry. If none remains, no role can ever be granted or revoked again, including to remove a compromised holder. |
| RoleRevoked (Vault — pause / oracle / queue-composition roles) | RoleChange | ERROR | A holder loses one of the emergency or oracle roles. If it was the last holder, the pre-staged freeze, queue pause or curator-revocation operations become unexecutable and nobody can halt the product. |
| RoleRevoked (Vault — other roles) | RoleChange | WARNING | A bounded operational role is removed — generally risk-reducing. |
| RoleAdded (Vault) | RoleChange | ERROR | A role in the Vault registry goes from having no holders to having one. Seventeen role classes normally have no holder at all — including account blacklisting, hook setting, and queue and subvault creation — so this is the signal that a whole class of otherwise-impossible privileged action just became possible. |
| RoleRemoved (Vault — pause / oracle / queue-composition roles) | RoleChange | ERROR | An emergency or oracle role loses its last holder, retiring that capability entirely; the resulting state looks identical to a healthy protocol but incident response is gone. |
| RoleRemoved (Vault — other roles) | RoleChange | WARNING | A bounded operational role loses its last holder — the expected tail of a temporary grant-use-revoke maintenance sequence. |
| RoleAdminChanged (Vault) | RoleChange | ERROR | Re-points which role administers another role. No code path in the deployed Vault implementation can do this, so a firing implies the implementation changed underneath the monitor. |
| SetQueueStatus (redeem queue paused) | EmergencyAction | CRITICAL | One of the redemption queues is paused, closing a user exit path. Also pre-staged inside the TimelockController as a permanently-executable operation, so it can co-fire with CallExecuted in the same transaction. |
| SetQueueStatus (deposit queue paused) | EmergencyAction | ERROR | One deposit queue is paused, blocking new money into that asset while existing holders can still exit. Six earnETH instant-deposit queues were held paused for four weeks in 2026. |
| SetQueueStatus (queue unpaused) | EmergencyAction | WARNING | A previously paused queue is reopened — the recovery signal. |
| QueueCreated (Vault) | ContractUpgrade | WARNING | A new deposit or redeem queue is registered on the vault — a new mint or redeem path for user funds, constrained to a queue implementation the corresponding Mellow Factory has already accepted. |
| QueueRemoved (Vault) | ContractUpgrade | WARNING | A queue is de-registered. It cannot strand funds: removal reverts unless the queue reports no outstanding user claims. |
| QueueLimitSet (Vault) | ProtocolParameterChange | INFO | Changes the cap on the *number* of queues the vault may hold. A count, not a value, so there is no fund exposure. |
| SubvaultCreated (Vault) | ContractUpgrade | WARNING | A new subvault is registered — a new destination the curator can push user assets into, arriving with its own verifier. |
| SubvaultDisconnected (Vault) | EmergencyAction | ERROR | A subvault is removed from the vault's set, after which assets held there stop being reachable by the pull path used to fund redemptions. |
| SubvaultReconnected (Vault) | ContractUpgrade | WARNING | A previously disconnected subvault is restored after its verifier is re-validated — the all-clear pairing. |
| CustomHookSet (Vault — hook set) | ContractUpgrade | CRITICAL | Installs a hook for one specific queue. Hooks are invoked with `delegatecall`, so the hook's code runs in the Vault's own storage context and can rewrite the access-control registry and share accounting — the same class of change as an implementation upgrade, not a parameter tweak. |
| CustomHookSet (Vault — hook cleared) | ContractUpgrade | ERROR | The queue's custom hook is removed and it falls back to the vault-wide default hook. |
| DefaultHookSet (Vault — hook set) | ContractUpgrade | CRITICAL | Installs the vault-wide default deposit or redeem hook, applying to every queue without a custom hook. Same `delegatecall` mechanism as above, so it runs in the Vault's storage context. |
| DefaultHookSet (Vault — hook cleared) | ContractUpgrade | ERROR | The vault-wide default hook is removed. |
| SetFlags (ShareManager — exits blocked) | EmergencyAction | CRITICAL | Burn or transfer is paused, or `globalLockup` is set to a future time. `globalLockup` is an **absolute timestamp**, not a duration, and is enforced on every path that moves shares away from a holder — so it blocks redemptions as well as transfers. The operation staged in the timelock sets it to `uint32.max` (year 2106). It is reversible, but asymmetrically: freezing executes an already-armed operation with one signature, while unfreezing needs a fresh proposal from a 5-of-8 Safe and no unfreeze operation is staged. |
| SetFlags (ShareManager — entry gated) | EmergencyAction | ERROR | Minting is paused or a whitelist is switched on, so new deposits are gated while existing holders can still transfer and redeem. |
| SetFlags (ShareManager — all flags clear) | EmergencyAction | WARNING | The share-token flag bitmask is rewritten to fully open — the all-clear state. |
| SetAccountInfo (ShareManager — blacklisted) | EmergencyAction | ERROR | One account is blacklisted on the share token, after which it can neither transfer nor burn — meaning it cannot redeem. |
| SetAccountInfo (ShareManager — other) | EmergencyAction | WARNING | One account's deposit or transfer permission is changed without blacklisting it. |
| SetWhitelistMerkleRoot (ShareManager — root set) | ProtocolParameterChange | WARNING | Sets the deposit-whitelist root on the share token. It gates the mint path only and cannot block an exit, and it is inert unless the whitelist flag is also on. The root's contents are off-chain, so who is on the list is not observable. |
| SetWhitelistMerkleRoot (ShareManager — root cleared) | ProtocolParameterChange | INFO | The deposit whitelist root is cleared, removing the deposit gate. |
| ReportAccepted (Oracle) | EmergencyAction | ERROR | A NAV price report that failed the oracle's own suspicion check is manually force-accepted and applied to every queue. Note it also fires benignly when a new asset is onboarded — the first report for any asset is always flagged suspicious, so an accept is a required step in listing an asset — meaning this can fire on routine asset additions as well as on a genuine price override. |
| SecurityParamsSet (Oracle — guard rails loosened) | ProtocolParameterChange | ERROR | The oracle's price-validation guard rails are widened: a larger permitted deviation, a shorter report timeout, or a longer redeem interval. These checks are the only on-chain protection between a compromised rate submitter and every holder's share value. Compared against the previous on-chain values. On earnETH the bounds have twice been opened to 100% and 200% with a one-second timeout, then restored. |
| SecurityParamsSet (Oracle — tightened or unchanged) | ProtocolParameterChange | WARNING | The guard rails are narrowed or left effectively unchanged — the conservative direction. |
| SupportedAssetsAdded (Oracle) | ProtocolParameterChange | WARNING | The oracle starts pricing additional assets into NAV. A bad price on any supported asset moves the whole share price, so the set of priced assets is a real risk surface. |
| SupportedAssetsRemoved (Oracle) | ProtocolParameterChange | WARNING | The oracle stops pricing assets. Guarded — it reverts if the asset still has queues or a non-zero vault balance — so it cannot orphan user funds. |
| RoleGranted (OracleSubmitter — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the root key of the OracleSubmitter's own registry, the second permission layer that decides who may move the published exchange rate. |
| RoleGranted (OracleSubmitter — SUBMIT_REPORTS / ACCEPT_REPORT) | RoleChange | ERROR | A new address gains the ability to push NAV prices into the oracle, or to force-accept a report the oracle flagged as suspicious. Either is a write path to the value of every holder's shares. |
| RoleGranted (OracleSubmitter — other roles) | RoleChange | WARNING | A role with no specific mapping on this contract is granted. |
| RoleRevoked (OracleSubmitter — root admin or last rate submitter) | RoleChange | ERROR | The registry's root admin is removed, or the last remaining rate submitter is. Losing the last submitter silently stops NAV updates: the published rate goes stale and, past the oracle timeout, the instant deposit and redeem paths stop accepting it. |
| RoleRevoked (OracleSubmitter — other roles) | RoleChange | WARNING | A submitter or report-acceptor is rotated out while others remain. |
| RoleAdminChanged (OracleSubmitter) | RoleChange | ERROR | Re-points which role administers another on the submitter. The contract is not upgradeable and has no code path that does this, so a firing is structurally anomalous. |
| SetFees (FeeManager — outside the demonstrated range) | ProtocolParameterChange | ERROR | Any deposit or redeem fee is switched on, or the performance fee exceeds 10% or the protocol fee 1%. The contract permits a total fee of 100%, and fees have not always been zero here: a 10% performance plus 1% protocol fee ran on both Earn products for three weeks in July 2026. |
| SetFees (FeeManager — all four rates zero) | ProtocolParameterChange | INFO | All four fee rates are set to zero — fees are off. |
| SetFees (FeeManager — within the demonstrated range) | ProtocolParameterChange | WARNING | A non-zero performance or protocol fee is set inside the range already used in production, with no deposit or redeem fee. |
| SetFeeRecipient (FeeManager) | AdminChange | ERROR | Re-points the address that receives freshly minted fee shares on every NAV report, and which is exempt from the redeem fee. |
| OwnershipTransferred (FeeManager — real transfer) | AdminChange | CRITICAL | Ownership of the FeeManager moves to a new address. The owner can set a 100% fee and re-point the recipient, so this is direct authority over value diverted from holders. |
| OwnershipTransferred (FeeManager — initial assignment) | AdminChange | INFO | The deploy-time log where ownership is first assigned from the zero address. |
| SetVaultLimit (RiskManager — at or below the live balance) | ProtocolParameterChange | ERROR | The vault-wide deposit cap is set to a value at or below the current balance, which halts all deposits immediately. The live balance is read in-handler to distinguish this from a routine cap change. |
| SetVaultLimit (RiskManager — above the live balance) | ProtocolParameterChange | WARNING | The vault-wide deposit cap is changed while leaving headroom for new deposits. |
| SetSubvaultLimit (RiskManager) | ProtocolParameterChange | WARNING | Caps how much a single subvault may hold, bounded by the vault-level limit. |
| AllowSubvaultAssets (RiskManager) | ProtocolParameterChange | WARNING | Widens the set of assets a subvault may hold. Doubly constrained: the asset must already be oracle-priced and the curator still needs a verifier proof to move it. |
| DisallowSubvaultAssets (RiskManager) | ProtocolParameterChange | WARNING | Narrows a subvault's allowed asset set — the risk-reducing pairing. |
| CallScheduled (TimelockController) | TimelockChange | ERROR | An operation is staged in the product's timelock. The timelock's minimum delay is **zero**, so a scheduled operation is immediately executable — "timelock" here is propose/execute role separation across two different Safes, not a waiting period. Scheduling therefore means armed, and the message decodes the target and function. |
| CallExecuted (TimelockController — freeze, curator revocation or queue pause) | EmergencyAction | CRITICAL | A staged operation that freezes the share token, clears a verifier's permission root, or pauses a queue has actually been fired. Each timelock permanently holds such operations in state `Ready` — sixteen on earnETH, none ever executed — including a full mint, burn and transfer freeze, and the executor role includes a **1-of-8** Safe. |
| CallExecuted (TimelockController — other payload) | EmergencyAction | ERROR | A staged timelock operation with some other payload has been executed; the message decodes the target and function. |
| Cancelled (TimelockController) | TimelockChange | ERROR | A pending timelock operation is cancelled. Because the pending operations are the emergency plan itself, cancelling one silently disarms a pre-staged freeze, curator revocation or queue pause. |
| MinDelayChange (TimelockController — decrease) | TimelockChange | ERROR | The timelock's minimum delay is reduced. The current value is already zero, so a decrease is not possible from here without an implementation change. |
| MinDelayChange (TimelockController — increase) | TimelockChange | WARNING | The minimum delay is raised, introducing a real waiting period where there is currently none. |
| RoleGranted (TimelockController — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the timelock's root admin, which can hand out the proposer, canceller and executor roles — full control over both the staging and the firing of the pre-staged emergency operations. |
| RoleGranted (TimelockController — EXECUTOR / PROPOSER) | RoleChange | ERROR | A new address gains the ability to fire any ready operation, or to stage arbitrary new privileged calls. With the minimum delay at zero, anything staged is immediately fireable. |
| RoleGranted (TimelockController — other roles) | RoleChange | WARNING | Another timelock role, such as canceller, is granted. |
| RoleRevoked (TimelockController — root admin or last executor) | RoleChange | ERROR | The timelock's root admin is removed, or the last known executor is. Without an executor the pre-staged emergency operations stay permanently ready but unfireable — the kill switch is present and dead. |
| RoleRevoked (TimelockController — other roles) | RoleChange | WARNING | A proposer, canceller or one of several executors is removed. |
| RoleAdminChanged (TimelockController) | RoleChange | ERROR | Re-points which role administers another on the timelock. No code path in OpenZeppelin's TimelockController does this, so a firing is structurally anomalous. |
| SetMerkleRoot (Verifier — root cleared) | EmergencyAction | ERROR | A verifier's permission root is cleared to zero, revoking every call the curator was allowed to make against subvault assets. This is the pre-staged emergency revocation of curator powers. |
| SetMerkleRoot (Verifier — root replaced) | ProtocolParameterChange | ERROR | A verifier's permission root is replaced with a different one, changing the set of calls the curator may execute. Only the 32-byte root is on-chain and the tree's contents are off-chain, so there is no way to tell from the event whether the curator's powers widened or narrowed. |
| AllowCall (Verifier) | RoleChange | ERROR | Writes an explicit caller-target-selector allowance on a verifier that **bypasses the merkle tree entirely**. The one historical use of this granted a raw wstETH transfer permission. |
| DisallowCall (Verifier) | RoleChange | WARNING | Removes an explicit verifier allowance — the risk-reducing pairing. |
| SyncDepositParamsSet (SyncDepositQueue — materially costly) | ProtocolParameterChange | ERROR | An instant-deposit queue's penalty reaches 0.5% or its maximum accepted oracle-price age exceeds 48 hours. The penalty is a direct haircut on the shares an instant depositor receives and the contract permits up to 50%; the max-age setting governs how stale a price the instant path will accept, against an oracle reporting roughly every 20 hours. |
| SyncDepositParamsSet (SyncDepositQueue — other change) | ProtocolParameterChange | WARNING | An instant-deposit queue's penalty or oracle max-age is changed to a level that is not materially costly to depositors. This includes values above anything used in production so far — the alert records that separately, but a penalty of a few hundredths of a percent is not treated as urgent. |
| SyncRedeemParamsSet (SyncRedeemQueue — materially costly) | ProtocolParameterChange | ERROR | The instant-exit path gains a penalty of 0.25% or more (a direct haircut on instant exits, permitted up to 50%), or is set to accept an oracle price older than 48 hours. The role needed to call this has never been granted on either Earn vault. |
| SyncRedeemParamsSet (SyncRedeemQueue — other change) | ProtocolParameterChange | WARNING | The instant-exit parameters are changed to a level that is not materially costly, including a reduction in daily exit capacity. The instant path is capped at a small fraction of supply per day and the standard redemption queue carries no penalty, so small changes here are recorded rather than treated as urgent. |
| Upgraded (any earnETH proxy) | ContractUpgrade | CRITICAL | The implementation behind one of the product's proxies is replaced. A Vault or ShareManager upgrade can rewrite the access-control registry, the share accounting and the pause logic in a single transaction, and the upgrade authority is a 5-of-8 Safe acting with no delay. Monitored on all 43 Earn proxies; the proxies' own `AdminChanged` is not monitored because the OpenZeppelin v5 proxy admin is immutable and can only fire at construction, which is why the ProxyAdmin ownership event below is the substitute signal. |
| OwnershipTransferred (ProxyAdmin — real transfer) | AdminChange | CRITICAL | Upgrade authority over one specific contract moves to a new owner. Each proxy has its own dedicated ProxyAdmin, and that ProxyAdmin is the only way to change the proxy's implementation, so this is the sole on-chain signal that the power to upgrade a given contract changed hands. |
| OwnershipTransferred (ProxyAdmin — initial assignment) | AdminChange | INFO | The deploy-time log where a ProxyAdmin's ownership is first assigned from the zero address. |
| AcceptProposedImplementation (Factory — shared Earn governance) | ContractUpgrade | ERROR | The Factory owner admits a new implementation into the set that may be instantiated for queues, subvaults or verifiers. It does not upgrade anything already deployed, but it is a reliable precursor: the implementation accepted on 2026-07-21 is the one both new instant-redeem queues were deployed from two days later. |
| ProposeImplementation (Factory — shared Earn governance) | ContractUpgrade | INFO | An implementation address is proposed to a Factory. **The function is permissionless** — it has no access control at all, so anyone can propose any address — and a proposal grants nothing until the owner accepts it via the event above. Recorded so a stranger cannot generate noise. |
| SetBlacklistStatus (Factory — shared Earn governance) | ProtocolParameterChange | WARNING | A Factory implementation version is marked as blacklisted, or unmarked. It affects future deployments only; instances already deployed are untouched. |
| OwnershipTransferred (Factory — real transfer, shared Earn governance) | AdminChange | CRITICAL | Ownership of one of the four Mellow-global Factories moves. The owner gates which implementations either Earn product can ever deploy. |
| OwnershipTransferred (Factory — initial assignment, shared Earn governance) | AdminChange | INFO | The deploy-time log where a Factory's ownership is first assigned from the zero address. |
| AddedOwner (Safe — Upgrade Authority, LazyVaultAdmin, Curator, OracleUpdater, Lido Pauser, Mellow Pauser) | MultisigChange | ERROR | A new signer joins one of the Safes that hold upgrade authority, vault root admin, curator keys, the rate-submitter role, or the timelock executor role. On the Mellow Pauser Safe, which is 1-of-8, each new owner is one more party able to fire the pre-staged freeze on both products alone. |
| AddedOwner (Safe — ActiveVaultAdmin) | MultisigChange | WARNING | A new signer joins the Safe that holds only the deposit-cap and balance-accounting roles. |
| RemovedOwner (Safe — Upgrade Authority, LazyVaultAdmin, Curator, OracleUpdater, Lido Pauser, Mellow Pauser) | MultisigChange | ERROR | A signer leaves one of the high-authority Safes, concentrating control among fewer parties at an unchanged threshold. |
| RemovedOwner (Safe — ActiveVaultAdmin) | MultisigChange | WARNING | A signer leaves the limits-only Safe. |
| ChangedThreshold (Safe — Upgrade Authority or LazyVaultAdmin, lowered) | MultisigChange | CRITICAL | The signature requirement is lowered on one of the two root-of-trust Safes — the one owning all 43 ProxyAdmins and all four Factories, or the one holding root admin on both vaults and both oracle submitters. Fewer signatures for total control. Compared against the previous on-chain value. |
| ChangedThreshold (Safe — root-of-trust raised, or any other Safe lowered) | MultisigChange | ERROR | A root-of-trust Safe raises its requirement, or one of the asset, oracle, pauser or limits Safes lowers its own. |
| ChangedThreshold (Safe — any other Safe raised) | MultisigChange | WARNING | A non-root Safe raises its signature requirement — the conservative direction. |
| EnabledModule (Safe) | MultisigChange | CRITICAL | A module is enabled on a governing Safe. A module can execute transactions from that Safe with no signatures at all, bypassing the signing threshold entirely. No module has ever been enabled on any of the seven Safes. |
| DisabledModule (Safe) | MultisigChange | WARNING | A module is disabled, removing a signature-bypass path. |
| ChangedGuard (Safe) | MultisigChange | ERROR | A transaction guard is installed on or removed from a governing Safe. A guard's pre-execution hook can revert unconditionally, which would brick the pauser Safes and with them the ability to fire the emergency operations. |
| ChangedFallbackHandler (Safe) | MultisigChange | WARNING | A governing Safe's fallback handler is changed. The handler is invoked with `call` rather than `delegatecall`, so it cannot write Safe storage; the exposure is signature-validation spoofing. |
## Lido — earnUSD (`lido-finance`)
- **Chain(s):** Ethereum
- **Products:** `earnusd`. The Mellow-global Factories and the seven governing Safes are shared with earnETH, so their events are emitted protocol-wide (`product: ""`) and appear in both Lido Earn sections
- **Contracts monitored:**
- `Vault` — `0x014e6DA8F283C4aF65B2AA0f201438680A004452`
- `ShareManager (earnUSD share token)` — `0x4Ce1ac8F43E0E5BD7A346A98aF777bF8fbeA1981`
- `Oracle` — `0x827044735c9708a2cf850e7Ea37EBa43bc786028`
- `OracleSubmitter` — `0xB105DaEeFEb1390ce49172c99E3e12C607367156`
- `FeeManager` — `0x72fa23f40e08eB9E45953233b2Dd9665E347e8Dc`
- `RiskManager` — `0x7b1e06C46d4510277FC37a37bBeF65F3794fdDE4`
- `TimelockController` — `0xdA6Da82DFF8cD29D828e4775Cc003f504A968845`
- Verifiers (the curator's permission set):
- `Verifier 0` — `0xB65A8E0937c77a76C3f4F86A1110f81A299CB481`
- `Verifier 1` — `0xBEa44cd2f58f3CC6f37aaeC82A2dee57911d0b36`
- Redemption queues:
- `RedeemQueue (USDC)` — `0x9e36A74FE278906a76e7615263e46a83fC40c47F`
- `SyncRedeemQueue (USDC)` — `0xE0eee7e956A94BD00546d9CA07e5012F11A5059d`
- Instant-deposit queues:
- `SyncDepositQueue (USDC)` — `0xf6AFAf6afcAe116dD37A779D50fE6c5fa6f8C8f5`
- `SyncDepositQueue (USDT)` — `0x534d0bEb82C47cf703BFb9E959297658b65Ec8E9`
- Subvaults and async deposit queues (monitored for proxy upgrades and upgrade-authority changes only):
- `Subvault 0` — `0x77B9441d5Cb89fca435190A9B6D108ad4B00ccFd`
- `Subvault 1` — `0xe3e0111e31FA3AEB7A528128F2DbAe1C15397242`
- `DepositQueue (USDC)` — `0xC75E7E73B25fEa8bB23EB55CC48BA55067b5be76`
- `DepositQueue (USDT)` — `0xEeC5041c47Cba1e31321AC6941Bf09Ad60645B73`
- `DepositQueue (USDe)` — `0xeEc37568b01e0C4d5028501A49E024B475E2D7cA`
- Shared Earn governance (also covers earnETH) — Mellow-global Factories:
- `DepositQueue Factory` — `0xBB92A7B9695750e1234BaB18F83b73686dd09854`
- `RedeemQueue Factory` — `0xfe76b5fd238553D65Ce6dd0A572C0fda629F8421`
- `Subvault Factory` — `0x75FE0d73d3C64cdC1C6449D9F977Be6857c4d011`
- `Verifier Factory` — `0x04B30b1e98950e6A13550d84e991bE0d734C2c61`
- Shared Earn governance (also covers earnETH) — Safes:
- `Mellow Upgrade Authority (Safe)` — `0x81698f87C6482bF1ce9bFcfC0F103C4A0Adf0Af0`
- `LazyVaultAdmin (Safe)` — `0x0Dd73341d6158a72b4D224541f1094188f57076E`
- `Curator (Safe)` — `0xe5abcc40196174Ae0d12153dE286F0D8E401769d`
- `OracleUpdater (Safe)` — `0x93a797643d74fC81e7A51F3f84a9D78F930435D1`
- `Lido Pauser (Safe)` — `0xA916fD5252160A7E56A6405741De76dc0Da5A0Cd`
- `Mellow Pauser (Safe)` — `0x6E887aF318c6b29CEE42Ea28953Bd0BAdb3cE638`
- `ActiveVaultAdmin (Safe)` — `0x982aB69785f5329BB59c36B19CBd4865353fEf10`
- Every proxy listed above also has its own dedicated OpenZeppelin v5 `ProxyAdmin` contract, each monitored for ownership transfer — 43 across both Earn products and the four Factories, all currently owned by the Mellow Upgrade Authority Safe
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| RoleGranted (Vault — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the root access-control key of the Vault. The Vault is the single access-control registry for the whole earnUSD stack — the share token, oracle, risk manager, verifiers and every queue all check permissions against it — so this key can hand out every other privilege in the product. |
| RoleGranted (Vault — pause / oracle / queue-composition roles) | RoleChange | ERROR | A new address gains one of the roles that can freeze the share token, blacklist accounts, pause a queue, replace a verifier's permission root, set a hook, create a queue or subvault, write oracle prices, or loosen the oracle's price checks. |
| RoleGranted (Vault — other roles) | RoleChange | WARNING | A new address gains a bounded operational role — deposit/subvault caps, balance accounting, or moving assets between the vault and its subvaults. |
| RoleRevoked (Vault — DEFAULT_ADMIN) | RoleChange | CRITICAL | A root admin is removed from the Vault registry. If none remains, no role can ever be granted or revoked again, including to remove a compromised holder. |
| RoleRevoked (Vault — pause / oracle / queue-composition roles) | RoleChange | ERROR | A holder loses one of the emergency or oracle roles. If it was the last holder, the pre-staged freeze, queue pause or curator-revocation operations become unexecutable and nobody can halt the product. |
| RoleRevoked (Vault — other roles) | RoleChange | WARNING | A bounded operational role is removed — generally risk-reducing. |
| RoleAdded (Vault) | RoleChange | ERROR | A role in the Vault registry goes from having no holders to having one. Seventeen role classes normally have no holder at all — including account blacklisting, hook setting, and queue and subvault creation — so this is the signal that a whole class of otherwise-impossible privileged action just became possible. |
| RoleRemoved (Vault — pause / oracle / queue-composition roles) | RoleChange | ERROR | An emergency or oracle role loses its last holder, retiring that capability entirely; the resulting state looks identical to a healthy protocol but incident response is gone. |
| RoleRemoved (Vault — other roles) | RoleChange | WARNING | A bounded operational role loses its last holder — the expected tail of a temporary grant-use-revoke maintenance sequence. |
| RoleAdminChanged (Vault) | RoleChange | ERROR | Re-points which role administers another role. No code path in the deployed Vault implementation can do this, so a firing implies the implementation changed underneath the monitor. |
| SetQueueStatus (redeem queue paused) | EmergencyAction | CRITICAL | One of the redemption queues is paused, closing a user exit path. Also pre-staged inside the TimelockController as a permanently-executable operation, so it can co-fire with CallExecuted in the same transaction. |
| SetQueueStatus (deposit queue paused) | EmergencyAction | ERROR | One deposit queue is paused, blocking new money into that asset while existing holders can still exit. |
| SetQueueStatus (queue unpaused) | EmergencyAction | WARNING | A previously paused queue is reopened — the recovery signal. |
| QueueCreated (Vault) | ContractUpgrade | WARNING | A new deposit or redeem queue is registered on the vault — a new mint or redeem path for user funds, constrained to a queue implementation the corresponding Mellow Factory has already accepted. |
| QueueRemoved (Vault) | ContractUpgrade | WARNING | A queue is de-registered. It cannot strand funds: removal reverts unless the queue reports no outstanding user claims. |
| QueueLimitSet (Vault) | ProtocolParameterChange | INFO | Changes the cap on the *number* of queues the vault may hold. A count, not a value, so there is no fund exposure. |
| SubvaultCreated (Vault) | ContractUpgrade | WARNING | A new subvault is registered — a new destination the curator can push user assets into, arriving with its own verifier. |
| SubvaultDisconnected (Vault) | EmergencyAction | ERROR | A subvault is removed from the vault's set, after which assets held there stop being reachable by the pull path used to fund redemptions. |
| SubvaultReconnected (Vault) | ContractUpgrade | WARNING | A previously disconnected subvault is restored after its verifier is re-validated — the all-clear pairing. |
| CustomHookSet (Vault — hook set) | ContractUpgrade | CRITICAL | Installs a hook for one specific queue. Hooks are invoked with `delegatecall`, so the hook's code runs in the Vault's own storage context and can rewrite the access-control registry and share accounting — the same class of change as an implementation upgrade, not a parameter tweak. |
| CustomHookSet (Vault — hook cleared) | ContractUpgrade | ERROR | The queue's custom hook is removed and it falls back to the vault-wide default hook. |
| DefaultHookSet (Vault — hook set) | ContractUpgrade | CRITICAL | Installs the vault-wide default deposit or redeem hook, applying to every queue without a custom hook. Same `delegatecall` mechanism as above, so it runs in the Vault's storage context. |
| DefaultHookSet (Vault — hook cleared) | ContractUpgrade | ERROR | The vault-wide default hook is removed. |
| SetFlags (ShareManager — exits blocked) | EmergencyAction | CRITICAL | Burn or transfer is paused, or `globalLockup` is set to a future time. `globalLockup` is an **absolute timestamp**, not a duration, and is enforced on every path that moves shares away from a holder — so it blocks redemptions as well as transfers. The operation staged in the timelock sets it to `uint32.max` (year 2106). It is reversible, but asymmetrically: freezing executes an already-armed operation with one signature, while unfreezing needs a fresh proposal from a 5-of-8 Safe and no unfreeze operation is staged. |
| SetFlags (ShareManager — entry gated) | EmergencyAction | ERROR | Minting is paused or a whitelist is switched on, so new deposits are gated while existing holders can still transfer and redeem. |
| SetFlags (ShareManager — all flags clear) | EmergencyAction | WARNING | The share-token flag bitmask is rewritten to fully open — the all-clear state. |
| SetAccountInfo (ShareManager — blacklisted) | EmergencyAction | ERROR | One account is blacklisted on the share token, after which it can neither transfer nor burn — meaning it cannot redeem. |
| SetAccountInfo (ShareManager — other) | EmergencyAction | WARNING | One account's deposit or transfer permission is changed without blacklisting it. |
| SetWhitelistMerkleRoot (ShareManager — root set) | ProtocolParameterChange | WARNING | Sets the deposit-whitelist root on the share token. It gates the mint path only and cannot block an exit, and it is inert unless the whitelist flag is also on. The root's contents are off-chain, so who is on the list is not observable. |
| SetWhitelistMerkleRoot (ShareManager — root cleared) | ProtocolParameterChange | INFO | The deposit whitelist root is cleared, removing the deposit gate. |
| ReportAccepted (Oracle) | EmergencyAction | ERROR | A NAV price report that failed the oracle's own suspicion check is manually force-accepted and applied to every queue. Note it also fires benignly when a new asset is onboarded — the first report for any asset is always flagged suspicious, so an accept is a required step in listing an asset — meaning this can fire on routine asset additions as well as on a genuine price override. |
| SecurityParamsSet (Oracle — guard rails loosened) | ProtocolParameterChange | ERROR | The oracle's price-validation guard rails are widened: a larger permitted deviation, a shorter report timeout, or a longer redeem interval. These checks are the only on-chain protection between a compromised rate submitter and every holder's share value. Compared against the previous on-chain values. |
| SecurityParamsSet (Oracle — tightened or unchanged) | ProtocolParameterChange | WARNING | The guard rails are narrowed or left effectively unchanged — the conservative direction. |
| SupportedAssetsAdded (Oracle) | ProtocolParameterChange | WARNING | The oracle starts pricing additional assets into NAV. A bad price on any supported asset moves the whole share price, so the set of priced assets is a real risk surface. |
| SupportedAssetsRemoved (Oracle) | ProtocolParameterChange | WARNING | The oracle stops pricing assets. Guarded — it reverts if the asset still has queues or a non-zero vault balance — so it cannot orphan user funds. |
| RoleGranted (OracleSubmitter — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the root key of the OracleSubmitter's own registry, the second permission layer that decides who may move the published exchange rate. |
| RoleGranted (OracleSubmitter — SUBMIT_REPORTS / ACCEPT_REPORT) | RoleChange | ERROR | A new address gains the ability to push NAV prices into the oracle, or to force-accept a report the oracle flagged as suspicious. Either is a write path to the value of every holder's shares. |
| RoleGranted (OracleSubmitter — other roles) | RoleChange | WARNING | A role with no specific mapping on this contract is granted. |
| RoleRevoked (OracleSubmitter — root admin or last rate submitter) | RoleChange | ERROR | The registry's root admin is removed, or the last remaining rate submitter is. Losing the last submitter silently stops NAV updates: the published rate goes stale and, past the oracle timeout, the instant deposit and redeem paths stop accepting it. |
| RoleRevoked (OracleSubmitter — other roles) | RoleChange | WARNING | A submitter or report-acceptor is rotated out while others remain. |
| RoleAdminChanged (OracleSubmitter) | RoleChange | ERROR | Re-points which role administers another on the submitter. The contract is not upgradeable and has no code path that does this, so a firing is structurally anomalous. |
| SetFees (FeeManager — outside the demonstrated range) | ProtocolParameterChange | ERROR | Any deposit or redeem fee is switched on, or the performance fee exceeds 10% or the protocol fee 1%. The contract permits a total fee of 100%, and fees have not always been zero here: a 10% performance plus 1% protocol fee ran on both Earn products for three weeks in July 2026. |
| SetFees (FeeManager — all four rates zero) | ProtocolParameterChange | INFO | All four fee rates are set to zero — fees are off. |
| SetFees (FeeManager — within the demonstrated range) | ProtocolParameterChange | WARNING | A non-zero performance or protocol fee is set inside the range already used in production, with no deposit or redeem fee. |
| SetFeeRecipient (FeeManager) | AdminChange | ERROR | Re-points the address that receives freshly minted fee shares on every NAV report, and which is exempt from the redeem fee. |
| OwnershipTransferred (FeeManager — real transfer) | AdminChange | CRITICAL | Ownership of the FeeManager moves to a new address. The owner can set a 100% fee and re-point the recipient, so this is direct authority over value diverted from holders. |
| OwnershipTransferred (FeeManager — initial assignment) | AdminChange | INFO | The deploy-time log where ownership is first assigned from the zero address. |
| SetVaultLimit (RiskManager — at or below the live balance) | ProtocolParameterChange | ERROR | The vault-wide deposit cap is set to a value at or below the current balance, which halts all deposits immediately. The live balance is read in-handler to distinguish this from a routine cap change. |
| SetVaultLimit (RiskManager — above the live balance) | ProtocolParameterChange | WARNING | The vault-wide deposit cap is changed while leaving headroom for new deposits. |
| SetSubvaultLimit (RiskManager) | ProtocolParameterChange | WARNING | Caps how much a single subvault may hold, bounded by the vault-level limit. |
| AllowSubvaultAssets (RiskManager) | ProtocolParameterChange | WARNING | Widens the set of assets a subvault may hold. Doubly constrained: the asset must already be oracle-priced and the curator still needs a verifier proof to move it. |
| DisallowSubvaultAssets (RiskManager) | ProtocolParameterChange | WARNING | Narrows a subvault's allowed asset set — the risk-reducing pairing. |
| CallScheduled (TimelockController) | TimelockChange | ERROR | An operation is staged in the product's timelock. The timelock's minimum delay is **zero**, so a scheduled operation is immediately executable — "timelock" here is propose/execute role separation across two different Safes, not a waiting period. Scheduling therefore means armed, and the message decodes the target and function. |
| CallExecuted (TimelockController — freeze, curator revocation or queue pause) | EmergencyAction | CRITICAL | A staged operation that freezes the share token, clears a verifier's permission root, or pauses a queue has actually been fired. Each timelock permanently holds such operations in state `Ready` — seven on earnUSD, none ever executed — including a full mint, burn and transfer freeze, and the executor role includes a **1-of-8** Safe. |
| CallExecuted (TimelockController — other payload) | EmergencyAction | ERROR | A staged timelock operation with some other payload has been executed; the message decodes the target and function. |
| Cancelled (TimelockController) | TimelockChange | ERROR | A pending timelock operation is cancelled. Because the pending operations are the emergency plan itself, cancelling one silently disarms a pre-staged freeze, curator revocation or queue pause. |
| MinDelayChange (TimelockController — decrease) | TimelockChange | ERROR | The timelock's minimum delay is reduced. The current value is already zero, so a decrease is not possible from here without an implementation change. |
| MinDelayChange (TimelockController — increase) | TimelockChange | WARNING | The minimum delay is raised, introducing a real waiting period where there is currently none. |
| RoleGranted (TimelockController — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the timelock's root admin, which can hand out the proposer, canceller and executor roles — full control over both the staging and the firing of the pre-staged emergency operations. |
| RoleGranted (TimelockController — EXECUTOR / PROPOSER) | RoleChange | ERROR | A new address gains the ability to fire any ready operation, or to stage arbitrary new privileged calls. With the minimum delay at zero, anything staged is immediately fireable. |
| RoleGranted (TimelockController — other roles) | RoleChange | WARNING | Another timelock role, such as canceller, is granted. |
| RoleRevoked (TimelockController — root admin or last executor) | RoleChange | ERROR | The timelock's root admin is removed, or the last known executor is. Without an executor the pre-staged emergency operations stay permanently ready but unfireable — the kill switch is present and dead. |
| RoleRevoked (TimelockController — other roles) | RoleChange | WARNING | A proposer, canceller or one of several executors is removed. |
| RoleAdminChanged (TimelockController) | RoleChange | ERROR | Re-points which role administers another on the timelock. No code path in OpenZeppelin's TimelockController does this, so a firing is structurally anomalous. |
| SetMerkleRoot (Verifier — root cleared) | EmergencyAction | ERROR | A verifier's permission root is cleared to zero, revoking every call the curator was allowed to make against subvault assets. This is the pre-staged emergency revocation of curator powers. |
| SetMerkleRoot (Verifier — root replaced) | ProtocolParameterChange | ERROR | A verifier's permission root is replaced with a different one, changing the set of calls the curator may execute. Only the 32-byte root is on-chain and the tree's contents are off-chain, so there is no way to tell from the event whether the curator's powers widened or narrowed. |
| AllowCall (Verifier) | RoleChange | ERROR | Writes an explicit caller-target-selector allowance on a verifier that **bypasses the merkle tree entirely**. |
| DisallowCall (Verifier) | RoleChange | WARNING | Removes an explicit verifier allowance — the risk-reducing pairing. |
| SyncDepositParamsSet (SyncDepositQueue — materially costly) | ProtocolParameterChange | ERROR | An instant-deposit queue's penalty reaches 0.5% or its maximum accepted oracle-price age exceeds 48 hours. The penalty is a direct haircut on the shares an instant depositor receives and the contract permits up to 50%; the max-age setting governs how stale a price the instant path will accept, against an oracle reporting roughly every 20 hours. |
| SyncDepositParamsSet (SyncDepositQueue — other change) | ProtocolParameterChange | WARNING | An instant-deposit queue's penalty or oracle max-age is changed to a level that is not materially costly to depositors. This includes values above anything used in production so far — the alert records that separately, but a penalty of a few hundredths of a percent is not treated as urgent. |
| SyncRedeemParamsSet (SyncRedeemQueue — materially costly) | ProtocolParameterChange | ERROR | The instant-exit path gains a penalty of 0.25% or more (a direct haircut on instant exits, permitted up to 50%), or is set to accept an oracle price older than 48 hours. The role needed to call this has never been granted on either Earn vault. |
| SyncRedeemParamsSet (SyncRedeemQueue — other change) | ProtocolParameterChange | WARNING | The instant-exit parameters are changed to a level that is not materially costly, including a reduction in daily exit capacity. The instant path is capped at a small fraction of supply per day and the standard redemption queue carries no penalty, so small changes here are recorded rather than treated as urgent. |
| Upgraded (any earnUSD proxy) | ContractUpgrade | CRITICAL | The implementation behind one of the product's proxies is replaced. A Vault or ShareManager upgrade can rewrite the access-control registry, the share accounting and the pause logic in a single transaction, and the upgrade authority is a 5-of-8 Safe acting with no delay. Monitored on all 43 Earn proxies; the proxies' own `AdminChanged` is not monitored because the OpenZeppelin v5 proxy admin is immutable and can only fire at construction, which is why the ProxyAdmin ownership event below is the substitute signal. |
| OwnershipTransferred (ProxyAdmin — real transfer) | AdminChange | CRITICAL | Upgrade authority over one specific contract moves to a new owner. Each proxy has its own dedicated ProxyAdmin, and that ProxyAdmin is the only way to change the proxy's implementation, so this is the sole on-chain signal that the power to upgrade a given contract changed hands. |
| OwnershipTransferred (ProxyAdmin — initial assignment) | AdminChange | INFO | The deploy-time log where a ProxyAdmin's ownership is first assigned from the zero address. |
| AcceptProposedImplementation (Factory — shared Earn governance) | ContractUpgrade | ERROR | The Factory owner admits a new implementation into the set that may be instantiated for queues, subvaults or verifiers. It does not upgrade anything already deployed, but it is a reliable precursor: the implementation accepted on 2026-07-21 is the one both new instant-redeem queues were deployed from two days later. |
| ProposeImplementation (Factory — shared Earn governance) | ContractUpgrade | INFO | An implementation address is proposed to a Factory. **The function is permissionless** — it has no access control at all, so anyone can propose any address — and a proposal grants nothing until the owner accepts it via the event above. Recorded so a stranger cannot generate noise. |
| SetBlacklistStatus (Factory — shared Earn governance) | ProtocolParameterChange | WARNING | A Factory implementation version is marked as blacklisted, or unmarked. It affects future deployments only; instances already deployed are untouched. |
| OwnershipTransferred (Factory — real transfer, shared Earn governance) | AdminChange | CRITICAL | Ownership of one of the four Mellow-global Factories moves. The owner gates which implementations either Earn product can ever deploy. |
| OwnershipTransferred (Factory — initial assignment, shared Earn governance) | AdminChange | INFO | The deploy-time log where a Factory's ownership is first assigned from the zero address. |
| AddedOwner (Safe — Upgrade Authority, LazyVaultAdmin, Curator, OracleUpdater, Lido Pauser, Mellow Pauser) | MultisigChange | ERROR | A new signer joins one of the Safes that hold upgrade authority, vault root admin, curator keys, the rate-submitter role, or the timelock executor role. On the Mellow Pauser Safe, which is 1-of-8, each new owner is one more party able to fire the pre-staged freeze on both products alone. |
| AddedOwner (Safe — ActiveVaultAdmin) | MultisigChange | WARNING | A new signer joins the Safe that holds only the deposit-cap and balance-accounting roles. |
| RemovedOwner (Safe — Upgrade Authority, LazyVaultAdmin, Curator, OracleUpdater, Lido Pauser, Mellow Pauser) | MultisigChange | ERROR | A signer leaves one of the high-authority Safes, concentrating control among fewer parties at an unchanged threshold. |
| RemovedOwner (Safe — ActiveVaultAdmin) | MultisigChange | WARNING | A signer leaves the limits-only Safe. |
| ChangedThreshold (Safe — Upgrade Authority or LazyVaultAdmin, lowered) | MultisigChange | CRITICAL | The signature requirement is lowered on one of the two root-of-trust Safes — the one owning all 43 ProxyAdmins and all four Factories, or the one holding root admin on both vaults and both oracle submitters. Fewer signatures for total control. Compared against the previous on-chain value. |
| ChangedThreshold (Safe — root-of-trust raised, or any other Safe lowered) | MultisigChange | ERROR | A root-of-trust Safe raises its requirement, or one of the asset, oracle, pauser or limits Safes lowers its own. |
| ChangedThreshold (Safe — any other Safe raised) | MultisigChange | WARNING | A non-root Safe raises its signature requirement — the conservative direction. |
| EnabledModule (Safe) | MultisigChange | CRITICAL | A module is enabled on a governing Safe. A module can execute transactions from that Safe with no signatures at all, bypassing the signing threshold entirely. No module has ever been enabled on any of the seven Safes. |
| DisabledModule (Safe) | MultisigChange | WARNING | A module is disabled, removing a signature-bypass path. |
| ChangedGuard (Safe) | MultisigChange | ERROR | A transaction guard is installed on or removed from a governing Safe. A guard's pre-execution hook can revert unconditionally, which would brick the pauser Safes and with them the ability to fire the emergency operations. |
| ChangedFallbackHandler (Safe) | MultisigChange | WARNING | A governing Safe's fallback handler is changed. The handler is invoked with `call` rather than `delegatecall`, so it cannot write Safe storage; the exposure is signature-validation spoofing. |
## Lido — stETH (`lido`)
- **Chain(s):** Ethereum
- **Products:** `steth`
- **Contracts monitored:**
- `Lido stETH` — `0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84`
- `WithdrawalQueue` — `0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1`
- `Aragon Voting` — `0x2e59A20f205bB85a89C53f1936454680651E618e`
- `NodeOperatorsRegistry` — `0x55032650b14df07b85bF18A3a3eC8E0Af2e028d5`
- `InsuranceFund` — `0x8B3f33234ABD88493c0Cd28De33D583B70beDe35`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| ContractVersionSet (stETH) | ContractUpgrade | ERROR | The stETH proxy's implementation is upgraded — new code for the core token contract while user balances and storage stay in the unchanged proxy. Governance-gated (Aragon DAO) and rare (twice in the protocol's life), so every upgrade pages to be matched against a known governance vote. |
| LidoLocatorSet | ContractUpgrade | CRITICAL | Re-points stETH at a different **LidoLocator** — the central registry that resolves ~15 core system components (the oracle, withdrawal queue, treasury, staking router, reward vaults). Because the protocol resolves these dependencies at runtime, swapping the locator instantly redirects the whole system's trust to a new set of contracts — the same top-tier root-of-trust change as swapping an access-control manager or price oracle. Outside initial setup this is not a normal operation; any occurrence is top-urgency. |
| StakingPaused | EmergencyAction | ERROR | New deposits (`submit()`) are halted while transfers and withdrawals stay live — user funds are not frozen, so this sits one tier below a full protocol stop. A deliberate, privileged emergency action worth paging. |
| StakingResumed | EmergencyAction | WARNING | The deposit path is re-opened after a staking pause — the recovery / all-clear signal. The paired StakingPaused already paged, so this is recorded for visibility rather than paged. |
| Stopped | EmergencyAction | CRITICAL | The Aragon-era top-level halt of the entire stETH contract — freezes the core mutating paths. Has never fired in production and can only be triggered by the privileged pauser; if it ever does, the whole protocol is halted, so it pages at top urgency. |
| Resumed | EmergencyAction | WARNING | The top-level protocol halt is lifted and normal operation resumes — the recovery / all-clear signal. The paired Stopped already paged (CRITICAL), so the resume is recorded rather than paged. |
| StakingLimitSet | ProtocolParameterChange | WARNING | Configures the staking rate-limiter (max stake limit + per-block refill) that smooths large ETH inflows. It never touches withdrawals, transfers, fees, or trust — worst case it briefly throttles new deposits — so it is recorded for visibility, not paged. |
| StakingLimitRemoved | ProtocolParameterChange | WARNING | Removes the deposit rate-limiter entirely (deposits become unthrottled). Still only affects new-deposit smoothing, with no bearing on withdrawals, custody, or solvency, so it is recorded rather than paged. |
| MaxExternalRatioBPSet (increase) | ProtocolParameterChange | ERROR | Caps the fraction of stETH backing that may come from V3 stVaults (external shares) rather than the core staking pool — the ceiling on how much of the rated token can be exposed to the newer vault mechanism and its socialised-bad-debt risk. **Raising** the cap expands that risk surface, so it pages. Evaluated against the previous on-chain value; an unset prior counts as 0, so first establishing a cap pages. |
| MaxExternalRatioBPSet (decrease) | ProtocolParameterChange | WARNING | The stVault backing cap is **lowered**, shrinking the share of stETH exposed to the external-vault mechanism. A de-risking change, so it is recorded rather than paged. Evaluated against the previous on-chain value. |
| RoleGranted (WithdrawalQueue — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the root access-control key of the WithdrawalQueue, which can grant or revoke every other role on the contract that processes user redemptions. The highest-trust change on this contract, so it pages at top urgency. |
| RoleGranted (WithdrawalQueue — FINALIZE / ORACLE / PAUSE) | RoleChange | ERROR | A new address gains a powerful operational role: finalizing withdrawal batches (controls payouts), feeding the finalization oracle data, or the GateSeal ability to freeze all withdrawals. Each can materially affect redemptions, so granting it pages. (PAUSE is periodically rotated to a fresh GateSeal — expected but still page-worthy to confirm the new holder.) |
| RoleGranted (WithdrawalQueue — RESUME) | RoleChange | WARNING | A new address gains the ability to lift a withdrawal pause — a recovery-side capability. Recorded for visibility; does not page. |
| RoleGranted (WithdrawalQueue — MANAGE_TOKEN_URI) | RoleChange | INFO | A new address gains control of the withdrawal-NFT metadata URI — cosmetic, with no power over funds or protocol state. Logged for completeness only. |
| RoleGranted (WithdrawalQueue — unrecognized role) | RoleChange | ERROR | A role the monitor cannot map to a known name is granted. Because an unmapped or custom role could be powerful, it is paged ("fail loud") rather than silently ignored. |
| RoleRevoked (WithdrawalQueue — DEFAULT_ADMIN / FINALIZE / ORACLE) | RoleChange | ERROR | A role whose *loss* is dangerous is removed — the root key (removal can lock out governance), the finalize capability, or the oracle feed (losing either can stall withdrawal finalization). Worth paging even though revocations usually reduce risk, since these can also signal a hostile takeover or an operational mistake. |
| RoleRevoked (WithdrawalQueue — other roles) | RoleChange | WARNING | A lower-impact role (PAUSE, RESUME, token-URI) is removed. PAUSE revocation is the other half of a routine GateSeal rotation, so it is recorded rather than paged (the matching grant already carries the signal). |
| RoleAdminChanged (WithdrawalQueue) | RoleChange | ERROR | The rule for *who may grant or revoke* a WithdrawalQueue role is rewired — a structural change to the permission graph rather than to who holds a role. Rare and deeply privileged, so it pages. |
| Paused (WithdrawalQueue) | EmergencyAction | CRITICAL | The entire WithdrawalQueue is paused — halting requests, finalization, and claims, so users cannot redeem in-flight withdrawals. Fires for any holder of PAUSE_ROLE: the **GateSeal** break-glass is the expected caller, but governance can pause directly and did so at the V2 launch. The pause is either time-boxed (a GateSeal seal runs for a fixed window) or indefinite with no expiry, which the alert reports explicitly. Distinct from bunker mode (this is a manual guardian action, typically taken when an active threat is suspected), so it pages at top urgency. |
| Resumed (WithdrawalQueue) | EmergencyAction | WARNING | The pause on withdrawals is lifted and redemptions resume — the recovery / all-clear signal. The paired Paused already paged, so this is recorded rather than paged. |
| BunkerModeEnabled | EmergencyAction | CRITICAL | The oracle detected abnormal beacon-chain losses (mass slashing or a large validator-balance drop) and activated bunker mode, which pauses withdrawal finalization so the loss is socialised fairly instead of letting early withdrawers escape it. One of the strongest distress signals the protocol can emit, so it pages at top urgency. |
| BunkerModeDisabled | EmergencyAction | WARNING | Bunker mode is lifted and normal finalization resumes — losses have been resolved. The recovery / all-clear signal, recorded rather than paged. |
| ContractVersionSet (WithdrawalQueue) | ContractUpgrade | ERROR | The WithdrawalQueue proxy's implementation is upgraded — new code for the contract that processes user redemptions, while funds and storage stay in the proxy. Governance-gated; pages so it can be matched to a known governance vote. |
| ChangeSupportRequired | ProtocolParameterChange | ERROR | Changes the % of yes-votes a governance proposal needs to pass — one of the two thresholds that define Lido's governance-capture resistance. Lowering it makes it cheaper for a coalition to pass proposals (which control upgrades, roles, and the locator), so any change is a rating-relevant governance-security event and pages. Has never been changed on-chain. |
| ChangeMinQuorum | ProtocolParameterChange | ERROR | Changes the minimum turnout a vote needs to be valid — the second governance-security threshold. Lowering it weakens capture resistance, so any change pages. Has never been changed on-chain. |
| ChangeVoteTime (shortened) | ProtocolParameterChange | ERROR | Changes how long a governance vote stays open — a governance safety-time window. **Shortening** it reduces the time to react to a malicious proposal, so it pages. Evaluated against the previous on-chain value. |
| ChangeVoteTime (lengthened) | ProtocolParameterChange | WARNING | The vote-open window is **lengthened**, giving more time to react to a proposal. A conservative change, so it is recorded rather than paged. A first, baseline-establishing value (no previous on-chain value to compare) is also recorded rather than paged. |
| ChangeObjectionPhaseTime (shortened) | ProtocolParameterChange | ERROR | Changes the length of Lido's final objection window, during which token holders can veto a passed vote. **Shortening** it cuts the veto reaction time, so it pages. Same directional, previous-value comparison as the vote-time window. |
| ChangeObjectionPhaseTime (lengthened) | ProtocolParameterChange | WARNING | The objection/veto window is **lengthened**, giving holders more time to veto a passed vote. A conservative change, so it is recorded rather than paged. A first, baseline-establishing value is also recorded rather than paged. |
| StartVote | TimelockChange | INFO | A new governance proposal is created. Fires well before the proposal can execute (a multi-day vote plus objection window), and its metadata is an opaque IPFS reference, so it is recorded as governance-lifecycle context for review rather than paged. |
| ExecuteVote | TimelockChange | WARNING | A passed governance vote is enacted. The specific privileged changes it makes fire their own events (upgrades, role grants, parameter changes), so this is recorded as the governance-level "a proposal executed" marker to correlate those changes against — surfaced for visibility, not paged. |
| ExitDeadlineThresholdChanged | ProtocolParameterChange | WARNING | Sets how long after a requested validator exit an operator is considered delinquent (plus the reporting window) — operator exit-discipline tuning. Operational rather than a fund/security lever, so it is recorded rather than paged. |
| ContractVersionSet (NodeOperatorsRegistry) | ContractUpgrade | ERROR | The NodeOperatorsRegistry proxy's implementation is upgraded — new code for the operator/validator registry, funds and storage unchanged. Governance-gated; pages to be matched to a known governance vote. |
| LocatorContractSet (NodeOperatorsRegistry) | ContractUpgrade | ERROR | Re-points the NodeOperatorsRegistry at a different LidoLocator (used to resolve the StakingRouter and Burner). A root-of-trust redirect for operator/reward plumbing — a malicious locator could let an attacker impersonate the StakingRouter and manipulate validator accounting or reward distribution. Its damage ceiling is the operator/reward layer (not user custody or withdrawals), so it pages at ERROR, one tier below the stETH-hub locator change. |
| OwnershipTransferred (InsuranceFund) | AdminChange | CRITICAL | Ownership of the InsuranceFund — the protocol's cover reserve (thousands of stETH, tens of millions of dollars) — moves to a new address. The owner can transfer every asset out of the fund, so a handover is control of the entire reserve and pages at top urgency, giving the earliest possible warning before any drain. |
| ERC20Transferred (InsuranceFund) | EmergencyAction | CRITICAL | An ERC-20 asset (the fund holds stETH) is transferred out of the InsuranceFund. A material outflow of the cover reserve is either a covered-loss event (the reserve being used because a loss occurred) or theft — both are top-urgency signals, so it pages at CRITICAL. |
| EtherTransferred (InsuranceFund) | EmergencyAction | CRITICAL | Raw ETH is transferred out of the InsuranceFund — the same reserve-drain signal as the ERC-20 path (covered loss or theft), paged at top urgency. |
| ERC1155Transferred (InsuranceFund) | EmergencyAction | ERROR | An ERC-1155 asset is transferred out of the InsuranceFund via the same owner-only drain path. NFTs are not a designed reserve asset here (the fund holds stETH), so the drain vector is monitored but at ERROR rather than the CRITICAL of the fungible-value paths. |
| ERC721Transferred (InsuranceFund) | EmergencyAction | ERROR | An ERC-721 asset is transferred out of the InsuranceFund via the owner-only drain path. Monitored for completeness at ERROR, since NFTs are not a designed/valued reserve asset here. |
## Lido — strETH (`lido`)
- **Chain(s):** Ethereum
- **Products:** `streth`
- **Contracts monitored:**
- `OracleSubmitter` — `0x00000000df0088bd598df1e4ae57943dc481907a`
- `Vault` — `0x277c6a642564a91ff78b008022d65683cee5ccc5`
- `Oracle` — `0x8a78e6b7e15c4ae3aeaee3bf0de4f2de4078c1cd`
- `LazyAdmin (Safe)` — `0xabe20d266ae54b9ae30492dea6b6407bf18feeb5`
- `VaultProxyAdmin` — `0x94abdf2b59c6495071f32eb8fb4a0f4d2465a2f2`
- `OracleProxyAdmin` — `0x6ce7c72d54e9bdfb97101bd5c4988b61eb4fa156`
- `wstETH RedeemQueue` — `0x1ae8c006b5c97707aa074aaed42becad2cf80da2`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| RoleGranted (OracleSubmitter) | RoleChange | WARNING | Role granted on Oracle Submitter |
| RoleRevoked (OracleSubmitter) | RoleChange | WARNING | Role revoked on Oracle Submitter |
| RoleAdminChanged (OracleSubmitter) | RoleChange | ERROR | Role admin changed on Oracle Submitter |
| Upgraded (Vault proxy) | ContractUpgrade | ERROR | Vault contract upgraded |
| AdminChanged (Vault proxy) | AdminChange | ERROR | Vault proxy admin changed |
| RoleGranted (Vault impl) | RoleChange | WARNING | Vault role granted |
| RoleRevoked (Vault impl) | RoleChange | WARNING | Vault role revoked |
| RoleAdminChanged (Vault impl) | RoleChange | ERROR | Vault role admin changed |
| SetQueueStatus | EmergencyAction | CRITICAL | Vault queue paused/unpaused |
| QueueLimitSet | ProtocolParameterChange | INFO | Vault queue limit set |
| Upgraded (Oracle proxy) | ContractUpgrade | ERROR | Oracle contract upgraded |
| AdminChanged (Oracle proxy) | AdminChange | ERROR | Oracle proxy admin changed |
| AddedOwner (Safe) | MultisigChange | WARNING | Signer added to LazyAdmin Safe |
| RemovedOwner (Safe) | MultisigChange | WARNING | Signer removed from LazyAdmin Safe |
| ChangedThreshold (Safe) | MultisigChange | WARNING | LazyAdmin Safe threshold changed |
| EnabledModule (Safe) | MultisigChange | WARNING | Module enabled on LazyAdmin Safe |
| DisabledModule (Safe) | MultisigChange | WARNING | Module disabled on LazyAdmin Safe |
| ChangedGuard (Safe) | MultisigChange | WARNING | Guard changed on LazyAdmin Safe |
| ChangedFallbackHandler (Safe) | MultisigChange | WARNING | Fallback handler changed on LazyAdmin Safe |
| OwnershipTransferred (VaultProxyAdmin) | AdminChange | ERROR | Vault ProxyAdmin ownership transferred |
| OwnershipTransferred (OracleProxyAdmin) | AdminChange | ERROR | Oracle ProxyAdmin ownership transferred |
## Lombard (`lombard`)
- **Chain(s):** Ethereum
- **Products:** `lbtc` (timelock and consortium incidents are protocol-wide)
- **Contracts monitored:**
- `LBTC Token` — `0x8236a87084f8B84306f72007F36F2618A5634494`
- `Timelock` — `0x055E84e7FE8955E2781010B866f10Ef6E1E77e59`
- `Consortium` — `0xdAD58DfA5c1a7a34419AFdBE1f0d610efeea95E4`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| Upgraded | ContractUpgrade | ERROR | LBTC proxy upgraded to new implementation |
| AdminChanged | AdminChange | ERROR | LBTC proxy admin changed |
| OwnershipTransferred | AdminChange | ERROR | LBTC ownership transferred |
| OwnershipTransferStarted | AdminChange | WARNING | LBTC ownership transfer initiated |
| PauserRoleTransferred | RoleChange | WARNING | LBTC pauser role transferred |
| OperatorRoleTransferred | RoleChange | WARNING | LBTC operator role transferred |
| MinterUpdated | RoleChange | WARNING | LBTC minter added or removed |
| ClaimerUpdated | RoleChange | WARNING | LBTC claimer added or removed |
| ConsortiumChanged | ProtocolParameterChange | ERROR | LBTC consortium address changed |
| BasculeChanged | ProtocolParameterChange | ERROR | LBTC bascule drawbridge address changed |
| AssetRouterChanged | ProtocolParameterChange | WARNING | LBTC asset router changed |
| TreasuryAddressChanged | ProtocolParameterChange | WARNING | LBTC treasury address changed |
| FeeChanged | ProtocolParameterChange | WARNING | LBTC minting fee changed |
| RedeemFeeChanged | ProtocolParameterChange | WARNING | LBTC redeem fee changed |
| BurnCommissionChanged | ProtocolParameterChange | WARNING | LBTC burn commission changed |
| DustFeeRateChanged | ProtocolParameterChange | WARNING | LBTC dust fee rate changed |
| RedeemsForBtcEnabled | ProtocolParameterChange | WARNING | LBTC redeems for BTC enabled/disabled |
| NameAndSymbolChanged | ProtocolParameterChange | INFO | LBTC name and symbol changed |
| Paused | EmergencyAction | CRITICAL | LBTC token paused |
| Unpaused | EmergencyAction | CRITICAL | LBTC token unpaused |
| MinDelayChange (decreased) | TimelockChange | ERROR | Timelock min delay decreased |
| MinDelayChange (increased) | TimelockChange | WARNING | Timelock min delay increased |
| CallScheduled | TimelockChange | WARNING | Timelock call scheduled |
| CallExecuted | TimelockChange | INFO | Timelock call executed |
| Cancelled | TimelockChange | INFO | Timelock call cancelled |
| RoleGranted (Timelock) | RoleChange | WARNING | Timelock role granted |
| RoleRevoked (Timelock) | RoleChange | WARNING | Timelock role revoked |
| RoleAdminChanged (Timelock) | RoleChange | ERROR | Timelock role admin changed |
| OwnershipTransferred (Consortium) | AdminChange | ERROR | Consortium ownership transferred |
| OwnershipTransferStarted (Consortium) | AdminChange | WARNING | Consortium ownership transfer initiated |
| ValidatorSetUpdated | ProtocolParameterChange | ERROR | Consortium validator set updated |
## Looping Collective — lcBTC (`looping-collective`)
- **Chain(s):** Ethereum
- **Products:** `lcbtc`
- **Contracts monitored:**
- `Vault` — `0xaa3cb36be406e6cf208d218fd214e0f1a71e957d`
- `Oracle` — `0xbae89dc56874ed0f790ce9bc698674b2da947ebf`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| UpgradeExecuted | ContractUpgrade | ERROR | Vault upgrade executed |
| UpgradeProposed | ContractUpgrade | INFO | Vault upgrade proposed |
| UpgradeCancelled | ContractUpgrade | INFO | Vault upgrade cancelled |
| Upgraded | ContractUpgrade | ERROR | Vault contract upgraded |
| RoleAdminChanged (Vault) | RoleChange | WARNING | Vault role admin changed |
| RoleGranted (Vault) | RoleChange | WARNING | Vault role granted |
| RoleRevoked (Vault) | RoleChange | WARNING | Vault role revoked |
| Paused | EmergencyAction | CRITICAL | Vault paused |
| Unpaused | EmergencyAction | CRITICAL | Vault unpaused |
| FeesUpdated | ProtocolParameterChange | WARNING | Vault fees updated |
| FeesRecipientUpdated | ProtocolParameterChange | WARNING | Vault fees recipient updated |
| OperatorSet | RoleChange | WARNING | Vault operator set |
| OracleProposed | ProtocolParameterChange | WARNING | Oracle change proposed |
| OracleUpdated | ProtocolParameterChange | WARNING | Oracle updated |
| RateProviderProposed | ProtocolParameterChange | WARNING | Rate provider change proposed |
| RateProviderUpdated | ProtocolParameterChange | WARNING | Rate provider updated |
| FundsHolderProposed | ProtocolParameterChange | WARNING | Funds holder change proposed |
| FundsHolderChanged | ProtocolParameterChange | WARNING | Funds holder changed |
| OwnershipTransferred (Oracle) | AdminChange | ERROR | Oracle ownership transferred |
| OwnershipTransferStarted (Oracle) | AdminChange | WARNING | Oracle ownership transfer started |
## Maple (`maple`)
- **Chain(s):** Ethereum
- **Products:** `syrupusdc`, `syrupusdt`, plus protocol-wide for the shared GovernorTimelock
- **Contracts monitored:**
- `Maple Pool (syrupUSDC)` — `0x80ac24aa929eaf5013f6436cda2a7ba190f5cc0b`
- `Maple PoolManager (syrupUSDC)` — `0x7ad5ffa5fdf509e30186f4609c2f6269f4b6158f`
- `Maple WithdrawalManagerQueue (syrupUSDC)` — `0x1bc47a0dd0fdab96e9ef982fdf1f34dc6207cfe3`
- `Maple Pool (syrupUSDT)` — `0x356b8d89c1e1239cbbb9de4815c39a1474d5ba7d`
- `Maple PoolManager (syrupUSDT)` — `0x0cda32e08b48bfddbc7ee96b44b09cf286f9e21a`
- `Maple WithdrawalManagerQueue (syrupUSDT)` — `0x86ebdf902d800f2a82038290b6dbb2a5ee29eb8c`
- `Maple GovernorTimelock` — `0x2efff88747eb5a3ff00d4d8d0f0800e306c0426b`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| PendingOwnerSet (Pool) | AdminChange | WARNING | Pool two-step ownership transfer initiated |
| OwnershipAccepted (Pool) | AdminChange | ERROR | Pool ownership transfer completed |
| PendingDelegateSet (PoolManager) | AdminChange | WARNING | Pool delegate change initiated |
| PendingDelegateAccepted (PoolManager) | AdminChange | ERROR | Pool delegate changed |
| DelegateManagementFeeRateSet | ProtocolParameterChange | INFO | Delegate management fee rate set |
| LiquidityCapSet | ProtocolParameterChange | INFO | Pool liquidity cap changed |
| CollateralLiquidationTriggered | EmergencyAction | CRITICAL | Loan default / collateral liquidation started |
| CollateralLiquidationFinished | EmergencyAction | WARNING | Collateral liquidation completed |
| SetAsActive (active) | EmergencyAction | WARNING | Pool activated |
| SetAsActive (inactive) | EmergencyAction | ERROR | Pool deactivated |
| PoolPermissionManagerSet | AdminChange | ERROR | Pool access control manager changed |
| WithdrawalManagerSet | ContractUpgrade | ERROR | Withdrawal manager contract changed |
| StrategyAdded | ProtocolParameterChange | WARNING | New lending strategy added |
| IsStrategySet | ProtocolParameterChange | WARNING | Strategy enabled/disabled |
| Upgraded (PoolManager) | ContractUpgrade | ERROR | PoolManager implementation upgraded |
| Upgraded (WithdrawalManager) | ContractUpgrade | ERROR | WithdrawalManager implementation upgraded |
| DefaultTimelockSet | TimelockChange | ERROR | Default timelock delay/execution window changed |
| FunctionTimelockSet | TimelockChange | WARNING | Per-function timelock override set |
| ProposalScheduled | TimelockChange | WARNING | Governance proposal scheduled |
| ProposalExecuted | TimelockChange | WARNING | Governance proposal executed |
| ProposalUnscheduled | TimelockChange | WARNING | Governance proposal unscheduled |
| RoleUpdated | RoleChange | WARNING | Timelock role granted/revoked |
| PendingTokenWithdrawerSet | AdminChange | WARNING | Pending token withdrawer set |
| TokenWithdrawerAccepted | AdminChange | WARNING | Token withdrawer accepted |
## Moonwell Flagship ETH (`moonwell`)
- **Chain(s):** Base
- **Products:** `moonwell-flagship-eth` (Morpho Blue base layer, governor, and multisig incidents are protocol-wide)
- **Contracts monitored:**
- `Moonwell Flagship ETH Vault` — `0xa0E430870c4604CcfC7B38Ca7845B1FF653D0ff1`
- `Moonwell Temporal Governor` — `0x8b621804a7637b781e2BbD58e256a591F2dF7d51`
- `Moonwell Security Council (Guardian 3-of-5)` — `0xB9d4acf113a423Bc4A64110B8738a52E51C2AB38`
- `Block Analitica + B.Protocol (Curator 2-of-4)` — `0x08eDEbFFaE68970DCf751baa826182b3a4aCFC05`
- `MorphoBlue (Base)` — `0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| SetOwner (MorphoBlue) | AdminChange | ERROR | MorphoBlue (Base) owner changed |
| SetFee (MorphoBlue) | ProtocolParameterChange | WARNING | MorphoBlue (Base) market fee changed |
| SetFeeRecipient (MorphoBlue) | ProtocolParameterChange | WARNING | MorphoBlue (Base) fee recipient changed |
| EnableIrm (MorphoBlue) | ProtocolParameterChange | WARNING | MorphoBlue (Base) IRM enabled |
| EnableLltv (MorphoBlue) | ProtocolParameterChange | WARNING | MorphoBlue (Base) LLTV tier enabled |
| OwnershipTransferred (Vault) | AdminChange | ERROR | Vault ownership transferred |
| OwnershipTransferStarted (Vault) | AdminChange | WARNING | Vault ownership transfer started |
| SetCurator | RoleChange | WARNING | Vault curator changed |
| SetGuardian | RoleChange | WARNING | Vault guardian set |
| SubmitGuardian | AdminChange | WARNING | Vault guardian change submitted |
| RevokePendingGuardian | AdminChange | INFO | Pending guardian change revoked |
| SetIsAllocator | RoleChange | WARNING | Vault allocator added/removed |
| SetTimelock | TimelockChange | WARNING | Vault timelock set |
| SubmitTimelock | TimelockChange | WARNING | Vault timelock change submitted |
| RevokePendingTimelock | TimelockChange | INFO | Pending timelock change revoked |
| SetFee (Vault) | ProtocolParameterChange | WARNING | Vault performance fee changed |
| SetFeeRecipient (Vault) | ProtocolParameterChange | WARNING | Vault fee recipient changed |
| SetSkimRecipient | ProtocolParameterChange | INFO | Vault skim recipient changed |
| RevokePendingCap | ProtocolParameterChange | INFO | Pending market cap change revoked |
| SubmitMarketRemoval | ProtocolParameterChange | WARNING | Market removal submitted |
| RevokePendingMarketRemoval | ProtocolParameterChange | INFO | Pending market removal revoked |
| OwnershipTransferred (Governor) | AdminChange | ERROR | Temporal Governor ownership transferred |
| GuardianChanged (Governor) | RoleChange | WARNING | Temporal Governor guardian changed |
| GuardianPauseGranted | RoleChange | WARNING | Temporal Governor guardian pause window granted |
| GuardianRevoked | RoleChange | WARNING | Temporal Governor guardian revoked |
| TrustedSenderUpdated | AdminChange | WARNING | Temporal Governor trusted (cross-chain) sender added/removed |
| Paused (Governor) | EmergencyAction | CRITICAL | Temporal Governor paused |
| Unpaused (Governor) | EmergencyAction | WARNING | Temporal Governor unpaused |
| PermissionlessUnpaused | EmergencyAction | WARNING | Temporal Governor permissionlessly unpaused |
| AddedOwner (Safe) | MultisigChange | WARNING | Multisig owner added |
| RemovedOwner (Safe) | MultisigChange | WARNING | Multisig owner removed |
| ChangedThreshold (Safe) | MultisigChange | CRITICAL | Multisig threshold changed (takeover prelude) |
| EnabledModule (Safe) | MultisigChange | CRITICAL | Multisig module enabled (arbitrary-tx backdoor) |
| DisabledModule (Safe) | MultisigChange | WARNING | Multisig module disabled |
| ChangedGuard (Safe) | MultisigChange | ERROR | Multisig guard changed |
| ChangedFallbackHandler (Safe) | MultisigChange | ERROR | Multisig fallback handler changed |
## Morpho (`morpho`)
- **Chain(s):** Ethereum
- **Products:** the rated Morpho vaults, each a per-vault slug (the slugified vault label, e.g. `steakhouse-usdc`, `gauntlet-usdc-prime-v2`). MorphoBlue-core events apply protocol-wide — MorphoBlue is the shared lending singleton every vault is built on, so those events touch all of them; vault-scoped events attach only to the specific vault that emitted them
- **Contracts monitored:**
- `MorphoBlue` (core singleton) — `0xBBBBBBBBbb9cc5e90e3b3Af64bdAF62C37EEFFCb`
- MetaMorpho V1 vaults:
- `Steakhouse USDC` — `0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB`
- `Steakhouse USDT` — `0xbEef047a543E45807105E51A8BBEFCc5950fcfBa`
- `Steakhouse ETH` — `0xBEEf050ecd6a16c4e7bfFbB52Ebba7846C4b8cD4`
- `Smokehouse USDC` — `0xBEeFFF209270748ddd194831b3fa287a5386f5bC`
- `Gauntlet USDC Frontier` — `0xc582F04d8a82795aa2Ff9c8bb4c1c889fe7b754e`
- `Gauntlet USDC Prime` — `0xdd0f28e19C1780eb6396170735D45153D261490d`
- `Gauntlet USDC Core` — `0x8eB67A509616cd6A7c1B3c8C21D48FF57df3d458`
- `Gauntlet LRT Core` — `0x4881Ef0BF6d2365D3dd6499ccd7532bcdBCE0658`
- `Gauntlet EURC Core` — `0x2ed10624315b74a78f11FAbedAa1A228c198aEfB`
- `VaultBridge WBTC` — `0x812B2C6Ab3f4471c0E43D4BB61098a9211017427`
- Morpho Vaults V2 (adapter-based):
- `Steakhouse Prime Instant V2 USDT` — `0xbeef003C68896c7D2c3c60d363e8d71a49Ab2bf9`
- `Steakhouse Prime Instant V2 USDC` — `0xbeef088055857739C12CD3765F20b7679Def0f51`
- `Steakhouse Prime Instant V2 EURCV` — `0xbeef0C075Da5D01112AE5cF34d257074fB5DDB2f`
- `Gauntlet USDC Prime V2` — `0x8c106EEDAd96553e64287A5A6839c3Cc78afA3D0`
- `Gauntlet USDC Frontier V2` — `0x9a1D6bd5b8642C41F25e0958129B85f8E1176F3e`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| SetOwner (MorphoBlue) | AdminChange | CRITICAL | Transfers ownership of MorphoBlue, the shared lending singleton that every monitored vault is built on. This is the protocol's ultimate root of trust — its owner can change core lending parameters for all vaults — so any change pages at the highest urgency. |
| SetFee (MorphoBlue) | ProtocolParameterChange | WARNING | Turns on or changes MorphoBlue's protocol fee on a lending market — a revenue skim capped at 25% of borrow interest that never touches deposited principal. The fee has never been switched on anywhere, so a change is surfaced on the dashboard, not paged. |
| SetFeeRecipient (MorphoBlue) | ProtocolParameterChange | WARNING | Changes where MorphoBlue's protocol fees are sent. Revenue routing only — it cannot affect deposits or solvency — so it is recorded for visibility, not paged. |
| EnableIrm (MorphoBlue) | ProtocolParameterChange | WARNING | Whitelists a new interest-rate model that markets may opt into. It is additive (it removes nothing and cannot alter existing markets) and has only happened at protocol genesis, so it is tracked on the dashboard, not paged. |
| EnableLltv (MorphoBlue) | ProtocolParameterChange | WARNING | Whitelists a new maximum loan-to-value tier that new markets may use. Additive and genesis-era only — it cannot change any existing market — so it is tracked on the dashboard, not paged. |
| OwnershipTransferred (V1 Vault) | AdminChange | ERROR | Ownership of a monitored vault passes to a new address. The vault owner controls its curator, guardian and timelock, so a completed handover is a root-of-trust change for that vault and pages. |
| OwnershipTransferStarted (V1 Vault) | AdminChange | WARNING | The first step of a two-step vault-ownership handover: a new owner is nominated but not yet in control, and the move can still be cancelled. Surfaced as an early signal; the page comes when it finalizes (the ERROR above). |
| SetCurator (V1 Vault) | RoleChange | WARNING | Changes the vault's curator — the role that proposes market caps and risk policy. Its powers are timelocked and cap-bounded and the guardian can veto them, so a change is surfaced for review but does not page. |
| SetGuardian (V1 Vault) | RoleChange | WARNING | Sets or replaces the vault's guardian, the safety role that can veto risky pending changes. A safety-role change worth recording, but going through the normal process, so it is surfaced rather than paged. |
| SubmitGuardian (V1 Vault) | AdminChange | WARNING | Proposes a new guardian; the change enters the timelock queue and is not yet effective. Surfaced as an early signal of a safety-role change, not paged. |
| RevokePendingGuardian (V1 Vault) | AdminChange | INFO | Cancels a pending guardian change before it takes effect, restoring the prior state. Logged for completeness only. |
| SetIsAllocator (V1 Vault) | RoleChange | WARNING | Grants or removes an allocator — the role that can move vault funds between lending markets, but only within the caps the curator has set. Bounded authority, so it is surfaced for visibility rather than paged. |
| SetTimelock (V1 Vault) | TimelockChange | WARNING | Finalizes a new timelock length for the vault's governance queue. The dangerous direction (shortening the safety window) is caught earlier and pages via SubmitTimelock below, so this finalization is surfaced but not paged. |
| SubmitTimelock (V1 Vault) | TimelockChange | ERROR | Proposes shortening the vault's timelock — the delay that gives holders and the guardian time to react to risky changes. The handler fires only on a decrease, i.e. a request to weaken that safety window, so it pages as the earliest warning. |
| RevokePendingTimelock (V1 Vault) | TimelockChange | INFO | Cancels a pending timelock change before it takes effect, keeping the safer existing window. Logged for completeness only. |
| SetFee (V1 Vault) | ProtocolParameterChange | WARNING | Changes the vault's performance fee, capped at 50% and charged only on yield — it never touches deposited principal. A routine economic knob, surfaced for visibility rather than paged. |
| SetFeeRecipient (V1 Vault) | ProtocolParameterChange | WARNING | Changes where the vault's performance fee is sent. Revenue routing only, with no effect on deposits or solvency, so it is recorded but not paged. |
| SetSkimRecipient (V1 Vault) | ProtocolParameterChange | INFO | Sets the address allowed to sweep stray tokens accidentally sent to the vault — dust only, with no effect on user funds. Logged for completeness. |
| SubmitCap (V1 Vault) | ProtocolParameterChange | WARNING | Proposes raising a market's supply cap — the main lever that increases the vault's exposure to a given lending market. The increase is timelocked and guardian-vetoable, so the proposal is surfaced for review but does not page. |
| SetCap (V1 Vault) | ProtocolParameterChange | INFO | Finalizes a supply cap or lowers one. A decrease reduces risk, and any increase was already surfaced when proposed (above), so this is logged for completeness. |
| RevokePendingCap (V1 Vault) | ProtocolParameterChange | INFO | Cancels a pending supply-cap increase before it takes effect — a de-risking reversal, logged for completeness. |
| SubmitMarketRemoval (V1 Vault) | ProtocolParameterChange | WARNING | Proposes removing a lending market from the vault — a timelocked de-risking step, typically to wind down exposure to a market. Surfaced for review; not paged. |
| RevokePendingMarketRemoval (V1 Vault) | ProtocolParameterChange | INFO | Cancels a pending market removal before it takes effect. A reversal, logged for completeness. |
| SetOwner (V2 Vault) | AdminChange | ERROR | Changes the owner of a V2 vault, effective immediately (no two-step handover). The owner is that vault's root authority, so a change pages. |
| SetCurator (V2 Vault) | RoleChange | WARNING | Changes a V2 vault's curator, the risk-policy role. Its actions are timelocked and a sentinel can veto them, so a change is surfaced for review but does not page. |
| SetIsSentinel (V2 Vault, revoke) | RoleChange | ERROR | Removes a sentinel — the V2 safety role that can veto risky pending changes. Losing a safety role weakens the vault's defenses, so a revocation pages. |
| SetIsSentinel (V2 Vault, grant) | RoleChange | WARNING | Adds a sentinel (safety-veto) role. Strengthening safety is not dangerous, so it is surfaced for visibility, not paged. |
| SetIsAllocator (V2 Vault, grant) | RoleChange | WARNING | Grants an allocator — the role that routes vault funds between adapters, within the vault's caps. Bounded authority, surfaced for visibility, not paged. |
| SetIsAllocator (V2 Vault, revoke) | RoleChange | INFO | Removes an allocator. Reducing privilege is safe, so it is logged for completeness. |
| Submit (V2 Vault, timelock decrease) | TimelockChange | ERROR | The V2 governance queue takes actions keyed by function selector; this submission requests shortening a timelock, weakening the window holders rely on to react to risky changes. It pages as the earliest signal. |
| Submit (V2 Vault, other actions) | TimelockChange | WARNING | A timelocked action is queued in the V2 governance queue. Most queued actions are routine, so they are surfaced for review but do not page (the dangerous timelock-decrease case is the ERROR above). |
| Accept (V2 Vault) | TimelockChange | WARNING | A previously queued V2 action clears its timelock and executes. High-volume routine governance flow; the risky specifics were already flagged when submitted, so acceptance is surfaced but not paged. |
| Revoke (V2 Vault) | TimelockChange | INFO | Cancels a queued V2 action before it executes — a reversal, logged for completeness. |
| IncreaseTimelock (V2 Vault) | TimelockChange | INFO | Lengthens the timelock on a V2 action selector — the safe direction, giving holders more time to react. Logged for visibility, not paged. |
| DecreaseTimelock (V2 Vault) | TimelockChange | ERROR | Shortens the timelock on a V2 action selector, weakening the safety window holders rely on. This is the dangerous direction — it has occurred, once dropping a selector's window to zero — so it pages. |
| Abdicate (V2 Vault) | TimelockChange | ERROR | The owner permanently gives up the ability to ever change a given action selector. It is irreversible, so even though it usually locks in a safer state, it pages so the renunciation can be confirmed as intended. |
| SetPerformanceFee (V2 Vault) | ProtocolParameterChange | WARNING | Changes a V2 vault's performance fee, a bounded charge on yield that never touches deposited principal. A routine economic knob, surfaced for visibility, not paged. |
| SetManagementFee (V2 Vault) | ProtocolParameterChange | WARNING | Changes a V2 vault's management fee, a bounded charge that never touches deposited principal. Surfaced for visibility, not paged. |
| SetPerformanceFeeRecipient (V2 Vault) | ProtocolParameterChange | INFO | Changes where a V2 vault's performance fee is sent — revenue routing only, with no effect on deposits or solvency. Logged for completeness. |
| SetManagementFeeRecipient (V2 Vault) | ProtocolParameterChange | INFO | Changes where a V2 vault's management fee is sent — revenue routing only. Logged for completeness. |
| AddAdapter (V2 Vault) | ProtocolParameterChange | WARNING | Adds an adapter — a venue the vault can route funds into. New adapters are timelocked and constrained to a whitelisted registry, so an addition is surfaced for review but does not page. |
| RemoveAdapter (V2 Vault) | ProtocolParameterChange | INFO | Removes an adapter (only possible once its allocation is zero) — a de-risking step that takes a venue off the menu. Logged for completeness. |
| IncreaseAbsoluteCap (V2 Vault) | ProtocolParameterChange | WARNING | Raises the absolute cap on how much the vault can allocate to an adapter — the main lever that increases exposure to a venue. Cap changes are timelocked, so the increase is surfaced for review but does not page. |
| DecreaseAbsoluteCap (V2 Vault) | ProtocolParameterChange | INFO | Lowers an adapter's absolute allocation cap — a de-risking move that takes effect immediately. Logged for completeness. |
| IncreaseRelativeCap (V2 Vault) | ProtocolParameterChange | WARNING | Raises the relative (percentage-of-vault) cap on an adapter, increasing how much of the vault may sit in that venue. Surfaced for review; not paged. |
| DecreaseRelativeCap (V2 Vault) | ProtocolParameterChange | INFO | Lowers an adapter's relative cap — a de-risking move, logged for completeness. |
| SetReceiveSharesGate (V2 Vault) | ProtocolParameterChange | WARNING | Sets the gate controlling who may receive vault shares — a deposit-side restriction (e.g. an allowlist for new entrants). It cannot trap existing holders, so it is surfaced for visibility, not paged. |
| SetSendSharesGate (V2 Vault, gate set) | ProtocolParameterChange | ERROR | Sets a non-zero gate controlling who may send (transfer or redeem) vault shares — this can stop holders from exiting, so setting one pages. |
| SetSendSharesGate (V2 Vault, cleared) | ProtocolParameterChange | INFO | Clears the send-shares gate back to open, removing the exit restriction. Logged for completeness. |
| SetReceiveAssetsGate (V2 Vault, gate set) | ProtocolParameterChange | ERROR | Sets a non-zero gate controlling who may receive assets when redeeming — this can block withdrawal payouts, so setting one pages. |
| SetReceiveAssetsGate (V2 Vault, cleared) | ProtocolParameterChange | INFO | Clears the receive-assets gate, removing the payout restriction. Logged for completeness. |
| SetSendAssetsGate (V2 Vault) | ProtocolParameterChange | WARNING | Sets the gate controlling who may send assets into the vault — a deposit-side restriction that cannot trap existing holders. Surfaced for visibility, not paged. |
| SetMaxRate (V2 Vault) | ProtocolParameterChange | WARNING | Changes the vault's maximum interest-accrual rate, a bounded accounting cap on how fast value can be booked. It cannot move funds, so it is surfaced for visibility, not paged. |
| SetForceDeallocatePenalty (V2 Vault) | ProtocolParameterChange | WARNING | Changes the penalty (capped at 2%) that a user self-pays when forcing liquidity out of an adapter to exit. Bounded, and the fee accrues to the vault, so a change is surfaced for visibility, not paged. |
| SetAdapterRegistry (V2 Vault) | ProtocolParameterChange | WARNING | Swaps the registry that whitelists which adapters the vault may use — a change to a core guardrail. It is double-timelocked, so it is surfaced for review but does not page. |
| SetLiquidityAdapterAndData (V2 Vault) | ProtocolParameterChange | WARNING | Sets which adapter serves as the vault's liquidity source, plus its routing data — high-volume allocator flow within existing caps. Surfaced for visibility, not paged. |
| ForceDeallocate (V2 Vault, ≥10% TVL) | ProtocolParameterChange | WARNING | Anyone can call this to pull liquidity back into the vault's cash buffer and withdraw immediately, self-paying a capped (≤2%) fee that benefits other holders — normal behavior, not an attack. An unusually large pull (≥10% of the vault) raises a non-paging WARNING as a liquidity-stress signal. |
| ForceDeallocate (V2 Vault, <10% TVL) | ProtocolParameterChange | INFO | A routine permissionless force-deallocation: a user pulls liquidity into the buffer to withdraw, self-paying a capped (≤2%) fee that accrues to the vault. Logged for visibility; never pages. |
## Ondo (`ondo`)
- **Chain(s):** Ethereum
- **Products:** `usdy`, `ousg` (Blocklist and Safe multisig events are protocol-wide)
- **Contracts monitored:**
- `USDY Token` — `0x96f6ef951840721adbf46ac996b59e0235cb985c`
- `USDY Manager` — `0x25a103a1d6aec5967c1a4fe2039cdc514886b97e`
- `USDY Oracle` — `0xa0219aa5b31e65bc920b5b6dfb8edf0988121de0`
- `OUSG Token` — `0x1b19c19393e2d034d8ff31ff34c81252fcbbee92`
- `OUSG InstantManager` — `0x93358db73b6cd4b98d89c8f5f230e81a95c2643a`
- `Blocklist` — `0xd8c8174691d936e2c80114ec449037b13421b0a8`
- `ProxyAdmin Owner Multisig` — `0x1a694a09494e214a3be3652e4b343b7b81a73ad7`
- `Management Multisig` — `0xaed4caf2e535d964165b4392342f71bac77e8367`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| Upgraded (USDY) | ContractUpgrade | ERROR | USDY proxy upgraded to new implementation |
| AdminChanged (USDY) | AdminChange | ERROR | USDY proxy admin changed |
| RoleGranted (USDY) | RoleChange | WARNING | USDY role granted |
| RoleRevoked (USDY) | RoleChange | WARNING | USDY role revoked |
| RoleAdminChanged (USDY) | RoleChange | ERROR | USDY role admin changed |
| AllowlistSet (USDY) | ProtocolParameterChange | WARNING | USDY allowlist contract changed |
| BlocklistSet (USDY) | ProtocolParameterChange | WARNING | USDY blocklist contract changed |
| SanctionsListSet (USDY) | ProtocolParameterChange | WARNING | USDY sanctions list contract changed |
| Paused (USDY) | EmergencyAction | CRITICAL | USDY token paused |
| Unpaused (USDY) | EmergencyAction | CRITICAL | USDY token unpaused |
| RoleGranted (USDY Manager) | RoleChange | WARNING | USDY Manager role granted |
| RoleRevoked (USDY Manager) | RoleChange | WARNING | USDY Manager role revoked |
| RoleAdminChanged (USDY Manager) | RoleChange | ERROR | USDY Manager role admin changed |
| MintFeeSet | ProtocolParameterChange | WARNING | USDY mint fee changed |
| RedemptionFeeSet | ProtocolParameterChange | WARNING | USDY redemption fee changed |
| MinimumDepositAmountSet | ProtocolParameterChange | INFO | USDY minimum deposit amount changed |
| MinimumRedemptionAmountSet | ProtocolParameterChange | INFO | USDY minimum redemption amount changed |
| OffChainRedemptionMinimumSet | ProtocolParameterChange | INFO | USDY off-chain redemption minimum changed |
| AssetSenderSet | AdminChange | WARNING | USDY Manager asset sender changed |
| FeeRecipientSet | AdminChange | WARNING | USDY Manager fee recipient changed |
| NewPricerSet | AdminChange | WARNING | USDY Manager pricer changed |
| BlocklistSet (USDY Manager) | ProtocolParameterChange | WARNING | USDY Manager blocklist contract changed |
| SanctionsListSet (USDY Manager) | ProtocolParameterChange | WARNING | USDY Manager sanctions list changed |
| SubscriptionPaused | EmergencyAction | WARNING | USDY subscriptions (minting) paused |
| SubscriptionUnpaused | EmergencyAction | WARNING | USDY subscriptions (minting) unpaused |
| RedemptionPaused | EmergencyAction | WARNING | USDY redemptions paused |
| RedemptionUnpaused | EmergencyAction | WARNING | USDY redemptions unpaused |
| OffChainRedemptionPaused | EmergencyAction | WARNING | USDY off-chain redemptions paused |
| OffChainRedemptionUnpaused | EmergencyAction | WARNING | USDY off-chain redemptions unpaused |
| RangeSet (USDY Oracle) | ProtocolParameterChange | WARNING | USDY oracle range set (new interest rate range) |
| RangeOverriden (USDY Oracle) | ProtocolParameterChange | ERROR | USDY oracle range overridden |
| RoleGranted (USDY Oracle) | RoleChange | WARNING | USDY Oracle role granted |
| RoleRevoked (USDY Oracle) | RoleChange | WARNING | USDY Oracle role revoked |
| RoleAdminChanged (USDY Oracle) | RoleChange | ERROR | USDY Oracle role admin changed |
| Paused (USDY Oracle) | EmergencyAction | WARNING | USDY oracle paused |
| Unpaused (USDY Oracle) | EmergencyAction | WARNING | USDY oracle unpaused |
| Upgraded (OUSG) | ContractUpgrade | ERROR | OUSG proxy upgraded to new implementation |
| AdminChanged (OUSG) | AdminChange | ERROR | OUSG proxy admin changed |
| RoleGranted (OUSG) | RoleChange | WARNING | OUSG role granted |
| RoleRevoked (OUSG) | RoleChange | WARNING | OUSG role revoked |
| RoleAdminChanged (OUSG) | RoleChange | ERROR | OUSG role admin changed |
| KYCRegistrySet | ProtocolParameterChange | WARNING | OUSG KYC registry contract changed |
| KYCRequirementGroupSet | ProtocolParameterChange | WARNING | OUSG KYC requirement group changed |
| Paused (OUSG) | EmergencyAction | CRITICAL | OUSG token paused |
| Unpaused (OUSG) | EmergencyAction | CRITICAL | OUSG token unpaused |
| RoleGranted (OUSG InstantManager) | RoleChange | WARNING | OUSG InstantManager role granted |
| RoleRevoked (OUSG InstantManager) | RoleChange | WARNING | OUSG InstantManager role revoked |
| RoleAdminChanged (OUSG InstantManager) | RoleChange | ERROR | OUSG InstantManager role admin changed |
| MinimumDepositAmountSet (OUSG IM) | ProtocolParameterChange | INFO | OUSG InstantManager minimum deposit amount changed |
| MinimumRedemptionAmountSet (OUSG IM) | ProtocolParameterChange | INFO | OUSG InstantManager minimum redemption amount changed |
| MinimumRwaPriceSet | ProtocolParameterChange | WARNING | OUSG InstantManager minimum RWA price changed |
| OndoOracleSet | ContractUpgrade | ERROR | OUSG InstantManager oracle contract changed |
| OndoComplianceSet | ProtocolParameterChange | WARNING | OUSG InstantManager compliance contract changed |
| OndoIDRegistrySet | ProtocolParameterChange | WARNING | OUSG InstantManager ID registry changed |
| OndoRateLimiterSet | ProtocolParameterChange | WARNING | OUSG InstantManager rate limiter changed |
| OndoRedemptionFeesSet | ProtocolParameterChange | WARNING | OUSG InstantManager redemption fees contract changed |
| OndoSubscriptionFeesSet | ProtocolParameterChange | WARNING | OUSG InstantManager subscription fees contract changed |
| OndoTokenRouterSet | ContractUpgrade | ERROR | OUSG InstantManager token router changed |
| AcceptedRedemptionTokenSet | ProtocolParameterChange | WARNING | OUSG InstantManager redemption token added/removed |
| AcceptedSubscriptionTokenSet | ProtocolParameterChange | WARNING | OUSG InstantManager subscription token added/removed |
| AdminSubscriptionCheckerSet | ProtocolParameterChange | WARNING | OUSG InstantManager admin subscription checker changed |
| SubscribePaused | EmergencyAction | WARNING | OUSG instant subscriptions (minting) paused |
| SubscribeUnpaused | EmergencyAction | WARNING | OUSG instant subscriptions (minting) unpaused |
| RedeemPaused | EmergencyAction | WARNING | OUSG instant redemptions paused |
| RedeemUnpaused | EmergencyAction | WARNING | OUSG instant redemptions unpaused |
| OwnershipTransferred (Blocklist) | AdminChange | ERROR | Blocklist ownership transferred |
| OwnershipTransferStarted (Blocklist) | AdminChange | WARNING | Blocklist ownership transfer started |
| AddedOwner (Safe) | MultisigChange | WARNING | Owner added to multisig |
| RemovedOwner (Safe) | MultisigChange | WARNING | Owner removed from multisig |
| ChangedThreshold (Safe) | MultisigChange | WARNING | Multisig threshold changed |
| EnabledModule (Safe) | MultisigChange | WARNING | Module enabled on multisig |
| DisabledModule (Safe) | MultisigChange | WARNING | Module disabled on multisig |
| ChangedGuard (Safe) | MultisigChange | WARNING | Guard changed on multisig |
| ChangedFallbackHandler (Safe) | MultisigChange | WARNING | Fallback handler changed on multisig |
## Puffer (`puffer`)
- **Chain(s):** Ethereum
- **Products:** `pufeth` (governance/multisig/timelock incidents are protocol-wide)
- **Contracts monitored:**
- `PufferVault (pufETH)` — `0xD9A442856C234a39a81a089C06451EBAa4306a72`
- `PufferWithdrawalManager` — `0xDdA0483184E75a5579ef9635ED14BacCf9d50283`
- `Timelock` — `0x3C28B7c7Ba1A1f55c9Ce66b263B33B204f2126eA`
- `AccessManager` — `0x8c1686069474410E6243425f4a10177a94EBEE11`
- `PufferOracle` — `0x0BE2aE0edbeBb517541DF217EF0074FC9a9e994f`
- `CommunityMultisig` — `0x446d4d6b26815f9bA78B5D454E303315D586Cb2a`
- `OperationsMultisig` — `0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d`
- `PauserMultisig` — `0x1ba8e3aA853F73ae8093E26B7B8F2520c3620Df4`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| Upgraded (Vault) | ContractUpgrade | ERROR | PufferVault (pufETH) proxy upgraded |
| AuthorityUpdated (Vault) | AdminChange | CRITICAL | PufferVault authority (AccessManager) swapped — access-control takeover vector on the fund-bearing vault |
| ExitFeeBasisPointsSet | ProtocolParameterChange | WARNING | Exit fee changed (basis points) |
| TreasuryExitFeeBasisPointsSet | ProtocolParameterChange | WARNING | Treasury exit fee changed (basis points) |
| UpdatedTotalRewardsAmount | ProtocolParameterChange | INFO | Total rewards updated (affects exchange rate) |
| DelayChanged (Timelock, decreased) | TimelockChange | ERROR | Timelock delay decreased |
| DelayChanged (Timelock, increased) | TimelockChange | WARNING | Timelock delay increased |
| TransactionQueued | TimelockChange | INFO | Timelock transaction queued |
| TransactionExecuted | TimelockChange | INFO | Timelock transaction executed |
| TransactionCanceled | TimelockChange | INFO | Timelock transaction cancelled |
| PauserChanged (Timelock) | AdminChange | ERROR | Timelock pauser changed |
| RoleGranted (AccessManager, ADMIN_ROLE) | RoleChange | CRITICAL | Root admin role granted — protocol root of trust |
| RoleGranted (AccessManager, powerful role) | RoleChange | ERROR | Powerful protocol role granted (Puffer DAO, Puffer Protocol, Vault Withdrawer, pufETH Burner), or an unknown/unlabeled role (fail-loud) |
| RoleGranted (AccessManager, operational role) | RoleChange | WARNING | Operational role granted (Operations Multisig/Paymaster, Withdrawal Finalizer, Revenue Depositor, VT_PRICER) |
| RoleRevoked (AccessManager, ADMIN_ROLE) | RoleChange | ERROR | Root admin role revoked |
| RoleRevoked (AccessManager, other role) | RoleChange | WARNING | Non-root role revoked (risk-reducing) |
| RoleAdminChanged | RoleChange | CRITICAL | AccessManager role-admin rewired — meta-authority over the permission system |
| RoleGuardianChanged | RoleChange | WARNING | AccessManager role guardian changed |
| RoleLabel | RoleChange | INFO | AccessManager role labeled |
| RoleGrantDelayChanged | TimelockChange | WARNING | AccessManager grant delay changed |
| TargetClosed (pufETH vault, closed) | EmergencyAction | CRITICAL | pufETH vault closed — live product pause, funds locked |
| TargetClosed (other target, closed) | EmergencyAction | ERROR | Non-core AccessManager target closed (paused) |
| TargetClosed (reopened) | EmergencyAction | WARNING | AccessManager target reopened (unpaused) |
| TargetAdminDelayUpdated (decreased) | TimelockChange | ERROR | Per-target admin delay decreased — shrinks the observation window for admin ops |
| TargetAdminDelayUpdated (increased) | TimelockChange | WARNING | Per-target admin delay increased (hardening) |
| TargetFunctionRoleUpdated (core target → PUBLIC_ROLE) | RoleChange | ERROR | Core contract function opened to anyone (PUBLIC_ROLE) |
| TargetFunctionRoleUpdated (other) | RoleChange | WARNING | AccessManager function-selector role updated |
| OperationScheduled | TimelockChange | INFO | AccessManager operation scheduled |
| OperationExecuted | TimelockChange | INFO | AccessManager operation executed |
| OperationCanceled | TimelockChange | INFO | AccessManager operation cancelled |
| AuthorityUpdated (Oracle) | AdminChange | ERROR | PufferOracle authority updated |
| TotalNumberOfValidatorsUpdated | ProtocolParameterChange | INFO | Total number of validators updated |
| ValidatorTicketMintPriceUpdated (dropped to zero) | ProtocolParameterChange | ERROR | Validator ticket mint price dropped to zero — oracle-fault canary |
| ValidatorTicketMintPriceUpdated (non-zero move) | ProtocolParameterChange | INFO | Validator ticket mint price changed (off the pufETH-backing path — no peg/solvency signal) |
| AddedOwner (Safe) | MultisigChange | ERROR | Multisig owner added |
| RemovedOwner (Safe) | MultisigChange | ERROR | Multisig owner removed |
| ChangedThreshold (Safe) | MultisigChange | CRITICAL | Multisig signing threshold changed |
| EnabledModule (Safe) | MultisigChange | CRITICAL | Multisig module enabled — can bypass the owner-threshold check |
| DisabledModule (Safe) | MultisigChange | ERROR | Multisig module disabled |
| ChangedGuard (Safe) | MultisigChange | ERROR | Multisig guard changed |
| ChangedFallbackHandler (Safe) | MultisigChange | ERROR | Multisig fallback handler changed |
| MaxWithdrawalAmountChanged | ProtocolParameterChange | WARNING | Max 2-step withdrawal amount changed |
| Upgraded (WithdrawalManager) | ContractUpgrade | ERROR | PufferWithdrawalManager proxy upgraded |
| AuthorityUpdated (WithdrawalManager) | AdminChange | ERROR | PufferWithdrawalManager authority updated |
## Rocket Pool (`rocketpool`)
- **Chain(s):** Ethereum
- **Products:** `reth`
- **Contracts monitored:**
- `rETH Token` — `0xae78736cd615f374d3085123a210448e74fc6393`
- `RocketStorage` — `0x1d8f8f00cfa6758d7be78336684788fb0ee0fa46`
- `RocketDAONodeTrustedUpgrade` — `0x952999ec97248547d810fd6464fdb78855b022ab`
- `RocketDAOProposal` — `0x37714d3a9d3b3091220d68184e3afec4ec911368`
- `RocketDAOProtocol` — `0x0429cdd8ceace24d4dc2b97ce22a780a407df0e1`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| GuardianChanged | AdminChange | ERROR | Protocol guardian (most privileged admin) changed |
| ContractUpgraded | ContractUpgrade | ERROR | Existing protocol contract replaced |
| ContractAdded | ContractUpgrade | WARNING | New contract registered |
| ABIUpgraded | ContractUpgrade | INFO | ABI upgraded |
| ABIAdded | ContractUpgrade | INFO | New ABI registered |
| ProposalExecuted | ProtocolParameterChange | WARNING | oDAO proposal executed (changes take effect) |
| ProposalAdded | ProtocolParameterChange | INFO | oDAO proposal submitted |
| ProposalCancelled | ProtocolParameterChange | INFO | oDAO proposal cancelled |
| BootstrapSettingUint (call) | ProtocolParameterChange | WARNING | Guardian-only bootstrap uint setting changed |
| BootstrapSettingBool (call) | ProtocolParameterChange | WARNING | Guardian-only bootstrap bool setting changed |
| BootstrapSettingAddress (call) | ProtocolParameterChange | WARNING | Guardian-only bootstrap address setting changed |
| BootstrapDisable (call) | AdminChange | ERROR | Bootstrap mode disabled (governance transition) |
## Sky (`sky`)
- **Chain(s):** Ethereum
- **Products:** `susds`
- **Contracts monitored:**
- `sUSDS Vault` — `0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD`
- `USDS Token` — `0xdC035D45d973E3EC169d2276DDab16f1e407384F`
- `GSM (MCD Pause)` — `0xbE286431454714F511008713973d3B053A2d38f3`
- `ESM (Emergency Shutdown Module)` — `0x09e05fF6142F2f9de8B6B65855A1d56B6cfE4c58`
- `End (Global Settlement)` — `0x0e2e8f1D1326A4B9633D96222Ce399c708B19c28`
- `Protego (Emergency Spells)` — `0x5C9c3cb0490938c9234ABddeD37a191576ED8624`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| File (sUSDS Vault) | ProtocolParameterChange | INFO | sUSDS parameter changed (e.g. SSR) |
| Upgraded (sUSDS Vault) | ContractUpgrade | ERROR | sUSDS vault contract upgraded |
| Rely (sUSDS Vault) | AdminChange | WARNING | sUSDS ward added |
| Deny (sUSDS Vault) | AdminChange | WARNING | sUSDS ward removed |
| Rely (USDS Token) | AdminChange | WARNING | USDS ward added |
| Deny (USDS Token) | AdminChange | WARNING | USDS ward removed |
| Upgraded (USDS Token) | ContractUpgrade | ERROR | USDS token contract upgraded |
| LogSetOwner (GSM) | AdminChange | ERROR | GSM owner changed |
| LogSetAuthority (GSM) | AdminChange | ERROR | GSM authority changed |
| setDelay call (GSM) | TimelockChange | WARNING | GSM delay (timelock) changed |
| plot call (GSM) | TimelockChange | WARNING | Governance spell scheduled |
| exec call (GSM) | TimelockChange | WARNING | Governance spell executed |
| drop call (GSM) | TimelockChange | WARNING | Governance spell dropped |
| Fire (ESM) | EmergencyAction | CRITICAL | Emergency shutdown triggered |
| Join (ESM) | EmergencyAction | WARNING | MKR/SKY burned toward shutdown threshold |
| Rely (ESM) | AdminChange | WARNING | ESM ward added |
| Deny (ESM) | AdminChange | WARNING | ESM ward removed |
| Cage (End, no args) | EmergencyAction | CRITICAL | Global settlement initiated |
| Cage (End, collateral) | EmergencyAction | ERROR | Collateral type caged |
| Rely (End) | AdminChange | WARNING | End ward added |
| Deny (End) | AdminChange | WARNING | End ward removed |
| Thaw (End) | EmergencyAction | ERROR | Global settlement debt finalized |
| Deploy (Protego) | EmergencyAction | WARNING | Emergency drop spell deployed |
| Drop (Protego) | EmergencyAction | ERROR | Governance plan dropped via Protego |
## Spark (`spark`)
- **Chain(s):** Ethereum
- **Products:** the 4 rated Spark products — `spweth` (SparkLend WETH market), `wsteth` (SparkLend wstETH market), `spusdc` and `spusdt` (ERC4626 savings vaults). Per-asset SparkLend events only escalate above INFO for the rated reserves (WETH, wstETH); changes on other reserves are tracked on the dashboard. Most governance/infra events are protocol-wide (`product: ""`)
- **Contracts monitored:**
- `Pool` — `0xc13e21b648a5ee794902342038ff3adab66be987`
- `PoolConfigurator` — `0x542dba469bde58faee189ffb60c6b49ce60e0738`
- `PoolAddressesProvider` — `0x02c3ea4e34c0cbd694d2adfa2c690eecbc1793ee`
- `ACLManager` — `0xda135cd78a086025bcdc87b038a1c462032b510c`
- `GovernanceExecutor` — `0x3300f198988e4c9c63f75df86de36421f06af8c4`
- `ALMFreezerMultisig` — `0x90d8c80c028b4c09c0d8dcaab9bbb057f0513431`
- `SparkFoundationMultisig` — `0x92e4629a4510af5819d7d1601464c233599ff5ec`
- `SparkLendFreezerMultisig` — `0x44effc473e81632b12486866aa1678edbb7beec3`
- `ALMProxy` — `0x1601843c5e9bc251a3272907010afa41fa18347e`
- `Oracle` — `0x8105f69d9c41644c6a0803fda7d03aa70996cfd9`
- `Treasury` — `0xb137e7d16564c81ae2b0c8ee6b55de81dd46ece5`
- `spUSDC Vault` — `0x28b3a8fb53b741a8fd78c0fb9a6b2393d896a43d`
- `spUSDT Vault` — `0xe2e7a17dff93280dec073c995595155283e3c372`
- `spWETH (aToken)` — `0x59cd1c87501baa753d0b5b5ab5d8416a45cd71db`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| RoleGranted (ACLManager — DEFAULT_ADMIN) | RoleChange | CRITICAL | A new address gains the root access-control key that administers every other ACL role — effectively whole-protocol control. Highest-trust change; pages at top urgency. |
| RoleGranted (ACLManager — POOL_ADMIN / EMERGENCY_ADMIN / ASSET_LISTING_ADMIN) | RoleChange | ERROR | A new address gains a powerful privileged role: pool administration (including upgrading the aTokens that hold supplier funds), the ability to pause/freeze reserves, or authority to list new assets. Each can materially affect funds or availability, so it pages. |
| RoleGranted (ACLManager — RISK_ADMIN / BRIDGE) | RoleChange | WARNING | A new address gains a bounded operational role — tuning risk parameters within limits, or bridge minting capped by configuration. Expected governance activity; recorded but not paged. |
| RoleGranted (ACLManager — FLASH_BORROWER) | RoleChange | INFO | A new address gains the flash-borrower role (fee-exempt flashloans). Low-power; dashboard-only. |
| RoleRevoked (ACLManager — DEFAULT_ADMIN / EMERGENCY_ADMIN / POOL_ADMIN) | RoleChange | ERROR | A powerful role is removed from an address (e.g. de-authorizing an old admin during a governance migration). Pages to confirm against a known governance action. |
| RoleRevoked (ACLManager — other roles) | RoleChange | WARNING | A bounded/operational role is removed. Privilege reduction is low-risk; recorded but not paged. |
| RoleAdminChanged (ACLManager) | RoleChange | CRITICAL | Changes which role administers another ACL role — re-pointing this can hand control of an entire privilege branch (e.g. making a new role the admin of POOL_ADMIN). Restructures the permission hierarchy itself; pages at top urgency. Never fired on Spark. |
| Rely (GovernanceExecutor) | AdminChange | ERROR | Sky/Maker `rely(usr)` — authorizes a new address (`wards[usr]=1`) to call every auth-gated function on the governance executor that runs passed spells, i.e. grants governance-execution authority. Pages to confirm against governance. A tier below Aave's executor ownership transfer (CRITICAL) since it adds a ward rather than transferring sole ownership. 4 on-chain (deploy-time wiring of the Sky stack). |
| Deny (GovernanceExecutor) | AdminChange | WARNING | Sky/Maker `deny(usr)` — clears a ward (`wards[usr]=0`), removing that address's authority on the governance executor. The inverse of Rely; removing authority is risk-reducing, so recorded but not paged. 1 on-chain (deploy-time cleanup). |
| ACLAdminUpdated (PoolAddressesProvider) | AdminChange | ERROR | Changes the registered ACL admin — the account treated as the access-control superuser (holds DEFAULT_ADMIN_ROLE on the ACLManager). Pages to confirm against governance. Matches Aave. 3 on-chain (early governance setup). |
| ACLManagerUpdated (PoolAddressesProvider) | ContractUpgrade | CRITICAL | Points the protocol at a new ACLManager contract. Since the ACLManager is the registry of every role, this swaps the entire permission system at once (a malicious one could grant any role to anyone). Matches Aave. 1 on-chain (deploy). |
| PoolUpdated (PoolAddressesProvider) | ContractUpgrade | ERROR | Registry-side announcement that the main Pool implementation was upgraded. The Pool holds all core lending logic (supply/borrow/withdraw/repay/liquidate, interest accrual), so it changes core behavior. Twins with the Pool proxy's own `Upgraded`. Matches Aave. 4 on-chain (SparkLend version upgrades). |
| PoolConfiguratorUpdated (PoolAddressesProvider) | ContractUpgrade | ERROR | Upgrades the implementation behind the PoolConfigurator proxy — the contract governance uses to set every per-reserve risk parameter (caps, collateral config, freeze/pause, fees, token upgrades). A tier below the ACLManager/Oracle swaps (it cannot itself move funds or forge prices). Matches Aave. 1 on-chain (deploy). |
| PriceOracleUpdated (PoolAddressesProvider) | ContractUpgrade | CRITICAL | Points the protocol at a new price oracle contract. The oracle values all collateral and debt, so a malicious one can mark collateral to zero (liquidate everyone) or inflate it (drain the pool) — drives the market to insolvency. Matches Aave. Distinct from per-asset `AssetSourceUpdated` on the oracle. 1 on-chain (deploy). |
| PriceOracleSentinelUpdated (PoolAddressesProvider) | ContractUpgrade | ERROR | Sets/replaces the PriceOracleSentinel, which gates borrows/liquidations during sequencer or oracle downtime (a grace-period so users aren't liquidated on stale prices). A bad one could allow liquidations on stale prices. A tier below the oracle itself (it gates timing, not prices). Matches Aave. 0 on-chain (trip-wire). |
| PoolDataProviderUpdated (PoolAddressesProvider) | ContractUpgrade | WARNING | Swaps the PoolDataProvider — a read-only aggregator UIs/integrators use to fetch reserve data. No fund-moving or risk logic, so recorded but not paged. Matches Aave. 1 on-chain (deploy). |
| OwnershipTransferred (AddressesProvider) | AdminChange | CRITICAL | Transfers ownership of the PoolAddressesProvider — the root key that can swap the Pool, PoolConfigurator, ACLManager, and Oracle. This is SparkLend's root upgrade authority, so an ownership move is top-urgency. Matches Aave. 4 on-chain (early handoffs into the Sky governance pipeline). |
| ProxyCreated (PoolAddressesProvider) | ContractUpgrade | INFO | Deploys a new proxy for a registry id — first-time setup of a core contract (Pool, PoolConfigurator) at launch. Subsequent implementation changes are caught by the Updated events above. Matches Aave. 2 on-chain (deploy). |
| AddressSetAsProxy (PoolAddressesProvider) | ContractUpgrade | ERROR | Sets/updates the implementation for a registry id via the provider's own managed proxy — a registry-driven upgrade of a core contract (same risk class as PoolUpdated/PoolConfiguratorUpdated). Matches Aave. 0 on-chain (trip-wire). |
| AddressSet (PoolAddressesProvider) | ContractUpgrade | ERROR | Registers or changes a core address stored under a registry id (non-proxy variant — points an id directly at an address). A structural change to the protocol's wiring. Matches Aave. 0 on-chain (trip-wire). |
| ReserveFactorChanged | ProtocolParameterChange | INFO (WARNING if >50%) | Sets a reserve's reserve factor — the % of borrow interest skimmed to the treasury vs. paid to suppliers. Purely an economic split; routine within the 5–50% band (INFO), only an abnormal >50% setting warns. Rated reserves carry their product key. Matches Aave. 32 on-chain (all routine). |
| FlashloanPremiumTotalUpdated | ProtocolParameterChange | INFO (WARNING if >100bps) | Sets the total flash-loan fee (bps). Historically 5–9 bps; only an anomalous >1% setting (misconfig/tampering) warns. Market-wide. Matches Aave. 3 on-chain (all routine). |
| FlashloanPremiumToProtocolUpdated | ProtocolParameterChange | INFO | Sets the share of the flash-loan fee routed to the treasury (vs. suppliers) — a pure internal fee-split, no solvency/access impact. Matches Aave. 0 on-chain. |
| BridgeProtocolFeeUpdated | ProtocolParameterChange | INFO | Sets the fee on bridged/'portal' unbacked liquidity (Aave cross-chain feature; unused on Spark). Matches Aave. 0 on-chain. |
| LiquidationProtocolFeeChanged | ProtocolParameterChange | INFO (WARNING if >30%) | Sets the protocol's cut of the liquidation bonus for a reserve. Too high erodes liquidator incentive → stalled liquidations → bad-debt risk (gradual, so WARNING not ERROR above the band). Historical 0–20%. Rated reserves carry their product key. Matches Aave. 16 on-chain (all routine). |
| ATokenUpgraded | ContractUpgrade | ERROR | Upgrades a reserve's aToken (deposit receipt that custodies supplier funds) implementation — fund-bearing code. Matches Aave. 0 on-chain. |
| StableDebtTokenUpgraded | ContractUpgrade | ERROR | Upgrades a reserve's stable-debt-token (fixed-rate borrow positions) implementation. Spark v3.0.2 still ships stable-rate debt (no Aave-v3.2 analog). 0 on-chain. |
| VariableDebtTokenUpgraded | ContractUpgrade | ERROR | Upgrades a reserve's variable-debt-token (variable-rate borrow positions) implementation. Matches Aave. 0 on-chain. |
| ReserveInterestRateStrategyChanged | ProtocolParameterChange | INFO | Points a reserve at a new interest-rate-strategy contract (the utilization→APR curve). Only changes rates going forward — cannot touch principal or collateral config — so dashboard-only. Rated reserves carry their product key. Matches Aave. 56 on-chain (frequent rate tuning). |
| ReservePaused (rated asset — paused) | EmergencyAction | CRITICAL | A rated reserve (WETH/wstETH) is paused — ALL actions blocked (supply/borrow/withdraw/repay/liquidate), so funds go dark. Top-urgency. Matches Aave. 0 on-chain. |
| ReservePaused (rated asset — unpaused) | EmergencyAction | WARNING | A rated reserve is unpaused (recovery). Matches Aave. |
| ReservePaused (non-rated asset) | EmergencyAction | INFO | Pause/unpause on a non-rated reserve — dashboard-only. |
| ReserveFrozen (rated asset — frozen) | EmergencyAction | ERROR | A rated reserve (WETH/wstETH) is frozen — blocks new supply/borrow but exit still allowed (one tier below pause). A de-risking signal worth confirming. Matches Aave. 0 on-chain (rated). |
| ReserveFrozen (rated asset — unfrozen) | EmergencyAction | WARNING | A rated reserve is unfrozen (recovery). Matches Aave. |
| ReserveFrozen (non-rated asset) | EmergencyAction | INFO | Freeze/unfreeze on a non-rated reserve — routine risk-management, dashboard-only. 13 on-chain (all non-rated). |
| CollateralConfigurationChanged (rated asset — LT drop ≥500bps or LTV→0) | ProtocolParameterChange | ERROR | A rated reserve's (WETH/wstETH) solvency config is tightened dangerously — liquidation threshold cut ≥5% or LTV set to 0. Lowering the threshold can make existing positions instantly liquidatable. Stateful (compares to prior on-chain config). Matches Aave/HyperLend. 0 on-chain (rated configs only ever loosened). |
| CollateralConfigurationChanged (rated asset — other) | ProtocolParameterChange | WARNING | Other collateral-config change on a rated reserve (e.g. LTV/threshold raised). Recorded for visibility. |
| CollateralConfigurationChanged (non-rated asset) | ProtocolParameterChange | INFO | Collateral config change on a non-rated reserve — dashboard-only. 50 total on-chain. |
| BorrowCapChanged | ProtocolParameterChange | INFO (WARNING if a rated asset's cap is disabled →1) | Sets the max total borrowable for a reserve (0=unlimited). Touches only new borrowing. A reduction to 1 (effectively disabled) on a rated asset is a wind-down canary → WARNING. Matches Aave. 498 on-chain — incl. one real signal: wstETH 17444→1 (block 23218585). |
| SupplyCapChanged | ProtocolParameterChange | INFO (WARNING if a rated asset's cap is disabled →1) | Sets the max total suppliable for a reserve (0=unlimited). Same wind-down-canary logic. Matches Aave. 867 on-chain (all routine). |
| DebtCeilingChanged | ProtocolParameterChange | INFO (WARNING if a rated asset crosses the isolation boundary) | Sets the isolation-mode debt ceiling (USD) for an isolated-collateral reserve. WARNING when a rated asset enters/exits isolation mode; else INFO. Matches Aave. 12 on-chain (none on rated). |
| SiloedBorrowingChanged | ProtocolParameterChange | WARNING (rated asset toggle) / INFO (non-rated) | Toggles siloed borrowing — a siloed asset can only be borrowed alone. A real toggle on a rated reserve is a risk-posture change (WARNING); non-rated toggles and listing-time no-ops are INFO. Matches Aave. 15 on-chain. |
| EModeCategoryAdded | ProtocolParameterChange | ERROR (rated-holding category, LT drop ≥500bps) / WARNING (rated-holding, other change) / INFO | Defines/updates an efficiency-mode category's LTV & liquidation threshold. For a position *in* the category, the category LT — not the per-asset LT — is binding, so a ≥500bps drop on a category that holds a rated asset (WETH/wstETH both sit in cat 1 "ETH", LT 93%) can make e-mode positions instantly liquidatable → ERROR. Stateful (compares to prior category LT). 4 on-chain (cat-1 LT only ever raised → 0 ERROR historically; clean trip-wire). |
| EModeAssetCategoryChanged | ProtocolParameterChange | ERROR (rated asset removed, newCategory 0) / WARNING (rated added/moved) / INFO (non-rated) | Assigns an asset to an e-mode category (or removes it). Removing a rated asset from e-mode collapses its effective LT from the category (93%) to its base value → mass-liquidation risk → ERROR. Adding/moving is governance-normal leverage → WARNING. 2 on-chain on rated assets (WETH & wstETH → cat 1 at launch). |
| Upgraded (Pool proxy) | ContractUpgrade | ERROR | ERC1967 implementation swap on the main Pool proxy — the contract holding all core lending logic. Twins with PoolUpdated (registry-side). Matches Aave/HyperLend. 3 on-chain (SparkLend version upgrades). |
| Upgraded (spUSDC Vault proxy) | ContractUpgrade | ERROR | ERC1967 implementation swap on the spUSDC savings-vault proxy — fund-bearing code on a rated product. Consistent with every fund-bearing proxy upgrade (Pool, aTokens, Treasury). 1 on-chain (setup). |
| RoleGranted (spUSDC Vault) | RoleChange | CRITICAL (DEFAULT_ADMIN) / WARNING (SETTER, TAKER) | Grants a vault role. DEFAULT_ADMIN controls the rated vault → CRITICAL; SETTER_ROLE (sets VSR/caps) and TAKER_ROLE (takes surplus) are bounded operational roles → WARNING. 5 on-chain (DEFAULT_ADMIN ×1, SETTER ×3, TAKER ×1). |
| RoleRevoked (spUSDC Vault) | RoleChange | ERROR (DEFAULT_ADMIN) / WARNING (others) | Removes a vault role. Losing the admin key is notable (ERROR); other revokes are privilege reductions (WARNING). 2 on-chain. |
| RoleAdminChanged (spUSDC Vault) | RoleChange | CRITICAL | Changes which role administers another vault role — restructures the vault's permission tree (consistent with the ACLManager decision). 0 on-chain (trip-wire). |
| DepositCapSet (spUSDC) | ProtocolParameterChange | INFO (WARNING if cap →0) | Sets the vault's max total deposits (0 = disabled here). Routine raises are INFO; a reduction to 0 (deposits disabled = wind-down) warns. 5 on-chain (all increases). |
| VsrSet (spUSDC) | ProtocolParameterChange | INFO | Sets the Vault Savings Rate (depositor yield). Bounded on-chain by VsrBounds and economic-only, so dashboard-only regardless of value. On-chain range ~2.5–4.9% APY. |
| VsrBoundsSet (spUSDC) | ProtocolParameterChange | INFO (WARNING if max bound raised) | Sets the min/max the VSR may take — the governance guard-rail. Widening the max bound (what would enable an abnormal rate) warns; tightening is INFO. 1 on-chain (setup, max set to ~10% APY). |
| Upgraded (spUSDC Vault impl, UUPS) | ContractUpgrade | ERROR | UUPS self-upgrade of the spUSDC vault implementation (impl upgrades itself) — fund-bearing on a rated product. 1 on-chain. |
| Upgraded (spUSDT Vault proxy) | ContractUpgrade | ERROR | ERC1967 implementation swap on the spUSDT savings-vault proxy — fund-bearing code on a rated product. Mirrors spUSDC. 1 on-chain. |
| RoleGranted (spUSDT Vault) | RoleChange | CRITICAL (DEFAULT_ADMIN) / WARNING (SETTER, TAKER) | Grants a vault role. DEFAULT_ADMIN controls the rated vault → CRITICAL; SETTER/TAKER → WARNING. Mirrors spUSDC. 5 on-chain. |
| RoleRevoked (spUSDT Vault) | RoleChange | ERROR (DEFAULT_ADMIN) / WARNING (others) | Removes a vault role. Admin-key loss → ERROR; others → WARNING. Mirrors spUSDC. 2 on-chain. |
| RoleAdminChanged (spUSDT Vault) | RoleChange | CRITICAL | Changes which role administers another vault role — restructures the permission tree. Mirrors spUSDC. 0 on-chain (trip-wire). |
| DepositCapSet (spUSDT) | ProtocolParameterChange | INFO (WARNING if cap →0) | Sets the vault's max total deposits (0 = disabled). Routine raises INFO; reduction to 0 (wind-down) warns. 5 on-chain (all increases). |
| VsrSet (spUSDT) | ProtocolParameterChange | INFO | Sets the Vault Savings Rate. Bounded on-chain + economic-only → dashboard regardless. Fired 816× (automated) — confirms INFO. Range ~2.4–4.9% APY. |
| VsrBoundsSet (spUSDT) | ProtocolParameterChange | INFO (WARNING if max bound raised) | Sets the VSR guard-rail bounds. Widening the max bound warns; tightening INFO. 1 on-chain (setup). |
| Upgraded (spUSDT Vault impl, UUPS) | ContractUpgrade | ERROR | UUPS self-upgrade of the spUSDT vault implementation — fund-bearing. Mirrors spUSDC. 1 on-chain. |
| RoleGranted (ALMProxy) | RoleChange | CRITICAL (DEFAULT_ADMIN) / WARNING (CONTROLLER, FREEZER) / INFO (RELAYER) | Grants a role on the ALM (Spark Liquidity Layer) proxy that routes protocol liquidity. DEFAULT_ADMIN controls the router → CRITICAL; CONTROLLER routes liquidity but is rotated routinely (11× on-chain) → WARNING (not a page); FREEZER → WARNING; RELAYER (operational executor) → INFO. Not a rated product. 12 on-chain (DEFAULT_ADMIN ×1, CONTROLLER ×11). |
| RoleRevoked (ALMProxy) | RoleChange | ERROR (DEFAULT_ADMIN) / WARNING (others) | Removes an ALM role. Admin-key loss → ERROR; others → WARNING. 10 on-chain. |
| RoleAdminChanged (ALMProxy) | RoleChange | CRITICAL | Changes which role administers another ALM role — restructures the permission tree (consistent with all RoleAdminChanged). 0 on-chain (trip-wire). |
| AssetSourceUpdated (rated asset) | ContractUpgrade | ERROR | Replaces the price-feed source (e.g. Chainlink aggregator) for a rated asset (WETH/wstETH). A manipulation vector — a malicious feed can misprice the asset and trigger bad liquidations. A tier below the whole-oracle swap (CRITICAL). 7 on-chain on rated assets (legitimate feed migrations). |
| AssetSourceUpdated (non-rated asset) | ContractUpgrade | INFO | Price-feed source change on a non-rated reserve — dashboard-only. 33 total on-chain. |
| BaseCurrencySet (Oracle) | ProtocolParameterChange | WARNING | Sets the oracle's base/quote currency and its unit (e.g. USD, 8-decimal) — the denomination all prices are reported in. One-time foundational config. 1 on-chain (deploy). |
| FallbackOracleUpdated (Oracle) | ContractUpgrade | WARNING | Sets/replaces the fallback oracle, queried only when a primary feed returns no/zero price — dormant while feeds are healthy. A tier below the live-path oracle events (it activates only during a primary-feed outage). 1 on-chain (deploy). |
| AdminChanged (Treasury) | AdminChange | CRITICAL | Changes the proxy admin of the Treasury — the account allowed to upgrade its implementation. A malicious upgrade could drain protocol reserves, so it pages at top tier (consistent with how every upgrade-to-drain proxy-admin key is treated). 1 on-chain (early governance handoff). |
| Upgraded (Treasury) | ContractUpgrade | ERROR | ERC1967 implementation swap on the Treasury proxy (the act event 56's admin can perform). Kept at ERROR for consistency with all other proxy `Upgraded` events — CRITICAL is reserved for the control/key moves (the AdminChanged that grants upgrade rights). 0 on-chain (never upgraded). |
| AddedOwner (Safe) | MultisigChange | ERROR | A signer is added to a Spark admin Safe (ALMFreezer / Foundation / SparkLendFreezer) — changes the multisig's trust set. Pages to confirm against governance. Matches HyperLend/Moonwell. 10 on-chain across safes. |
| RemovedOwner (Safe) | MultisigChange | ERROR | A signer is removed from a Spark admin Safe. Matches HyperLend/Moonwell. 6 on-chain. |
| ChangedThreshold (Safe) | MultisigChange | CRITICAL | Changes M in the M-of-N requirement. Lowering it can hand fewer parties unilateral control. Matches HyperLend/Moonwell. 4 on-chain. |
| EnabledModule (Safe) | MultisigChange | CRITICAL | Enables a module that executes through the Safe bypassing owner signatures entirely — the most dangerous Safe change. Matches HyperLend/Moonwell. 0 on-chain (trip-wire). |
| DisabledModule (Safe) | MultisigChange | ERROR | Disables a previously-enabled module. Execution-surface change. Matches HyperLend/Moonwell. 0 on-chain. |
| ChangedGuard (Safe) | MultisigChange | ERROR | Sets/removes the transaction guard that gates every Safe txn (a malicious guard can freeze the Safe). Matches HyperLend/Moonwell. 0 on-chain. |
| ChangedFallbackHandler (Safe) | MultisigChange | ERROR | Sets the fallback handler (callable surface, e.g. EIP-1271 signature validation). Matches HyperLend/Moonwell. 0 on-chain. |
| Upgraded (spWETH aToken proxy) | ContractUpgrade | ERROR | ERC1967 implementation swap on the spWETH aToken proxy — the SparkLend WETH-market deposit receipt (rated product `spweth`). Fund-bearing code. 0 on-chain. |
| Initialized (spWETH aToken impl) | ContractUpgrade | INFO | One-time aToken initializer (sets underlying, pool, treasury, incentives controller, decimals, name/symbol). Setup metadata, not a risk event. |
## Stader (`stader`)
- **Chain(s):** Ethereum
- **Products:** `ethx` (ProxyAdmin, Timelock, and Safe multisig events are protocol-wide)
- **Contracts monitored:**
- `ETHx Token` — `0xa35b1b31ce002fbf2058d22f30f95d405200a15b`
- `StakingPoolManager` — `0xcf5ea1b38380f6af39068375516daf40ed70d299`
- `UserWithdrawalManager` — `0x9f0491b32dbce587c50c4c43ab303b06478193a7`
- `Stader Oracle` — `0xf64bae65f6f2a5277571143a24faafdfc0c2a737`
- `StaderConfig` — `0x4abef2263d5a5ed582fc9a9789a41d85b68d69db`
- `PermissionlessPool` — `0xd1a72bd052e0d65b7c26d3dd97a98b74acbbb6c5`
- `PermissionedPool` — `0x09134c643a6b95d342bdaf081fa473338f066572`
- `SDCollateral` — `0x7af4730cc8ebad1a050dcad5c03c33d2793ee91f`
- `CommunityMultisig (6-of-9)` — `0x45b977cecb9dfaa17dfcba88826ef684b8489ff6`
- `ManagerMultisig (3-of-5)` — `0xaafb31780e4b9c95bc920e388f4925a874cd07af`
- `ProxyAdmin` — `0x67b12264ca3e0037fc7e22f2457b42643a04c86e`
- `Timelock (7-day)` — `0x1112d5c55670cb5144bf36114c20a122908068b9`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| Upgraded (each of 8 proxies) | ContractUpgrade | ERROR | Proxy implementation upgraded |
| AdminChanged (each of 8 proxies) | AdminChange | ERROR | Proxy admin changed |
| OwnershipTransferred (ProxyAdmin) | AdminChange | ERROR | ProxyAdmin ownership transferred (controls upgrade authority for all proxies) |
| MinDelayChange (Timelock, decreased) | TimelockChange | ERROR | Timelock min delay decreased |
| MinDelayChange (Timelock, increased) | TimelockChange | WARNING | Timelock min delay increased |
| CallScheduled (Timelock) | TimelockChange | WARNING | Timelock call scheduled |
| CallExecuted (Timelock) | TimelockChange | INFO | Timelock call executed |
| Cancelled (Timelock) | TimelockChange | INFO | Timelock call cancelled |
| RoleGranted (Timelock) | RoleChange | WARNING | Timelock role granted |
| RoleRevoked (Timelock) | RoleChange | WARNING | Timelock role revoked |
| RoleAdminChanged (Timelock) | RoleChange | ERROR | Timelock role admin changed |
| AddedOwner (Safe) | MultisigChange | WARNING | Multisig owner added |
| RemovedOwner (Safe) | MultisigChange | WARNING | Multisig owner removed |
| ChangedThreshold (Safe) | MultisigChange | WARNING | Multisig threshold changed |
| EnabledModule (Safe) | MultisigChange | WARNING | Multisig module enabled |
| DisabledModule (Safe) | MultisigChange | WARNING | Multisig module disabled |
| ChangedGuard (Safe) | MultisigChange | WARNING | Multisig guard changed |
| ChangedFallbackHandler (Safe) | MultisigChange | WARNING | Multisig fallback handler changed |
| RoleGranted (StaderConfig) | RoleChange | WARNING | StaderConfig role granted |
| RoleRevoked (StaderConfig) | RoleChange | WARNING | StaderConfig role revoked |
| RoleAdminChanged (StaderConfig) | RoleChange | ERROR | StaderConfig role admin changed |
| SetAccount | AdminChange | WARNING | StaderConfig account address rotated |
| SetContract | ContractUpgrade | ERROR | StaderConfig contract address rotated (upgrade-by-pointer) |
| SetToken | ContractUpgrade | ERROR | StaderConfig token address rotated |
| SetConstant | ProtocolParameterChange | WARNING | StaderConfig constant updated |
| SetVariable | ProtocolParameterChange | WARNING | StaderConfig variable updated |
| RoleGranted (ETHx) | RoleChange | WARNING | ETHx role granted |
| RoleRevoked (ETHx) | RoleChange | WARNING | ETHx role revoked |
| RoleAdminChanged (ETHx) | RoleChange | ERROR | ETHx role admin changed |
| Paused (ETHx) | EmergencyAction | CRITICAL | ETHx token paused (mints/burns/transfers halted) |
| Unpaused (ETHx) | EmergencyAction | WARNING | ETHx token unpaused |
| RoleGranted (StakingPoolManager) | RoleChange | WARNING | StakingPoolManager role granted |
| RoleRevoked (StakingPoolManager) | RoleChange | WARNING | StakingPoolManager role revoked |
| RoleAdminChanged (StakingPoolManager) | RoleChange | ERROR | StakingPoolManager role admin changed |
| Paused (StakingPoolManager) | EmergencyAction | CRITICAL | StakingPoolManager paused (deposits halted) |
| Unpaused (StakingPoolManager) | EmergencyAction | WARNING | StakingPoolManager unpaused |
| UpdatedExcessETHDepositCoolDown | ProtocolParameterChange | INFO | StakingPoolManager excess ETH deposit cooldown updated |
| UpdatedStaderConfig (StakingPoolManager) | ContractUpgrade | ERROR | StakingPoolManager StaderConfig pointer rotated |
| RoleGranted (UserWithdrawalManager) | RoleChange | WARNING | UserWithdrawalManager role granted |
| RoleRevoked (UserWithdrawalManager) | RoleChange | WARNING | UserWithdrawalManager role revoked |
| RoleAdminChanged (UserWithdrawalManager) | RoleChange | ERROR | UserWithdrawalManager role admin changed |
| Paused (UserWithdrawalManager) | EmergencyAction | CRITICAL | UserWithdrawalManager paused (withdrawal requests halted) |
| Unpaused (UserWithdrawalManager) | EmergencyAction | WARNING | UserWithdrawalManager unpaused |
| UpdatedFinalizationBatchLimit | ProtocolParameterChange | INFO | Withdrawal finalization batch limit updated |
| UpdatedStaderConfig (UserWithdrawalManager) | ContractUpgrade | ERROR | UserWithdrawalManager StaderConfig pointer rotated |
| TrustedNodeAdded | MultisigChange | WARNING | Oracle TrustedNode added (Oracle multisig membership change) |
| TrustedNodeRemoved | MultisigChange | WARNING | Oracle TrustedNode removed (Oracle multisig membership change) |
| TrustedNodeChangeCoolingPeriodUpdated | ProtocolParameterChange | INFO | Oracle TrustedNode change cooling period updated |
| SafeModeEnabled | EmergencyAction | CRITICAL | Oracle Safe Mode enabled (withdrawals disabled) |
| SafeModeDisabled | EmergencyAction | WARNING | Oracle Safe Mode disabled |
| Paused (Oracle) | EmergencyAction | CRITICAL | Oracle paused |
| Unpaused (Oracle) | EmergencyAction | WARNING | Oracle unpaused |
| UpdatedERChangeLimit | ProtocolParameterChange | WARNING | Oracle exchange-rate change limit updated |
| UpdateFrequencyUpdated | ProtocolParameterChange | INFO | Oracle update frequency changed |
| ERDataSourceToggled | ProtocolParameterChange | WARNING | Oracle exchange-rate data source toggled (PoR-based) |
| ERInspectionModeActivated | EmergencyAction | WARNING | Oracle ER inspection mode activated |
| RoleGranted (Oracle) | RoleChange | WARNING | Oracle role granted |
| RoleRevoked (Oracle) | RoleChange | WARNING | Oracle role revoked |
| RoleAdminChanged (Oracle) | RoleChange | ERROR | Oracle role admin changed |
| UpdatedStaderConfig (Oracle) | ContractUpgrade | ERROR | Oracle StaderConfig pointer rotated |
| RoleGranted (PermissionlessPool) | RoleChange | WARNING | PermissionlessPool role granted |
| RoleRevoked (PermissionlessPool) | RoleChange | WARNING | PermissionlessPool role revoked |
| RoleAdminChanged (PermissionlessPool) | RoleChange | ERROR | PermissionlessPool role admin changed |
| UpdatedCommissionFees (PermissionlessPool) | ProtocolParameterChange | WARNING | Permissionless pool commission fees updated |
| UpdatedStaderConfig (PermissionlessPool) | ContractUpgrade | ERROR | PermissionlessPool StaderConfig pointer rotated |
| RoleGranted (PermissionedPool) | RoleChange | WARNING | PermissionedPool role granted |
| RoleRevoked (PermissionedPool) | RoleChange | WARNING | PermissionedPool role revoked |
| RoleAdminChanged (PermissionedPool) | RoleChange | ERROR | PermissionedPool role admin changed |
| UpdatedCommissionFees (PermissionedPool) | ProtocolParameterChange | WARNING | Permissioned pool commission fees updated |
| UpdatedStaderConfig (PermissionedPool) | ContractUpgrade | ERROR | PermissionedPool StaderConfig pointer rotated |
| RoleGranted (SDCollateral) | RoleChange | WARNING | SDCollateral role granted |
| RoleRevoked (SDCollateral) | RoleChange | WARNING | SDCollateral role revoked |
| RoleAdminChanged (SDCollateral) | RoleChange | ERROR | SDCollateral role admin changed |
| UpdatedPoolThreshold | ProtocolParameterChange | WARNING | SDCollateral pool threshold updated |
| SDSlashed | EmergencyAction | WARNING | SD operator collateral slashed |
| UpdatedStaderConfig (SDCollateral) | ContractUpgrade | ERROR | SDCollateral StaderConfig pointer rotated |
## StakeWise (`stakewise`)
- **Chain(s):** Ethereum
- **Products:** `oseth`, plus protocol-wide for Keeper/VaultsRegistry/Multisig governance contracts
- **Contracts monitored:**
- `OsToken (osETH)` — `0xf1C9acDc66974dFB6dEcB12aA385b9cD01190E38`
- `OsTokenVaultController` — `0x2A261e60FB14586B474C208b1B7AC6D0f5000306`
- `Keeper` — `0x6B5815467da09DaA7DC83Db21c9239d98Bb487b5`
- `VaultsRegistry` — `0x3a0008a588772446f6e656133C2D5029CC4FC20E`
- `OsTokenConfig` — `0x287d1e2A8dE183A8bf8f2b09Fa1340fBd766eb59`
- `OsTokenVaultEscrow` — `0x09e84205DF7c68907e619D07aFD90143c5763605`
- `OsTokenRedeemer` — `0xdF3123dD182b8d3e0266a2DC37eEb8366d149B5A`
- `StakeWise Multisig (4-of-7)` — `0x144a98cb1cdbb23610501fe6108858d9b7d24934`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| OwnershipTransferred (OsToken) | AdminChange | ERROR | osETH ownership transferred |
| OwnershipTransferStarted (OsToken) | AdminChange | WARNING | osETH ownership transfer started |
| ControllerUpdated (OsToken) | RoleChange | WARNING | osETH controller enabled/disabled (mint/burn authority) |
| OwnershipTransferred (OsTokenVaultController) | AdminChange | ERROR | OsTokenVaultController ownership transferred |
| OwnershipTransferStarted (OsTokenVaultController) | AdminChange | WARNING | OsTokenVaultController ownership transfer started |
| FeePercentUpdated (OsTokenVaultController) | ProtocolParameterChange | WARNING | osETH fee percent updated |
| CapacityUpdated (OsTokenVaultController) | ProtocolParameterChange | WARNING | osETH minting capacity updated |
| TreasuryUpdated (OsTokenVaultController) | ProtocolParameterChange | WARNING | osETH treasury address updated |
| KeeperUpdated (OsTokenVaultController) | ContractUpgrade | ERROR | Keeper address updated (critical infrastructure) |
| OwnershipTransferred (Keeper) | AdminChange | ERROR | Keeper ownership transferred |
| OwnershipTransferStarted (Keeper) | AdminChange | WARNING | Keeper ownership transfer started |
| OracleAdded (Keeper) | RoleChange | WARNING | Keeper oracle added |
| OracleRemoved (Keeper) | RoleChange | WARNING | Keeper oracle removed |
| RewardsMinOraclesUpdated (Keeper) | ProtocolParameterChange | WARNING | Rewards min oracles updated |
| ValidatorsMinOraclesUpdated (Keeper) | ProtocolParameterChange | WARNING | Validators min oracles updated |
| ConfigUpdated (Keeper) | ProtocolParameterChange | INFO | Keeper config updated (IPFS hash) |
| OwnershipTransferred (VaultsRegistry) | AdminChange | ERROR | VaultsRegistry ownership transferred |
| OwnershipTransferStarted (VaultsRegistry) | AdminChange | WARNING | VaultsRegistry ownership transfer started |
| VaultImplAdded (VaultsRegistry) | ContractUpgrade | WARNING | Vault implementation added |
| VaultImplRemoved (VaultsRegistry) | ContractUpgrade | WARNING | Vault implementation removed |
| FactoryAdded (VaultsRegistry) | ContractUpgrade | WARNING | Vault factory added |
| FactoryRemoved (VaultsRegistry) | ContractUpgrade | WARNING | Vault factory removed |
| VaultAdded (VaultsRegistry) | ContractUpgrade | INFO | New vault registered |
| OwnershipTransferred (OsTokenConfig) | AdminChange | ERROR | OsTokenConfig ownership transferred |
| OwnershipTransferStarted (OsTokenConfig) | AdminChange | WARNING | OsTokenConfig ownership transfer started |
| OsTokenConfigUpdated (OsTokenConfig) | ProtocolParameterChange | WARNING | LTV/liquidation threshold/bonus parameters updated |
| RedeemerUpdated (OsTokenConfig) | RoleChange | WARNING | Redeemer updated |
| OwnershipTransferred (OsTokenVaultEscrow) | AdminChange | ERROR | OsTokenVaultEscrow ownership transferred |
| OwnershipTransferStarted (OsTokenVaultEscrow) | AdminChange | WARNING | OsTokenVaultEscrow ownership transfer started |
| AuthenticatorUpdated (OsTokenVaultEscrow) | RoleChange | WARNING | Escrow authenticator updated |
| LiqConfigUpdated (OsTokenVaultEscrow) | ProtocolParameterChange | WARNING | Escrow liquidation config updated |
| OwnershipTransferred (OsTokenRedeemer) | AdminChange | ERROR | OsTokenRedeemer ownership transferred |
| OwnershipTransferStarted (OsTokenRedeemer) | AdminChange | WARNING | OsTokenRedeemer ownership transfer started |
| PositionsManagerUpdated (OsTokenRedeemer) | RoleChange | WARNING | Positions manager updated |
| AddedOwner (Multisig) | MultisigChange | WARNING | Multisig owner added |
| RemovedOwner (Multisig) | MultisigChange | WARNING | Multisig owner removed |
| ChangedThreshold (Multisig) | MultisigChange | WARNING | Multisig threshold changed |
| EnabledModule (Multisig) | MultisigChange | WARNING | Multisig module enabled |
| DisabledModule (Multisig) | MultisigChange | WARNING | Multisig module disabled |
| ChangedGuard (Multisig) | MultisigChange | WARNING | Multisig guard changed |
| ChangedFallbackHandler (Multisig) | MultisigChange | WARNING | Multisig fallback handler changed |
## USD.ai (`usdai`)
- **Chain(s):** Arbitrum One
- **Products:** `susdai`, `usdai`. sUSDai is the yield-bearing ERC-7540 vault and carries the credit exposure — it is the senior-tranche lender on the loan book. Governance, oracle, timelock, ProxyAdmin, Safe and bridge events are protocol-wide and apply to both products
- **Contracts monitored:** 28. The V2 lending stack replaced V1 on 2026-06-26; both generations are monitored, V1 so its remaining positions and history stay visible
- **Products** — `sUSDai Vault` `0x0b2b2b2076d95dda7817e785989fe353fe955ef9`, `USDai Token` `0x0a1a1a107e45b7ced86833863f482bc5f4ed82ef`
- **Lending stack (V2, live)** — `LoanRouter V2` `0x1c2ed170de32846316784c4fd58a5e3c7563e12f`, `DepositTimelock V2` `0x1d710cc0c435ba6e27abc82a51dfbca17c41fe3c`, `EscrowTimelock V2` `0x1e710cc0b64e1d7572d35e43ad261587789b6438`
- **Lending stack (V1, superseded)** — `LoanRouter V1` `0x0c2ed170f2bb1df1a44292ad621b577b3c9597d1`, `DepositTimelock V1` `0x0d710cc05f34d2ead9fba3c78d53d76a0623c9f8`
- **Yield** — `BaseYieldEscrow` `0x9ddfd49ac4689cf894203794d792dcb38e4b1a9e`
- **Pricing** — `Price Oracle` `0xd40a5298c6fced81eb5da8bb1f9328b16f741ebc`
- **Governance** — `Chip Governor` `0x0ddc1dd03c58e425f96567679b52f349db847b26`, `CHIP Token` `0x0c1c1c109fe34733fca54b82d7b46b75cfb71f6e`, `Governance Timelock` `0x0eec1ee03add82342a6ac68a9c5cf62cb2398221`, `Upgrade Timelock` `0x0eea1ee08611ff4a4e83bfe3916712751995639b`
- **Cross-chain** — `BridgeAdapter (LayerZero OFT)` `0xffb20098fd7b8e84762eea4609f299d101427f24` (immutable, not a proxy)
- **Nine ProxyAdmins** — sUSDai `0x0b3296b6f50611b28d466a6d5a49754dad4d8d9f`, USDai `0x2ddf39c731377adcfa7f2a056ac60a8a81aadc3c`, CHIP `0xaa93f045b057ac64f79ae3f7d115cd3880e854d9`, LoanRouter V1 `0xf53ae82727d40fefbf6088212e1fd7354a63b212`, LoanRouter V2 `0x506e15026a449103ca35616712c3434b2834ce35`, DepositTimelock V1 `0x86d266c383437e496c2972a02e379d7457688f15`, DepositTimelock V2 `0xfb7f94c6c3a3513d4da19a35d4711500bea19cbd`, EscrowTimelock V2 `0x8701a738af540d6115ea7262098c66fb8ce8f54f`, BaseYieldEscrow `0xbbc62c75b72b233aa8d878adc4530bc495d055a3`. **The owner of each decides whether an upgrade is delayed at all** — three (sUSDai, USDai, CHIP) are owned by the Upgrade Timelock; the six on the lending stack are owned directly by a 3-of-3 Safe with no delay
- **Five Safes** — STRATEGY_ADMIN (3-of-4) `0xe7e53f940f8242fec57cbe88054463d4944b3670`, DEFAULT_ADMIN (3-of-3) `0x5f0bc72fb5952b2f3f2e11404398ed507b25841f`, upgrade-executor (3-of-3) `0x783b08aa21de056717173f72e04be0e91328a07b`, PAUSE_ADMIN (2-of-3) `0x3a32e198cafeb0fcd061ac0c9d8a2256bccab872`, ORIGINATOR (3-of-4) `0x844bb7b6223f6af028189bb34d6341a5733d6286`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| Upgraded (any of the nine proxies) | ContractUpgrade | ERROR | The implementation behind a proxy is replaced while funds and storage stay in the unchanged proxy. Every upgrade pages so it can be matched to a known change. The alert also reports the **previous** implementation and the **upgrade path** — both read from chain state at the block of the upgrade itself, not at alert time, because six of the nine ProxyAdmins are owned directly by a Safe with no delay, and ownership has moved twice. A backfilled 2025 upgrade must not be described using today's ownership. |
| Initialized (version 1) | ContractUpgrade | INFO | An upgradeable contract cannot use a constructor, so OpenZeppelin replaces it with a one-shot `initialize()`. Version 1 is that first call, emitted inside the contract's own deployment transaction, when there is no prior state, no users and no funds. It means "this contract now exists" and is recorded for completeness only. |
| Initialized (version > 1) | ContractUpgrade | ERROR | A **reinitializer** — an upgrade shipped code that rewrote live storage on a contract that already holds state and user funds. Unlike an implementation swap this is not undoable by a further upgrade, because rolling back the code does not roll back the storage. Three have occurred; one of them ran with no accompanying `Upgraded` in the same transaction, i.e. live storage mutated outside an upgrade window, which is exactly why this is separated from the genesis case rather than blended with it. |
| AdminChanged (any proxy) | AdminChange | ERROR | The ProxyAdmin registered against a proxy is replaced — a change to *who may upgrade this contract at all*. A root-of-trust change, so it always pages. |
| OwnershipTransferred (any of the nine ProxyAdmins) | AdminChange | CRITICAL | Ownership of a ProxyAdmin moves. Its owner is the single key that can replace the implementation of the contract behind it — for the sUSDai and USDai ProxyAdmins that means the code custodying every depositor's funds. Legitimate transfers happen only during a governance migration, so any other occurrence is a top-urgency, funds-at-risk event. |
| OwnershipTransferred (BridgeAdapter) | AdminChange | CRITICAL | Ownership of the LayerZero OFT adapter moves. The owner sets which remote chains and addresses are trusted peers, so control of it is control of cross-chain USDai minting. The adapter is immutable — it has no ProxyAdmin — making ownership its only lever, and therefore total. |
| RoleGranted / RoleRevoked (`DEFAULT_ADMIN_ROLE` or `BLACKLIST_ADMIN_ROLE`) | RoleChange | ERROR | The two sweeping roles. `DEFAULT_ADMIN_ROLE` is the root key that administers every other role on that contract. `BLACKLIST_ADMIN_ROLE` gates `setBlacklist` on the USDai token and **has never been held by anyone** — so a grant is the only advance warning that USDai has gained a working censorship power. Escalation keys off the role, never off which contract emitted it. |
| RoleGranted / RoleRevoked (any other role) | RoleChange | WARNING | A bounded operational role changes hands — strategy administration, pausing, liquidation, origination, deposit or escrow administration, or a timelock proposer/executor/canceller. Expected governance activity, recorded for visibility without paging. Seventeen role names are decoded; two hashes on this stack have never resolved to a preimage and are reported as raw `bytes32` rather than labelled speculatively. |
| RoleAdminChanged (any AccessControl contract) | RoleChange | ERROR | The rule for *who may grant or revoke* a role is rewired — a structural change to the access-control graph rather than to who holds a role. A privilege-escalation vector and not part of normal operations, so it always pages. |
| Paused (sUSDai, USDai, either LoanRouter) | EmergencyAction | CRITICAL | An emergency halt. On the vault it stops deposits and redemption-queue processing, so holders cannot exit; on the token it stops transfers; on a router it stops new origination. Whether protective incident response or hostile, it pages immediately. |
| Unpaused (sUSDai, USDai, either LoanRouter) | EmergencyAction | CRITICAL | The protocol is taken out of pause. Held at the same tier as the pause deliberately: on this stack an unpause is the moment user funds become movable again, and confirming *who* performed it matters as much as the halt itself. |
| BlacklistUpdated (USDai) | EmergencyAction | ERROR | An address is frozen or unfrozen on the USDai token. A `notBlacklisted` modifier reverts for frozen addresses and sUSDai gates withdraw, redeem and `setOperator` on it too, so a frozen holder cannot exit. Flat rather than conditional because the payload is an address and a boolean — the significance of the target is not knowable from it. **Structurally incomplete as a signal:** `isBlacklisted()` also falls through to native USDC's `isBlacklisted()` and USD₮0's `isBlocked()`, so USDai inherits Circle's and Tether's lists and those changes emit nothing here. sUSDai itself is hardcoded exempt and can never be frozen. |
| HookFailed (either LoanRouter) | EmergencyAction | CRITICAL | The router called sUSDai's loan-accounting hook, the call reverted, and the router **swallowed the error and continued**. Cash moved while the vault's view of its own loan state may not have updated — a silent accounting divergence between the two contracts that no other event reports. |
| TransferFailed (either LoanRouter) | EmergencyAction | CRITICAL | A transfer to its intended recipient failed and the funds were sent somewhere else instead. Money reaching an address other than the one the protocol selected is a direct funds-at-risk condition. |
| ERC20Rescued (LoanRouter V2) | EmergencyAction | ERROR | An admin sweeps an arbitrary ERC-20 balance out of the router to a chosen address. Intended for tokens sent by mistake, but it is a discretionary withdrawal path from a contract that handles loan cash, so every use pages for confirmation that it moved only stranded tokens. |
| LoanLiquidated (either LoanRouter) | EmergencyAction | CRITICAL | Collateral has been seized and the outcome is not yet known — the time-sensitive moment in a default. The recovery figures arrive later in separate events. |
| LoanBreached (LoanRouter V2) | EmergencyAction | ERROR | A loan is declared in breach of its terms by a `LIQUIDATOR_ROLE` holder — the step before liquidation. An early warning on the vault's credit exposure. |
| LoanCollateralLiquidated (V1) / LiquidationProceedsDeposited (V2) | EmergencyAction | ERROR | Proceeds from liquidated collateral arrive, reporting the gross recovery, the liquidation fee and any surplus. Deliberately one tier below `LoanLiquidated`, which already paged on the same default — paging twice on one event was rejected. The payload carries what was recovered but not what was owed, so a shortfall cannot be computed on chain and no conditional is possible. |
| LenderLiquidationRepaid (either LoanRouter) | EmergencyAction | ERROR | What one tranche actually got back after a liquidation. Since sUSDai is the senior-tranche lender, this is the vault's realised recovery. Flat for the same reason: the amount owed is absent from the payload. |
| LoanMigratedOut (V1) / LoanMigrated (V2) | ProtocolParameterChange | ERROR | A loan moves between router generations — the most directly readable signal that **the lending stack itself has changed**. The router address is an immutable constructor parameter, so a router swap otherwise surfaces only as an ordinary `Upgraded` on sUSDai and cannot be identified without decoding constructor arguments off chain. This event says it outright. All 17 occurrences fell inside one week during the June 2026 V1→V2 migration. |
| LoanOriginated (either LoanRouter) | ProtocolParameterChange | INFO | A new loan is written. The alert decodes the borrower, the currency, the collateral count and each tranche's principal and annualised rate, and reports the vault's own exposure aggregated across whichever tranches it holds. Routine business activity, so it is tracked rather than paged. |
| LoanRepaid (either LoanRouter, loan closure only) | ProtocolParameterChange | INFO | A loan is fully repaid and closed. The handler fires only on closure, not on each instalment — instalments are roughly 36× more frequent and carry no distinct risk signal. |
| LoanRefinanced (LoanRouter V2, both signatures) | ProtocolParameterChange | WARNING | Existing loan terms are replaced — rate, duration, tranches or collateral can all change, and cash may move in either direction. It rewrites an existing credit position rather than creating a new one, so it is surfaced for review without paging. Two signatures are monitored because a July 2026 upgrade changed the event's shape. |
| LenderPositionMinted / LenderPositionsBurned (either LoanRouter) | ProtocolParameterChange | INFO | The ERC-721 position tokens representing a lender's claim on a tranche are issued or retired. Bookkeeping that accompanies origination and closure, both of which carry their own entries. |
| FeePaid (LoanRouter V2) | ProtocolParameterChange | INFO | A fee is actually paid, naming which kind (origination, repayment, exit, liquidation or refinance) and the recipient. A record of money moving under existing rules rather than a change to them, so it is tracked rather than paged. |
| LiquidationFeeRateSet (LoanRouter V1) | ProtocolParameterChange | WARNING | The liquidation fee *rate* changes — the share of liquidation proceeds the protocol keeps before the remainder reaches lenders. Unlike the fee payment above this is a rule change, and it affects what the vault recovers on every future default, so it is surfaced for review. It does not page: the rate is bounded and cannot reach funds directly. |
| FeeRecipientSet (LoanRouter V1) | ProtocolParameterChange | ERROR | The address that receives protocol fees is changed. Fee redirection is a value-diversion lever, and V2 has no equivalent setter event at all, so this is the only place a recipient change is observable on either router. |
| BaseYieldRateTiersSet (USDai) | ProtocolParameterChange | ERROR | **This event sets what USDai holders earn.** Accrual is principal × rate × elapsed time and the rate is an administratively chosen number, not a pass-through of the backing assets' actual performance — the spread between them is protocol margin or subsidy. The alert renders each tier's annualised rate rather than just counting tiers, because the base yield has already been cut from 4.5% to 2.0% and restored roughly a day later, and a tier count alone cannot distinguish that from a no-op reordering. It has fired three times in six months, so it cannot spam. |
| Withdrawn (BaseYieldEscrow) | ProtocolParameterChange | ERROR | Funds leave the reservoir that pays holder yield — the adverse direction, and it has never happened. Worth understanding alongside how the reservoir is filled: `setRateTiers` sets accrual independently of funding, so if top-ups stop or fall short the accrual keeps running and the escrow drains. |
| Deposited / Harvested (BaseYieldEscrow) | ProtocolParameterChange | INFO | The reservoir is topped up by the STRATEGY_ADMIN Safe, or drawn down by the USDai token to pay accrued yield. Notable as a structural fact rather than a per-event risk: deposits are round numbers chosen by hand while harvests are exact and rate-driven, i.e. **the base yield is manually funded, and two independent quantities are kept in line by discretionary transfers**. |
| BaseYieldDeposited / BaseYieldHarvested / AdminFeeWithdrawn (sUSDai) | ProtocolParameterChange | INFO | Yield credited to the vault, drawn from it, or the admin fee taken from it. The alert reports the admin fee as a share of the gross amount. Base yield arrives in discrete lumps rather than continuously, so the vault's exchange rate steps up in jumps at these moments. |
| Harvested / BaseTokenConverted (USDai) | ProtocolParameterChange | INFO | Yield pulled into the token to accrue to holders, or a backing asset converted between forms. Routine operational activity. |
| SupplyCapSet (USDai) | ProtocolParameterChange | WARNING | The ceiling on total USDai supply changes. It limits new minting only and never affects existing holders, so it is surfaced without paging. |
| TokenPriceFeedAdded / TokenPriceFeedRemoved (Price Oracle) | ProtocolParameterChange | ERROR | The feed mapping that converts a deposit into a mint amount is edited. Whoever controls it controls the mint rate — repoint USDC's feed at $2 and every depositor mints double. A single call takes arrays and can rewrite several feeds at once. Also worth knowing what this oracle does *not* cover: `price(wM)` reverts and wM is unsupported, despite wM being roughly 73% of USDai's deposits — so the dominant backing asset is not priced by this contract at all. |
| CallScheduled (either Timelock) | TimelockChange | ERROR | A privileged call is queued behind a delay. This is the **only pre-warning** in the system — it arrives while there is still time to inspect the call and act before it executes. |
| CallExecuted (either Timelock) | TimelockChange | ERROR | A queued call runs. It pages independently of the target's own events because a timelock can act on contracts whose events are not monitored, making this the backstop for anything the per-contract handlers would miss. |
| Cancelled (either Timelock) | TimelockChange | WARNING | A queued operation is withdrawn before execution — a veto. Recorded for the audit trail; the interesting case is a cancellation that reveals an abandoned plan, which the scheduled call already reported. |
| MinDelayChange (either Timelock, delay decreased) | TimelockChange | ERROR | The enforced waiting period is **shortened**, directly weakening the guarantee that a change can be reviewed before it takes effect. The conditional is exact — both the old and new durations are in the payload. |
| MinDelayChange (either Timelock, delay increased) | TimelockChange | WARNING | The waiting period is lengthened, strengthening the guarantee. Recorded without paging. Note the Upgrade Timelock's delay has already moved twice (from none, to 24 hours, to 48 hours), which is why no alert on this protocol states a delay as a fixed value — the delay in force is read from chain at the block of each event. |
| TimelockChange (Chip Governor) | TimelockChange | ERROR | The governor is repointed at a different timelock. This bypasses the delay itself rather than transferring a role, so it pages. |
| ProposalGuardianSet (Chip Governor) | AdminChange | ERROR | Sets the account that can cancel proposals outside the normal rules. It is currently unset, so a first assignment creates a veto power that did not previously exist. |
| ProposalQueued / ProposalExecuted (Chip Governor) | ProtocolParameterChange | ERROR | A governance proposal reaches the timelock, or executes. **The Chip Governor has never been used** — zero proposals, zero votes, and every one of its six on-chain events to date is configuration from a single block. A first proposal is therefore a genuinely novel event on this protocol. |
| ProposalCreated (Chip Governor) | ProtocolParameterChange | WARNING | A proposal is filed. Surfaced early so the queued and executed stages are not the first anyone hears of it. |
| VotingDelaySet / VotingPeriodSet / ProposalThresholdSet / QuorumNumeratorUpdated | ProtocolParameterChange | WARNING | The rules of governance itself — how long before voting opens, how long it runs, how much voting power is needed to propose, and what quorum applies. Bounded parameters, but they determine who can pass a proposal, so each is surfaced. |
| LateQuorumVoteExtensionSet / ProposalCanceled / ProposalExtended | ProtocolParameterChange | INFO | Lower-impact governance mechanics: the late-quorum extension window, a withdrawn proposal, and a vote extended because quorum arrived late. Recorded for completeness. |
| DelegateVotesChanged (CHIP, crossing the proposal threshold) | ProtocolParameterChange | WARNING | A delegate's voting power crosses the threshold needed to file a proposal, in either direction. Deliberately edge-triggered on the crossing rather than level-triggered on the value: the event re-fires on every transfer in or out of a delegating holder, so a level test would re-alert indefinitely once any delegate sat above the line. This is the tripwire for governance becoming usable at all — total delegated voting power is currently a tiny fraction of the threshold. |
| DelegateChanged (CHIP) | ProtocolParameterChange | INFO | A holder points their voting power at a different delegate. Ordinary token activity; the threshold crossing above is the signal that matters. |
| ChangedThreshold (any Safe) | MultisigChange | CRITICAL | The number of signatures a Safe requires changes. Lowering it directly weakens every privilege that Safe holds — and these Safes hold root administration, pausing, origination and direct ownership of six ProxyAdmins. |
| EnabledModule (any Safe) | MultisigChange | CRITICAL | A module is enabled on a Safe. **A module can execute transactions on the Safe's behalf without collecting any signatures**, so enabling one creates a parallel authority path that bypasses the threshold entirely. |
| ChangedMasterCopy (any Safe) | MultisigChange | CRITICAL | The Safe's own implementation is swapped — the multisig equivalent of a proxy upgrade, replacing the code that enforces signature checking. Emitted by Safe 1.1.1 and seen once per Safe at creation. |
| AddedOwner / RemovedOwner / DisabledModule / ChangedGuard / ChangedFallbackHandler | MultisigChange | ERROR | Signer membership changes, or a module, guard or fallback handler is altered. Each changes who or what can act through the Safe, or removes a check on it, so each pages one tier below the threshold and module-enable cases. |
| ExecutionFromModuleSuccess / ExecutionFromModuleFailure (any Safe) | MultisigChange | ERROR | A transaction is executed through the module path rather than by collecting signatures. Zodiac Delay modules are enabled on three of the five Safes, but **not one transaction has ever been routed through a module** and every module's queue is empty — so a first occurrence means a dormant bypass has been activated. |
| ExecutionFailure (any Safe) | MultisigChange | WARNING | A Safe transaction was authorised by its signers but reverted on execution. Usually operational, but a failed privileged action is worth seeing. |
| SafeSetup (any Safe) | MultisigChange | INFO | A Safe's creation, carrying its initial owner set and threshold. This is the **only** place a Safe's starting threshold is emitted — `ChangedThreshold` never fires for it — which is why one Safe's 2-of-3 configuration was previously invisible to monitoring. |
| SwapAdapterAdded / SwapAdapterRemoved (DepositTimelock V1) | ProtocolParameterChange | WARNING | The set of whitelisted swap adapters changes. An adapter sits in the path deposits take, so which contracts are trusted there is a meaningful configuration change. |
| PeerSet (BridgeAdapter) | ProtocolParameterChange | ERROR | Sets which remote chain and address are trusted as the counterpart for cross-chain USDai. A wrong or hostile peer is a direct path to unbacked minting, so every change pages. |
| RateLimitsChanged / MsgInspectorSet / PreCrimeSet (BridgeAdapter) | ProtocolParameterChange | WARNING | The bridge's throughput caps and its optional message-inspection and pre-crime hooks change. These are the containment controls around cross-chain flow — relaxing them widens the blast radius of a bridge failure without being an exploit itself. |
| EnforcedOptionSet (BridgeAdapter) | ProtocolParameterChange | INFO | LayerZero execution options (gas limits and similar) for a destination are set. Message-delivery plumbing with no bearing on custody or authority. |
| RedemptionsServiced (sUSDai) | ProtocolParameterChange | INFO | The `STRATEGY_ADMIN` role services the redemption queue. Holders cannot force their own exit, so this is the mechanism by which withdrawals actually complete; the per-request timing is tracked as a metric rather than paged. |
| LoanTimelockDeposited / LoanDepositTimelockDeposited / LoanEscrowTimelockDeposited / LoanEscrowTimelockWithdrawn / LoanRepaymentDeposited / PoolDeposited (sUSDai) | ProtocolParameterChange | INFO | Vault capital being committed to, or returned from, the deposit and escrow timelocks on its way into and out of the loan book. Where a rate is present the alert reports it annualised. Routine capital movement. |
| LoanTimelockCancelled / LoanDepositTimelockCancelled / LoanEscrowTimelockCancelled (sUSDai) | ProtocolParameterChange | WARNING | A queued deployment of vault capital is cancelled before it lands. The cancellation is the more informative half of the pair — it means an intended allocation was called off. |
| Migrated (sUSDai, USDai) | ProtocolParameterChange | WARNING | An admin-gated settings migration runs on the vault or the token. It rewrites configuration outside the normal parameter setters, so each occurrence is surfaced for review. |
## Valantis — stHYPE (`valantis`)
- **Chain(s):** HyperEVM
- **Products:** `sthype`
- **Contracts monitored:**
- `Overseer` — `0xB96f07367e69e86d6e9C3F29215885104813eeAE`
- `stHYPE Token` — `0xffaa4a3d97fe9107cef8a3f48c069f577ff76cc1`
- `wstHYPE Token` — `0x94e8396e0869c9F2200760aF0621aFd240E1CF38`
- **Events monitored:**
| On-chain trigger | Incident type | Severity | What it means |
|---|---|---|---|
| ProtocolFeeSet (Overseer) | ProtocolParameterChange | INFO | Protocol fee changed |
| RoleGranted (Overseer) | RoleChange | WARNING | Role granted |
| RoleRevoked (Overseer) | RoleChange | WARNING | Role revoked |
| RoleAdminChanged (Overseer) | RoleChange | ERROR | Role admin changed |
| DefaultAdminTransferScheduled (Overseer) | AdminChange | WARNING | Admin transfer scheduled |
| DefaultAdminTransferCanceled (Overseer) | AdminChange | INFO | Admin transfer canceled |
| DefaultAdminDelayChangeScheduled (Overseer) | TimelockChange | WARNING | Admin delay change scheduled |
| DefaultAdminDelayChangeCanceled (Overseer) | TimelockChange | INFO | Admin delay change cancelled |
| AprThresholdSet (Overseer) | ProtocolParameterChange | INFO | APR threshold set |
| SlashThresholdSet (Overseer) | ProtocolParameterChange | INFO | Slash threshold set |
| SyncIntervalSet (Overseer) | ProtocolParameterChange | INFO | Sync interval set |
| Upgraded (stHYPE Token) | ContractUpgrade | ERROR | stHYPE token contract upgraded |
| AdminChanged (stHYPE Token) | AdminChange | ERROR | stHYPE token proxy admin changed |
| RoleGranted (stHYPE Token) | RoleChange | WARNING | Token role granted |
| RoleRevoked (stHYPE Token) | RoleChange | WARNING | Token role revoked |
| RoleAdminChanged (stHYPE Token) | RoleChange | ERROR | Token role admin changed |
| DefaultAdminTransferScheduled (stHYPE Token) | AdminChange | WARNING | Token admin transfer scheduled |
| DefaultAdminTransferCanceled (stHYPE Token) | AdminChange | INFO | Token admin transfer canceled |
| DefaultAdminDelayChangeScheduled (stHYPE Token) | TimelockChange | WARNING | Token admin delay change scheduled |
| DefaultAdminDelayChangeCanceled (stHYPE Token) | TimelockChange | INFO | Admin delay change cancelled |
| Upgraded (wstHYPE Token) | ContractUpgrade | ERROR | wstHYPE token contract upgraded |
| AdminChanged (wstHYPE Token) | AdminChange | ERROR | wstHYPE token proxy admin changed |
| RoleGranted (wstHYPE Token) | RoleChange | WARNING | wstHYPE role granted |
| RoleRevoked (wstHYPE Token) | RoleChange | WARNING | wstHYPE role revoked |
| RoleAdminChanged (wstHYPE Token) | RoleChange | ERROR | wstHYPE role admin changed |
| DefaultAdminTransferScheduled (wstHYPE Token) | AdminChange | WARNING | wstHYPE admin transfer scheduled |
| DefaultAdminTransferCanceled (wstHYPE Token) | AdminChange | INFO | wstHYPE admin transfer canceled |
| DefaultAdminDelayChangeScheduled (wstHYPE Token) | TimelockChange | WARNING | wstHYPE admin delay change scheduled |
| DefaultAdminDelayChangeCanceled (wstHYPE Token) | TimelockChange | INFO | wstHYPE admin delay change cancelled |
## List DeFi Chains
Source: https://docs.stakingrewards.com/ratings-api/endpoints/defi/listDefiChains
Returns the list of blockchains available in DeFi ratings. Use the returned `slug` values as the `chain` filter parameter in `GET /ratings/defi` and `GET /ratings/defi/{provider-slug}`.
Endpoint: `GET /ratings/defi/chains`
## List DeFi Ratings
Source: https://docs.stakingrewards.com/ratings-api/endpoints/defi/listDefiRatings
Returns a paginated list of all DeFi product ratings across all platforms. Supports filtering by type, chain, TVL, APY, user count, date ranges, and version, as well as sorting and pagination.
Endpoint: `GET /ratings/defi`
## List DeFi Platform Ratings
Source: https://docs.stakingrewards.com/ratings-api/endpoints/defi/listDefiPlatformRatings
Returns a paginated list of DeFi product ratings for a specific platform identified by its slug. Supports the same filtering, sorting, and pagination options as the global DeFi listing.
Endpoint: `GET /ratings/defi/{provider_slug}`
## Get DeFi Product Rating
Source: https://docs.stakingrewards.com/ratings-api/endpoints/defi/getDefiProductRating
Returns the rating for a specific DeFi product identified by its platform slug and product identifier.
Endpoint: `GET /ratings/defi/{provider_slug}/{contract_address}`
## List DeFi Alerts
Source: https://docs.stakingrewards.com/ratings-api/endpoints/defi/listDefiAlerts
Returns a paginated list of on-chain DeFi rating alerts across all tracked protocols, ordered by the time the incident occurred on-chain (most recent first). Supports filtering by protocol, product, contract address, severity, and chain.
Endpoint: `GET /ratings/defi/alerts`
## List Infrastructure Ratings
Source: https://docs.stakingrewards.com/ratings-api/endpoints/infrastructure/listInfraRatings
Returns a paginated list of infrastructure provider ratings. Supports filtering by rating grade, date ranges, and version, as well as sorting and pagination.
Endpoint: `GET /ratings/infra`
## Get Infrastructure Rating
Source: https://docs.stakingrewards.com/ratings-api/endpoints/infrastructure/getInfraRating
Returns the rating for a specific infrastructure provider identified by its slug.
Endpoint: `GET /ratings/infra/{slug}`
---
# Manage Subscription
## Subscription Plans
Source: https://docs.stakingrewards.com/billing/subscription-plans
## Plans & Pricing
The Staking Data API offers four subscription tiers designed for different usage levels. Each credit is roughly equivalent to 1 data point. Requests are blocked upon reaching monthly quotas.
| Plan | Monthly Cost | Annual Credits |
|------|--------------|----------------|
| Standard | €166 | 1.5M |
| Advanced | €333 | 10M |
| Professional | €666 | 50M |
| Enterprise | Custom | Custom |
### Plan Details
**Standard:** Entry-level option providing 1.5M request credits per month at €166 monthly (billed annually).
**Advanced:** Mid-range offering at €333 per month (annual billing) with 10 million monthly credits.
**Professional:** Higher-capacity plan at €666 monthly (annual billing) supporting 50 million monthly credits.
**Enterprise:** Customized solution with pricing negotiated directly. Contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) for more information.
All standard plans require annual billing commitments. Credits represent individual data points from staking networks and provider benchmarks.
### Enterprise Inquiries
For custom enterprise solutions, contact us at [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) or via Telegram [@berlincrypto](https://t.me/berlincrypto).
## Credits & Limits
Source: https://docs.stakingrewards.com/billing/credits-and-limits
## Rate Limits
The API enforces a limit of **60 requests per minute** per API Key.
## Credit Calculation
Each credit represents approximately one data point. The system measures resource consumption based on query complexity and data returned.
### Credit Consumption Formula
The core calculation involves three components:
1. **Field Count:** Total number of fields requested in the GraphQL query
2. **Response Entries:** Number of records returned
3. **Total Calculation:** `(Fields × Entries) + Fields = Credits Consumed`
### Per-Field Credit Rates
Not all fields cost the same. The credit rate depends on which entity the field belongs to:
| Entity | Credits per datapoint |
|--------|----------------------|
| `metrics` | **3 credits** |
| All other entities | 1 credit |
Fields under a `metrics` node — such as `metricKey`, `defaultValue`, `value`, or `createdAt` — cost 3 credits per leaf scalar, both in the query fields counted and in the response data returned.
### Example
Querying 1 non-metrics field and 2 metrics fields across 100 assets:
```
Non-metrics: (1 field × 100 entries) + 1 = 101 credits
Metrics: (2 fields × 100 entries) + 2 = 202 credits × 3 = 606 credits
Total: 707 credits
```
Credits are based on **actual data returned**, not theoretical maximums. If only 50 assets exist instead of 100, actual consumption is lower.
## Nested Query Complexity
For queries with nested fields, credits accumulate at each level. Parent and child field counts are multiplied by their respective entry counts, then summed together with total unique fields in the query.
## Historical Data Surcharge
Historical data queries incur a flat **5,000-credit surcharge** on top of the normal per-field cost. This reflects the higher value of historical data.
The following fields are **not available** for historical data queries: `changePercentages`, `changeAbsolutes`. Requesting, filtering, or ordering by these fields in a historical query returns a 400 error.
## Tracking Credit Usage Per Request
Every successful GraphQL and Ratings API response includes an `X-Used-Credits` header showing the exact number of credits consumed by that request:
```
X-Used-Credits: 703
```
You can use this header to monitor consumption in real time, validate your credit estimates, and identify expensive queries before they impact your quota.
## Optimization Strategies
- Request only necessary fields to reduce per-query consumption
- Use specific filters (date ranges, metric keys) to limit returned data
- Structure queries to explicitly target needed datapoints rather than requesting broad results
## Update Subscription
Source: https://docs.stakingrewards.com/billing/update-subscription
## Check Status
Use the status endpoint to retrieve your current subscription details and usage information.
### Endpoint
```
GET https://api.stakingrewards.com/public/billing/status
```
### Request
Include your API key in the request headers:
```bash title="Check subscription status"
curl -H "X-API-KEY: " https://api.stakingrewards.com/public/billing/status
```
### Response
```json title="Response"
{
"plan_name": "pro",
"available_credits": 95559803,
"monthly_quota": 100000000,
"subscribed_at": "2023-05-18T18:30:53.170577Z",
"requests_allowed": true,
"billing_date": "2023-06-18T18:30:53.172798Z"
}
```
### Response Fields
| Field | Description |
|-------|-------------|
| `plan_name` | Current subscription tier |
| `available_credits` | Remaining credits in account |
| `monthly_quota` | Total monthly credit allowance |
| `subscribed_at` | Subscription initiation timestamp |
| `requests_allowed` | Boolean indicating active status |
| `billing_date` | Next billing cycle date |
## Upgrade
To increase API credit limits, purchase another API Package that suits your needs by visiting our [API page](https://www.stakingrewards.com/data-api).
Complete the transaction using the same email address. Upon completion, a new API key corresponding to the upgraded package is issued, enabling immediate use of enhanced credit limits without service interruption.
### Custom Requirements
The platform accommodates specialized needs including high-volume data handling and custom rate limits. Organizations with unique requirements can explore tailored solutions by contacting us.
To discuss custom options, email [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com) or message [@berlincrypto](https://t.me/berlincrypto) on Telegram.
## Cancel Subscription
Source: https://docs.stakingrewards.com/billing/cancel-subscription
## Cancel
To discontinue your Staking Data API subscription, complete the cancellation form.
### Cancellation Form
[Submit Cancellation Request](https://share.hsforms.com/2LJ75L5e_Riyx3GRE1hH8jwsn3mf)
Let us know the reason for your cancellation—whether it's a feature gap, pricing, or any other concern. Your feedback helps shape future product improvements.
### Support Channels
If you have questions before canceling, reach out through:
- Email: [partnerships@stakingrewards.com](mailto:partnerships@stakingrewards.com)
- Telegram: [@berlincrypto](https://t.me/berlincrypto)
## API Key Management
Source: https://docs.stakingrewards.com/billing/api-keys/overview
Users on a paid plan can create multiple API keys that share a single billing pool. Each key can optionally have its own credit limit as a sub-cap within the plan quota.
All endpoints require authentication via an existing `X-API-Key` header.
**Base path:** `/public/billing/api-keys`
## Endpoints
- **List API Keys** — Returns all API keys for your account (active and revoked). The key value is masked.
- **Create API Key** — Creates a new key under the same billing subscription. The full key value is only returned once — save it.
- **Update API Key** — Updates the label, active status, or credit limit of a key. Revoked keys cannot be modified.
- **Revoke API Key** — Permanently revokes a key. Revoked keys stop working immediately and cannot be re-activated.
## Credit Limits and Quota
- The plan quota is shared across all keys on the account.
- Setting `credit_limit` on a key adds a secondary per-key cap. A request is rejected if either the plan quota or the key's credit limit is exhausted.
- Setting `credit_limit` to `null` makes the key share the full plan quota without restriction.
- The last active key on an account cannot be revoked.
## Get Billing Status
Source: https://docs.stakingrewards.com/billing/api-keys/getBillingStatus
Returns the current subscription status and usage information, including remaining credits, monthly quota, and next billing date.
Endpoint: `GET /public/billing/status`
## List API Keys
Source: https://docs.stakingrewards.com/billing/api-keys/listApiKeys
Returns all API keys for the authenticated user (active and revoked). The api_key value is masked in this response.
Endpoint: `GET /public/billing/api-keys`
## Create API Key
Source: https://docs.stakingrewards.com/billing/api-keys/createApiKey
Creates a new API key under the same billing subscription. The full api_key value is only returned in this response — save it now.
Endpoint: `POST /public/billing/api-keys`
## Update API Key
Source: https://docs.stakingrewards.com/billing/api-keys/updateApiKey
Updates the label, active status, or credit limit of an API key. All fields are optional. Revoked keys cannot be modified.
Endpoint: `PATCH /public/billing/api-keys/{id}`
## Revoke API Key
Source: https://docs.stakingrewards.com/billing/api-keys/revokeApiKey
Permanently revokes an API key. Revoked keys stop working immediately and cannot be re-activated. The last active key on an account cannot be revoked.
Endpoint: `DELETE /public/billing/api-keys/{id}`