SafHandle Contract
On-chain short names and phone links for Safrochain
Status: v1 implemented and deployed to testnet. The CosmWasm contract is built, covered by
cw-multi-testintegration tests, and live onsafro-testnet-1. v1 registers short names only — phone linking is a Phase 2 feature compiled out of the shipped wasm (Cargo featurephone, off by default).
SafHandle lets users send SAF to short names like john.saf instead of long addr_safro1... addresses. This repository contains the CosmWasm smart contract, its tests, and deployment documentation. Phone-number handles are planned for Phase 2.
Read the full explanation: docs/HOW_IT_WORKS.md
| Problem | SafHandle solution |
|---|---|
| Long, error-prone wallet addresses | Human-readable short names (john, john.saf) |
| Copy-paste friction in P2P payments | Resolve a name or phone to addr_safro in one query |
| No standard name registry on Safrochain | Canonical on-chain registry any wallet or dApp can query |
| Phone-based payments off-chain only | On-chain phone links planned for Phase 2 (see PHONE_LINKING.md) |
User registers "john.saf" → pays 50 SAF → contract stores john.saf → addr_safro1...
Anyone calls get_address → contract returns wallet address
sequenceDiagram
participant User as User
participant Wallet as Wallet
participant Contract as SafHandle_Contract
participant Dev as Dev_Module_Wallet
User->>Wallet: Register john.saf
Wallet->>Contract: register_name + 50 SAF fee
Contract->>Dev: Transfer fee
Contract-->>Wallet: Name registered
participant App as dApp_or_Wallet
App->>Contract: get_address(john)
Contract-->>App: addr_safro1...
| Action | Default fee | Routing | Availability |
|---|---|---|---|
| Register short name | 50 SAF | Dev module wallet | v1 |
| Link phone number | 100 SAF | Dev module wallet | Phase 2 |
Fees are governance-updatable. See docs/FEES_AND_GOVERNANCE.md.
| Document | Contents |
|---|---|
| docs/README.md | Documentation index |
| HOW_IT_WORKS.md | End-to-end user journey |
| ARCHITECTURE.md | On-chain design and components |
| CONTRACT_API.md | Execute and query message specification |
| NAME_RULES.md | Allowed formats and normalization |
| FEES_AND_GOVERNANCE.md | Fee defaults and governance params |
| PHONE_LINKING.md | On-chain phone links, Phase 2 verification |
| ANTI_SQUATTING.md | Squatting protections |
| STATE_SCHEMA.md | Storage layout for implementers |
| DEPLOYMENT.md | Deployment workflow |
| MIGRATION.md | Contract migration strategy |
| SECURITY_MODEL.md | Threat model |
| ROADMAP.md | Implementation phases |
contracts/safhandle/
├── Cargo.toml
├── src/
│ ├── contract.rs # entry points: instantiate / execute / query / migrate
│ ├── msg.rs # InstantiateMsg / ExecuteMsg / QueryMsg / MigrateMsg
│ ├── state.rs # Config, NameRecord, storage Maps/Items
│ ├── error.rs # ContractError variants
│ ├── validation.rs # name normalization + hardened validation
│ ├── helpers.rs # fee assertion helper
│ ├── lib.rs
│ └── bin/schema.rs # JSON schema generator
├── tests/
│ └── integration.rs # cw-multi-test coverage
└── schema/ # generated JSON schema (gitignored)
scripts/
└── deploy-testnet.sh # store + instantiate on testnet
artifacts/
├── safhandle.wasm # optimized build (gitignored)
└── checksums.txt
config/
├── testnet.json
└── mainnet.json
Phone linking code (state, messages, queries, validation) also lives in src/
but is compiled out unless built with --features phone. See
PHONE_LINKING.md.
| Network | Chain ID | Bech32 prefix | Denom |
|---|---|---|---|
| Mainnet | safrochain-1 |
addr_safro |
usaf (6 decimals) |
| Testnet | safro-testnet-1 |
addr_safro |
usaf (6 decimals) |
See config/ for RPC endpoints and fee defaults.
| Repository | Description |
|---|---|
| safhandle-sdk | TypeScript/JavaScript client for wallets and dApps |
See CONTRIBUTING.md. Security issues: SECURITY.md — do not open public issues for vulnerabilities.
MIT — Copyright (c) 2026 Safrochain