Contract ff70c6cc39b3e9a24b5ac773efc4c1c39763f9fc1b3be516a076c457c7d06990

← Back to Index 📥 Download WASM

Meta

cliver 28.0.0#300aaf69ab100536678bdb641428b06f06b318ea
rssdkver 27.0.6#60926a20d1f9f0a669d5fe551636f42a1302f0c0
rsver 1.96.0

Instances

  • CCILIJUSNCS4BOIWEKQU7UYXKN6B4DIUJJ4BSC6NJMUVP5WTE5Z4MYZR

Interface

Deposit backer money. Counts toward capacity after 7 days.

fn back(
    env: soroban_sdk::Env,
    backer: soroban_sdk::Address,
    amount: i128,
) -> Result<(), PoolError>
fn pause(env: soroban_sdk::Env)
fn stake(
    env: soroban_sdk::Env,
    staker: soroban_sdk::Address,
    amount: i128,
    beneficiary: soroban_sdk::Address,
) -> Result<(), PoolError>

r3 (2026-09-29): permissionless. Redeems only the vault's growth above book value and splits it (stakers / backers / protocol). Best effort: returns 0 rather than failing. Also runs inside every yield payout, so nobody has to call it. Replaces the admin-only extract_yield.

fn harvest(env: soroban_sdk::Env) -> i128
fn unpause(env: soroban_sdk::Env)
fn withdraw(
    env: soroban_sdk::Env,
    staker: soroban_sdk::Address,
    beneficiary: soroban_sdk::Address,
) -> Result<(), PoolError>
fn get_admin(env: soroban_sdk::Env) -> soroban_sdk::Address
fn get_claim(env: soroban_sdk::Env, claim_id: soroban_sdk::BytesN<32>) -> Option
fn get_stake(
    env: soroban_sdk::Env,
    wallet: soroban_sdk::Address,
) -> Option
fn get_vault(env: soroban_sdk::Env) -> Option
fn is_paused(env: soroban_sdk::Env) -> bool
fn get_backer(
    env: soroban_sdk::Env,
    backer: soroban_sdk::Address,
) -> Option
fn get_oracle(env: soroban_sdk::Env) -> soroban_sdk::Address

r3: a staker takes their yield without unstaking. Paid to the beneficiary (hash-checked as in withdraw).

fn claim_yield(
    env: soroban_sdk::Env,
    staker: soroban_sdk::Address,
    beneficiary: soroban_sdk::Address,
) -> Result
fn get_setting(env: soroban_sdk::Env, key: SettingKey) -> i128

V8 isEligible: has an active, non-withdrawn, non-suspended stake. Does NOT check the time gate, see is_claim_eligible.

fn is_eligible(env: soroban_sdk::Env, wallet: soroban_sdk::Address) -> bool
fn cancel_claim(
    env: soroban_sdk::Env,
    claim_id: soroban_sdk::BytesN<32>,
) -> Result<(), PoolError>
fn claim_stream(
    env: soroban_sdk::Env,
    claim_id: soroban_sdk::BytesN<32>,
    beneficiary: soroban_sdk::Address,
) -> Result

Staker principal + matured backer money: what claims are sized against.

fn get_capacity(env: soroban_sdk::Env) -> i128
fn get_guardian(env: soroban_sdk::Env) -> soroban_sdk::Address
fn set_pool_cap(env: soroban_sdk::Env, new_cap: i128) -> Result<(), PoolError>

CHANGED T2/D1: deadline + signature are now required arguments. When caller is the oracle the contract verifies an Ed25519 signature over the verdict on-chain; when caller is the admin (manual fallback) both are ignored, exactly as in V8. See claim::submit_claim for the full auth-model rationale.

fn submit_claim(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    wallet: soroban_sdk::Address,
    tx_hash: soroban_sdk::BytesN<32>,
    entitlement: i128,
    tier: u32,
    hack_timestamp: u64,
    deadline: u64,
    signature: soroban_sdk::BytesN<64>,
) -> Result, PoolError>

