ethereum-mysql
Design Purpose:
ethereum-mysql is the missing bridge between Rust Web3 application code and SQL databases. While alloy provides foundational Ethereum types, writing production backend code still involves tedious boilerplate — manual conversions, unreadable arithmetic, and type-unsafe string handling.
This crate solves two real-world pain points:
🔥 Pain Point 1: Intuitive Arithmetic
Without this crate, every calculation requires verbose U256::from() wrappers:
// ❌ Vanilla alloy: verbose, error-prone
let fee = balance * U256from / U256from;
let doubled = balance + U256from;
With ethereum-mysql, write natural, readable code:
// ✅ ethereum-mysql: clean, intuitive
let fee = balance * 25u64 / 10000u64;
let doubled = balance + 2u64;
🚀 Pain Point 2: API-Ready Types
Without this crate, your web API structs need manual conversions between Rust primitives and Ethereum types:
// ❌ Without ethereum-mysql: manual parsing in every handler
With ethereum-mysql, use types directly — validation happens automatically:
// ✅ ethereum-mysql: type-safe, validated automatically
Features
- 🔥 Intuitive Arithmetic: Direct
+,-,*,/,%(and+=,-=,*=,/=,%=) betweenSqlU256/SqlU128and all Rust unsigned primitives (u8–u128,usize). Plusiter().sum()/iter().product()for aggregation. - 🚀 API-Ready:
Serialize/Deserialize/FromRowall work out of the box — useSqlAddress/SqlU256/SqlU128directly in your DTOs - Binary storage: Big-endian bytes (BINARY/BYTEA/BLOB) following alloy-rs/core#970 and #1020
- Multi-database: MySQL, PostgreSQL, SQLite via SQLx
- Type-safe wrappers:
SqlAddress,SqlU128,SqlU256,SqlFixedBytes<N>,SqlBytes - Unified error type:
SqlTypeErrorenum instead of ad-hoc&'static str— properstd::error::Errorimpl - Compile-time macros:
sqladdress!,sqlhash! - Constants:
SqlAddress::ZERO,SqlU256::ZERO,SqlU256::ETHER - Decimal utilities:
parse_sether/format_setherfor human-readable ETH amounts - Serde + SQLx native: Implements
Serialize/Deserializeandsqlx_core::Type/Encode/Decode
Database Column Types
All types are stored as raw big-endian bytes:
| Type | MySQL | PostgreSQL | SQLite |
|---|---|---|---|
| SqlAddress | BINARY(20) | BYTEA | BLOB |
| SqlU128 | BINARY(16) | BYTEA | BLOB |
| SqlU256 | BINARY(32) | BYTEA | BLOB |
| SqlFixedBytes<N> | BINARY(N) | BYTEA | BLOB |
| SqlBytes | VARBINARY | BYTEA | BLOB |
Binary Encoding
- All fixed-size types (Address, U128, U256, FixedBytes) are stored as big-endian byte arrays matching their exact byte width.
SqlBytesis stored as a variable-length byte array.- For predictable sorting/comparison, big-endian encoding ensures binary-order matches numeric-order for Uint types.
Key Advantages
� Intuitive Arithmetic
let mut balance = from_str.unwrap; // 1 ETH
let fee = balance * 25u64 / 10000u64; // 0.25% fee — clean & readable
balance += 500u64; // assign ops with primitives
balance *= 2u64;
// Iterator aggregation
let amounts = vec!;
let total: SqlU256 = amounts.iter.sum; // 30
Supports +, -, *, /, %, +=, -=, *=, /=, %=, sum(), product() with u8–u128, usize.
🚀 API-Ready
Works with serde_json, sqlx::FromRow, actix-web, axum, and any serde-compatible framework.
🛡️ Type Safety
Compile-time macros (sqladdress!, sqlhash!) and runtime validation for all types. Unified SqlTypeError for conversion errors (no &'static str).
⚡ Binary Storage
Direct Vec<u8> encoding via SQLx — optimal performance, BINARY/BYTEA/BLOB natively.
Quick Start
Add to your Cargo.toml:
= "4.0.0"
Example Usage
Address Creation
use ;
use FromStr;
let zero = ZERO;
let addr = sqladdress!;
let addr2 = from_str.unwrap;
const ADMIN: SqlAddress = sqladdress!;
U256 Usage & Ethereum Constants
use ;
use FromStr;
// Basic usage
let small = from;
let large = from;
let zero = ZERO;
let from_decimal = from_str.unwrap;
let from_hex = from_str.unwrap;
assert_eq!;
// Ethereum amount calculations
let one_ether = ETHER; // 10^18 wei
let half_ether = ETHER / 2u64;
let gas_price = from; // 20 gwei
// Decimal string parsing and formatting
let amount = parse_sether.unwrap; // Parse 1.5 ETH
assert_eq!;
// Arithmetic operations
let a = from;
let b = from;
let sum = a + b;
let product = a * b;
let doubled = a * 2u64;
let tripled = 3u64 * a;
U128 Usage
use SqlU128;
// Common for Solidity uint128 values
let amount = from;
let supply: SqlU128 = from_str.unwrap; // max uint128
let half = amount / 2u64;
Hash and FixedBytes Creation
use ;
// Create various sized hashes at compile time
const TX_HASH: = sqlhash!;
const FUNCTION_SELECTOR: = sqlhash!;
const TOPIC: = sqlhash!;
SQLx Integration (Binary Mode)
use ;
use MySqlPool;
use FromStr;
async
JSON Serialization (with serde)
use ;
use ;
let user = User ;
let json = to_string?;
Migration from v3.x (String Storage)
Starting from v4.0, this crate uses binary storage (BINARY/BYTEA/BLOB) instead of hex string storage (VARCHAR/TEXT).
Migrating your database schema:
| Type | v3.x Column | v4.0 Column |
|---|---|---|
| SqlAddress | VARCHAR(42) | BINARY(20) |
| SqlU256 | VARCHAR(66) | BINARY(32) |
| SqlFixedBytes<N> | VARCHAR(2+2*N) | BINARY(N) |
| SqlBytes | TEXT | VARBINARY |
To migrate existing data, use hex-to-binary conversion:
-- MySQL example: migrate VARCHAR(42) address column to BINARY(20)
users ADD COLUMN wallet_address_bin BINARY(20);
UPDATE users SET wallet_address_bin = UNHEX(SUBSTRING(wallet_address, 3));
users DROP COLUMN wallet_address;
users CHANGE wallet_address_bin wallet_address BINARY(20);
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.