On most EVM chains, a contract cannot act unless someone sends it a transaction. Anything that should happen after an event (liquidations, settlements, rebalancing, scheduled upkeep) needs an off-chain bot or keeper network that watches the chain and pays to send a follow-up transaction. That adds an operator, latency and a failure mode.
Somnia Reactivity removes that step. It has been live on mainnet since the Ingot release of 15 April 2026 and comes in two forms that can be used independently or together.
Onchain reactivity
A contract creates a subscription by calling the Somnia reactivity precompile at address 0x0100. The subscription is stored in chain state and holds:
- A filter: event topics, the emitting contract, and the transaction origin.
- A handler contract and function selector.
- Gas parameters for the handler.
Every event log emitted in a block is checked against active subscriptions. Matches go into a per-block queue ordered by priority fee. After the block's user transactions have run, validators execute each pending handler as a synthetic transaction in the same block.
These reactive transactions are ordinary in every other respect. They appear on the explorer, have normal receipts, emit normal logs and pay normal gas. The subscription owner pays for them.
Subscriptions can also be scheduled for a specific block, epoch or timestamp, which covers cron-style jobs such as settlement at a deadline or upkeep at each epoch boundary. Somnia produces blocks every 100 milliseconds, so a handler responds within the same 100 ms block as the event that triggered it.
Writing a handler
The Solidity package @somnia-chain/reactivity-contracts provides a base contract. Inherit from SomniaEventHandler and override the _onEvent hook:
import { SomniaEventHandler } from "@somnia-chain/reactivity-contracts/contracts/SomniaEventHandler.sol";
contract MyHandler is SomniaEventHandler {
function _onEvent(
address emitter,
bytes32[] calldata eventTopics,
bytes calldata data
) internal override {
// react to the event here
}
}The contract then calls SomniaExtensions.subscribe(address(this), filter, options) to register itself and becomes the subscription owner. For a one-shot schedule, it uses scheduleSubscriptionAtBlock, scheduleSubscriptionAtEpoch or scheduleSubscriptionAtTimestamp. The owner must hold at least 32 SOMI, and a subscription runs until it is removed with unsubscribe(id) or the owner can no longer pay.
One caution from the documentation: logs emitted by a handler are themselves checked against subscriptions. A handler that triggers its own subscription can recurse and drain the owner's balance, so filters should be specific.
Off-chain reactivity
Some reactions belong in the application rather than on the chain: a UI that updates when a trade lands, an indexer writing to a database, a bot watching a pool. For these, a client opens a WebSocket to a Somnia node and subscribes with eth_subscribe using the somnia_watch method.
Events are pushed as they land. Each notification can also carry the results of read-only calls simulated against the same block, so the app receives the event and the resulting state together in one message, with no extra round trip and no risk of reading inconsistent state.
Off-chain subscriptions cost no SOMI and end when the client disconnects. The TypeScript package @somnia-chain/reactivity wraps the protocol with viem; sdk.watch() takes contract sources, topic filters and optional calls to run alongside each event.
Choosing between them
- Use onchain reactivity when the reaction must be a guaranteed, public effect: settlement at expiry, automatic liquidation, a callback that fires even if its owner is offline.
- Use off-chain reactivity when the reaction lives in your app: interfaces, analytics, monitoring and trading bots.
In production
The Somnia Oracle schedules every resolution with onchain reactivity, so no keeper is involved. Consumers can subscribe to its AnswerPosted event to settle as soon as an answer is posted. The April 2026 Reactivity hackathon drew more than 350 developers and 146 projects (Somnia blog, 6 April 2026), and several Event Contracts hackathon entries use the precompile for keeperless redemption.