Solidity on-chain Reactivity Tutorial

Create a smart contract that reacts to events from other contracts automatically

This tutorial guides you through building on-chain reactivity on Somnia. You'll create a smart contract that reacts to events from other contracts automatically—invoked by chain validators. Subscriptions trigger handler logic directly in the EVM.

Overview

On-chain reactivity lets Solidity contracts "subscribe" to events emitted by other contracts. When an event fires, your handler contract gets called with the event data, enabling automated business logic like auto-swaps or updates. This is powered by Somnia's native push mechanism, funded by a minimum SOM balance (currently 32 SOM) held by the subscription owner.

Key benefits:

  • Atomic: Event + state from the same block (state reads have to be handled by your own contract unlike off-chain subscriptions).

  • Decentralized: Runs on-chain without off-chain servers removing liveness assumptions.

  • Efficient: Pay only for invocations via gas params.

Prerequisites:

Key Objectives

  1. Create a SomniaEventHandler Contract: Inherit from the abstract contract and override _onEvent virtual function with your logic.

  2. Deploy the Handler: Use your tool of choice (e.g., Remix or Hardhat).

  3. Create a Subscription: Use the SDK to set up and fund the sub (owner must hold min SOM) or setup the subscription in Solidity.

  4. Handle Callbacks: The chain invokes your handler on matching filters based on subscription configuration.

Step 1: Install Dependencies

Install the reactivity contracts package for the SomniaEventHandler abstract contract:

This provides the interface to import. (Public Foundry repo coming soon for easier Forge integration.)

Step 2: Create the Handler Contract

Inherit from SomniaEventHandler and implement _onEvent. This is where your business logic goes—e.g., update state or call other contracts.

Example: A simple handler that logs or reacts to any event (wildcard).

  • Customization: Filter in the subscription (Step 4) or add checks in _onEvent (e.g., if emitter == specificAddress).

  • Warnings: Keep gas usage low; handlers run in validator context. Test for reentrancy.

Step 3: Deploy the Handler

Example Hardhat deploy script (scripts/deploy.ts):

Run: npx hardhat run scripts/deploy.ts --network somniaTestnet (configure networks in hardhat.config.ts).

Note the deployed address (e.g., 0x123...).

Step 4: Create and Manage the Subscription

Use the TypeScript SDK to create the subscription. The caller becomes the owner and must hold 32+ SOM.

  • Funding: Chain enforces min SOM; top up if needed.

  • Filters: See API reference for more filters that can be passed to createSoliditySubscription

Step 5: Test the Callback

  1. Deploy an emitter contract that emits events (e.g., simple ERC20 with Transfer).

  2. Trigger an event (e.g., transfer tokens).

  3. Check your handler: Use explorers or logs to see _onEvent executed (e.g., your ReactedToEvent emitted).

Troubleshooting

  • No Invocation? Verify sub ID (via sdk.getAllSoliditySubscriptionsForOwner), filters match, and balance funded.

  • Gas Errors? Increase gasLimit or optimize handler.

  • Cancel: await sdk.cancelSoliditySubscription(subId); (get ID from listing).

Next Steps

  • Add filters for targeted reactivity.

  • Integrate with DeFi/NFT logic.

  • Explore hybrid: Off-chain monitoring + on-chain actions.

Last updated