Contract e3675dabc646ac9d7af9a95f58c849ca036f6d99bf57c62b539dfe4d1e9f406b

← Back to Index 📥 Download WASM

Meta

rssdkver 23.5.3#d3e1ab2424388b10893b796b0c8e405c5edd03d2
rsver 1.89.0

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. sender_identity: SHA256(GroupIdentifier || UUID) — opaque composite identity. Authenticated by TEE signature over (sender_identity).

fn register(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    sender_identity: 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 identity (read-only).

fn get_account_no(env: soroban_sdk::Env, identity: soroban_sdk::BytesN<32>) -> u64

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

fn get_stellar_address(
    env: soroban_sdk::Env,
    identity: soroban_sdk::BytesN<32>,
) -> soroban_sdk::Address

Migrate a user's Stellar address. Requires BOTH the current address holder AND admin to authorize.

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_identity: soroban_sdk::BytesN<32>,
    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_identity: soroban_sdk::BytesN<32>,
    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. Non-custodial exit: relay cannot prevent this.

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_identity || signing_key).

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

Migrate an account from the old UUID-keyed schema to the new composite identity schema. Called by the relay at startup after WASM upgrade. Old entries are orphaned (TTL expiry). The relay queries old data via simulation BEFORE the upgrade, then calls this after.

TEE signature over (new_identity || account_no as u64 BE bytes) authenticates the relay.

fn migrate_account(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    new_identity: soroban_sdk::BytesN<32>,
    account_no: u64,
    stellar_address: soroban_sdk::Address,
    frozen: bool,
    balances: soroban_sdk::Vec<(soroban_sdk::Address, i128)>,
    sender_key: Option>,
    msg_counter: Option,
    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_identity || sender_key_msg || seed || relay_data)

fn execute_signal_instruction(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    sender_identity: soroban_sdk::BytesN<32>,
    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) ▶