Contract f6e96a294eafa7ffc4b61f37d8cf8765228c2db77b387c4f6744ac7859f59f89

← Back to Index 📥 Download WASM

Meta

rssdkver 23.5.3#d3e1ab2424388b10893b796b0c8e405c5edd03d2
rsver 1.89.0

Instances

  • CBU7ZTUNOJLSXYGKJL7MG6Y2TRCJSEZUGVBPWFPDT24QQ2AZXO77JLP4

Interface

Initialize the contract with Signal's trust root, relay admin, verifier, and treasury. trust_root_key: 32-byte Montgomery u-coordinate (from Signal's config). verifier_contract: Nethermind Groth16 verifier (stored once, used by register_tee). protocol_treasury: Stellar address for protocol fee collection.

fn initialize(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    trust_root_key: soroban_sdk::BytesN<32>,
    verifier_contract: soroban_sdk::Address,
    protocol_treasury: soroban_sdk::Address,
)

Update the relay admin address (admin-only).

fn update_admin(env: soroban_sdk::Env, new_admin: soroban_sdk::Address)

Set the trusted Docker image hash (admin-only). Only TEE keys generated by containers matching this image will be accepted.

fn set_trusted_image(env: soroban_sdk::Env, image_digest: soroban_sdk::BytesN<32>)

Upgrade the contract WASM (admin-only).

fn upgrade(env: soroban_sdk::Env, new_wasm_hash: soroban_sdk::BytesN<32>)

Register a new user account via a specific relay. Auto-assigns an account number. Returns the assigned account number.

Authenticated by TEE signature over (uuid || identity_key || stellar_address). No admin.require_auth() — the TEE signature proves an attested relay is registering.

fn register(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    uuid: soroban_sdk::String,
    identity_key: soroban_sdk::BytesN<32>,
    stellar_address: soroban_sdk::Address,
    tee_signature: soroban_sdk::BytesN<64>,
) -> u64

Look up account number by Stellar G-address.

fn account_no(env: soroban_sdk::Env, stellar_address: soroban_sdk::Address) -> u64

Look up account number by UUID (read-only).

fn get_account_no(env: soroban_sdk::Env, uuid: soroban_sdk::String) -> u64

Look up Stellar G-address by UUID (read-only).

fn get_stellar_address(
    env: soroban_sdk::Env,
    uuid: soroban_sdk::String,
) -> soroban_sdk::Address

Migrate a user's Stellar address. Requires BOTH the current address holder AND admin to authorize — prevents unilateral relay or user address changes.

fn migrate_stellar_address(
    env: soroban_sdk::Env,
    account_no: u64,
    new_address: soroban_sdk::Address,
)

Add a whitelisted token by symbol (e.g. "USDC") and contract address.

fn add_token(
    env: soroban_sdk::Env,
    symbol: soroban_sdk::String,
    token_address: soroban_sdk::Address,
)
fn remove_token(
    env: soroban_sdk::Env,
    symbol: soroban_sdk::String,
    token_address: soroban_sdk::Address,
)

Set the protocol base fee (admin-only). Applied to all transactions regardless of relay.

fn set_protocol_fee_bps(env: soroban_sdk::Env, fee_bps: u32)

Update the protocol treasury address (admin-only).

fn set_protocol_treasury(env: soroban_sdk::Env, treasury: soroban_sdk::Address)

Authorize a Signal username as a relay identity (admin-only). The TEE operating under this username can self-register via register_tee.

fn authorize_relay(env: soroban_sdk::Env, signal_username: soroban_sdk::String)

Deauthorize a relay (admin-only). Removes authorization and relay info.

fn deauthorize_relay(env: soroban_sdk::Env, signal_username: soroban_sdk::String)

Post a broadcast message (admin-only). All relays poll this and distribute to their users. Used for migration notices, upgrades, etc.

fn set_broadcast(env: soroban_sdk::Env, message: soroban_sdk::String)

Get the latest broadcast message. Returns None if no broadcast has been set.

fn get_broadcast(env: soroban_sdk::Env) -> Option

Deposit any whitelisted token into a user's balance. Anyone can deposit to any account number.

fn deposit(
    env: soroban_sdk::Env,
    token: soroban_sdk::Address,
    funding_address: soroban_sdk::Address,
    account_no: u64,
    amount: i128,
)

Sweep a user's G-address balance for a specific token into their contract balance. Uses the SAC transfer_from with a pre-existing approval set during registration. Only moves funds IN — never out. Callable only by the account holder's S-key.

fn sweep(env: soroban_sdk::Env, account_no: u64, token: soroban_sdk::Address) -> i128

Query a user's balance for a given token.

fn balance(env: soroban_sdk::Env, account_no: u64, token: soroban_sdk::Address) -> i128

