Debugging smart contracts on the Somnia Network requires an understanding of how and why transactions fail. Every reverted transaction carries encoded data that can reveal the root cause of failure, whether it’s due to logic errors, insufficient gas, failed access checks, or internal Solidity panics.
1.1 Anatomy of a Revert
When a transaction fails on Somnia, the EVM halts execution and returns revert data, an ABI-encoded payload that follows one of these three formats:
If your contract uses custom errors, Hardhat will not automatically print the name. Decode it manually:
1.3 Decoding Panic Codes
Internal Solidity panics correspond to low-level EVM exceptions. Somnia propagates these codes like any other EVM chain.
Panic Code
Description
Typical Cause
0x01
Assertion failed
Logic invariant broken
0x11
Arithmetic overflow/underflow
Unchecked math operation
0x12
Division by zero
Incorrect math division
0x21
Invalid enum conversion
Out-of-bounds value
0x31
Storage array index out of bounds
Bad loop or mapping access
0x32
Memory array index out of bounds
Corrupt array operation
To detect Panic errors dynamically:
1.4 Advanced Revert Inspection with Hardhat Traces
Hardhat’s tracing layer can reveal the full execution path of a revert.
You’ll see nested calls, gas usage per function, and exactly where the failure occurred. This is invaluable for multi-contract interactions like on-chain governance or liquidity management.
Example output:
1.5 Custom Error Decoding for Verified Contracts
If a Somnia contract is verified on the explorer, you can fetch its ABI dynamically to decode errors programmatically:
Then use iface.parseError(error.data) to decode reverts directly from on-chain logs or transactions.
2. Common Error Patterns on Somnia
Even experienced developers encounter recurring issues. Below are the most common EVM-level errors observed when deploying or testing on Somnia Testnet (Shannon) and Mainnet.
Error Type
Cause
Fix
execution reverted
Fallback revert with no message
Add explicit revert messages or decode ABI data
out of gas
Gas exhausted mid-call
Use estimateGas() or increase gas limit
invalid opcode
Calling a non-existent function
Validate ABI and deployed bytecode
nonce too low
Pending transaction not mined yet
Wait for confirmation or reset nonce
replacement underpriced
Gas bump too small
Raise gas price by 10–20%
static call violation
State-changing call via eth_call
Use .sendTransaction() instead
2.1 Example: Catching a Custom Error in Somnia Treasury Contract
Decoding in JS:
2.2 Handling Complex Contract Interactions
When interacting with multi-layered DeFi protocols or bridging modules on Somnia, reverts can originate several calls deep. Use Hardhat’s trace or Foundry’s -vvvv verbosity to see the full stack.
Foundry example:
This reveals each opcode execution, event emission, and revert reason.
2.3 Invalid ABI or Proxy Conflicts
Many Somnia projects use upgradeable proxies. Reverts from a proxy may originate in the implementation contract. If you get a generic execution reverted, verify you’re using the correct implementation ABI:
3. Transaction Simulation
Simulating transactions allows developers to predict revert causes, estimate gas usage, and test behaviors without risking real SOMI or STT.
3.1 Fork Somnia Networks Locally
Create a local fork of Somnia Mainnet or Shannon Testnet:
Or in configuration:
This mirrors on-chain state locally, so you can safely replay any transaction.
3.2 Using callStatic for Dry-Run Simulation
callStatic runs a transaction without broadcasting or altering state.
3.3 Using eth_call Manually
For raw RPC simulation:
If the call reverts, inspect error.data to decode it with the ABI.
3.4 Impersonating Accounts for Privileged Actions
Simulate admin or contract-controlled operations:
Stop impersonation when finished:
3.5 Snapshot and Rollback Control
Snapshots let you test different outcomes quickly:
This resets the blockchain to its previous state instantly.
3.6 Simulating On-Chain Transactions
If you have a failed transaction hash from Somnia Mainnet:
This reproduces the failure locally and lets you inspect the revert reason directly in Hardhat.
3.7 Advanced Fork Testing with Foundry
You can use cheatcodes like:
3.8 Gas Profiling and Cost Analysis
Somnia gas costs can differ from Ethereum due to consensus differences. Always estimate gas usage per function:
Compare against Shannon and Mainnet to identify anomalies.
3.9 Full Transaction Lifecycle Test
1
Fork Somnia Testnet
Create a fork of the testnet to reproduce on-chain state locally.
2
Impersonate the deployer account
Use impersonation to perform privileged actions and reproduce behavior.
3
Run callStatic to simulate critical functions
Dry-run core functions to inspect return values and revert reasons.
4
Capture reverts and decode with ABI
Decode revert data, custom errors, and panic codes to get actionable context.
5
Use snapshot/revert to iterate quickly
Take snapshots to test multiple scenarios and revert between them.
6
Once clean, deploy and verify on testnet
After local verification, deploy to the testnet and verify behavior.
7
Run same steps on mainnet fork before release
Final validation on a mainnet fork ensures production parity.
Summary
Always decode revert data rather than relying on generic error strings.
Decode custom errors to get structured failure context.
Use forked local environments for safe and realistic debugging.
Combine callStatic, trace, and snapshot/revert for fast iteration.
Validate gas behavior across testnet and mainnet for accurate production cost.
Debugging on Somnia means understanding the EVM intimately. Every revert, panic, and trace is a clue—decode them, simulate safely, and ship with confidence.