Shielded Writes
Send encrypted write transactions with shieldedWriteContract
Shielded writes encrypt transaction calldata before submission. This prevents calldata from being visible on-chain -- an observer can see that a transaction was sent to a particular contract address, but not what function was called or what arguments were passed.
seismic-viem provides two approaches:
shieldedWriteContract()-- standalone function, same API shape as viem'swriteContractcontract.write.functionName()-- via aShieldedContractfrom getShieldedContract
Both produce the same on-chain result: an encrypted type 0x4A Seismic transaction.
Standalone: shieldedWriteContract
shieldedWriteContractimport { shieldedWriteContract } from "seismic-viem";Parameters
address
Hex
Yes
Contract address
abi
Abi
Yes
Contract ABI
functionName
string
Yes
Function to call
args
array
No
Function arguments
gas
bigint
No
Gas limit
gasPrice
bigint
No
Gas price
value
bigint
No
ETH value to send
Returns
Promise<Hash> -- the transaction hash.
Example
Debug: shieldedWriteContractDebug
shieldedWriteContractDebugReturns the plaintext transaction, the shielded (encrypted) transaction, and the transaction hash. Useful for inspecting what the SDK encrypts and broadcasts.
Low-level: sendShieldedTransaction
sendShieldedTransactionFor cases where you have raw transaction data instead of ABI-encoded calls -- for example, contract deployments, pre-encoded calldata, or bypassing the contract abstraction entirely:
How It Works
When you call shieldedWriteContract (or contract.write.functionName), the SDK performs the following steps:
ABI-encode the function call into plaintext calldata
Build Seismic metadata -- encryption nonce, recent block hash, expiry block
Encrypt calldata with AES-GCM using a shared key derived via ECDH between your ephemeral keypair and the node's TEE public key
Construct a type
0x4Atransaction with the encrypted calldata and Seismic-specific fieldsSign and broadcast the transaction
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.
Security Parameters
Every shielded transaction includes a block-hash freshness check and an expiry window. The defaults are sensible for most cases, but you can override them per-call via SeismicSecurityParams:
blocksWindow
bigint
100n
Number of blocks before the transaction expires
encryptionNonce
Hex
Random
Override the encryption nonce
recentBlockHash
Hex
Latest
Override the recent block hash
expiresAtBlock
bigint
Calculated
Override the expiry block directly
The default 100-block window, random nonce, and latest block hash are appropriate for nearly all use cases. Override these only if you have a specific reason -- for example, reducing the window for time-sensitive operations or pinning the block hash in tests.
See Also
Contract Instance --
getShieldedContractwith.writeand.dwritenamespacesSigned Reads -- Authenticated reads that also use the encryption pipeline
Encryption -- ECDH key exchange and AES-GCM details
Shielded Wallet Client -- Creating the client used for shielded writes
Last updated

