Contract bcd1765bd178020fa5f64752c48c79a15e296de4f056e5ab42981f5b68f58c17

โ† Back to Index ๐Ÿ“ฅ Download WASM

Meta

cliver 23.4.1#a152ec2488c25136808ad28277c24b3a0765ffd4
rssdkver 23.5.3#d3e1ab2424388b10893b796b0c8e405c5edd03d2
rsver 1.92.0

Instances

  • CDOKC47YXFHZ5COFB667QEXTGXRLCDSELDFD57BPVPCYFMBVOTTNUDYM

Interface

Draw: send NGNC from vault to hot wallet. ReytsCAD settlement to partner is handled off-chain by the API using the same ref_hash for linkage. OPS only.

fn draw(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    deposit_asset_sac: soroban_sdk::Address,
    payment_asset_sac: soroban_sdk::Address,
    deposit_amount: i128,
    payment_amount: i128,
    hot_wallet: soroban_sdk::Address,
    ref_hash: soroban_sdk::BytesN<32>,
)

Block deposits, draws, normal withdrawals โ€” admin only. Emergency withdraw still works.

fn pause(env: soroban_sdk::Env)

Returns (paused, admin, ops, max_draw_per_tx, throttled_max_draw).

fn status(
    env: soroban_sdk::Env,
) -> (bool, soroban_sdk::Address, soroban_sdk::Address, i128, i128)

Rotate ops address โ€” admin + new_ops must co-sign.

fn set_ops(env: soroban_sdk::Env, new_ops: soroban_sdk::Address)

Resume operations โ€” admin only.

fn unpause(env: soroban_sdk::Env)

Normal withdrawal to partner's allowlisted wallet โ€” OPS only.

fn withdraw(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    asset_sac: soroban_sdk::Address,
    amount: i128,
    destination: soroban_sdk::Address,
)

Rotate admin address โ€” both admin and new_admin must co-sign.

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

Check if address is an allowed partner.

fn is_partner(env: soroban_sdk::Env, partner: soroban_sdk::Address) -> bool

Add a KYC'd partner with an initial deposit cap for a specific asset (M-02). Caps for additional assets are added via set_deposit_cap. Admin only.

fn add_partner(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    asset: soroban_sdk::Address,
    deposit_cap: i128,
)

Set exchange rate for the (deposit_asset, payment_asset) pair โ€” OPS only.

Rate semantics (verified 2026-06-05 from the I-07 check at line 1253)

Rate is stored as (deposit-currency-per-payment-currency) ร— 10^7.

For the canonical NGNCโ†’CAD draw:

  • deposit_asset = NGNC (7 decimals)
  • payment_asset = CAD/RCAD (7 decimals)
  • At 1 CAD = 1100 NGN: new_rate = 1100 ร— 10^7 = 11_000_000_000
  • At 1 CAD = 1320 NGN: new_rate = 13_200_000_000

During draw, the I-07 check enforces: expected_payment_stroops = deposit_amount_stroops ร— 10^7 / rate Worked example: 1,000,000 NGNC (= 10^13 stroops) at rate 11_000_000_000: 10^13 ร— 10^7 / 11ร—10^9 = 10^11 / 11 โ‰ˆ 9_090_909_091 CAD stroops โ‰ˆ 909.09 CAD

Auto-calculates drift band. >=15% single-step OR >=1500 bps cumulative drift within the UTC-day window โ†’ pauses draws (RateBandPaused); 5-14% โ†’ throttles to throttled_max_draw per tx (RateBandThrottled).

fn update_rate(
    env: soroban_sdk::Env,
    deposit_asset: soroban_sdk::Address,
    payment_asset: soroban_sdk::Address,
    new_rate: i128,
)

Get current rate for an asset pair.

fn current_rate(
    env: soroban_sdk::Env,
    deposit_asset: soroban_sdk::Address,
    payment_asset: soroban_sdk::Address,
) -> (i128, u64)

Set/rotate the governance contract draw() settles RCAD through. Admin-only. Mainnet hardening: timelock this (deferred; proposal ยง3.6).

fn set_gov_addr(env: soroban_sdk::Env, gov: soroban_sdk::Address)

Update normal max draw per tx โ€” admin only.

fn set_max_draw(env: soroban_sdk::Env, new_max: i128)

I-01: deployment-time constructor. Runs atomically with contract creation, closing the deploy-init race window that initialize() had. Sets roles, draw limits, paused=false.

fn __constructor(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    ops: soroban_sdk::Address,
    max_draw_per_tx: i128,
    throttled_max_draw: i128,
)

