For the complete documentation index, see llms.txt. This page is also available as Markdown.

Shielded Write

Encrypted transactions — lifecycle, security parameters, and the filler pipeline


How it works

When you send a shielded write (either via auto-encryption for functions with shielded params, or via .seismic().send() for other functions), the SDK:

  1. Fetches your nonce and the latest block hash from the node

  2. Populates TxSeismicElements (encryption nonce, TEE public key reference, block hash, expiry block)

  3. Encrypts the calldata using AES-GCM with a shared key derived via ECDH between the provider's keypair and the node's TEE public key

  4. Signs and broadcasts the transaction as type 0x4A

The encrypted calldata is bound to the transaction context (chain ID, nonce, block hash, expiry) via AES-GCM additional authenticated data, so it cannot be replayed or tampered with.


Step-by-step

1. Set up a signed provider

Shielded writes require a SeismicSignedProvider because you need a private key for both transaction signing and ECDH key derivation.

use seismic_prelude::client::*;
use seismic_alloy_network::reth::SeismicReth;

let signer: PrivateKeySigner = "0xYOUR_PRIVATE_KEY".parse()?;
let wallet = SeismicWallet::<SeismicReth>::from(signer);
let url: reqwest::Url = "https://testnet-1.seismictest.net/rpc".parse()?;

let provider = SeismicProviderBuilder::new()
    .wallet(wallet)
    .connect_http(url)
    .await?;

connect_http() is async because it fetches the TEE public key from the node and caches it for all subsequent encryption operations.

2. Define the contract interface

Use Alloy's sol! macro with #[sol(rpc)] to define your contract interface. Shielded Solidity types (suint256, sbool, etc.) map to their standard ABI counterparts for encoding:

This generates type-safe call builders with .call() and .send() methods.

3. Build and send

Functions with shielded parameters (like setNumber(suint256)) auto-encrypt — just call .send() directly. For functions without shielded parameters (like increment()), use .seismic().send() to opt into encryption:

4. Verify success


Security parameters

Every shielded transaction includes a block-hash freshness check and an expiry window. The SeismicElementsFiller automatically populates these with sane defaults:

Parameter
Default
Description

encryption_nonce

Random 12 bytes

Unique per-transaction AES-GCM nonce

encryption_pubkey

Provider's public key

Client's ECDH public key for key derivation

blocks_window

100 blocks

Freshness window for the block hash

expires_at_block

current_block + blocks_window

Block number after which the transaction is invalid

recent_block_hash

Latest block hash

Anchors the transaction to a specific chain state

These values are set automatically by the filler pipeline. You can override them per-call:

You can also pass SecurityParams directly when using the provider-level _with methods:


What happens under the hood

The filler pipeline processes your transaction in this order:

In source the chain is composed Wallet → (Nonce + ChainId) → SeismicElements → Gas. Chain position doesn't equal execution order — WalletFiller's status() only reports ready after the other fillers populate the tx, so signing ends up last in practice.

You never call encryption functions manually. For functions with shielded parameters, the ShieldedCallBuilder handles everything automatically. For other functions, the .seismic() marker tells the filler pipeline to handle everything.

You never need to call encryption functions manually. The provider's filler pipeline handles all cryptographic operations — either automatically for functions with shielded parameters, or when you use .seismic().


Create transactions cannot be seismic

Contract deployment (TxKind::Create) always uses transparent transactions. The Seismic protocol does not support encrypting deployment bytecode. Deploy your contract first, then interact with it using shielded calls:


Error handling

Common failure modes and how to handle them:


Complete example

See Also

Last updated