Banked: 2026-06-11 Source cycle: SEAMS/oracle dead-feed follow-up on ZeroLend mainnet-lrt (Ethereum mainnet, fork block 25295046) Finding doc: /home/babakinzo/bounty/findings/zerolend-deadfeed-dos-2026-06-11.md Verdict that produced this lesson: WALK-CLEAN (mechanically real + LIVE, but OUT OF SCOPE)
A reverting oracle feed in an Aave-v3 fork is a real DoS MECHANISM, but a finding requires (a) a LIVE victim, (b) the right dead-state class, and (c) a live in-scope program. Skip any of the three and it is a WALK even if the feed genuinely reverts.
A reverting AaveOracle source bricks getUserAccountData + liquidationCall for ANY position
touching that reserve (collateral OR debt), because GenericLogic.calculateUserAccountData prices
EVERY reserve the user has. If getFallbackOracle() == 0 (no fallback), the source revert propagates
all the way up. Result: that user is un-liquidatable and cannot compute health -> bad-debt risk with
no remedy. Aave's if (price > 0) ... else fallback never runs because the source REVERTS rather
than returning <=0.
decimals()/description() revert; the EIP-1967 impl slot
points at a stub (e.g. 63 bytes of code). Structural/deployment error. Reverts -> availability only.InvalidLastUpdateDetails(bytes32,uint256,uint256,uint256)
(selector 0x4f319ffe). Decode the bytes32 to the feedId ascii and the uint to the data-package
timestamp to PROVE the data age. Reverts -> availability only."The feed reverts" is only the mechanism. To confirm a LIVE DoS: passive-scan the variable-debt
token Transfer logs (mint-from-0x0 = borrower) to enumerate borrowers, then call
getUserAccountData(user) on each and show it reverts. A bricked account-data on a REAL address is
the confirmed-live signal. Found 3 such live users on ZeroLend (rsETH-debt + pzETH-debt) whose
account-data calls revert at HEAD.
Check in order: - (i) Is there a LIVE program, or only a FINISHED audit competition? (ZeroLend's only Immunefi program was the "Boost" competition, FINISHED 2024-03-14.) - (ii) Does it cover THIS chain? A zkSync-Era-only program does NOT cover Ethereum-mainnet contracts. (ZeroLend Boost = "deployed on zkSync Era exclusively, no Ethereum mainnet scope.") - (iii) Is "incorrect data supplied by third party oracles" out-of-scope? (ZeroLend: yes, explicit.) A dead RedStone push feed is precisely "incorrect third-party-oracle data." Even a real, live mainnet DoS is a WALK when the only program is finished, wrong-chain, and excludes third-party-oracle data.
cast call $ORACLE "getReservesList()(address[])"
cast call $ORACLE "getSourceOfAsset(address)(address)" $ASSET
cast call $ORACLE "getAssetPrice(address)(uint256)" $ASSET # revert? 0? fine?
cast call $ORACLE "getFallbackOracle()(address)" # 0 => revert propagates
cast storage $SOURCE 0 ; cast storage $SOURCE 1 # 2-feed adapter slots
cast storage $FEED 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc # EIP1967 impl
cast call $VARDEBT "totalSupply()(uint256)" ; cast call $ATOKEN "totalSupply()(uint256)"
cast logs --address $VARDEBT "Transfer(address,address,uint256)" --from-block X --to-block Y --json # find borrowers
cast call $POOL "getUserAccountData(address)(...)" $BORROWER # reverts => live DoS confirmed
Decode RedStone staleness: 0x4f319ffe = InvalidLastUpdateDetails(bytes32,uint256,uint256,uint256);
word1 ascii = feedId, word2 = data-package ts (prove age).