> For the complete documentation index, see [llms.txt](https://docs.seismic.systems/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.seismic.systems/clients/alloy/examples/signed-read-pattern.md).

# Signed Read Pattern

This example demonstrates the authenticated read pattern: create a signed provider, deploy a contract, write shielded data, read it back with a signed read, and compare with a transparent read to show the difference.

## Prerequisites

```bash
export PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
export RPC_URL="https://testnet-1.seismictest.net/rpc"
```

`Cargo.toml` — see [Installation](/clients/alloy/installation.md) for the full template including the required `[patch.crates-io]` block:

```toml
[package]
name = "signed-read-pattern"
version = "0.1.0"
edition = "2021"
rust-version = "1.82"

[dependencies]
seismic-prelude        = { git = "https://github.com/SeismicSystems/seismic-alloy" }
seismic-alloy-network  = { git = "https://github.com/SeismicSystems/seismic-alloy" }
seismic-alloy-provider = { git = "https://github.com/SeismicSystems/seismic-alloy" }
alloy-provider         = "1.1"
alloy-signer-local     = "1.1"
alloy-primitives       = "1.1"
alloy-sol-types        = "1.1"
alloy-network          = "1.1"
tokio                  = { version = "1", features = ["full"] }
reqwest                = "0.12"

# [patch.crates-io] block required — see Installation.
```

## Complete Example

```rust
use seismic_prelude::client::*;
use seismic_alloy_network::reth::SeismicReth;
use alloy_network::ReceiptResponse;
use alloy_provider::Provider;

sol! {
    #[sol(rpc, bytecode = "6080604052...")]
    contract SeismicCounter {
        function setNumber(suint256 newNumber) public;
        function increment() public;
        function isOdd() public view returns (bool);
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // -------------------------------------------------------
    // 1. Create signed provider
    // -------------------------------------------------------
    let signer: PrivateKeySigner = std::env::var("PRIVATE_KEY")?.parse()?;
    let wallet = SeismicWallet::<SeismicReth>::from(signer);
    let url: reqwest::Url = std::env::var("RPC_URL")?.parse()?;

    let provider = SeismicProviderBuilder::new()
        .wallet(wallet)
        .connect_http(url)
        .await?;
    println!("Provider ready. Block: {}", provider.get_block_number().await?);

    // -------------------------------------------------------
    // 2. Deploy contract
    // -------------------------------------------------------
    let contract = SeismicCounter::deploy(&provider).await?;
    println!("Contract deployed at: {:?}", contract.address());

    // -------------------------------------------------------
    // 3. Write data (shielded) — setNumber(42)
    // -------------------------------------------------------
    // setNumber has suint256 param — auto-encrypts
    let write_receipt = contract
        .setNumber(alloy_primitives::aliases::SUInt(U256::from(42)))
        .send()
        .await?
        .get_receipt()
        .await?;
    assert!(write_receipt.status());
    println!("Shielded write confirmed (setNumber(42))");

    // -------------------------------------------------------
    // 4. Read it back (signed read) — isOdd()
    // -------------------------------------------------------
    println!("\n--- Signed Read (.seismic().call()) ---");
    let signed_result = contract.isOdd().seismic().call().await?;
    println!("isOdd() via signed read: {signed_result}");
    println!("  - msg.sender = your wallet address");
    println!("  - Calldata was encrypted");
    println!("  - Response was encrypted, then decrypted by provider");

    // -------------------------------------------------------
    // 5. Compare with transparent read — .call()
    // -------------------------------------------------------
    println!("\n--- Transparent Read (.call()) ---");
    let transparent_result = contract.isOdd().call().await?;
    println!("isOdd() via transparent read: {transparent_result}");
    println!("  - msg.sender = 0x0 (zero address)");
    println!("  - Calldata was plaintext");
    println!("  - Response was plaintext");

    // -------------------------------------------------------
    // 6. Show the difference
    // -------------------------------------------------------
    println!("\n--- Comparison ---");
    println!("Signed read result:      {signed_result}");
    println!("Transparent read result:  {transparent_result}");

    // For isOdd() which does not depend on msg.sender,
    // both results should be the same.
    // For functions that check msg.sender (e.g., balanceOf()),
    // the transparent read would return the zero address's data.
    if signed_result == transparent_result {
        println!("Results match — isOdd() does not depend on msg.sender");
    } else {
        println!("Results differ — the function depends on msg.sender");
    }

    Ok(())
}
```

## When Results Differ

The example above uses `isOdd()`, which does not depend on `msg.sender`. Both reads return the same value. To see a real difference, consider a contract where the view function uses `msg.sender`:

```rust
sol! {
    #[sol(rpc)]
    contract PrivateBalance {
        // Uses msg.sender internally to look up caller's balance
        function balanceOf() public view returns (uint256);
    }
}

let contract = PrivateBalance::new(contract_address, &provider);

// Signed read: msg.sender = your address, returns YOUR balance
let your_balance = contract.balanceOf().seismic().call().await?;
println!("Your balance: {your_balance}");
// e.g., "Your balance: 1000"

// Transparent read: msg.sender = 0x0, returns zero address balance
let zero_balance = contract.balanceOf().call().await?;
println!("Zero address balance: {zero_balance}");
// e.g., "Zero address balance: 0"
```

## Key Differences at a Glance

| Aspect       | `.seismic().call()` (Signed Read)       | `.call()` (Transparent Read)       |
| ------------ | --------------------------------------- | ---------------------------------- |
| Method       | `contract.method().seismic().call()`    | `contract.method().call()`         |
| `msg.sender` | Your wallet address                     | Zero address (`0x0`)               |
| Calldata     | Encrypted with AES-GCM                  | Plaintext                          |
| Response     | Encrypted by TEE, decrypted by provider | Plaintext                          |
| Provider     | `SeismicSignedProvider` only            | Any provider                       |
| Privacy      | Full (observers see nothing)            | None (calldata and result visible) |

## Expected Output

```
Provider ready. Block: 12345
Contract deployed at: 0x5FbDB2315678afecb367f032d93F642f64180aa3
Shielded write confirmed (setNumber(42))

--- Signed Read (.seismic().call()) ---
isOdd() via signed read: false
  - msg.sender = your wallet address
  - Calldata was encrypted
  - Response was encrypted, then decrypted by provider

--- Transparent Read (.call()) ---
isOdd() via transparent read: false
  - msg.sender = 0x0 (zero address)
  - Calldata was plaintext
  - Response was plaintext

--- Comparison ---
Signed read result:      false
Transparent read result:  false
Results match — isOdd() does not depend on msg.sender
```

## Next Steps

* [Shielded Write Complete](/clients/alloy/examples/shielded-write-complete.md) - Full shielded write lifecycle
* [Contract Deployment](/clients/alloy/examples/contract-deployment.md) - Deploy and interact patterns
* [Basic Setup](/clients/alloy/examples/basic-setup.md) - Provider setup details

## See Also

* [Signed Reads Guide](/clients/alloy/guides/signed-reads.md) - Step-by-step guide
* [Shielded Calls](/clients/alloy/contract-interaction/shielded-calls.md) - API reference
* [Transparent Calls](/clients/alloy/contract-interaction/transparent-calls.md) - Non-encrypted operations
* [SeismicSignedProvider](/clients/alloy/provider/seismic-signed-provider.md) - Provider documentation


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.seismic.systems/clients/alloy/examples/signed-read-pattern.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
