5 entries · Solana / Ethereum / Base · Signed log v1Pre-release · Not audited · Read the signed manifest ↗
01 / From source to understanding
How it works
Signed entries
Each change is an entry built from primary sources — a SIMD or an EIP, the client's code, the chain itself. A version of the registry is a Merkle root, signed by its publisher and anchored by a program on Solana devnet.
Checks
check repo finds the code a change breaks; check rpc asks a provider, read-only, whether it behaves as the entry says; registry read --status reads the activation from each chain at the moment you ask.
Watcher
Every day it reads the feature gates agave declares and their state on three Solana clusters, and drafts an entry for what moved outside the registry. A person finishes the draft from the SIMD and signs it.
02 / The easiest way in
Ask your AI agent
The Epochnotes skill lets you ask in plain words: is this upgrade live, and does my project break? Your agent answers from the signed registry, not from what it remembers, and checks your code with the same tool. It works with any agent that can run a command in your terminal: Claude Code, Codex and others.
Answers from the registry
Every answer names the registry version, its signature and the slot or block it read the status from. If the registry cannot be verified, it does not answer at all.
Checks your whole project
Code, contracts, lockfiles and your RPC provider: it runs the same checks as the command line and points at the line to fix.
Says what it did not check
A rule that could not run, a file it did not read, a guess of its own: each is named, so silence never reads as a clean result.
Then add it to your agent. The skill is one folder with a SKILL.md file, the common format for agent skills.
# Claude Code (terminal, or the Code tab of Claude Desktop)
mkdir -p ~/.claude/skills && cp -R ~/epochnotes-src/skills/epochnotes ~/.claude/skills/
# Codex
mkdir -p ~/.codex/skills && cp -R ~/epochnotes-src/skills/epochnotes ~/.codex/skills/
# Any other agent: add this line to the project's AGENTS.md (or its own instructions file)
For questions about network upgrades on Solana, Ethereum or Base, follow ~/epochnotes-src/skills/epochnotes/SKILL.md.
Optional: point it at the published log before you start the agent. Without this the skill names the published log and asks you first, because the publishers file is your trust anchor.
Is transaction v1 live on Solana mainnet, and does this project break?
What does EIP-7702 change for my contracts on Base?
Check this project against recent network changes.
In Claude Code you can also call the skill by name: /epochnotes followed by the question.
A real answer
From a run on Oct 12, 2026, in Claude Code on a small demo app; shortened.
Yes, transaction v1 is live on Solana mainnet, and my-app breaks.
my-app/src/history.ts:6 calls getTransaction with maxSupportedTransactionVersion: 0.
Fix (from the entry): pass 1; with @solana/web3.js use 1.99.0 or later.
Status: active on mainnet-beta since slot 447120000, read at slot 456149984 (feature account)
Registry: version 1, root 77216c0c..., signature verified, on-chain anchor matches
Not checked: the web3.js version (my-app has no lockfile); the runtime probe
03 / Found in the field
What it found in public code
We ran epochnotes check repo over 59 public Solana repositories, checked every hit by hand and reproduced each breakage on mainnet before reporting it. 9 reported, 2 already fixed and merged.
Outcomes as of 2026-10-23. An open pull request is a proposal, not an acceptance.
04 / The latest field reading
What the Solana watcher sees
Read on 2026-10-15 from agave 929e9fb658d8 and three clusters (mainnet-beta slot 457175726, testnet slot 452698980, devnet slot 511293223): 290 feature gates declared, 11 of them covered by the registry.
On the way to mainnet-beta (5)
Not active on mainnet-beta yet, but active on testnet or devnet, or already scheduled on mainnet-beta.
Gate
SIMD
mainnet-beta
testnet
devnet
Entry
virtual_address_space_adjustments SIMD-0460: Virtual Address Space Adjustments
stream Votes stop being transactions on chain: validators send them directly to each other. Initially a validator admission ticket reproduces the incentives of today's vote transaction fees. Voting is not invisible afterwards: for rewards, the leader of slot s+8 can post up to two vote aggregates for slot s. Code that reads individual vote transactions out of blocks no longer finds them.
rpc Optimistic confirmation is superseded by faster actual finality; the SIMD names this as the most visible change.
How to fix it
Do not derive validator activity from vote transactions in blocks, and review code that relies on optimistic confirmation as something distinct from finality.
Activations (1) and sources (2)
alpenglow — feature gate A1pengvuM6JEcyNuTnMqepBKhwHE3N6PmUrdATGawhJS Feature gate registered in agave as "SIMD-0326: Alpenglow: new consensus algorithm".
program EIP-7702 breaks the invariant that msg.sender == tx.origin holds only in the top frame of a transaction: a delegated account can make several calls in one transaction. Reentrancy guards of the style require(tx.origin == msg.sender) and atomic sandwich protections that rely on tx.origin no longer hold. Using that check only to know that the sender is an EOA is, by the EIP's own reading, not affected.
program An account delegated under EIP-7702 has code: the delegation indicator, 0xef0100 followed by the address of the delegate, and EXTCODESIZE returns 23 for it. A check that reads code as "a contract" or no code as "an EOA" — an isContract call, a test of code.length or extcodesize — now takes a delegated EOA for a contract.
program OpenZeppelin's SignatureChecker.isValidSignatureNow checks an ECDSA signature only when the signer has no code, and otherwise asks the signer for ERC-1271. A delegated EOA has code, so its ECDSA signature is not checked as such: it is valid only if the delegate implements ERC-1271 and accepts it.
wallet OpenZeppelin's ERC721Utils.checkOnERC721Received calls onERC721Received on any recipient with code, and reverts when the call fails or returns another value. A safe transfer or a safe mint to a delegated EOA reverts unless its delegate implements the receiver.
sdk eth_getCode of a delegated EOA returns the 23-byte delegation indicator, and the account still sends transactions. Telling contracts from EOAs by whether eth_getCode is empty no longer works.
How to fix it
Replace a reentrancy guard built on tx.origin == msg.sender with one held in a transient storage variable, as the EIP suggests. A sandwich protection built on tx.origin has no replacement in the EIP, which calls relying on it a bad practice: it has to be designed again, not patched.
Where it matters whether an account is a delegated EOA, read the first three bytes of its code: 0xef0100 marks the delegation indicator (OpenZeppelin's EIP7702Utils.fetchDelegate returns the delegate), and decide explicitly how such an account is treated — for a signature, ECDSA, ERC-1271, or both.
A contract meant to be a delegate implements the receiver hooks the accounts that delegate to it rely on, such as onERC721Received: OpenZeppelin's ERC721Utils calls it on every recipient with code.
Activations (2) and sources (16)
prague — ethereum at 2025-05-07T10:05:11Z Prague, the execution layer of the Pectra upgrade: go-ethereum sets PragueTime to this time for mainnet, and EIP-7600 lists EIP-7702 and EIP-7685 among its EIPs.
isthmus — base at 2025-05-09T16:00:01Z Isthmus, the OP Stack upgrade that brings the Pectra execution layer, EIP-7702 included, to the chain; on OP Stack chains requestsHash is always sha256(''), the hash of no requests, so its presence marks the fork.
economics The minimum balance of an account is (128 + data size in bytes) * lamports_per_byte, and every step lowers lamports_per_byte. An account funded at an earlier, higher minimum keeps the difference: the SIMD allows reducing the balance to the new minimum, it does not return anything by itself.
sdk A lamports_per_byte value compiled into a client or program goes stale at every step: on activation the value changes in the bank and in the Rent sysvar, while DEFAULT_LAMPORTS_PER_BYTE in the SDKs is updated only after activation. The SIMD calls the reduction strictly a relaxation: existing program logic keeps working, so a stale higher constant overpays rather than fails.
program The reduction is not guaranteed to be one-way. The SIMD states that rent can be increased back to the legacy value in case of excessive state growth, noting that SIMD-0392 allows this without significant disruption to existing accounts; agave already declares a gate set_lamports_per_byte_to_6960, registered as "SIMD-0438: Reset lamports per byte to legacy value of 6960". A minimum balance fixed at a reduced value can therefore become too low for newly created accounts.
How to fix it
Take the minimum balance from the cluster at run time (the Rent sysvar in programs, getMinimumBalanceForRentExemption in clients) instead of a compiled-in lamports_per_byte.
Activations (5) and sources (3)
set_lamports_per_byte_to_6333 — feature gate 4a6f7o7iTcA8hRDCrPLkSatnt5Ykxiu36wo5p1Tt12wC Step 1 of 5. Sets lamports_per_byte to 6333 (from 6960).
set_lamports_per_byte_to_5080 — feature gate 61BtM7BkDEE8Yq5fskEVAQT9mYA8qCejJWoLe5apqg81 Step 2 of 5. Sets lamports_per_byte to 5080.
set_lamports_per_byte_to_2575 — feature gate rntCigrTppP5JdZz7K8TyN9sMzLdAcXp8SejYpVpX6D Step 3 of 5. Sets lamports_per_byte to 2575.
set_lamports_per_byte_to_1322 — feature gate rntD7invRBswCAdKtRsh1G4psKjrPdS3BKqtnA78C7N Step 4 of 5. Sets lamports_per_byte to 1322.
set_lamports_per_byte_to_696 — feature gate rntTjNZ9boq8owDxjGVFHPfWNQPDaKiM5JcjxmDGg47 Step 5 of 5. Sets lamports_per_byte to 696.
rpc-observation mainnet-beta getAccountInfo SysvarRent111111111111111111111111111111111 at slot 448085582 retrieved 2026-09-18
Reduce Slot Times
SIMD-0525Solanaentry slot-duration · rev 1
What breaks
program A duration expressed in slots shrinks in wall-clock time with every stage: the SIMD tells dapp developers and off-chain services to stop assuming that 400 ms * slots is a stable conversion. A timer of N slots lasts half as long at 200 ms as it did at 400 ms.
sdk SDK constants stay at their 400 ms values at first: static constants for default slot duration, ticks per second, slots per year and slot-to-time conversion may keep describing 400 ms while the cluster runs 350, 300, 250 or 200 ms banks.
economics Per-slot limits scale down in proportion to the slot time so that the wall-clock rate stays approximately the same. From the 400 ms baseline of 60,000,000 the maximum block compute units become 37,500,000 at 250 ms and 30,000,000 at 200 ms; the maximum writable-account compute units go from 24,000,000 to 15,000,000 and 12,000,000. The ratios apply to whatever baseline is active: with the 100,000,000 block limit of SIMD-0286 the values are 62,500,000 and 50,000,000. Code tuned to the per-block or per-account limit of a 400 ms slot exceeds the scaled one.
program An epoch stays 432,000 slots, so it lasts half as long at 200 ms as at 400 ms. Anything scheduled per epoch happens twice as often in wall-clock time.
How to fix it
Keep slot counts only where slot semantics are intended; where a duration means wall-clock time, do not derive it from a fixed milliseconds-per-slot constant. The SIMD advises preferring cluster-provided timing parameters once they are available.
Activations (4) and sources (2)
reduce_slot_time_to_350ms — feature gate iBRL5RuWhw4yqaAZu96RUULHckHTZAoe2b77qaV38JZ Target slot time 350 ms. Takes effect one epoch after the gate is activated.
reduce_slot_time_to_300ms — feature gate iBRLL3k18HST852F1Mf3Lv83waTNQmmqvKDxvYGwQFL Target slot time 300 ms. Takes effect one epoch after the gate is activated.
reduce_slot_time_to_250ms — feature gate iBRLMc81UjRa8fn8A6eE8bJTnRbgQoPTynM51akENCV Target slot time 250 ms. Takes effect one epoch after the gate is activated.
reduce_slot_time_to_200ms — feature gate iBRLjhJnkmDZgNoZRDMW11d8ZV7HvsL3vAyRjZB5npW Target slot time 200 ms. Takes effect one epoch after the gate is activated.
rpc getTransaction, and getBlock with transactionDetails full or accounts, fail with JSON-RPC error -32015 "Transaction version (1) is not supported by the requesting client" when the request omits maxSupportedTransactionVersion or sets it to 0 and the result contains a version 1 transaction. getBlock with transactionDetails signatures or none is not affected.
decoder A serialized version 1 transaction starts with the version byte 129 (0x81). A decoder written for the legacy and version 0 layouts has no branch for that value.
sdk @solana/kit 8.0.0 removed three compute-unit-limit helpers from @solana/kit in favour of resource-limit helpers that also set the loaded accounts data size limit for version 1 transactions, and removed the fixed transaction size constants from @solana/transactions because version 1 transactions have a larger size limit.
decoder The maximum size of a version 1 transaction is 4096 bytes; the prior maximum was 1232. A buffer or a size check fixed at 1232 bytes is too small for a valid version 1 transaction.
sdk @solana/web3.js 1.98.4 cannot read a version 1 transaction even when maxSupportedTransactionVersion is 1: getTransaction and getParsedTransaction throw a StructError on the version field, and getBlock fails the same way. 1.99.0 reads all three and returns a MessageV1.
How to fix it
Pass maxSupportedTransactionVersion 1 in getTransaction and getBlock; with @solana/web3.js this also needs version 1.99.0 or later.
When moving to @solana/kit 8.0.0 or later, replace the compute-unit-limit helpers with the resource-limit helpers named in the release notes.
Set the maximum supported transaction version to 1 in the configuration of the RPC client (Some(1) in Rust, rpc.MaxSupportedTransactionVersion1 or uint64(1) in Go, max_supported_transaction_version=1 in Python), and check that the client library in use can decode a version 1 transaction.
Activations (1) and sources (7)
enable_tx_v1 — feature gate txv1aq4pp281K9um3tnPgkfX8UqtFT6wcVW3hNezGLL Feature gate registered in agave as "SIMD-0385: Transaction V1".
epochnotes registry read --json --status mainnet-beta # verified entries and the state of each activation
epochnotes registry read --status base # the same entries, read on Base
epochnotes check repo <path> # where a change breaks this code
epochnotes check rpc --rpc-url <endpoint> # does this provider behave as the entry says
When it cannot verify what it reads, it refuses to answer rather than guess.
07 / What comes next
Roadmap
Now
Entries for Solana, Ethereum and Base in one signed log, anchored and verified against the program on Solana devnet
Free and open source (MIT): a public good for developers
Static rules for TypeScript, JavaScript, Rust, Go, Python, Solidity and lockfiles; read-only RPC probes
Rent held above the minimum: scan, close plan, withdraw template
An agent skill for Claude Code, Codex and others that answers from the verified registry only
The Solana watcher, run daily by a scheduled Claude task that drafts from the SIMD
Next
status and watch read the signed log, not only a clone of the repository
Watchers for Ethereum and Base: fork times in the client configurations
A notification when something outside the registry moves
This page updated from each watcher report
Entries for the gates already on the way to mainnet-beta