Deploy-time initialization.

CHANGED 2026-08-17 (7a audit, Finding 3): was a separate initialize entrypoint. Renamed to __constructor, the SDK-recognised constructor hook, which runs as part of the deploy invocation itself.

Why this mattered: initialize authorized the admin argument passed to it, and the only thing stopping a second call was the AlreadyInitialized guard. That guard protects against re-initialization but not against being first, between the deploy transaction and the legitimate init transaction, anyone observing the chain could call initialize with themselves as admin and satisfy require_auth trivially. The T1 testnet deployment used two separate transactions (README), so the window was real rather than theoretical. Stellar's own guidance is explicit: prefer __constructor because it "removes the front-running window between deploy and init", and note that a contract deployed without one can never gain it afterwards, which is why this had to change before D4's deploy,

fn __constructor(
    env: soroban_sdk::Env,
    admin: soroban_sdk::Address,
    oracle: soroban_sdk::Address,
    oracle_pubkey: soroban_sdk::BytesN<32>,
    co_signer: soroban_sdk::Address,
    guardian: soroban_sdk::Address,
    xlm_token: soroban_sdk::Address,
    pool_cap: i128,
) -> Result<(), PoolError>

NEW 2026-07-22 (Rule A), staker-authorized. Burns the wallet's entire lifetime points balance, forfeits the stake, starts cooldown/vesting. Must be called within APPROVE_WINDOW_LEDGERS of the claim entering AwaitingApproval.

fn approve_claim(
    env: soroban_sdk::Env,
    claim_id: soroban_sdk::BytesN<32>,
) -> Result<(), PoolError>

Returns true once cancelled (standard changes need two roles).

fn cancel_change(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    kind: GovKind,
) -> Result
fn get_co_signer(env: soroban_sdk::Env) -> soroban_sdk::Address
fn suspend_stake(
    env: soroban_sdk::Env,
    wallet: soroban_sdk::Address,
) -> Result<(), PoolError>
fn approve_change(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    change: GovChange,
) -> Result<(), PoolError>
fn cancel_setting(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    key: SettingKey,
) -> Result<(), PoolError>
fn emergency_exit(
    env: soroban_sdk::Env,
    staker: soroban_sdk::Address,
) -> Result<(), PoolError>
fn execute_change(env: soroban_sdk::Env, kind: GovKind) -> Result<(), PoolError>
fn get_deploy_bps(env: soroban_sdk::Env) -> i128

r3: false until the first stake or backing; while false, vault / treasury / deploy-ceiling changes apply without the 7-day wait.

fn is_ever_funded(env: soroban_sdk::Env) -> bool

Permissionless: start counting a matured deposit toward capacity.

fn mature_backing(
    env: soroban_sdk::Env,
    backer: soroban_sdk::Address,
) -> Result
fn propose_change(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    change: GovChange,
) -> Result<(), PoolError>

Send already-liquid excess above staker principal to treasury.

fn withdraw_yield(env: soroban_sdk::Env, amount: i128) -> Result<(), PoolError>
fn approve_setting(
    env: soroban_sdk::Env,
    key: SettingKey,
    value: i128,
) -> Result<(), PoolError>

Supply liquid XLM into the vault. Returns shares gained. min_shares_out is the caller's floor against an adverse share price: quote it off-chain via the vault's get_asset_amounts_per_shares first.

fn deploy_to_vault(
    env: soroban_sdk::Env,
    amount: i128,
    min_shares_out: i128,
) -> Result
fn execute_setting(env: soroban_sdk::Env, key: SettingKey) -> Result<(), PoolError>

Additive staker yield index. Starts at YIELD_INDEX_PRECISION; grows only via credit_yield's staker-share split. Exposed mainly for audit/observability: callers wanting a staker's actual withdrawable balance should call get_withdrawable_amount instead of re-deriving the ratio themselves.

