Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changelog/gentle-doves-play.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
tempo-common: minor
tempo-request: minor
tempo-wallet: minor
---

Adds EIP-1186 MPT proof verification for on-chain reads. Introduces a new `proof` module in `tempo-common` with `verified_storage_at`, `verified_account_balance`, and `verified_token_balance` helpers, and adds a `balance_mapping_slot` field to `TokenConfig`. `tempo-request` and `tempo-wallet` now use verified reads via `eth_getProof`, falling back to unverified `eth_call` if proof pinning fails.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ all = "warn"

[workspace.dependencies]
alloy = { version = "1.6", default-features = false, features = ["std", "providers", "provider-http", "reqwest", "signer-local", "sol-types", "contract"] }
alloy-rlp = "0.3"
alloy-trie = "0.9"
nybbles = "0.4"
base64 = "0.22"
clap = { version = "4.6", features = ["derive", "env"] }
clap_complete = "4.6"
Expand Down
3 changes: 3 additions & 0 deletions crates/tempo-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ workspace = true

[dependencies]
alloy.workspace = true
alloy-rlp.workspace = true
alloy-trie.workspace = true
nybbles.workspace = true
clap.workspace = true
colored.workspace = true
dirs.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/tempo-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod error;
pub mod keys;
pub mod network;
pub mod payment;
pub mod proof;
pub mod security;

pub use payment::session;
Expand Down
7 changes: 7 additions & 0 deletions crates/tempo-common/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ const TEMPO_TOKEN: TokenConfig = TokenConfig {
symbol: "USDC.e",
decimals: 6,
address: USDCE_TOKEN,
balance_mapping_slot: 0,
};

/// Token configuration for Tempo Moderato testnet (pathUSD).
const TEMPO_MODERATO_TOKEN: TokenConfig = TokenConfig {
symbol: "pathUSD",
decimals: 6,
address: PATH_USD_TOKEN,
balance_mapping_slot: 0,
};

// ==================== Network Types ====================
Expand All @@ -53,6 +55,11 @@ pub struct TokenConfig {
pub decimals: u8,
/// Token address - contract address for EVM chains (ERC20)
pub address: Address,
/// Solidity storage slot index of the `balanceOf` mapping.
///
/// Used by proof verification to compute the correct storage key.
/// Standard OpenZeppelin ERC-20 uses slot 0; Tempo TIP-20 uses slot 0.
pub balance_mapping_slot: u8,
}

/// Static network identifier with compile-time metadata.
Expand Down
26 changes: 26 additions & 0 deletions crates/tempo-common/src/payment/session/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,29 @@ pub async fn query_token_balance(
})?;
Ok(balance)
}

/// Query and verify a TIP-20 token balance using an EIP-1186 storage proof.
///
/// Fetches the balance via `eth_getProof` and verifies the Merkle proof against
/// the given pinned block's state root. Detects inconsistent proof data from
/// the provider.
///
/// # Arguments
///
/// * `balance_slot` — Solidity storage slot index of the `balanceOf` mapping.
/// See [`crate::network::TokenConfig::balance_mapping_slot`].
///
/// # Errors
///
/// Returns an error when the RPC call or proof verification fails.
pub async fn query_token_balance_verified(
provider: &impl Provider,
token: Address,
account: Address,
balance_slot: u8,
block: &crate::proof::PinnedBlock,
) -> ChannelResult<U256> {
crate::proof::verified_token_balance(provider, token, account, balance_slot, block)
.await
.map_err(TempoError::from)
}
2 changes: 1 addition & 1 deletion crates/tempo-common/src/payment/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub use store::{
// Re-export public API from `channel`
pub use channel::{
find_all_channels_for_payer, get_channel_on_chain, query_channel_state, query_token_balance,
read_grace_period, DiscoveredChannel, OnChainChannel,
query_token_balance_verified, read_grace_period, DiscoveredChannel, OnChainChannel,
};

// Re-export public API from `close`
Expand Down
15 changes: 15 additions & 0 deletions crates/tempo-common/src/proof/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//! EIP-1186 state proof verification.
//!
//! Provides verified on-chain reads by fetching Merkle-Patricia trie proofs
//! via `eth_getProof` and verifying them against a pinned block's state root.
//!
//! This detects inconsistent or forged proof data from the RPC provider.
//! For full malicious-RPC resistance, the state root should be anchored
//! to an independent trust source (e.g., Tempo L1).

mod verify;

pub use verify::{
pin_latest_block, verified_account_balance, verified_storage_at, verified_token_balance,
verify_account_proof, verify_storage_proof, PinnedBlock, ProofError,
};
Loading
Loading