Why TinyWallet-Bus Rejects Uppercase 0X EVM Prefixes
TinyWallet-Bus rejects uppercase "0X" EVM prefixes because its validate_ethereum_address function delegates parsing to ethers_core::types::Address::from_str, which only strips the lowercase "0x" prefix before decoding, causing uppercase variants to fail validation.
The OpenHuman project's TinyWallet-Bus crate enforces strict formatting rules for Ethereum addresses submitted to its wallet API. When validating an address, the library specifically rejects any string beginning with an uppercase "0X" prefix, even when the subsequent hexadecimal characters are valid. This behavior stems from the underlying parsing logic inherited from the ethers-rs ecosystem, which enforces a canonical lowercase prefix representation.
How TinyWallet-Bus Validates Ethereum Addresses
In vendor/tinywallet-bus/src/validation.rs (lines 27-38), the validate_ethereum_address function serves as the entry point for all address validation within the OpenHuman wallet contract. Rather than implementing custom parsing logic, this wrapper delegates directly to the standard Ethers-Core parser:
// vendor/tinywallet-bus/src/validation.rs
pub fn validate_ethereum_address(s: &str) -> Result<Address, ValidationError> {
ethers_core::types::Address::from_str(s)
.map_err(|e| ValidationError::InvalidFormat(e.to_string()))
}
This delegation means TinyWallet-Bus inherits the strict prefix requirements defined in the upstream ethers_core::types::Address::from_str implementation, as utilized in the OpenHuman integration layer at src/openhuman/web3/wallet.rs.
The Root Cause: Case-Sensitive Prefix Stripping in Ethers-Core
The rejection occurs in the external dependency ethers-core, specifically within src/address.rs (lines 50-61). The parser checks for the prefix using a case-sensitive comparison that only recognizes the lowercase "0x" string:
// ethers-core/src/types/address.rs (lines 50-61)
if s.starts_with("0x") {
// Strip lowercase prefix and decode hex
} else {
// Any other prefix, including "0X", triggers InvalidPrefix error
Err(ParseHexError::InvalidPrefix)
}
Because the starts_with("0x") check is case-sensitive, an address beginning with "0X" bypasses the prefix-stripping logic. The subsequent hex-decode step then encounters the literal "0X" characters, fails to parse them as hexadecimal digits, and returns an error that TinyWallet-Bus propagates as a validation failure.
Practical Code Examples: Testing Address Validation
When integrating TinyWallet-Bus into your application, passing an address with an uppercase prefix results in immediate rejection, while the lowercase variant succeeds:
use tinywallet_bus::validation::validate_ethereum_address;
fn main() {
// ✅ Accepted – lowercase prefix (valid)
assert!(validate_ethereum_address(
"0x1234abcd5678ef901234abcd5678ef901234abcd"
).is_ok());
// ❌ Rejected – uppercase prefix (invalid)
assert!(validate_ethereum_address(
"0X1234ABCD5678EF901234ABCD5678EF901234ABCD"
).is_err());
}
This strict validation applies consistently across the OpenHuman codebase. The wallet integration at src/openhuman/web3/wallet.rs relies on TinyWallet-Bus for all EVM address processing, inheriting these case-sensitive requirements.
Summary
- TinyWallet-Bus delegates all address parsing to
ethers_core::types::Address::from_strviavendor/tinywallet-bus/src/validation.rs(lines 27-38). - The underlying parser only accepts the lowercase "0x" prefix, rejecting uppercase "0X" variants.
- Case-sensitive prefix matching in
ethers-core/src/types/address.rs(lines 50-61) causes validation failures for non-canonical formats. - This behavior enforces a single, unambiguous address representation throughout the OpenHuman wallet API.
Frequently Asked Questions
Does TinyWallet-Bus accept any uppercase letters in Ethereum addresses?
While the "0X" prefix is strictly rejected, the hexadecimal characters following a valid "0x" prefix may contain uppercase letters depending on the checksum implementation. However, the prefix itself must always be lowercase to pass initial validation in vendor/tinywallet-bus/src/validation.rs.
Is this rejection of 0X a bug or intentional design?
This is intentional. The design enforces a canonical representation for EVM addresses throughout the OpenHuman codebase, preventing ambiguities that could arise from mixed-case prefixes and ensuring consistent address handling across the wallet API.
How can I normalize addresses to avoid rejection?
Normalize user input by converting the first two characters to lowercase before validation, or use a standard library function that ensures the "0x" prefix conforms to the expected format prior to calling validate_ethereum_address.
Which files handle the validation logic in the OpenHuman repository?
The primary validation wrapper resides in vendor/tinywallet-bus/src/validation.rs, which is consumed by the integration layer in src/openhuman/web3/wallet.rs. The actual parsing rules are defined in the external ethers-core/src/types/address.rs dependency (lines 50-61).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →