> For the complete documentation index, see [llms.txt](https://docs.upshift.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.upshift.finance/vault-architecture/stellar-vaults/risk-and-security-model.md).

# Risk and Security Model

### AUM Change Limits

The vault enforces both per-call and cumulative-window rate limits on every move of deployed\_assets. Limits are asymmetric (increases and decreases are configured separately), denominated in basis points of the pre-move deployed\_assets, and applied by the same shared helper used by every aggregate-mutating function (update\_deployed\_assets, update\_wallet\_deployed, update\_wallet\_deployed\_batch, and remove\_wallet\_and\_reconcile).

* Per-call limits: `set_aum_limits(increase_bps, decrease_bps)` caps how much deployed\_assets can change in a single call. Decreases are typically configured tighter than increases
* Cumulative window limits: s`et_aum_window_limits(window_duration, cumulative_increase_bps, cumulative_decrease_bps)` caps the sum of changes within a fixed tumbling window (minimum 1 hour, maximum 7 days; default 24 hours). The window resets entirely on expiry, and changing limits resets it immediately so stale counters never interact with new configuration. Cumulative limits are measured against a base\_deployed snapshot captured at window start, not the live value
* Zero-boundary behavior: when deployed\_assets == 0, percentage-based limits are undefined and skipped. The admin controls risk at this boundary through operator key management and the subaccount whitelist

Calls that exceed the per-call limit revert with AumChangeExceedsLimit; calls that exceed the cumulative limit revert with AumCumulativeChangeExceedsLimit.

### Pause Mechanism

The admin can instantly halt user-facing operations via `pause()`. While paused:

* `deposit`, `mint`, `withdraw`, and `redeem` all revert; `max_deposit`, `max_mint`, `max_withdraw`, and `max_redeem` all return 0
* `add_subaccount` reverts (no new strategies or wallets can be onboarded mid-incident)
* Operator increases to deployed\_assets (and any per-wallet tracker increase, including a single positive entry inside an otherwise net-negative update\_wallet\_deployed\_batch) revert with VaultPaused. Decreases remain permitted so the operator can recognize losses and pull capital back
* `withdraw_from_subaccount` continues to operate so the curator can return capital
* The admin can unpause at any time via unpause()

The asymmetry is deliberate: a pause must not let a compromised operator inflate share prices by booking phantom gains, but it must still allow loss recognition and capital recovery during an emergency.

### Admin Transfer Safety

Admin role transfers use a two-step nomination process with an explicit deadline:

1. Current admin calls `propose_admin(new_admin, deadline)`. This records a pending nominee and an absolute ledger-timestamp expiry
2. Nominated admin calls `accept_admin()`. The pending nominee must require\_auth and the call must arrive before deadline

If the nomination expires (AdminProposalExpired) it must be re-issued. The current admin can cancel a pending proposal at any time via cancel\_admin\_proposal. Self-nominations (new\_admin == admin) and zero/past deadlines are rejected at proposal time. This prevents accidental or malicious ownership changes; the deadline also prevents a long-lived pending nomination from being exploited later.

Operator changes are a single-step admin action via `set_operator`.&#x20;

### Wallet-Attribution Invariant

For Wallet subaccounts the vault maintains a per-wallet WalletNetDeployed tracker that is moved in lockstep with the aggregate deployed\_assets on every routine operator action.&#x20;

| Σ WalletNetDeployed\[w] == deployed\_assets |
| ------------------------------------------- |

The invariant is enforced by deposit\_to\_subaccount, withdraw\_from\_subaccount, update\_wallet\_deployed, update\_wallet\_deployed\_batch, and remove\_wallet\_and\_reconcile. The vault also enforces a per-wallet over-pull guard: withdraw\_from\_subaccount rejects pulls that exceed the wallet's tracker (WalletOverWithdraw), so an operator cannot silently consume another wallet's share of deployed\_assets while informally recognizing a gain or recovering dust.

Two escape hatches can break the invariant by design — update\_deployed\_assets (aggregate-only) and seed\_wallet\_net\_deployed (per-wallet, admin-only, with a WalletSeedBelowTracker guard that prevents zeroing a tracker without a matching aggregate write-down). Both are reserved for emergency storage corrections; off-chain monitoring compares get\_deployed\_assets() against get\_wallet\_deployed\_assets() and alerts on divergence.

### Contract Upgradeability

The vault implements OpenZeppelin's UpgradeableInternal trait, gated on require\_admin.&#x20;

### Audit History

A separate audit has been conducted for the Stellar contracts and is available [here](https://docsend.com/view/vufj5dygn99dg3i7).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.upshift.finance/vault-architecture/stellar-vaults/risk-and-security-model.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
