signature.read

Signed read namespace for encrypted contract queries

The .read namespace provides encrypted contract read operations using signed eth_call. Both calldata and return values are encrypted end-to-end, and the transaction is signed to prove your identity to the contract.


Overview

When you call contract.read.functionName(...), the SDK:

  1. Encodes your function call using the contract ABI

  2. Encrypts the calldata using AES-GCM with a shared key derived via ECDH

  3. Constructs a full TxSeismic with encryption metadata (nonce, block hash, expiry)

  4. Signs the transaction with your private key

  5. Sends the signed transaction to eth_call endpoint

  6. Node decrypts calldata inside TEE, executes the call, encrypts the result

  7. Returns encrypted result (which the SDK can decrypt if needed)

Unlike standard eth_call, signed reads prove your identity to the contract via msg.sender, enabling access-controlled queries.


Usage Pattern

result = contract.read.functionName(arg1, arg2, ...)
  • Sync: Returns HexBytes immediately

  • Async: Returns HexBytes (must await)


Parameters

Function Arguments

Pass function arguments as positional parameters:

Call Options (Keyword Arguments)

All call options are optional keyword arguments:

Parameter
Type
Default
Description

value

int

0

ETH value for the call (in wei)

gas

int

30_000_000

Gas limit for the call

security

None

Custom security parameters (block expiry, nonce, etc.)

Note: Unlike .write, there is no gas_price parameter because reads don't consume gas.


Examples

Sync Usage

Async Usage

Reading with Arguments

Custom Gas Limit

Custom Security Parameters

Simulating Value Transfer


Return Value

Returns HexBytes:

  • Decrypted result from the contract (raw bytes)

  • Empty HexBytes if the contract returned no data

Decoding Results

Results are raw ABI-encoded bytes. Use eth_abi to decode:


Why Use Signed Reads?

Identity Matters

Many contracts use msg.sender to determine access or return personalized data:

With signed read (.read):

With transparent read (.tread):

Common Use Cases

Use signed reads when the contract function:

  • Checks msg.sender permissions

  • Returns data specific to the caller

  • Has access control (owner-only, role-based, etc.)

  • Uses msg.sender in any way

Examples:

  • balanceOf(address) — If it uses msg.sender internally

  • getMyVotes() — Returns caller's voting power

  • isAuthorized() — Checks if caller has permission

  • getPrivateData() — Access-controlled reads


Privacy Guarantees

What Gets Encrypted

  • Function selector (4 bytes)

  • All function arguments

  • Return value (encrypted by node)

An observer watching the network can see:

  • Your address (call sender)

  • Contract address (call recipient)

  • That you made a call (via signed transaction)

But cannot see:

  • Which function you called

  • What arguments you passed

  • What data was returned

What Remains Visible

These fields are not encrypted:

  • from — Your wallet address

  • to — Contract address

  • Gas limit

  • Transaction metadata (block hash, expiry, encryption nonce)


Comparison with .tread

Feature

.read (Signed)

.tread (Transparent)

Calldata encryption

Yes

No

Result encryption

Yes

No

Proves identity

Yes (msg.sender is your address)

No (msg.sender is 0x0)

Gas cost

None (doesn't broadcast)

None (doesn't broadcast)

Use case

Access-controlled reads

Public reads


Security Considerations

Block Hash Freshness

Like shielded writes, signed reads include a recent block hash. The node validates:

  1. Block hash corresponds to a real block

  2. Block is recent (within freshness window)

Transaction Expiry

Calls include an expiry block number:

  • Default: 100 blocks (~20 minutes)

  • After expiry, node rejects the call

Nonce Uniqueness

Each call uses a cryptographically random 12-byte encryption nonce. The SDK generates random nonces automatically.

Private Key Security

Signed reads require your private key to sign the call. Never expose your private key or share it with untrusted parties.


Error Handling


Best Practices

Use .read When

  • Contract function checks msg.sender

  • You need to prove your identity

  • Data is access-controlled (requires authentication)

  • Privacy is required (both query and result)

Don't Use .read When

  • Function is public and doesn't check msg.sender

  • No privacy needed (use .tread for lower overhead)

  • Function is a simple getter with no access control

Production Checklist

  • Verify contract function actually uses msg.sender

  • Handle None return values gracefully

  • Use appropriate gas limits for complex reads

  • Decode results correctly using matching ABI types

  • Consider caching read results if called frequently


Low-Level Alternative

If you need more control (e.g., pre-encoded calldata):

See Signed Read Guide for details.


Async Patterns

Concurrent Reads

Read with Timeout


See Also

Last updated