Complete catalog of all public read-only views on LiquifactEscrow. All functions are pure reads:
no state mutation, no authorization required unless specified otherwise.
Integrator note: Return types, defaults, and absent-key behavior documented for each view match the on-chain implementation exactly. Off-chain tooling should use these views rather than re-implementing storage reads to guarantee identical semantics.
Core Escrow State:
Immutable Bindings:
Admin & Governance:
- get_pending_admin
- get_pending_admin_expiry
- get_pending_admin_remaining_secs
- get_legal_hold
- get_legal_hold_clear_delay
- get_legal_hold_clearable_at
Funding Constraints:
- get_funding_deadline
- is_funding_expired
- get_min_contribution_floor
- get_max_unique_investors_cap
- get_remaining_investor_slots
- get_max_per_investor_cap
Maturity & Settlement:
Tier Lookup:
Per-Investor State:
- get_contribution
- get_unique_funder_count
- get_investor_yield_bps
- get_investor_claim_not_before
- is_investor_claimed
- is_investor_refunded
- compute_investor_payout
- get_claimable_payout
- get_settlement_pool
Attestations:
- get_primary_attestation_hash
- get_attestation_append_log
- get_attestation_log_stats
- is_attestation_revoked
Collateral Metadata:
Allowlist:
Distributed Principal:
Storage key: DataKey::Escrow
Signature: pub fn get_escrow(env: Env) -> InvoiceEscrow
Returns the full escrow snapshot containing all core state fields.
Requires initialization: Yes — emits [EscrowError::EscrowNotInitialized] (code 20) if called before init.
Return value:
InvoiceEscrowstruct with fields:invoice_id,admin,sme_address,amount,funding_target,funded_amount,yield_bps,maturity,status.
Storage key: DataKey::Version
Signature: pub fn get_version(env: Env) -> u32
Returns the stored schema version written by init (see SCHEMA_VERSION).
Requires initialization: No
Default when absent: 0
Return value:
u32schema version (current production:6).- Returns
0if called beforeinit.
Signature: pub fn get_escrow_summary(env: Env) -> EscrowSummary
Bundles multiple read-only values in a single host invocation, optimizing read latency and gas efficiency for off-chain indexers and frontend rendering.
Requires initialization: Yes — panics via get_escrow if escrow is not initialized.
Return value: EscrowSummary struct containing:
escrow: InvoiceEscrow— Full escrow snapshot.has_maturity_lock: bool— True whenescrow.maturity > 0.legal_hold: bool— True if compliance hold is active.funding_close_snapshot: EscrowCloseSnapshot— Custom option-like enum (NoneorSome(FundingCloseSnapshot)).unique_funder_count: u32— Distinct address count.is_allowlist_active: bool— Allowlist gate status.schema_version: u32— Contract schema version.sme_collateral_commitment: CollateralCommitmentSnapshot— Custom option-like enum (NoneorSome(SmeCollateralCommitment)).has_primary_attestation: bool— Primary attestation binding status.attestation_log_length: u32— Number of append-log entries.
Storage key: DataKey::FundingToken
Signature: pub fn get_funding_token(env: Env) -> Address
Returns the SEP-41 token contract address bound to this escrow instance at init.
Immutable: Set once at init; cannot change after deploy.
Requires initialization: Yes — emits [EscrowError::FundingTokenNotSet] (code 21) if called before init.
Return value:
Addressof the funding token contract.- This is the only token that
sweep_terminal_dustmay transfer to the treasury.
Storage key: DataKey::Treasury
Signature: pub fn get_treasury(env: Env) -> Address
Returns the protocol treasury address that receives terminal dust sweeps.
Immutable: Set once at init; cannot change after deploy.
Requires initialization: Yes — emits [EscrowError::TreasuryNotSet] (code 22) if called before init.
Return value:
Addressof the treasury.- The treasury must authorize
sweep_terminal_dust; the admin cannot sweep unless it is also the treasury.
Storage key: DataKey::RegistryRef
Signature: pub fn get_registry_ref(env: Env) -> Option<Address>
Returns the optional registry contract address supplied at init, or None when absent.
Immutable: Set once at init; cannot change after deploy.
Requires initialization: No
Default when absent: None
Non-authority model:
RegistryRefis a read-only discoverability hint for off-chain indexers only.- No on-chain logic in this contract reads or calls this address.
- Its presence does not prove registry membership; call the registry contract directly to verify.
- The key is omitted from instance storage entirely when
registry = Noneatinit.
Return value:
Some(Address)when a registry was configured.Noneotherwise.
Storage key: DataKey::PendingAdmin
Signature: pub fn get_pending_admin(env: Env) -> Option<Address>
Returns the proposed successor admin waiting for accept_admin, or None when no handover is in progress.
Requires initialization: No
Default when absent: None
Return value:
Some(Address)when a handover is pending.Nonewhen nopropose_adminhas been issued, or after a successfulaccept_admin.
Storage key: DataKey::PendingAdminExpiry
Signature: pub fn get_pending_admin_expiry(env: Env) -> Option<u64>
Returns the absolute ledger timestamp recorded by propose_admin, or None when no expiry has been recorded.
Requires initialization: No
Default when absent: None
Return value:
Some(timestamp)when a handover proposal with an expiry exists.Nonebeforepropose_admin, afteraccept_admin, aftercancel_pending_admin, or when no expiry key is present.
Storage keys: DataKey::PendingAdmin, DataKey::PendingAdminExpiry
Signature: pub fn get_pending_admin_remaining_secs(env: Env) -> Option<u64>
Returns the pending-admin proposal's remaining validity window computed against Env::ledger().timestamp().
Requires initialization: No
Default when absent: None
Return value:
Nonewhen no pending admin proposal is active.Some(expiry - now)whilenow < expiry.Some(0)whennow >= expiry, using saturating arithmetic.
Boundary parity with accept_admin:
- At
now == expiry, this view returnsSome(0)andaccept_adminstill accepts the proposal. - At
now > expiry, this view still returnsSome(0)andaccept_adminrejects withAdminProposalExpired. - Pure read: no authorization, no storage writes, no TTL bump.
Storage key: DataKey::Escrow
Returns the remaining funding capacity before the funding target is reached.
-
Calculation:
funding_target.saturating_sub(funded_amount)clamped at0(via.max(0)) so it never goes negative when over-funded. -
Informational only: This view is for frontend guidance. The
fundmethod may still accept deposits that over-fund past the target while the escrow status is0(Open). - No authorization: Pure read; no auth or signature required.
-
Complexity:
- Time Complexity:
$O(1)$ read from storage. - Space Complexity:
$O(1)$ in-memory calculation.
- Time Complexity:
- Panics with
"Escrow not initialized"beforeinit.
Storage key: DataKey::LegalHold
Signature: pub fn get_legal_hold(env: Env) -> bool
Returns true when a compliance hold is active; blocks settle, withdraw, claim_investor_payout, fund, and sweep_terminal_dust.
Requires initialization: No
Default when absent: false
Derived from: DataKey::Escrow (funded_amount, funding_target)
Returns true when funded_amount >= funding_target.
Exposes the contract's authoritative funding-completion predicate as a pure read view so
frontends no longer need to reimplement the funding logic client-side. Frontends and
indexers should call this view instead of reading get_escrow() and comparing fields
manually, because this view exactly mirrors the predicate used internally by the funding
transition logic and is therefore guaranteed to stay in sync with any future changes.
| Condition | Returns |
|---|---|
funded_amount < funding_target |
false |
funded_amount == funding_target |
true |
funded_amount > funding_target |
true |
funded_amount >= funding_target
This is identical to the condition in fund_impl that transitions status from 0
(open) to 1 (funded).
A true result before the funded status transition cannot occur because the transition
is atomic: funded_amount is updated and status is set to 1 in the same storage
write within fund_impl. Consequently is_fully_funded() == true implies status == 1.
None — pure read; no auth required, no state mutation, no side effects.
Storage key: DataKey::LegalHoldClearDelay
Signature: pub fn get_legal_hold_clear_delay(env: Env) -> u64
Returns the configured minimum delay (in seconds) between request_clear_legal_hold and set_legal_hold(false).
Requires initialization: No
Default when absent: 0 (no delay enforced; hold can be cleared immediately)
Storage key: DataKey::LegalHoldClearableAt
Signature: pub fn get_legal_hold_clearable_at(env: Env) -> Option<u64>
Returns the earliest ledger timestamp at which a pending legal-hold clear may be applied, or None when no clear request has been recorded.
Requires initialization: No
Default when absent: None
Return value:
Some(timestamp)afterrequest_clear_legal_holdis called.Nonewhen no request is pending (or after a successful clear removes the key).
Storage key: DataKey::FundingDeadline
Signature: pub fn get_funding_deadline(env: Env) -> Option<u64>
Returns the optional funding deadline (ledger timestamp). After this timestamp passes, fund calls are rejected.
Requires initialization: No
Default when absent: None (no deadline — funding is open indefinitely)
Return value:
Some(timestamp)when configured atinit.Nonewhen no deadline was set.
Signature: pub fn is_funding_expired(env: Env) -> bool
Returns true when a funding deadline is set and Env::ledger().timestamp() > deadline.
Requires initialization: No
Default when absent: false (no deadline set → never expired)
Logic:
if FundingDeadline exists:
return ledger.timestamp() > deadline
else:
return false
Storage key: DataKey::MinContributionFloor
Signature: pub fn get_min_contribution_floor(env: Env) -> i128
Returns the minimum per-call funding amount in token base units. Applies to every fund / fund_with_commitment call.
Requires initialization: No (but written as 0 at init)
Default when absent: 0 (no extra floor beyond "amount must be positive")
Notes:
- The floor applies to each individual deposit, not to cumulative principal.
- Written as
0even when unconfigured atinit, so reads always succeed post-init.
Storage key: DataKey::MaxUniqueInvestorsCap
Signature: pub fn get_max_unique_investors_cap(env: Env) -> Option<u32>
Returns the optional cap on distinct investor addresses. Reflects the current stored cap, including any reduction via lower_max_unique_investors.
Requires initialization: No
Default when absent: None (unlimited investors)
Return value:
Some(u32)when configured.Nonewhen no cap was set atinit.
Signature: pub fn get_remaining_investor_slots(env: Env) -> Option<u32>
Returns the number of remaining investor slots before the MaxUniqueInvestorsCap is reached. This safely resolves the gap between the cap and the get_unique_funder_count.
Requires initialization: No
Default when absent: None (unlimited investors)
Return value:
Nonewhen no cap is configured (i.e., the escrow accepts unlimited distinct investors).Some(u32)indicating the exact remaining capacity of new distinct investors. Calculated ascap - unique_funder_count. Floored at zero (saturating subtraction) ensuring it stays completely consistent and safe even if the cap is reduced vialower_max_unique_investors.
Storage key: DataKey::MaxPerInvestorCap
Signature: pub fn get_max_per_investor_cap(env: Env) -> Option<i128>
Returns the optional immutable cap on cumulative principal for a single investor address.
Requires initialization: No
Default when absent: None (unlimited per-investor)
Return value:
Some(i128)when configured atinit.Nonewhen unconfigured.
Derived from: DataKey::Escrow.maturity
Signature: pub fn has_maturity_lock(env: Env) -> bool
Returns true when InvoiceEscrow::maturity > 0 and settle() is gated by ledger time.
Requires initialization: Yes — calls get_escrow internally.
Logic:
return get_escrow().maturity > 0
Return value:
true— settlement requiresEnv::ledger().timestamp() >= maturity.false—maturity == 0; no time lock, funded escrow can settle immediately.
Storage key: DataKey::FundingCloseSnapshot
Signature: pub fn get_funding_close_snapshot(env: Env) -> Option<FundingCloseSnapshot>
Returns the pro-rata denominator snapshot captured exactly once when the escrow first transitioned from open (0) to funded (1).
Requires initialization: No
Default when absent: None (escrow has not yet reached funded status)
Immutable once written: the snapshot is never updated after the status-0-to-1 transition.
Return value:
Noneuntil the escrow reachesstatus == 1.Some(FundingCloseSnapshot)with fields:total_principal: i128—funded_amountat close (includes over-funding past target).funding_target: i128— Snapshot of target at close time.closed_at_ledger_timestamp: u64— Ledger timestamp of the funding transition.closed_at_ledger_sequence: u32— Ledger sequence at transition.
Historical alias of get_effective_yield_bps —
same return value, documented around the per-investor storage slot.
Storage key: DataKey::InvestorEffectiveYield(investor), falling back to DataKey::Escrow.yield_bps
Returns the resolved effective yield (bps) the investor would receive at settlement — exactly the
rate compute_investor_payout applies when computing the coupon. The resolution is identical to the
payout math:
effective_yield_bps = InvestorEffectiveYield(investor) // tier locked at first deposit
.unwrap_or(escrow.yield_bps) // else the escrow base yield
| Investor state | Returns |
|---|---|
Tiered (funded via fund_with_commitment) |
the tier yield_bps selected at first deposit |
| Base-only / non-tiered | the escrow base yield_bps |
| Unknown (never funded) | the escrow base yield_bps |
DataKey::InvestorEffectiveYield is the stored per-investor slot: present only after a tiered
first deposit, absent otherwise. This view returns the resolved value — the stored slot when
present, otherwise the base-yield fallback — so integrators read the same number the payout math uses
without re-implementing the unwrap_or fallback themselves.
get_investor_yield_bps returns the same value; prefer get_effective_yield_bps when the intent is
"the rate compute_investor_payout will actually apply."
Signature: pub fn preview_yield_tier(env: Env, amount: i128, lock: u64) -> YieldResolution
Pure read — no auth, no storage writes, safe for simulation.
Returns a YieldResolution for a hypothetical first deposit of amount
with lock seconds of commitment, using the exact same tier-selection rule applied by
fund_with_commitment. This lets a prospective investor see which tier they would receive before
depositing, without re-implementing the selection logic.
The amount parameter mirrors the fund_with_commitment signature. In the current release, tier
selection is lock-only; amount is accepted for API parity and forward-compatibility.
Return fields (YieldResolution):
| Condition | effective_yield_bps |
matched_lock_secs |
|---|---|---|
No YieldTierTable configured |
escrow base yield_bps |
0 |
lock == 0 |
escrow base yield_bps |
0 |
lock below every tier threshold |
escrow base yield_bps |
0 |
lock >= min_lock_secs of a tier |
highest qualifying tier's yield_bps |
that tier's min_lock_secs |
Note: this preview reflects the rule applied at first deposit only. A follow-on
fundcall does not re-select a tier.
Security note: the preview is guaranteed to agree with fund_with_commitment because it delegates
to the same internal effective_yield_for_commitment helper — there is no separate selection path.
Named return type for preview_yield_tier
and the internal effective_yield_for_commitment helper.
| Field | Type | Description |
|---|---|---|
effective_yield_bps |
i64 |
Resolved yield in basis points. Equals the escrow base yield when no tier matched, or the highest qualifying tier's yield_bps otherwise. |
matched_lock_secs |
u64 |
min_lock_secs of the matched tier, or 0 when base yield applies (no tier table, empty table, zero-lock, or no qualifying tier). |
Storage key: DataKey::InvestorContribution(investor) (persistent)
Signature: pub fn get_contribution(env: Env, investor: Address) -> i128
Returns the cumulative principal contributed by investor in token base units.
Requires initialization: No
Default when absent: 0 (never contributed)
Storage type: Persistent (independent TTL per address; see ADR-007)
Storage key: DataKey::InvestorContribution(investor) (persistent, one read per input)
Signature: pub fn get_contributions(env: Env, investors: Vec<Address>) -> Vec<i128>
Returns one contribution amount per supplied address, preserving input order. Unknown addresses
return 0, matching get_contribution.
Requires initialization: No
Default when absent: 0 per address
Batch bound: investors.len() <= MAX_INVESTOR_READ_BATCH (50)
Error: EscrowError::ContributionReadBatchTooLarge when the input exceeds the bound
Security note: Pure read-only; performs no authorization, storage writes, or TTL extension.
Storage key: DataKey::UniqueFunderCount
Signature: pub fn get_unique_funder_count(env: Env) -> u32
Returns the count of distinct investor addresses with non-zero contributions. Initialized to 0 at init.
Requires initialization: No (but written as 0 at init)
Default when absent: 0
Notes: counts distinct chain accounts, not real-world persons (Sybil resistance is not a goal of this counter).
Storage key: DataKey::InvestorEffectiveYield(investor) (persistent)
Signature: pub fn get_investor_yield_bps(env: Env, investor: Address) -> i64
Returns the effective annualized yield in basis points locked in at the investor's first deposit.
Requires initialization: Yes — reads get_escrow() for the base yield fallback.
Default when absent: falls back to InvoiceEscrow::yield_bps (base yield for legacy / simple fund positions)
Storage type: Persistent
Return value:
- Investor's tier-selected
yield_bpswhen set viafund_with_commitment. - Base
InvoiceEscrow::yield_bpsfor simplefunddeposits or pre-v2 positions.
Storage key: DataKey::DistributedPrincipal
Returns the total principal already returned to investors via [LiquifactEscrow::refund].
- Used by [
LiquifactEscrow::sweep_terminal_dust] to compute outstanding liabilities. - Absent ⇒
0(no refunds have occurred).
Storage key: None (reads [DataKey::FundingToken] and queries token contract)
Returns the contract's current funding-token balance for on-chain custody reconciliation.
- Emits [
EscrowError::FundingTokenNotSet] if called beforeinit. - Pure read — no authorization required, no state mutation.
Auditors can reconcile on-chain custody against recorded liabilities:
balance = get_token_balance()
funded_amount = get_escrow().funded_amount
distributed_principal = get_distributed_principal()
outstanding_liability = funded_amount - distributed_principal
excess_balance = balance - outstanding_liability // tokens available for sweep
// After the cancelled escrow's liability is fully discharged (all refunds complete):
// balance == distributed_principal == funded_amount (or less if partial sweep occurred)
This view surfaces the balance already consulted internally by [LiquifactEscrow::sweep_terminal_dust]
and [LiquifactEscrow::withdraw] for liability-floor enforcement.
Storage keys: reads DataKey::Escrow, DataKey::DistributedPrincipal, and
DataKey::FundingToken (then queries the token contract for the live balance).
Returns the contract's full reconciliation position in a single call, so operators no longer have to fetch the balance, funded amount, distributed principal, and settlement state separately and re-implement the liability arithmetic off-chain (see the Reconciliation relationship above).
outstanding_liability = max(funded_amount - distributed_principal, 0)
surplus = token_balance - outstanding_liability
outstanding_liability uses the identical floor that
[LiquifactEscrow::sweep_terminal_dust] enforces, so the view and the sweep guard
can never disagree. surplus is the sweepable dust when positive and a deficit
when negative.
| Field | Type | Description |
|---|---|---|
token_balance |
i128 |
Live SEP-41 funding-token balance held by the contract. |
outstanding_liability |
i128 |
Principal still owed to investors: max(funded_amount - distributed_principal, 0). |
surplus |
i128 |
token_balance - outstanding_liability. Positive = sweepable surplus; negative = deficit. |
- Pure read — no authorization required, no state mutation.
- Never panics on values — all arithmetic is saturating.
- Emits [
EscrowError::EscrowNotInitialized] / [EscrowError::FundingTokenNotSet] only when the escrow has not been initialized.
Security note: in settled (2) and withdrawn (3) states distributed_principal
is 0 by design, so outstanding_liability reflects the full funded_amount and the
reported surplus is never larger than what sweep_terminal_dust would actually
permit (that guard only applies the floor in the cancelled state 4). The view is
therefore conservative and can never over-report sweepable funds.
Storage key: DataKey::InvestorClaimed(investor) (persistent)
Signature: pub fn is_investor_claimed(env: Env, investor: Address) -> bool
Returns true when the investor has exercised claim_investor_payout after settlement.
Requires initialization: No
Default when absent: false
Storage type: Persistent
Notes: written once and never unset. A second claim_investor_payout call is a no-op (idempotent) rather than an error.
Storage key: DataKey::InvestorRefunded(investor)
Signature: pub fn is_investor_refunded(env: Env, investor: Address) -> bool
Returns true when an investor's principal has been returned via refund in a cancelled (status 4) escrow.
Requires initialization: No
Default when absent: false
Notes: written once; prevents double-refund. After refund succeeds, get_contribution for the same address returns 0.
Signature: pub fn compute_investor_payout(env: Env, investor: Address) → i128
None— Escrow is not yet funded; no close snapshot exists.Some(FundingCloseSnapshot)— The pro-rata denominator snapshot captured when the escrow first transitioned to funded.
Storage keys: DataKey::FundingCloseSnapshot, DataKey::Escrow
Signature: pub fn get_settlement_pool(env: Env) -> i128
Returns the total settlement pool owed by the SME — the aggregate principal plus base-yield coupon the SME must repay to fully satisfy all investors. Avoids rounding divergence that arises when off-chain tooling re-derives the formula from raw snapshot fields.
coupon = total_principal × yield_bps / 10_000 (floor)
settle_pool = total_principal + coupon
Where total_principal is from DataKey::FundingCloseSnapshot and yield_bps is the
escrow base yield from InvoiceEscrow::yield_bps.
Uses the escrow base yield only. Per-investor effective yields from fund_with_commitment
tier selection are reflected individually in compute_investor_payout but are not aggregated
here.
| Condition | Returns |
|---|---|
DataKey::FundingCloseSnapshot absent (escrow not yet funded) |
0 |
total_principal <= 0 (degenerate snapshot) |
0 |
| Normal funded state | total_principal + floor(total_principal × yield_bps / 10_000) |
All multiplications use i128::checked_mul; all divisions use i128::checked_div. Emits
EscrowError::ComputePayoutArithmeticOverflow (code 129) on overflow.
Sum of all per-investor compute_investor_payout values is guaranteed ≤ get_settlement_pool().
Any fractional residue is swept by sweep_terminal_dust.
None — pure read; no auth required and no state mutation.
Storage key: DataKey::YieldTierTable
Returns the yield-tier ladder configured at init, or an empty Vec when no tiers were configured (base yield applies to all investors).
- Immutable — set once at
init; the contract never mutates this key after initialization. - Order — returned order matches the validated non-decreasing ordering enforced at
init:min_lock_secsstrictly increasing,yield_bpsnon-decreasing. - Empty vec — returned for both "no tiers passed at init" and "legacy instance predating tier support"; callers must not treat an empty result as an error.
- Pure read — no auth required, no state mutation.
Returns a read-only paginated view of the configured yield-tier ladder using the same start/limit contract as the existing investor and allowlist read views.
- Start beyond the end — returns an empty page.
- Limit zero — returns an empty page.
- Limit above the pagination ceiling — clamps to the shared pagination ceiling (
MAX_INVESTOR_READ_BATCH). - Ordering — preserves the immutable tier-table order established at
init.
| Field | Type | Description |
|---|---|---|
min_lock_secs |
u64 |
Minimum committed_lock_secs an investor must pass to qualify for this tier |
yield_bps |
i64 |
Effective annualized yield in basis points for qualifying investors |