Query the protocol base fee in basis points.

fn protocol_fee_bps(env: soroban_sdk::Env) -> u32

Query a relay's hoster fee in basis points.

fn relay_fee_bps(env: soroban_sdk::Env, signal_username: soroban_sdk::String) -> u32

Query relay info (for discovery catalogue).

fn relay_info(env: soroban_sdk::Env, signal_username: soroban_sdk::String) -> RelayInfo

Query invite info (read-only, used by relay for collision checking).

fn get_invite(env: soroban_sdk::Env, invite_code: u32) -> Invite

Claim a sub-account code during the join registration flow. Called BEFORE the child can send instructions (they just registered). TEE signature authenticates the relay (same pattern as register).

fn claim_sub_account(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    claim_code: u32,
    child_uuid: soroban_sdk::String,
    tee_signature: soroban_sdk::BytesN<64>,
)

Claim an invite during the "register <code>" DM flow. Called immediately after register() for users who aren't in the group yet (so they don't have a SenderKey). TEE signature is the only auth.

For users already in the group, "claim <code>" goes through execute_signal_instruction with full SenderKey verification instead.

fn claim_invite(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    claimer_uuid: soroban_sdk::String,
    invite_code: u32,
    tee_signature: soroban_sdk::BytesN<64>,
) -> Result<(), ContractError>

Freeze account — only callable by the user's own Stellar key

fn freeze(env: soroban_sdk::Env, account_no: u64)

Unfreeze account — only callable by the user's own Stellar key

fn unfreeze(env: soroban_sdk::Env, account_no: u64)

Withdraw funds — only callable by the user's own Stellar key. This is the non-custodial exit: relay cannot prevent this. No hoster fee (no relay involved). No token whitelist check — users can always withdraw even if a token is de-listed (non-custodial guarantee).

fn withdraw(
    env: soroban_sdk::Env,
    account_no: u64,
    token: soroban_sdk::Address,
    amount: i128,
    destination: soroban_sdk::Address,
)

Register/re-register a TEE relay with Groth16 attestation proof.

PERMISSIONLESS — no admin.require_auth(). The Groth16 proof serves as authentication: only a genuine TEE running the trusted image can produce a valid proof. Admin controls access by pre-authorizing Signal usernames.

Journal layout (104 bytes): pubkey(32) || image_digest(32) || expiry(8 BE) || signal_id_hash(32)

On restart, the TEE generates a fresh ephemeral key and re-registers. The signal_username is stable across restarts (identity on persistent disk).

fn register_tee(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    seal: soroban_sdk::Bytes,
    image_id: soroban_sdk::BytesN<32>,
    journal: soroban_sdk::Bytes,
    hoster_address: soroban_sdk::Address,
    hoster_fee_bps: u32,
)

Register a SenderKey signing key for a user on a specific relay.

The TEE receives a SenderKey Distribution Message (SKDM) over the Signal group, decrypts it inside the enclave, and signs (sender_uuid || signing_key) with its attested Ed25519 key. The contract verifies this TEE signature and stores the binding per (relay, user).

signing_key: Curve25519 public key from the SenderKey (32 bytes, no prefix). tee_signature: Ed25519 signature over (sender_uuid_bytes || signing_key).

fn register_sender_key(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    sender_uuid: soroban_sdk::String,
    signing_key: soroban_sdk::BytesN<32>,
    tee_signature: soroban_sdk::BytesN<64>,
)

Execute an instruction verified by on-chain SenderKey decryption + TEE attestation.

The contract independently verifies the Signal SenderKey message:

  1. Verifies TEE signature (proves relay forwarded authentic data)
  2. Verifies SenderKey signature over the raw message (proves sender identity)
  3. Derives encryption keys from seed via HKDF("WhisperGroup")
  4. AES-256-CBC decrypts the ciphertext to recover the plaintext instruction
  5. Enforces replay protection via the SenderKeyMessage iteration counter
  6. Parses and executes the instruction

Parameters: sender_key_msg: Raw SenderKeyMessage bytes (version + protobuf + 64-byte signature) seed: SenderMessageKey seed (32 bytes, from the SenderKey chain ratchet) relay_data: Relay-appended data (e.g., invite code). Appended to decrypted instruction with space separator. Empty if no relay data. tee_signature: TEE signs (sender_uuid || sender_key_msg || seed || relay_data)

fn execute_signal_instruction(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    sender_uuid: soroban_sdk::String,
    sender_key_msg: soroban_sdk::Bytes,
    seed: soroban_sdk::BytesN<32>,
    relay_data: soroban_sdk::Bytes,
    tee_signature: soroban_sdk::BytesN<64>,
) -> Result<(), ContractError>

Imports

WebAssembly Text (WAT) ▶