Contract cd3e15f3a13d07dbda5561a4137035124f3cbdb964becfadf9bb54630f839daa

← 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. 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)

Add a trusted attestation provider signing key hash (admin-only bootstrap). The hash is SHA-256 of the RSA modulus bytes (big-endian). Used at deployment to seed the initial trusted key set.

fn set_trusted_jwks_key(
    env: soroban_sdk::Env,
    key_hash: soroban_sdk::BytesN<32>,
    trusted: bool,
)

Add a trusted attestation provider signing key hash via an attested relay. Any registered relay can call this with a TEE signature over the key hash. This enables autonomous key rotation without admin intervention, preserving non-custodial operation.

fn relay_add_jwks_key(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    key_hash: soroban_sdk::BytesN<32>,
    tee_signature: soroban_sdk::BytesN<64>,
)

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

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. claim_invite now takes a 32-byte invite_hash (SHA256(pepper || code)) instead of a plaintext code. The relay computes the hash using its TEE-held pepper and passes it here.

fn claim_invite(
    env: soroban_sdk::Env,
    signal_username: soroban_sdk::String,
    claimer_identity: soroban_sdk::BytesN<32>,
    invite_hash: soroban_sdk::BytesN<32>,
    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. Fee-free to preserve the non-custodial invariant (admin cannot tax the emergency exit).

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) ▶