SovaEVM Modules
The SovaEVM (sova-reth) is the execution engine that powers the Sova Network.
It extends the standard Ethereum Virtual Machine (EVM) with modules that make it natively aware of Bitcoin transactions, confirmations, and network state.
These extensions are what allow developers to build Bitcoin-integrated smart contracts using familiar Solidity patterns — without bridges, oracles, or wrapped assets.
Overview
While the SovaEVM maintains full compatibility with the EVM specification, it adds four major enhancements:
Module
Purpose
Inspector
Monitors storage writes (SSTORE) to enforce Bitcoin-linked locks and prevent unconfirmed state changes.
Sentinel Interface
Communicates with the off-chain Sentinel database to synchronize Bitcoin confirmation data.
Bitcoin Precompiles
Expose native Bitcoin RPC functionality to contracts.
Anchor Verifier
Validates Bitcoin block headers and anchors during block execution.
These modules together ensure that Sova’s execution logic is deterministic and Bitcoin-anchored, even while remaining EVM-compatible.
The Inspector Module
The Inspector is the central consensus mechanism for Bitcoin finality inside the EVM. It acts as a lightweight middleware layer between contract execution and state updates.
Why?
The Inspector module is provided by REVM and provides access to a state journal. This journal contains a list of the most recent storage actions. So when smart contracts write to state, it is captured in this journal. This is important because we want to capture all SSTORE opcodes that execute in a Sova transaction that is tied to a Bitcoin transaction. Essentially, the Inspector on Sova clients captures all of the state-related changes during a transaction and stores those changes in a separate database located in the Sentinel. The sentinel provides a place for the Inspector to store the changes and reference them later when checking for Bitcoin finality. Bitcoin finality is not immediately a pass/fail right off the bat; there are times when blocks are updated that are not at the head of the chain. When looking at the head of a chain—any chain, whether Bitcoin, Sova, Ethereum, Base, etc.—there is a 'safe' and an 'unsafe' head. The unsafe head leads the safe head by a number of blocks, and blocks are usually considered final after they reach the safe threshold. That is the Inspector's number one job: it makes sure that the state on Sova reflects the finalized or 'safe' state returned from Bitcoin.
Responsibilities
Detect contract storage writes tied to Bitcoin transactions.
Temporarily lock affected storage slots.
Register lock metadata (txid, slot, block number) with the Sentinel.
Await confirmation or expiration updates.
Revert or finalize state based on Bitcoin finality.
Internal Logic (Simplified)
if (isBitcoinLinkedSlot(slot)) {
lockStorage(slot);
emit LockRegistered(txid, slot);
if (confirmations >= 6) unlockStorage(slot);
else if (expired) revertStorage(slot);
}Lock Lifecycle
Detection: The Inspector identifies an SSTORE event writing to a “Bitcoin-linked” variable.
Lock Creation: Slot is frozen until associated Bitcoin tx reaches confirmation threshold.
Update: Sentinel periodically notifies Inspector when confirmations are sufficient.
Finalization: Slot unlocked, state written permanently.
Reversion: If confirmation fails or expires, state resets to its previous value.
Sentinel Interface
The Sentinel Interface is the communication layer between the SovaEVM and the off-chain Sentinel service. It receives Bitcoin transaction confirmations to enforce finality after a certain threshold of Bitcoin blocks. The most important design constraint in the Sentinel is that the Sentinel's operations are idempotent and deterministic—ensuring all nodes replay the same logic and reach identical state roots.
Why?
It allows the SovaEVM to maintain non-blocking synchronization with Bitcoin — execution continues while finality is validated asynchronously.
Basic Functions
Read more on Github repo.
// Check slot status
let status_response = client.get_slot_status(
current_block, // Current block
contract_address, // Contract address
slot_index, // Slot index as bytes
).await?;
// Lock a single slot
let lock_response = client.lock_slot(
locked_at_block, // Block where lock takes effect
contract_address, // Contract address
slot_index, // Slot index as bytes
revert_value, // Value to revert to if BTC tx fails
current_value, // Current value of the slot
btc_txid, // Bitcoin transaction ID
btc_block, // Bitcoin block number
).await?;This interface is implemented via local RPC, typically over secure WebSocket or gRPC channels.
Bitcoin Precompiles
A blockchain precompile refers to a set of special, predefined functions built into the blockchain client software. These precompiles are available to blockchain developers via smart contract calls and can be used for a variety of use cases.
The common use case for these features in an EVM execution clients is to perform complex cryptographic operations such as hashing, digital signature verification, and mathematical operations.
On Sova we have created our own set of "Bitcoin precompiles". These precompiles have the ability to interact with the Bitcoin network via and rpc connection to a full Bitcoin node. Every node connected to the Sova Network is responsible for running a full Bitcoin node for the purpose of validating the chain and also broadcasting Bitcoin transactions if necessary.
Technical Details
Sova introduces Bitcoin precompiles — built-in contracts at specific addresses that allow smart contracts to directly interact with the Bitcoin network.
Precompile
Address
Functionality
Description
sendrawtransaction
0x999
Broadcast signed raw BTC transaction
Allows contract-triggered BTC broadcasts.
decoderawtransaction
0x998
Decode raw BTC transaction bytes
Returns structured transaction metadata.
convertaddress
0x997
Convert EVM address to Bitcoin format
Generates P2TR or P2WPKH Bitcoin address equivalents.
Notes
Each precompile is stateless and deterministic.
Inputs and outputs are validated by Bitcoin Core RPC responses.
Execution cost (
gas) is fixed; external RPC latency is asynchronous and off-chain.Reverts occur if the node’s Bitcoin RPC is unreachable or data invalid.
Smart Contract: Bitcoin Precompile Library
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/**
* @title SovaBitcoin
* @author Sova Labs
*
* A library for integrating with Bitcoin precompiles on Sova.
*/
library SovaBitcoin {
/// @notice Bitcoin precompile address
address public constant BROADCAST_TRANSACTION_PRECOMPILE_ADDRESS = address(0x999);
address public constant DECODE_TRANSACTION_PRECOMPILE_ADDRESS = address(0x998);
address public constant CONVERT_ADDRESS_PRECOMPILE_ADDRESS = address(0x997);
/// @notice Bitcoin context contract address
address public constant SOVA_L1_BLOCK_ADDRESS = 0x2100000000000000000000000000000000000015;
/// @notice Native Bitcoin wrapper address
address public constant UBTC_ADDRESS = 0x2100000000000000000000000000000000000020;
struct Output {
string addr;
uint256 value;
bytes script;
}
struct Input {
bytes32 prevTxHash;
uint32 outputIndex;
bytes scriptSig;
bytes[] witness;
}
struct BitcoinTx {
bytes32 txid;
Output[] outputs;
Input[] inputs;
uint256 locktime;
}
error PrecompileCallFailed();
/**
* @notice Decodes a raw Bitcoin transaction into a structured format
*
* @param signedTx The raw signed Bitcoin transaction
*
* @return BitcoinTx Object containing the decoded transaction data
*/
function decodeBitcoinTx(bytes memory signedTx) internal view returns (BitcoinTx memory) {
(bool success, bytes memory returndata) =
DECODE_TRANSACTION_PRECOMPILE_ADDRESS.staticcall(abi.encodePacked(signedTx));
if (!success) revert PrecompileCallFailed();
return abi.decode(returndata, (BitcoinTx));
}
/**
* @notice Retrieves the unique deposit address for the corresponding EVM address
*
* @param addr The EVM address to convert
*
* @return returnData The Bitcoin deposit address in bytes format
*/
function convertToBtcAddress(address addr) internal returns (bytes memory) {
(bool success, bytes memory returnData) = CONVERT_ADDRESS_PRECOMPILE_ADDRESS.call(abi.encodePacked(addr));
if (!success) revert PrecompileCallFailed();
return returnData;
}
/**
* @notice Broadcasts a signed Bitcoin transaction to the Bitcoin network
*
* @param signedTx The raw signed Bitcoin transaction to broadcast
*/
function broadcastBitcoinTx(bytes memory signedTx) internal {
(bool success,) = BROADCAST_TRANSACTION_PRECOMPILE_ADDRESS.call(abi.encodePacked(signedTx));
if (!success) revert PrecompileCallFailed();
}
}This example demonstrates how the SovaEVM treats Bitcoin RPC actions as native EVM operations, not off-chain integrations.
Anchor Verifier
The Anchor Verifier ensures that each Sova block corresponds to a valid Bitcoin block header. It runs as a system contract, invoked automatically during block execution.
Operation
Each new block includes a transaction to
SovaL1Block.The contract records the latest Bitcoin block height and hash.
The Verifier queries the validator’s Bitcoin Core for the same header.
If mismatch → block invalid.
If valid → header is stored and indexed for cross-chain proofs.
State Example
struct L1Block {
uint256 height;
bytes32 blockHash;
uint256 timestamp;
}This mechanism creates a verifiable bridge between Bitcoin and Sova state, providing both runtime integrity and audit traceability.
Execution Flow Summary
User Transaction → EVM Execution (sova-reth)
↓
Inspector detects BTC-linked write
↓
Storage slot locked; event sent to Sentinel
↓
Sentinel monitors Bitcoin confirmations
↓
If confirmed → Inspector unlocks slot
If expired → Inspector reverts slot
↓
Block finalized by Consensus Layer
↓
Anchor Verifier stores Bitcoin header for cross-chain proofsThis process guarantees that no Bitcoin-related state finalizes prematurely and that Sova blocks are always aligned with canonical Bitcoin history.
Developer Implications
When developing on Sova, contracts behave just like on Ethereum — with one crucial distinction: Bitcoin-linked actions have a time dimension.
Key Considerations
Finality Delay: Bitcoin confirmation (default: 6 blocks) introduces latency.
State Locking: Contracts interacting with Bitcoin must handle pending or reverted states gracefully.
Error Handling: Be prepared for
LockExpiredorTxUnconfirmedevents.Asynchronous Flow: Design with callbacks or off-chain monitors for confirmation completion.
Gas Cost Awareness: Precompiles are cheap computationally but depend on off-chain RPC availability.
In exchange, developers gain the ability to build true Bitcoin-native applications — from vault protocols to cross-chain swaps — all within Solidity.
Example: BTC Vault Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "./SovaBitcoin.sol";
/**
* @title BTCVault
* @notice Manages Bitcoin deposits and their finalization on Sova
* @dev Integrates with the Sentinel service for Bitcoin finality confirmation
*/
contract BTCVault {
// State variables
mapping(bytes32 => uint256) public deposits;
mapping(bytes32 => bool) public finalizedDeposits;
// Events
event DepositRegistered(address indexed user, bytes32 indexed btcTxid, uint256 amount);
event DepositFinalized(bytes32 indexed btcTxid, uint256 amount, address indexed recipient);
// Errors
error NoDeposit();
error AlreadyFinalized();
error InvalidAmount();
error AmountDoesntMatch();
/**
* @notice Registers a new Bitcoin deposit
* @param btcTxid The Bitcoin transaction ID
* @param amount The amount deposited in satoshis
*/
function registerDeposit(bytes32 signedBtcTx, uint256 amount) external {
if (amount == 0) revert InvalidAmount();
SovaBitcoin.BitcoinTx memory btcTx = decodeBitcoinTx(signedTx);
if (btcTx.outputs[voutIndex].value != amount) {
revert AmountDoesntMatch();
}
deposits[btcTxid] = amount;
SovaBitcoin.broadcastBitcoinTx(signedBtcTx)
emit DepositRegistered(msg.sender, signedBtcTx, amount);
}
/**
* @notice Finalizes a deposit after Bitcoin confirmation
* @dev Called by Sentinel after confirmation threshold is met
* @param btcTxid The Bitcoin transaction ID to finalize
*/
function finalizeDeposit(bytes32 signedBtcTx) external onlySentinel {
uint256 amount = deposits[btcTxid];
if (amount == 0) revert NoDeposit();
if (finalizedDeposits[btcTxid]) revert AlreadyFinalized();
finalizedDeposits[btcTxid] = true;
// Logic to mint/credit/tokenize
emit DepositFinalized(signedBtcTx, amount, msg.sender);
}
}This pattern — using event-driven confirmations from Sentinel — is how most Bitcoin-integrated contracts on Sova operate.
Summary
The Inspector enforces Bitcoin-linked state correctness inside the EVM.
The Sentinel Interface synchronizes confirmation data asynchronously.
Bitcoin precompiles make RPC functions callable directly from contracts.
The Anchor Verifier ties every block to an authentic Bitcoin header.
Developers can use these modules to build auditable, Bitcoin-secured applications natively in Solidity.
Together, these modules make Sova not just “compatible” with Bitcoin — but structurally anchored to it.
Next → Sentinel & Signing Architecture
Learn how the Sentinel and Signing Service manage Bitcoin transaction tracking, confirmation, and withdrawal execution — the backbone of Sova’s finality and redemption system.
Last updated