yearn / yearn/monitoring

Bedrock uniBTC monitoring: Safe monitor + state polling (single-EOA mint path, supply feeder, PoR)

Open
#361 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Python
Stars
13
Forks
13
Avg merge
1d 9h
Merged PRs (30d)
19

Description

Add monitoring for Bedrock uniBTC (Ethereum) using the existing Safe monitor plus state polling only, with no event subscriptions. There is no coverage today.

Source: risk reassessment yearn/risk-score#468 (report, snapshot evidence). Baselines are from Ethereum block 25,981,132 (Sep 15, 2026).

Why

  • Single-EOA unbacked mint. EOA 0x3eea50ba10952e5e0dfaa50ecfcc5ab19ad591ef is the proxy admin of the legacy withdrawal router 0xbb45b3a09bffc15747d1a331775fa408e587f38d, which holds Vault OPERATOR_ROLE.
    • By upgrading the router, the EOA can call Vault.executeuniBTC.mint for any amount, with no reserve check.
    • An anvil fork confirmed it: 100,000 uniBTC minted, about 21 times the Chainlink reserves.
  • EOA roles outside the Safes. The EOAs below can change the reserve gate, the supply feeder and CCIP limits without any Safe transaction.
  • Unreliable supply feeder. The manually written supply value is 700.93 uniBTC (15.42%) below Bedrock's dashboard, and has been since Sep 13.

1. Safe monitor: add two Safes to protocols/safe/addresses.py

Safe Address What its queued transactions reveal
uniBTC ops Safe (3/5) 0xC9dA980fFABbE2bbe15d4734FDae5761B86b5Fc3 ProxyAdmin upgrades (token, Vault, CCIPPeer, live router, asset feeder, directBTC) and ProxyAdmin ownership; uniBTC token MINTER_ROLE / DEFAULT_ADMIN_ROLE / FREEZER_ROLE grants; token freezes (freezeUsers, setFreezeToRecipient, which emit no events); Vault admin (operator grants/revokes, allowed targets/tokens, caps); live router fees, delays, quotas and blacklist; owner/threshold changes
Bedrock admin Safe (3/5) 0xAeE017052DF6Ac002647229D58B786E380B9721A CCIP pool owner actions (lanes, remote pools, registry administrator); BurnProxy / TransferProxy use (moving Vault assets to the ops Safe); CCIPPeer and directBTC admin; owner/threshold changes

2. Polling script (hourly unless noted), for what the Safe monitor cannot see

Severity Check Call Baseline Alert when
CRITICAL Unexpected uniBTC minting uniBTC totalSupply() delta 2,981.12556288; 30-day mints were 3.07 uniBTC in total +10 uniBTC in 1h (CRITICAL); +2 uniBTC in 24h (HIGH)
CRITICAL Reserve gate changed by operational EOA (0x9251fd3d79522bb2243a58fff1db43e25a495aab, Vault MANAGER_ROLE) Vault adequacyRatio(), chainlinkReserveFeeder(), uniBTCSupplyFeeder(), feederHeartbeat() 900, 0xc590D9fb8eE78a0909dFF341ccf717000b7b7fF2, 0xE542919E4b281f10b437F947c8Ba224DdfaBc716, 86400 Any change
HIGH Vault stopped or paused (six pauser EOAs) Vault outOfService(), paused(); router 0xAA732c9c110A84d090a72da230eAe1E779f89246 paused() all false Any true
CRITICAL Reserves below supply PoR 0xc590D9fb8eE78a0909dFF341ccf717000b7b7fF2 latestRoundData().answer (18 dec) / reserve API data.total_supply 4,640.515623 / 4,546.67793 = 102.06% < 100% (CRITICAL), < 101% (HIGH)
HIGH PoR stale latestRoundData().updatedAt 38,534s old Older than 86,400s (Vault mint() reverts)
HIGH Supply feeder wrong or stale Feeder totalTokenSupply() (8 dec) vs API total_supply 3,845.74449304 vs 4,546.67793 (15.42% gap; firing since Sep 13) Gap > 2%; value unchanged for 48h (it normally changes daily)
HIGH Redemptions underfunded Router tokenDebts(WBTC) (totalDebts − totalCleared) vs WBTC balanceOf(Vault 0x047D41F2544B7F63A8e991aF2068a363d210d6Da) 0.75152598 vs 0.46065725 (includes requests still inside the 8-day delay) Uncleared > Vault WBTC for > 24h and growing
HIGH Peg CoinGecko universal-btc or other price provider in BTC 0.992417 < 0.98

Gaps accepted by skipping events

  • Lag: detection comes up to an hour after an EOA action or mint, not in real time.
  • No mint attribution: a supply jump shows that minting happened, not which minter did it. Check the transaction manually when the alert fires.
  • Safe transactions executed without being queued in the Safe tx service aren't seen beforehand; the implementation-slot and state polls only catch them afterwards. Role grants made that way (e.g., a new minter) show up only through the supply-delta check.

Checklist

  • Add both Safes to the Safe monitor
  • Hourly polling script (the CRITICAL/HIGH rows above), added to automation/jobs.yaml

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the existing Safe monitor and protocols/safe/addresses.py, then inspect automation/jobs.yaml and the repository’s current polling jobs. Add both listed Safes and implement the specified hourly state checks and thresholds without event subscriptions; done means the checklist is complete and all CRITICAL/HIGH conditions are covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devops, observability-sre
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.