Appearance
Join events to state
For every rebase in the last three days, read the share rate at the block it happened in, beside the rate the event itself reports.
cql
let stETH = ethereum:0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84;
from stETH events TokenRebased at latest-21600..latest as e
| project {
block: $block,
time: $timestamp,
tx: $tx,
pre: todecimal(e.preTotalEther) / todecimal(e.preTotalShares),
post: todecimal(e.postTotalEther) / todecimal(e.postTotalShares),
ethPerShare: format(e.getPooledEthByShares(1e18), 18),
fees: format(e.sharesMintedAsFees, 18)
}| block | time | tx | pre | post | ethPerShare | fees |
|---|---|---|---|---|---|---|
| 26032998 | 2026-09-22T12:22:23Z | 0x3c91f03dbf11863e632f49ab15667d341fa8d70fcba8475618dfedc8978fc09e | 1.2445580676490876900750487712638478138 | 1.2446334196020891566623489296363027703 | 1.244633419602089156 | 52.706246205190669139 |
| 26040148 | 2026-09-23T12:22:11Z | 0x573bc04ffa9f9051b1984581ae4c278cbbba8278a3f2147f42984784aa944bdb | 1.244633419602089156662372688362420484 | 1.2447109157008669027499385335723135194 | 1.244710915700866902 | 54.214483995073287142 |
| 26047293 | 2026-09-24T12:23:47Z | 0x4732fc5cb4a1f4abe1cb35b86a5933358d6c54cd488687a8a96b5045eb3eec95 | 1.2447109157008669027499561703721877764 | 1.2447877287426795751721702361958719958 | 1.244787728742679575 | 53.735023042916615934 |
One row per TokenRebased in the range — three, one a day — in block order: the block, its timestamp and transaction, the share rate before and after the rebase from the event's own arguments, ethPerShare read from the contract at that block, and the shares minted as fees. post and ethPerShare agree to eighteen places, which is the check.
How it reads
events TokenRebased makes this an event source, so each row is one log and e.preTotalEther, e.postTotalShares and e.sharesMintedAsFees are its arguments. The ABI is resolved from the address — through the proxy, as for any call — and TokenRebased is in it. Both totals are uint256, so todecimal turns them into decimals before the division; whole-number division would truncate the rate to 1.
e.getPooledEthByShares(1e18) is a call on the event row's alias, and it answers at the row's block — the block the rebase was mined in, after it applied. That is the whole join: no second source, no key, just a call on an event row.
This is the query most people want from stETH — every rebase, with what it did to the rate. Average daily change and annualised rate gets the same rate from daily samples, without reading the events.
Variations
- The rate a day earlier.
with { block: $block - 7200 }on the call. - The change as a percentage.
| extend pct = (post / pre - 1) * 100after theproject. - Every event the contract emits.
events *and| where $event in ('TokenRebased', 'Submitted'); the arguments each event lacks arenull.