fn get_yield_index(env: soroban_sdk::Env) -> i128
fn propose_setting(
    env: soroban_sdk::Env,
    key: SettingKey,
    value: i128,
) -> Result<(), PoolError>

T2/D1: admin-only. Cancels a signed-but-not-yet-submitted oracle approval. Takes the full approval parameters rather than a precomputed hash (V8's shape); see claim::revoke_approval for why.

fn revoke_approval(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    wallet: soroban_sdk::Address,
    tx_hash: soroban_sdk::BytesN<32>,
    entitlement: i128,
    tier: u32,
    hack_timestamp: u64,
    deadline: u64,
) -> Result<(), PoolError>
fn set_beneficiary(
    env: soroban_sdk::Env,
    staker: soroban_sdk::Address,
    new_beneficiary: soroban_sdk::Address,
) -> Result<(), PoolError>

claim_id optional: pass the wallet's in-flight claim (if any) so its Rule A/B deadline clock resets on unsuspend (eng review blocker #1). None if the wallet has no claim needing a reset.

fn unsuspend_stake(
    env: soroban_sdk::Env,
    wallet: soroban_sdk::Address,
    claim_id: Option>,
) -> Result<(), PoolError>
fn approve_override(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    wallet: soroban_sdk::Address,
    tx_hash: soroban_sdk::BytesN<32>,
    entitlement: i128,
    tier: u32,
) -> Result<(), PoolError>

T3 (2026-08-24), permissionless sibling of provide_liquidity. Pulls back only enough to cover total_allocated if liquid balance is short of it. No caller input. Works while paused, same reasoning as provide_liquidity. Returns 0 if nothing's short.

fn ensure_liquidity(env: soroban_sdk::Env) -> Result
fn get_paused_until(env: soroban_sdk::Env) -> u64
fn get_total_backed(env: soroban_sdk::Env) -> i128
fn get_total_staked(env: soroban_sdk::Env) -> i128
fn propose_recovery(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    change: GovChange,
) -> Result<(), PoolError>
fn get_total_stakers(env: soroban_sdk::Env) -> u32

The protocol's own realised, unwithdrawn yield share, "the protocol's own money", withdrawable any time via withdraw_yield. CHANGED 2026-09-18: now reads the explicit ProtocolYieldBalance counter, not the removed residual formula (documented bug history: see vault.rs).

fn get_yield_balance(env: soroban_sdk::Env) -> i128

V8 isClaimEligible: is_eligible AND the 90-day time gate has passed.

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

Redeem shares so the XLM sits liquid in the contract, ready to fund payouts and withdrawals. Nothing leaves the pool. Works while paused, deliberately: emergency_exit depends on it.

fn provide_liquidity(
    env: soroban_sdk::Env,
    shares: i128,
    min_asset_out: i128,
) -> Result

r3: a backer takes their yield, principal untouched. Paid to the backer.

fn claim_backer_yield(
    env: soroban_sdk::Env,
    backer: soroban_sdk::Address,
) -> Result

NEW 2026-07-22 (Rule B sweep), permissionless. Releases whatever's left uncollected if the staker goes COLLECTION_INACTIVITY_LEDGERS with zero claim_stream activity.

fn expire_stale_claim(
    env: soroban_sdk::Env,
    claim_id: soroban_sdk::BytesN<32>,
) -> Result<(), PoolError>

Real liquid XLM held by the contract, distinct from get_total_staked, which counts XLM sitting in the vault too.

fn get_liquid_balance(env: soroban_sdk::Env) -> i128
fn get_pending_change(env: soroban_sdk::Env, kind: GovKind) -> Option

V8 pointsOf: live-computed if still staked and not withdrawn, else the banked balance. NOT a raw storage read.

fn get_points_balance(env: soroban_sdk::Env, wallet: soroban_sdk::Address) -> i128

r3: set-aside yield (stakers, backers). Never deployed or spent on claims.

fn get_yield_reserved(env: soroban_sdk::Env) -> (i128, i128)

T3 (2026-08-24), permissionless. Sweeps a queued claim whose claim window ran out before capacity ever freed.

fn expire_queued_claim(
    env: soroban_sdk::Env,
    claim_id: soroban_sdk::BytesN<32>,
) -> Result<(), PoolError>
fn get_pending_setting(
    env: soroban_sdk::Env,
    key: SettingKey,
) -> Option
fn get_total_allocated(env: soroban_sdk::Env) -> i128
fn unlock_pending_claim(
    env: soroban_sdk::Env,
    claim_id: soroban_sdk::BytesN<32>,
) -> Result<(), PoolError>

T3 (2026-08-24), permissionless sibling of deploy_to_vault. Puts idle liquidity (above what's reserved for live claims) to work automatically, up to the existing deploy_bps ceiling. No caller input: the contract computes the amount and its own slippage floor. Requires at least one prior manual deploy_to_vault call (needs a reference rate); returns 0 if nothing's idle or no room remains under the ceiling.

fn auto_deploy_liquidity(env: soroban_sdk::Env) -> Result

r3: a backer's yield credited and not yet paid.

fn get_backer_yield_owed(env: soroban_sdk::Env, backer: soroban_sdk::Address) -> i128

r3: a staker's yield credited and not yet paid (excludes growth still in the vault until the next harvest).

fn get_staker_yield_owed(env: soroban_sdk::Env, staker: soroban_sdk::Address) -> i128
fn get_backer_yield_index(env: soroban_sdk::Env) -> i128
fn cancel_pending_override(
    env: soroban_sdk::Env,
    caller: soroban_sdk::Address,
    wallet: soroban_sdk::Address,
    tx_hash: soroban_sdk::BytesN<32>,
) -> Result<(), PoolError>

NEW 2026-07-22 (Rule A sweep), permissionless, mirrors unlock_pending_claim. Releases the reservation back to the pool if the staker never approved within the window.

fn expire_pending_approval(
    env: soroban_sdk::Env,
    claim_id: soroban_sdk::BytesN<32>,
) -> Result<(), PoolError>

A staker's current withdrawable value, principal plus their proportional share of yield realised since they staked. 0 for no stake, a withdrawn stake, or a forfeited (claimed) one.

fn get_withdrawable_amount(env: soroban_sdk::Env, staker: soroban_sdk::Address) -> i128
fn cancel_backer_withdrawal(
    env: soroban_sdk::Env,
    backer: soroban_sdk::Address,
) -> Result<(), PoolError>

Current deployed fraction in bps. May read above get_deploy_bps after a large withdrawal: that is drift, not a breach; see vault.rs.

fn get_deployment_ratio_bps(env: soroban_sdk::Env) -> i128
fn get_total_backed_pending(env: soroban_sdk::Env) -> i128

XLM in the vault at ORIGINAL deposit value, never marked to market.

fn get_total_deployed_asset(env: soroban_sdk::Env) -> i128

T3 (2026-08-24), permissionless. Re-checks a queued claim's original blocker (DailyStressCapExceeded/Insolvent) against current state; admits it for real if that now passes, otherwise returns QueueReleaseNotYetEligible and it stays Reserved.

fn try_release_queued_claim(
    env: soroban_sdk::Env,
    claim_id: soroban_sdk::BytesN<32>,
) -> Result<(), PoolError>
fn get_total_deployed_shares(env: soroban_sdk::Env) -> i128
fn get_total_extracted_yield(env: soroban_sdk::Env) -> i128

Start the notice period. Returns the earliest completion timestamp.

fn request_backer_withdrawal(
    env: soroban_sdk::Env,
    backer: soroban_sdk::Address,
    amount: i128,
) -> Result

Pay a requested withdrawal to the backer's own address, once the notice has passed and only from capital open claims don't need.

fn complete_backer_withdrawal(
    env: soroban_sdk::Env,
    backer: soroban_sdk::Address,
) -> Result

Imports

WebAssembly Text (WAT) ▶