Destination-safe Web3 Transfers

Prevent destination mistakes with pseudonym-first Safe IDs.

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

  • UUPS upgradeable Proxy-based contract lifecycle
  • 3 claim attempts max Auto-refund guardrail
  • Human-intelligible Safe ID Pseudonym + cryptographic hash

Why SafeSend

Wrong destination errors are expensive and usually irreversible.

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.

Human context is often missing

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.

Recovery paths are weak

Traditional transfers offer limited recovery. SafeSend adds lifecycle controls for expiry refunds, cancellation, and clear status tracking.

How It Works

Safe ID is the primary transfer primitive.

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.

  1. 1

    Create local identity and Safe ID

    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.

  2. 2

    Share Safe ID with sender

    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.

  3. 3

    Create transfer on-chain

    Sender creates ETH or ERC-20 transfer with recipient, Safe ID, and expiry. The contract records a pending transfer state.

  4. 4

    Recipient claims with proof context

    Recipient unlocks identity locally and submits claim. The verifier checks proof/public inputs that bind `safeIdHash`, `pseudonymHash`, `transferId`, and recipient address.

  5. 5

    Monitor status in indexer-backed UI

    Both parties track pending, claimed, refunded, or cancelled transfers through filtered history and cursor-based pagination.

Architecture

Three layers working together

Client dApp

Next.js + wagmi + viem UI for identity, transfer creation, claiming, and lifecycle visibility.

SafeSend Contract

UUPS upgradeable escrow state machine with status transitions and verifier-based claim authorization.

Indexer API

Sepolia event indexer with PostgreSQL-backed `/transfers` history API and cursor pagination.

Technical Specifications

Built with explicit, inspectable components.

Smart Contract Core

  • ContractSafeSend.sol (UUPS)
  • NetworkSepolia (11155111)
  • Proxy0x5b989a4C075df43Cf351CcBEA44A113653B53BFC
  • Verifier0xa0cc74f92e5d8f248f794ac3538fef1dbe2d4b24
  • Status Enum0 Pending | 1 Claimed | 2 Refunded | 3 Cancelled
  • Max Claim Attempts3 (then auto-refund)

Contract Methods

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]

Indexer API Surface

  • HealthGET /health
  • HistoryGET /transfers
  • Filtersaddress, sender, receiver, token, status
  • Paginationcursor + limit (default 20, max 100)
  • CORSGET, OPTIONS, access-control-allow-origin: *

Indexed Events

TransferCreated
TransferStatusChanged
ClaimFailed
ClaimSucceeded
TransferRefunded

Data is persisted in PostgreSQL with sender/receiver and ordering indexes.

Security and Reliability Controls

Secret handling

Raw identity secret is not sent to contract calldata. Claim validation is based on proof verification.

Replay prevention

Nullifier tracking prevents proof replay for already-used claims.

Recovery paths

Pending transfers can be cancelled by payer pre-expiry, refunded after expiry, or refunded after max failed claims.

Build destination-safe transfer flows with SafeSend.

Deploy the app at app.safesend.ch and serve this landing on safesend.ch.