Raw addresses are hard to verify
Long hex addresses are easy to mistype, truncate, or misread. A single character error can permanently route funds to the wrong destination.
Destination-safe Web3 Transfers
SafeSend is a transfer flow designed to reduce wrong-recipient risk in crypto payments. Instead of sharing
raw wallet addresses in chats, users share an intelligible Safe ID in the format
pseudonym@safeIdHash and complete claims through a recipient-bound,
proof-verified flow.
Example: sara@9f3e2c7b1a8d4e5f2b6c9d0a1e3f4b5c7d8e9f0a2b3c4d5e6f708192a3b4c5d6
Why SafeSend
Long hex addresses are easy to mistype, truncate, or misread. A single character error can permanently route funds to the wrong destination.
Teams often share addresses in chats and docs where copy-paste mistakes, stale data, and impersonation risks are common. A Safe ID starting with a pseudonym adds immediate human context before verification.
Traditional transfers offer limited recovery. SafeSend adds lifecycle controls for expiry refunds, cancellation, and clear status tracking.
How It Works
SafeSend uses an intelligible Safe ID string for sender UX, then anchors routing to the Safe ID commitment on-chain and validates final claim data against recipient identity and transfer metadata.
The recipient creates a local encrypted identity using a passphrase. SafeSend derives a Safe ID
commitment from that identity and displays a user-facing Safe ID as
pseudonym@safeIdHash.
Sender receives a Safe ID with a readable pseudonym prefix instead of manually managing a raw destination address through chat or email. This reduces destination-entry mistakes at source.
Sender creates ETH or ERC-20 transfer with recipient, Safe ID, and expiry. The contract records a pending transfer state.
Recipient unlocks identity locally and submits claim. The verifier checks proof/public inputs that bind `safeIdHash`, `pseudonymHash`, `transferId`, and recipient address.
Both parties track pending, claimed, refunded, or cancelled transfers through filtered history and cursor-based pagination.
Architecture
Next.js + wagmi + viem UI for identity, transfer creation, claiming, and lifecycle visibility.
UUPS upgradeable escrow state machine with status transitions and verifier-based claim authorization.
Sepolia event indexer with PostgreSQL-backed `/transfers` history API and cursor pagination.
Technical Specifications
SafeSend.sol (UUPS)Sepolia (11155111)0x5b989a4C075df43Cf351CcBEA44A113653B53BFC0xa0cc74f92e5d8f248f794ac3538fef1dbe2d4b240 Pending | 1 Claimed | 2 Refunded | 3 Cancelled3 (then auto-refund)The SafeSend contract will be deployed on Ethereum Mainnet soon. Mainnet contract addresses and verifier details will be published here once deployment is completed.
createTransfer(address recipient, bytes32 safeIdHash, bytes32 pseudonymHash, uint64 expiry)
createTransfer(address recipient, address token, uint256 amount, bytes32 safeIdHash, bytes32 pseudonymHash, uint64 expiry)
claim(uint256 transferId, bytes zkProof, uint256[] publicInputs)
refundExpired(uint256 transferId)
cancelTransfer(uint256 transferId)
Claim public input layout: [safeIdHash, pseudonymHash, transferId, recipient(uint160), nullifier]
GET /healthGET /transfersaddress, sender, receiver, token, statuscursor + limit (default 20, max 100)GET, OPTIONS, access-control-allow-origin: *TransferCreated
TransferStatusChanged
ClaimFailed
ClaimSucceeded
TransferRefunded
Data is persisted in PostgreSQL with sender/receiver and ordering indexes.
Security and Reliability Controls
Raw identity secret is not sent to contract calldata. Claim validation is based on proof verification.
Nullifier tracking prevents proof replay for already-used claims.
Pending transfers can be cancelled by payer pre-expiry, refunded after expiry, or refunded after max failed claims.
Deploy the app at app.safesend.ch and serve this landing on safesend.ch.