The Payment Flow


sequenceDiagram
autonumber
actor Payer
participant Registrar
participant Onramp
participant Safe as Safe (Smart Account)

Note over Payer: wants to pay an X handle (e.g., @X)

%% 1–2. Request deposit address
Payer->>Registrar: Ask for ETH deposit address for @X

%% 3. Registrar derives and returns address
Registrar->>Registrar: Deterministically derive deposit address
Registrar-->>Payer: Return deposit address (Safe address)

%% 4. Payment
alt Use onramp
    Payer->>Onramp: Start onramp (buy/bridge any token)
    Onramp->>Safe: Deposit funds to derived address
else Already has coins
    Payer->>Safe: Transfer tokens/ETH to derived address
end

Safe Smart Account

graph TD
    subgraph Safe["Safe Smart Account (deterministically derived address)"]
        RegistrarOwner["Owner: Registrar"]
        Exec["Ownable Executor Module"]
    end

    RegistrarOwner -->|controls| Safe
    Safe --> Exec
    Exec -->|later sets owner| Payee

    RegistrarOwner:::actor
    Payee:::actor
    Safe:::contract
    Exec:::module

Claim Flow (Setup)

sequenceDiagram
autonumber
actor Payee as Payee (X handle owner)
participant App as User App (browser / embedded wallet)
participant ZK as ZK Prover
participant Registrar
participant Safe as Safe (for @X)
participant Exec as Executor Module

%% 1–2. Payee arrives and enters handle
Payee->>App: Open site and enter handle (@X)

%% 3–4. App generates and stores embedded wallet
App->>App: Generate embedded wallet (private/public keypair)
Note right of App: Keypair securely stored locally<br/>within browser storage

%% 5. Generate zk proof for ownership and command
App->>ZK: Generate zk proof of handle ownership<br/>+ intent: setOwner(0x123)
ZK-->>App: zk proof

%% 6. Submit proof to registrar
App->>Registrar: Submit {handle=@X, proof, targetOwner=0x123}

%% 7. Registrar verifies and updates Safe
Registrar->>Registrar: Verify proof and resolve Safe for @X
Registrar->>Safe: Access Safe (owner = Registrar)
Registrar->>Exec: setOwner(0x123)
Exec-->>Registrar: Owner updated

%% Acknowledgement
Registrar-->>Payee: Confirmation: Executor Module owner set to 0x123

Claim Flow (Withdraw)

sequenceDiagram
autonumber
actor Payee
participant App as User App (browser + embedded wallet)
participant Exec as Executor Module (on Safe)
participant Safe as Safe (for @X)
participant Recipient as Recipient Address
participant Offramp as Off-ramp Service

%% Load embedded wallet
Payee->>App: Open site (Withdraw)
App->>App: Load embedded wallet from local storage

opt Wallet not found
    App-->>Payee: No wallet found → redirect to Setup / Claim flow
end

%% Choose withdrawal path
alt Direct on-chain withdrawal
    Payee->>App: Choose "Withdraw to address" (amount, token, recipient)
    App->>Exec: withdraw(token, amount, to=Recipient) signed by embedded wallet
    Exec->>Safe: Execute transfer
    Safe-->>Recipient: Tokens / ETH transferred
    App-->>Payee: Withdrawal complete (on-chain)
else Off-ramp withdrawal
    Payee->>App: Choose "Off-ramp" (amount, token, payout option)
    App->>Offramp: Initiate off-ramp request
    Offramp-->>App: Return deposit address (D)
    App->>Exec: withdraw(token, amount, to=D) signed by embedded wallet
    Exec->>Safe: Execute transfer
    Safe-->>Offramp: Tokens / ETH sent to D
    Offramp-->>Payee: Fiat payout to bank / card / wallet
end