fn pause(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
What a transfer of amount costs. recipient_needs_account must match what will be
passed to bridge, or the quote shown and the amount charged will differ.
fn quote(
env: soroban_sdk::Env,
amount: i128,
recipient_needs_account: bool,
) -> Result
fn bridge(
env: soroban_sdk::Env,
req: BridgeRequest,
) -> Result
fn get_seq(env: soroban_sdk::Env) -> u64
Unpause is admin-only: a pauser can stop the world but not restart it.
fn unpause(env: soroban_sdk::Env) -> Result<(), soroban_sdk::Error>
fn get_usdc(env: soroban_sdk::Env) -> soroban_sdk::Address
fn get_admin(env: soroban_sdk::Env) -> soroban_sdk::Address
fn is_paused(env: soroban_sdk::Env) -> bool
fn get_params(env: soroban_sdk::Env) -> Params
fn get_pauser(env: soroban_sdk::Env) -> soroban_sdk::Address
fn get_domains(env: soroban_sdk::Env) -> soroban_sdk::Vec
fn accept_admin(env: soroban_sdk::Env) -> Result<(), soroban_sdk::Error>
usdc and token_messenger are immutable for the life of the contract — there are
no setters and no upgrade entrypoint. A Circle migration means redeploying and
repointing the frontend, which strands nobody precisely because no funds are held
between transactions.
fn __constructor(
env: soroban_sdk::Env,
usdc: soroban_sdk::Address,
token_messenger: soroban_sdk::Address,
admin: soroban_sdk::Address,
pauser: soroban_sdk::Address,
fee_recipient: soroban_sdk::Address,
params: Params,
domains: soroban_sdk::Vec,
) -> Result<(), soroban_sdk::Error>
fn check_max_fee(
env: soroban_sdk::Env,
net_burned: i128,
max_fee: i128,
cap_bps: u32,
) -> Result
fn commit_domain(env: soroban_sdk::Env) -> Result<(), soroban_sdk::Error>
fn commit_params(env: soroban_sdk::Env) -> Result<(), soroban_sdk::Error>
fn commit_pauser(env: soroban_sdk::Env) -> Result<(), soroban_sdk::Error>
The fee split. account_fee is added on top of the percentage-or-floor part, and is zero
unless the destination needs a token account created.
fn compute_split(
env: soroban_sdk::Env,
amount: i128,
fee_bps: u32,
min_fee: i128,
account_fee: i128,
) -> Result
fn propose_admin(
env: soroban_sdk::Env,
new_admin: soroban_sdk::Address,
) -> Result
fn remove_domain(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
domain: u32,
) -> Result<(), soroban_sdk::Error>
fn withdraw_fees(env: soroban_sdk::Env, amount: i128) -> Result<(), soroban_sdk::Error>
The pauser's veto over every pending change, in one call.
fn cancel_pending(
env: soroban_sdk::Env,
caller: soroban_sdk::Address,
) -> Result<(), soroban_sdk::Error>
fn propose_domain(
env: soroban_sdk::Env,
cfg: DomainCfg,
) -> Result
fn propose_params(
env: soroban_sdk::Env,
params: Params,
) -> Result
Replacing the pauser is timelocked, and that is the point.
The pauser's veto over pending proposals is the only defence against a stolen admin key
during the 48h window. While this was instant that defence did not exist: an attacker
holding the admin key would replace the pauser with themselves in one transaction, then
propose maximum fees and a new fee recipient with nobody able to cancel them. Timelocked,
the sitting pauser sees pauser_proposed and can cancel_pending.
The cost is real and worth stating: if the pauser key is lost, rotating to a new one now takes 48 hours. That is the trade — a lost pauser key is an inconvenience, a stolen admin key is an incident.
fn propose_pauser(
env: soroban_sdk::Env,
new_pauser: soroban_sdk::Address,
) -> Result
fn tighten_params(
env: soroban_sdk::Env,
params: Params,
) -> Result<(), soroban_sdk::Error>
fn get_accrued_fees(env: soroban_sdk::Env) -> i128
fn get_fee_recipient(env: soroban_sdk::Env) -> soroban_sdk::Address
fn get_token_messenger(env: soroban_sdk::Env) -> soroban_sdk::Address
fn commit_fee_recipient(env: soroban_sdk::Env) -> Result<(), soroban_sdk::Error>
fn propose_fee_recipient(
env: soroban_sdk::Env,
new_recipient: soroban_sdk::Address,
) -> Result