Check if address is an allowed hot wallet.

fn is_hot_wallet(env: soroban_sdk::Env, addr: soroban_sdk::Address) -> bool

Add to draw source/destination allowlist โ€” admin only.

fn add_hot_wallet(env: soroban_sdk::Env, addr: soroban_sdk::Address)

Cancel a pending upgrade โ€” admin only.

fn cancel_upgrade(env: soroban_sdk::Env)

Remove partner from allowlist โ€” admin only. Positions preserved for emergency withdraw.

fn remove_partner(env: soroban_sdk::Env, partner: soroban_sdk::Address)

Execute pending WASM upgrade after 24h โ€” admin only.

fn execute_upgrade(env: soroban_sdk::Env)

Propose a WASM upgrade โ€” admin only. Starts 24h timer.

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

Set or update partner's deposit cap for a specific asset (M-02). Caps are enforced per (partner, asset). Admin only.

fn set_deposit_cap(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    asset: soroban_sdk::Address,
    new_cap: i128,
)

Companion to is_rate_band_overridden: returns the current cumulative drift counter (in basis points) for the asset pair. Useful for monitoring how close the system is to the throttle (>=500 bps) or pause (>=1500 bps) thresholds, and for understanding whether an override is about to auto-clear.

fn cumulative_drift(
    env: soroban_sdk::Env,
    deposit_asset: soroban_sdk::Address,
    payment_asset: soroban_sdk::Address,
) -> i128

Get partner position for a specific asset.

fn partner_position(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    asset_sac: soroban_sdk::Address,
) -> i128

Credit partner position after detecting incoming payment โ€” OPS only. Checks cap + velocity + replay.

fn register_deposit(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    asset_sac: soroban_sdk::Address,
    amount: i128,
    tx_ref: soroban_sdk::BytesN<32>,
)

Check if wallet is allowlisted for partner withdrawals.

fn is_partner_wallet(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    wallet: soroban_sdk::Address,
) -> bool

Remove from allowlist โ€” admin only.

fn remove_hot_wallet(env: soroban_sdk::Env, addr: soroban_sdk::Address)

Add a withdrawal destination for partner โ€” admin only.

fn add_partner_wallet(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    wallet: soroban_sdk::Address,
)

Emergency withdrawal โ€” partner auth (not OPS). Full balance for given asset. Works while paused and after removal.

fn emergency_withdraw(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    asset_sac: soroban_sdk::Address,
    destination: soroban_sdk::Address,
)

Acknowledge >=15% rate move (single-step OR cumulative across multiple sub-15% updates per M-01), re-enable draws โ€” admin only.

fn admin_override_rate(
    env: soroban_sdk::Env,
    deposit_asset: soroban_sdk::Address,
    payment_asset: soroban_sdk::Address,
)

Get partner's deposit cap for a specific asset (M-02 per-asset cap).

fn partner_deposit_cap(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    asset: soroban_sdk::Address,
) -> i128

Remove a withdrawal destination for partner โ€” admin only.

fn remove_partner_wallet(
    env: soroban_sdk::Env,
    partner: soroban_sdk::Address,
    wallet: soroban_sdk::Address,
)

Update throttled max draw (5-15% band) โ€” admin only.

fn set_throttled_max_draw(env: soroban_sdk::Env, new_max: i128)

Task #79 โ€” Certora Monitoring #4: sticky RateBandOverride getter.

Returns true if the rate-band-pause-override flag is currently SET for this asset pair (admin_override_rate has been called and cumulative drift has not yet returned below threshold to auto-clear it). When true, the >=15% single-step / >=1500 bps cumulative drift pause is being bypassed โ€” draws proceed with only the normal max_draw_per_tx cap, not the throttled cap.

Off-chain monitoring should read this and emit Slack alerts whenever the flag is on. See testnet-drift-experiment-2026-06-03.md for the discovered behavior: the flag can stay "stuck on" all day if drift accumulates slowly via small updates after an override.

fn is_rate_band_overridden(
    env: soroban_sdk::Env,
    deposit_asset: soroban_sdk::Address,
    payment_asset: soroban_sdk::Address,
) -> bool

Toggle whether draw() MUST perform the atomic gov settlement. Admin-only. Turning this on with GovAddr unset makes every draw fail (GovNotSet) rather than settle NGNC without RCAD โ€” refuse to set the foot-gun. Go-live order: set_gov_addr first, then turn this on.

fn set_require_atomic_settlement(env: soroban_sdk::Env, required: bool)

Imports

WebAssembly Text (WAT) โ–ถ