Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changelog/unreleased/deprecated/240-deprecation-sweep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Remove the never-released mixed-denom request surface outright, reserving the field numbers: `payment_denom` and `initial_payment_nav` (`InitialVaultNAV`) on `MsgCreateVaultRequest`, and the `redeem_denom` selection on `MsgSwapOutRequest` and `QueryEstimateSwapOutRequest`. The state fields `VaultAccount.payment_denom` (always equal to the underlying asset) and `PendingSwapOut.redeem_denom` (always the underlying asset) remain deprecated on the wire so the v1->v2 migration can decode pre-flatten state; their deletion is deferred to a future major release [#240](https://github.com/provlabs/vault/issues/240).

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Disallow vault creation with a payment denom that differs from the underlying asset. The payment denom must now be empty (defaulting to the underlying) or equal to it. This creation-time check does not itself alter existing vaults; a separate state-machine-breaking migration flattens pre-existing mixed-denom vaults [#239](https://github.com/provlabs/vault/issues/239).
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Remove the mixed-denom (payment denom) vault functionality: vaults are strictly single-denom on their underlying asset. Swap-outs always pay the underlying, AUM fees accrue and collect in the underlying, P2P settlement legs are resolved against the underlying, and internal NAV prices must be denominated in the underlying. The never-released request fields (`payment_denom` and `initial_payment_nav` on `MsgCreateVaultRequest`, `redeem_denom` on `MsgSwapOutRequest` and `QueryEstimateSwapOutRequest`) are removed outright with their field numbers reserved; the `VaultAccount.payment_denom` and `PendingSwapOut.redeem_denom` state fields remain deprecated on the wire for migration decoding. The v1->v2 migration now flattens pre-existing mixed-denom vaults in place (payment denom collapses to the underlying, outstanding AUM fees are re-denominated, pending swap-outs redeem in the underlying, `nav_authority` defaults to the admin), replacing the never-released internal NAV seed migration [#240](https://github.com/provlabs/vault/issues/240).
6 changes: 6 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ linters:
- linters:
- staticcheck
text: 'ST1003:'
# The module must keep implementing its own deprecated payment-denom
# surface until it is removed; the deprecation warnings are aimed at
# external integrators, not this repo's internals.
- linters:
- staticcheck
text: 'SA1019: .*deferred to a future major release'
- linters:
- revive
text: don't use leading k in Go names
Expand Down
2 changes: 1 addition & 1 deletion GEMINI.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# GEMINI.md - Vault Module

## Project Description
The **vault** project is a specialized Cosmos SDK module built for the **Provenance Blockchain**. It provides a robust framework for managing tokenized vaults, leveraging Provenance's native **marker** and **account** models. Key features include share issuance (Swap-In), redemptions (Swap-Out) with configured delays, dynamic interest accrual (positive/negative), and multi-asset accounting (underlying asset vs. optional payment denoms).
The **vault** project is a specialized Cosmos SDK module built for the **Provenance Blockchain**. It provides a robust framework for managing tokenized vaults, leveraging Provenance's native **marker** and **account** models. Key features include share issuance (Swap-In), redemptions (Swap-Out) with configured delays, dynamic interest accrual (positive/negative), and single-denom accounting in the vault's underlying asset (held assets acquired via P2P settlement are priced through the internal NAV table).

---

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Claude Code agent defined in `.claude/agents/provenance-drift.md`.

The `spec/` directory contains module documentation:

- [Concepts & Overview](spec/01_concepts.md) — what a vault is, share/asset model, payment denom behavior, module responsibilities.
- [Concepts & Overview](spec/01_concepts.md) — what a vault is, share/asset model, single-denom behavior, module responsibilities.
- [State](spec/02_state.md) — canonical vault accounts, queues/collections, addressing, genesis notes.
- [Msgs](spec/03_messages.md) — tx endpoints, endpoint gating matrix, flows and validation.
- [Events](spec/04_events.md) — event catalog and operational guidance (incl. swap-out success/refund signaling).
Expand Down
134 changes: 134 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Security

The `x/vault` module custodies user deposits on the Provenance Blockchain: each
vault is an on-chain account backed by a restricted share marker, and the
module holds swap-in principal, escrows shares for pending swap-outs, and pays
interest and fees from marker accounts. Vault code also runs inside consensus
(`BeginBlocker`/`EndBlocker` queues and state migrations), so a defect can halt
the chain, not just a single transaction. Security is a design requirement of
every change in this repository, not a review step at the end. This document
is the working guidance for engineers and coding agents; module behavior is
specified in [`spec/`](spec/).

## Reporting a vulnerability

Report vulnerabilities privately via GitHub Security Advisories on this
repository ("Report a vulnerability"). Do not open a public issue or pull
request for a suspected vulnerability, and do not include exploit details in
commit messages or changelog entries while a fix is coordinated. You should
receive an acknowledgment within a few business days; please allow coordinated
disclosure before publishing. There is no bounty program at this time.

## Project status

The module is released and deployed on Provenance networks (testnet and
mainnet). Third-party security reviews are part of the release process, and
review findings are triaged against current code before they are considered
resolved. State-machine-breaking changes ship behind consensus-version bumps
with in-place migrations.

## Secure development practices

### Consensus and chain-halt safety

- **No panics in ABCI paths.** Code reachable from `BeginBlocker`,
`EndBlocker`, `InitGenesis`, `ExportGenesis`, or a migration returns errors;
it never panics on data or arithmetic. A failure processing one vault must
never halt the chain: prefer pausing the affected vault, emitting a
structured log, and continuing over erroring the block.
- **Bounded work per block.** Queue processing (payouts, pending swap-outs,
reconciliation) is capped per block; no code path iterates state without a
bound. Migrations may only walk small, provably bounded sets.
- **Determinism everywhere.** State iteration goes through `collections`
ordered walks; no map iteration, wall-clock time, floating point, or
randomness in state-transition logic. The nondeterminism simulation in CI is
the backstop, not the guarantee.
- **Never strand escrowed funds.** Failure handling for queued jobs must
account for shares and coins already escrowed; a critical payout or refund
failure re-queues or preserves the pending entry rather than dropping it.

### Input validation and safe math

- **Validate at every boundary.** Stateless checks live in `ValidateBasic`
(addresses, denoms, amount signs, limit ranges); stateful checks live in the
keeper (marker existence, permissions, vault state). A value that cannot be
bounded safely is an error, never a best-effort continue.
- **Checked arithmetic only.** Use `cosmossdk.io/math` types with
overflow-guarded operations; scale into `uint64`-safe ranges before
conversion; round in the vault's favor so dust cannot be extracted by
repeated swap-in/swap-out cycles. Interest and NAV math must hold across the
full input domain, including zero, one base unit, and extreme TVL.
- **Estimates match execution.** Query-side estimation (`EstimateSwapIn`,
`EstimateSwapOut`) must use the same valuation path as the corresponding
state transition so users cannot be quoted a value the chain will not honor.

### Authorities and asset gating

- **Every privileged capability is enumerated.** Admin, asset manager, NAV
authority, and bridge address each have a defined capability set in
[`spec/`](spec/); adding or widening an authority is a spec-level event, not
a code detail. Handlers verify the signer against the specific authority the
action requires, never against "any authority".
- **Marker restrictions are the enforcement boundary.** Share markers are
restricted; transfers flow through the marker send-restriction checks, and
vault creation preflights `SendRestrictionFn` so a vault cannot be created
in a configuration whose fee or payout transfers would later fail. Never
bypass bank send restrictions with direct store writes.
- **Supply-of-record invariant.** `total_shares` is the authoritative share
supply across chains; local marker supply must never exceed it. Bridge
mint/burn paths must preserve this invariant on every transition.
- **Permissionless paths are safe for any caller.** Anyone may trigger
estimation queries and hold shares; nothing gates a safety property on who
calls, and no permissionless path may move value to the caller's benefit.

### Wire and state compatibility

- **Proto surface is append-only between major releases.** Released fields are
deprecated in place (`deprecated = true`, documented as inert) rather than
deleted; deletion waits for a major release and reserves field numbers and
names. Never-released fields may be removed outright, with numbers reserved.
- **Migrations ship with the consensus-version bump** that requires them, are
rehearsed against exported network state before upgrade, and log each
mutation they perform for auditability.

## Testing and verification

- **Table-driven, exhaustive tests** cover each changed branch, including
failure paths, with high-context assertion messages
([`CLAUDE.md`](CLAUDE.md) has the full conventions).
- **Simulations run in CI** (`make test-sim-simple`,
`make test-sim-nondeterminism`); simulation operations must generate the
full allowed input domain, and failures must stay seed-reproducible.
- **Invariants are machine-checked, not narrative.** Share supply-of-record,
escrow conservation across queue failures, and estimate/execution parity are
asserted by tests, not prose. A change that touches an invariant updates the
assertion and the spec together.

## Dependencies and supply chain

- `go.mod`/`go.sum` stay pinned and committed; dependency bumps go through
review and the changelog tooling rather than drive-by upgrades.
- The `provenance-drift` CI job keeps this module's dependency expectations
aligned with upstream Provenance, so consensus-affecting version skew is
caught before release.
- Adding a dependency is a reviewed decision: prefer the standard library,
Cosmos SDK, or Provenance first-party code, and check maintenance and
provenance of anything new.
- Never commit credentials or private keys. Local development uses the
disposable `./local.sh` chain; its keys and mnemonics are throwaway test
material and must never be reused on a public network.

## Audit readiness

Practices that keep formal review cheap and the trail honest:

- **Spec/code parity.** A behavior change updates [`spec/`](spec/) in the same
change; the spec is the reviewable statement of intended behavior.
- **Changelog discipline.** Every user-visible or state-machine-affecting
change carries a `.changelog/unreleased/` entry (CI enforces this), so the
release notes are the true diff of behavior.
- **Committed generated code.** `make proto-all` output (`api/`, `types/`,
swagger) is regenerated and committed with interface changes, so the
reviewed interface is the shipped one.
- **Traceable rationale.** Commits and PRs reference the issue they implement,
so reviewers can walk requirement to code to test.
18 changes: 12 additions & 6 deletions api/provlabs/vault/v1/events.pulsar.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading