Skip to main content

At 23:40 UTC on 30 September 2026, Lido’s governance forum published a thread titled “[Security Disclosure] MetaMask Staking Precautionary Out of Order Exits”. It is six short paragraphs. The most important sentence in it is five words long: “No action is required from stETH holders.”

That sentence is completely true. It is also true in a way almost nobody reads it. No action is required because no action is available. There is nothing a stETH holder can do, nothing they can opt out of, nothing they can accelerate, and no way for them to find out whether any of this touches them. The disclosure is not asking them to sit tight. It is telling them, politely, that they were never in the loop to begin with.

TL;DR

  • MetaMask Staking (formerly Consensys Staking) is exiting its Ethereum validators from Lido after “a security incident affecting part of our infrastructure”. It has not said what was compromised, how, or how much is involved.
  • We pulled all 11,213 of its signing keys from Lido’s on-chain registry and asked the beacon chain about each one: 6,906 validators are active_exiting and zero remain active_ongoing. That is 220,992 ETH, roughly $593m, and 2.245% of everything Lido holds.
  • The last exit epoch is 480,501, or 01:26 UTC on 7 October 2026, matching Lido’s stated deadline to the hour. You can verify that without trusting either party.
  • “Non-custodial” is a claim about where your money can go, not about when it moves. The Ethereum spec checks a voluntary exit against the validator’s signing key, and the withdrawal credential appears nowhere in that check. MetaMask holds the first key and told you about the second.
  • In 768 separate epochs these validators occupy all 8 exit slots Ethereum allows anybody. The cost lands on every stETH holder as a number that quietly fails to climb.

What was actually said, and what was not

MetaMask’s own statement, posted to X, reads in full: “Security Update: We are responding to a security incident affecting part of our infrastructure. At this time, we have identified no immediate threat to MetaMask wallets. As a precaution, we are proactively exiting affected validators within our non-custodial staking operations, in coordination with clients, partners and security advisors.”

Lido’s forum thread adds the operational detail: “Following an investigation into an infrastructure compromise, MetaMask Staking (ex Consensys Staking) has taken precautionary steps to protect client assets related to its operated Ethereum validators. These steps include exiting its Ethereum (ETH) validators in the Lido protocol, and will likely incur foregone rewards as well as possible downtime penalties should validators be taken offline in the near future to reduce risks related to potential network penalties.”

Then the timeline: “the final validators expected to be exited (but not fully withdrawn) by the end of October 7th, 2026”, with the ETH returning “gradually”, a cycle “estimated to take approximately up to 45 days due to the extended entry queue”. Lido notes its “ad hoc reserve fund (of over 6,750 stETH)” as a cushion.

What is absent is the entire causal story. Not what system was compromised. Not how. Not when it started, or when it was found, or by whom. Not how many validators. Not how much ETH. The word “affected” is doing enormous unexamined work. To be fair, this is roughly what competent incident response looks like while an investigation is live, and exiting beats carrying on signing. Nothing here is a scandal. The interesting part is not that they withheld the reason, but what the chain will and will not tell you in its place.

What the chain says instead

Lido’s curated node operator registry sits at 0x55032650b14df07b85bF18A3a3eC8E0Af2e028d5. Operator 21 is still listed on-chain under the name “Consensys”, which is a small reminder that rebrands are a marketing event and a registry entry is a fact. At Ethereum block 26,096,335 it reported 11,213 registered signing keys, all marked as used.

We fetched every one of those 11,213 public keys from the registry and asked a beacon node for their status at slot 15,335,026, epoch 479,219, which is 08:41:59 UTC on 1 October 2026. The results reconcile exactly:

  • 4,009 withdrawal_done, historic exits from previous years
  • 160 exited_unslashed, already gone as of this morning
  • 6,906 active_exiting, every one with an effective balance of exactly 32 ETH
  • 0 active_ongoing
  • 138 not on the beacon chain at all, still in the deposit queue waiting to be created

Read the last two lines together. There is no subset here. Every live validator this operator runs is on its way out, and 138 more, deposited between 25 August and 17 September, are still queued to be born into an operation that is being wound down.

The 6,906 exiting validators carry 220,992 ETH of effective balance and 221,027.41 ETH of actual balance. Against Lido’s getTotalPooledEther of 9,843,528.61 ETH, that is 2.245% of the protocol. At $2,683.51 per ETH it is roughly $593m. Their exit epochs run from 479,220 to 480,501, which is 08:48 UTC today through 01:26 UTC on 7 October. Lido said “by the end of October 7th”. The chain says 7 October at 01:26. The statement checks out, and checking it required nobody’s permission.

So the public record is complete on every question except the one that matters. You can count the validators, price them, timestamp their departure to the second, and confirm the press release against the ledger. You cannot learn why. The chain is an immaculate record of actions, and it has never recorded a single reason.

Non-custodial names the destination, not the moment

Both statements lean on the same reassurance. Lido’s version: “staking operations are non-custodial in nature and MetaMask does not manage withdrawal keys for staking on behalf of clients.”

This is verifiably true, and we verified it. Every one of those 11,075 validators carries the withdrawal credential 0x010000000000000000000000b9d7934878b5fb9610b3fe8a5e441e8fad7e293f. Not most of them. All of them, with no exceptions and no per-operator variation. Call getWithdrawalCredentials() on Lido’s StakingRouter and you get the same 32 bytes back. The ETH can only ever land in Lido’s withdrawal vault. MetaMask could not redirect a single gwei of it if it wanted to.

Now read the Ethereum consensus spec. Here is the heart of process_voluntary_exit, the function that removes a validator from the set, quoted from the Electra specification:

domain = compute_domain(DOMAIN_VOLUNTARY_EXIT, CAPELLA_FORK_VERSION, state.genesis_validators_root)
signing_root = compute_signing_root(voluntary_exit, domain)
assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)

The signature is checked against validator.pubkey. That is the signing key, the one a node operator must hold to do its job at all. The string withdrawal_credentials does not appear anywhere in that function. It is not consulted, not compared, not required.

Which gives you the actual shape of the arrangement. There are two keys. One decides where your money ends up. The other decides when it moves. They are held by different parties, and the reassuring sentence in the disclosure is about the one MetaMask does not have.

Nobody is lying. “Non-custodial” bounds the worst case beautifully: no operator can steal this ETH. But a word that answers “can they take it” gets heard as “can they decide anything”, and those are different questions. One company just removed $593m of other people’s stake from the Ethereum validator set, unilaterally, on a timetable it set, for a reason it has not given, and every sentence it published about that was accurate.

One honest wrinkle, because it cuts against the clean version of this story: since Pectra, EIP-7002 lets the address in the withdrawal credential trigger an exit too, via process_withdrawal_request. So the signing key is no longer the only exit authority. It remains a fully sufficient one, and it is the one the operator holds.

Six days of Ethereum’s exit capacity

Here is the detail that did not make any of the coverage. Ethereum caps how fast validators may leave. Under Electra, get_activation_exit_churn_limit returns at most MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT, which is 256 ETH per epoch. At 32 ETH per validator, that is exactly 8 validators per epoch for the entire network.

We grouped the 6,906 exiting validators by their assigned exit epoch. They occupy 933 distinct epochs. In 768 of them, the count is exactly 8. Never nine. Never more.

That number is not a coincidence, and it is its own proof. If the churn limit were anything below 256 ETH we would see fewer than 8 per epoch, so the observation pins the limit at 256 without us having to look up Ethereum’s total staked balance anywhere. And it means that for 768 epochs spread over the next six days, this one operator consumes one hundred per cent of the exit capacity the Ethereum protocol makes available to anybody.

If you decided to unstake on Tuesday for reasons entirely your own, you are now queued behind 6,906 validators belonging to a company you have never dealt with, over an incident nobody has described. The churn limit is a commons. An emergency at one operator is a congestion event for everyone, and none of that shows up on your screen as anything but a longer wait.

The same cap governs the way back in, from a separate budget. We counted the entry queue straight from the beacon state: 20,911 pending deposits totalling 1,557,509 ETH. At 256 ETH per epoch and 225 epochs per day, that is 57,600 ETH of activation capacity daily, so the existing queue alone takes 27.04 days to clear, and 30.88 days once the returning 220,992 ETH joins the back of it. Lido’s “up to 45 days” is, if anything, slightly conservative. They published a number that survives derivation.

The bill nobody received

So who pays for the idle fortnight and a half?

We wrote yesterday about stETH being a derived quantity rather than a stored one: your balance is shares × totalPooledEther ÷ totalShares, recomputed on every oracle report. Today is what that machinery delivers.

Foregone rewards do not arrive as a charge. They arrive as a smaller numerator. totalPooledEther grows by slightly less than it would have, the share rate rises slightly more slowly, and every stETH balance in existence sits a hair below where it would otherwise have been. There is no transaction. There is no line item. There is no notification, because there is nothing to notify anyone about: nothing happened, slightly.

The magnitude is small and we will not inflate it. We derived Lido’s net APR ourselves from the share rate rather than taking a dashboard on faith: 1.245250558 stETH per share today, against the same call 30 days ago, annualises to 2.238%, with the 7-day and 90-day windows at 2.249% and 2.219%. Apply that to 220,992 idle ETH for 45 days and you get roughly 610 ETH of lost yield, about $1.64m, or 0.0062% of the pool. On a 10 stETH position that is 0.00062 stETH. Lido’s 6,750 stETH reserve is about eleven times the estimated damage, which is presumably why they mentioned it.

The magnitude is not the point. The delivery mechanism is. A cost created by one company’s undisclosed security failure is collected from every stETH holder alive, pro rata, automatically, with no bill, no consent step and no way to tell from your own balance that it happened. Everybody pays and nobody is charged. That is not fraud; it is the design working exactly as intended. It is simply a form of payment that cannot be refused, because it cannot be perceived.

This is where “no action is required” stops being reassurance and becomes a description. A pooled position makes you a creditor of an average. You hold a claim on an aggregate operated by 35 active companies you did not pick, in proportions you were not told, and when one of them has a bad week there is no position of yours to defend. You cannot even identify yourself as affected, because there is no mapping from your address to a validator. The affected cohort has no members. It only has a denominator.

What this means for anyone running games

Every pooled-prize product in crypto gaming has this exact structure and almost none of them admit it. A jackpot pool, a shared liquidity vault backing payouts, a staking pool whose yield funds the rake rebate: in all of them the player holds a claim on an aggregate rather than a position they can point at, and the operator’s bad day is socialised through the same silent channel. Meanwhile the fairness widget proves the draw and says nothing about who can move the collateral behind the prize, when they can move it, or what they owe you when they do. The committee that authors the number and the operator that holds the signing key both sit outside the proof, and the proof is loudest about the part that was never in doubt.

Where Satoshie actually stands

A Satoshie raffle escrows the stake in the contract at entry. The prize is not a share of a pool somebody else operates on your behalf; it is a specific balance held against a specific draw, with ticketsMinted readable before you buy, so your odds are arithmetic rather than a promise. Chainlink’s documentation is explicit about the draw: “For each request, Chainlink VRF generates one or more random values and cryptographic proof of how those values were determined. The proof is published and verified onchain before any consuming applications can use it.” Resolution and payout happen in one transaction, and there is no admin key over a draw in flight.

What that buys is not superior security. It is that there is no pool in which your loss can be averaged with a stranger’s: if a Satoshie draw goes wrong it goes wrong with that draw, visibly, to the people in it. As with leaving a payment channel, what matters is whether your claim is yours alone or a slice of somebody’s aggregate.

Three things we are not pretending about

One: this is a property of being small, not of being clever. We do not pool prizes because we do not run a product that needs pooled prizes. Lido pools because pooling is the entire proposition, and 9.8m ETH of demand says the proposition is sound. The day we ship a shared jackpot or a common liquidity backstop, every paragraph above applies to us, and we will owe the answers before taking an entry rather than after an incident.

Two: we have signing keys too. Not validator keys, but the deployer and operational keys that decide when a draw opens, when it closes, and when a VRF request goes out. Nothing in our architecture means we hold no discretionary timing authority. It means the discretion is exercised before entry rather than during the draw, and is readable in the contract rather than announced afterwards. That is a real difference, not the absence of a key.

Three: we have never published an incident disclosure. MetaMask and Lido got a statement out within hours, named the affected system boundary, gave a deadline the chain corroborates, and flagged the cost before anyone asked. That is better behaviour than most of this industry manages, including the half that would simply have gone quiet. We have not been tested on it, and a track record you have not been tested on is not a track record.

Three questions worth asking

Which key does your counterparty hold, and which one did they tell you about? “Non-custodial” is a true and narrow statement about destinations. Ask separately who can decide that your money moves, because that is usually a different party with a different key and no reason to raise it. As the forced exits on Hyperliquid showed, the question is never only who owns the position.

If you are in a pool, can you tell whether an incident touched you? If the answer involves anybody’s internal records, you hold a claim on an average, and your exposure to any single operator is a number you are not permitted to know.

How would a cost reach you, if one did? A charge you can see is a charge you can dispute. A rebase that grows by less than it should is the same money, collected in a form with no notification, no consent and no receipt. Decide which one you are signed up for before the week you find out.

The Lido thread is right that no action is required, and it is worth sitting with why. Over the next six days, 6,906 validators leave the Ethereum validator set for a reason nobody has given, a sum is quietly apportioned across every stETH balance in existence, and the system works. Every record is public, every claim checks out, every number reconciles. None of it gave a single person a decision to make.


📷 Photo by Tim Evans on Unsplash

On-chain figures in this post were measured directly at Ethereum block 26,096,335 and beacon slot 15,335,026 (epoch 479,219), 08:41:59 UTC on 1 October 2026, and are reproducible by anyone with an RPC endpoint and a beacon API.

Satoshie runs provably fair raffles and coinflip on-chain, settled by Chainlink VRF with the proof verified before payout. See how it works.

Valentina Ní Críonna

Author Valentina Ní Críonna

More posts by Valentina Ní Críonna