# How the tinywallet‑bus Contract Validates Cryptocurrency Addresses: EVM, Bitcoin, and Solana

> Discover how the tinywallet-bus contract validates cryptocurrency addresses for EVM, Bitcoin, and Solana. Learn about its efficient and secure validation process.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: deep-dive
- Published: 2026-08-30

---

**The tinywallet‑bus contract validates cryptocurrency addresses by delegating to chain‑specific libraries—`ethers_core` for EVM, the `bitcoin` crate for BTC, and `solana_sdk` for SOL—returning a uniform `Result<(), AddressError>` that prevents malformed inputs from reaching the transaction signing layer.**

The tinywallet‑bus crate defines the public contract API for the OpenHuman wallet domain, establishing validation rules that the core implementation must satisfy. By separating the contract interface from the implementation logic, the system ensures that every supported blockchain ecosystem uses its most reliable validation libraries. This architecture guarantees that only syntactically correct, network‑compatible addresses are accepted before any RPC attempts to sign or broadcast a transaction.

## Architecture of the tinywallet‑bus Validation Layer

The contract defines a **`Validate`** trait for each supported chain in [`vendor/tinywallet-bus/src/lib.rs`](https://github.com/tinyhumansai/openhuman/blob/main/vendor/tinywallet-bus/src/lib.rs), establishing the interface that the core OpenHuman code must implement. The actual validation logic resides in [`src/openhuman/web3/wallet/validation.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web3/wallet/validation.rs), where chain‑specific crates handle the cryptographic verification. When validation fails, the system returns an **`AddressError`** defined in [`src/openhuman/web3/wallet/errors.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web3/wallet/errors.rs), which maps to RPC‑compatible error responses.

## EVM Address Validation Using ethers_core

For Ethereum‑compatible chains, the contract leverages the `FromStr` implementation of `ethers_core::types::Address` to verify address formatting.

### Strict Prefix and Length Requirements

The validation logic requires addresses to start with the lowercase prefix **`0x`** exclusively—an uppercase `0X` is rejected, matching the behavior of the upstream `fixed‑hash` crate. The code strips the prefix and verifies that the remaining 40 characters decode as valid hexadecimal. This ensures compliance with EIP‑55 and prevents common formatting errors from reaching the transaction construction phase.

```rust
// Example: validating an Ethereum address before a transfer
use tinywallet_bus::validation::{validate_evm_address, AddressError};

fn send_eth(to: &str, amount: u64) -> Result<(), AddressError> {
    // Verify the address format first
    validate_evm_address(to)?;
    // … continue with transaction construction …
    Ok(())
}

```

## Bitcoin Address Validation with P2WPKH Constraints

Bitcoin validation utilizes the `bitcoin` crate’s `Address::from_str` method to verify Base58Check encoding and network prefixes before allowing transaction construction.

### Base58Check and Network Prefix Verification

The implementation checks for valid network prefixes including `bc1`, `1`, and `3`, and validates the checksum embedded in the Base58Check encoding. This catches transcription errors and ensures the address belongs to the correct network.

### Sender‑Specific P2WPKH Requirements

For sending addresses, the stricter **`validate_btc_sender`** function enforces that the address must be a **Pay‑to‑Witness‑PubKey‑Hash (P2WPKH)** type. This requirement aligns with the current signing workflow implementation in OpenHuman, ensuring compatibility with the wallet's transaction construction logic before any RPC call proceeds.

```rust
// Example: validating a Bitcoin address for a sender
use tinywallet_bus::validation::{validate_btc_sender, AddressError};

fn send_btc(to: &str, amount: u64) -> Result<(), AddressError> {
    // Ensure the address is a P2WPKH (required by current signing flow)
    validate_btc_sender(to)?;
    // … continue with transaction construction …
    Ok(())
}

```

## Solana Address Validation via solana_sdk

Solana validation employs `solana_sdk::pubkey::Pubkey::from_str` to verify that the address represents a base‑58 encoded 32‑byte public key. The implementation verifies both the encoding format and the checksum test, ensuring the address corresponds to a valid Ed25519 public key on the Solana network.

```rust
// Example: validating a Solana address
use tinywallet_bus::validation::{validate_sol_address, AddressError};

fn send_sol(to: &str, amount: u64) -> Result<(), AddressError> {
    // Solana addresses must be a valid base‑58 public key
    validate_sol_address(to)?;
    // … continue with transaction construction …
    Ok(())
}

```

## The Validate Trait and Error Handling Flow

Each chain implements the **`Validate`** trait defined in the contract, returning a uniform `Result<(), AddressError>`. The wallet domain in [`src/openhuman/web3/wallet/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web3/wallet/mod.rs) routes validation calls through this interface before any transaction signing occurs. If validation fails, the RPC immediately returns an **`InvalidAddress`** error, preventing further processing and guaranteeing that only properly formatted addresses reach the broadcast stage.

## Summary

- The tinywallet‑bus contract defines validation interfaces in [`vendor/tinywallet-bus/src/lib.rs`](https://github.com/tinyhumansai/openhuman/blob/main/vendor/tinywallet-bus/src/lib.rs) while delegating implementation to [`src/openhuman/web3/wallet/validation.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web3/wallet/validation.rs).
- **EVM addresses** must use a lowercase `0x` prefix followed by exactly 40 hexadecimal characters.
- **Bitcoin addresses** undergo Base58Check validation with sender addresses specifically requiring P2WPKH format.
- **Solana addresses** must be valid base‑58 encoded 32‑byte public keys verified through `solana_sdk`.
- All validation failures return `AddressError`, blocking transaction signing before any RPC broadcast occurs.

## Frequently Asked Questions

### What happens if an Ethereum address uses an uppercase 0X prefix instead of 0x?

The validation logic in [`src/openhuman/web3/wallet/validation.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web3/wallet/validation.rs) rejects uppercase `0X` prefixes, accepting only lowercase `0x`. This behavior matches the upstream `fixed-hash` crate specification and ensures strict compliance with Ethereum address formatting standards.

### Why does the Bitcoin sender validation require a P2WPKH address type?

The **`validate_btc_sender`** function enforces Pay‑to‑Witness‑PubKey‑Hash (P2WPKH) format because OpenHuman's current signing workflow requires SegWit compatibility for transaction construction. This constraint ensures that the wallet can properly generate and sign the transaction script before broadcasting to the Bitcoin network.

### How does the validation contract prevent invalid addresses from reaching the RPC layer?

The wallet domain calls validation functions from `tinywallet_bus::validation` before any transaction signing begins. If validation returns an `AddressError`, the RPC layer immediately returns an `InvalidAddress` error response, guaranteeing that malformed addresses never proceed to the signing or broadcast stages.

### Which file contains the implementation logic for address validation?

The core implementation resides in [`src/openhuman/web3/wallet/validation.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web3/wallet/validation.rs), which contains the chain‑specific validation logic using `ethers_core`, `bitcoin`, and `solana_sdk` libraries. The contract definitions and error types live in [`vendor/tinywallet-bus/src/lib.rs`](https://github.com/tinyhumansai/openhuman/blob/main/vendor/tinywallet-bus/src/lib.rs) and [`src/openhuman/web3/wallet/errors.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web3/wallet/errors.rs) respectively.