Documentation
¶
Overview ¶
This file targets the SDK's invariant framework, which is deprecated along with x/crisis but is still the only wiring available for module invariants. Delete it once x/crisis is removed.
Index ¶
- Constants
- Variables
- func AllInvariants(k Keeper) sdk.Invariant
- func EscrowedSharesInvariant(k Keeper) sdk.Invariant
- func NewMsgServer(keeper *Keeper) types.MsgServer
- func NewQueryServer(keeper *Keeper) types.QueryServer
- func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper)
- func ShareSupplyInvariant(k Keeper) sdk.Invariant
- func TotalValueInvariant(k Keeper) sdk.Invariant
- type Keeper
- func (k *Keeper) AllowSwapInAmount(ctx sdk.Context, swapInAsset sdk.Coin, vault types.VaultAccount) (bool, string, error)
- func (k *Keeper) AllowSwapOutAmount(ctx sdk.Context, assets sdk.Coin, vault types.VaultAccount) (bool, string, error)
- func (k *Keeper) BeginBlocker(ctx sdk.Context) error
- func (k Keeper) CalculateAccruedAUMFee(ctx sdk.Context, vault types.VaultAccount, totalAssets sdkmath.Int) (sdkmath.Int, error)
- func (k Keeper) CalculateAccruedAUMFeePayment(ctx sdk.Context, vault types.VaultAccount, totalAssets sdkmath.Int) (sdk.Coin, error)
- func (k Keeper) CalculateAccruedInterest(ctx sdk.Context, vault types.VaultAccount, principal sdk.Coin) (sdkmath.Int, error)
- func (k Keeper) CalculateVaultTotalAssets(ctx sdk.Context, vault *types.VaultAccount, principal sdk.Coin) (sdkmath.Int, error)
- func (k Keeper) CanPayInterestDuration(ctx sdk.Context, vault *types.VaultAccount, duration int64) (bool, error)
- func (k Keeper) ConvertDepositToShares(ctx sdk.Context, vault types.VaultAccount, in sdk.Coin) (sdk.Coin, error)
- func (k Keeper) ConvertSharesToRedeemCoin(ctx sdk.Context, vault types.VaultAccount, shares math.Int) (sdk.Coin, error)
- func (k *Keeper) CreateVault(ctx sdk.Context, attributes VaultAttributer) (*types.VaultAccount, error)
- func (k *Keeper) EndBlocker(ctx sdk.Context) error
- func (k Keeper) EstimateTotalVaultValue(ctx sdk.Context, vault *types.VaultAccount) (sdk.Coin, error)
- func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState
- func (k *Keeper) FindVaultAccount(ctx sdk.Context, id string) (*types.VaultAccount, error)
- func (k Keeper) GetAUMFeeAddress(ctx sdk.Context) (sdk.AccAddress, error)
- func (k Keeper) GetAuthority() []byte
- func (k Keeper) GetAuthorityString() string
- func (k Keeper) GetNAVPerShare(ctx sdk.Context, vault types.VaultAccount) (math.Int, error)
- func (k Keeper) GetNetTVV(ctx sdk.Context, vault types.VaultAccount) (math.Int, error)
- func (k Keeper) GetTVV(ctx sdk.Context, vault types.VaultAccount) (math.Int, error)
- func (k Keeper) GetVault(ctx sdk.Context, address sdk.AccAddress) (*types.VaultAccount, error)
- func (k *Keeper) GetVaultNAV(ctx sdk.Context, vaultAddr sdk.AccAddress, denom string) (types.VaultNAV, error)
- func (k *Keeper) GetVaults(ctx context.Context) ([]sdk.AccAddress, error)
- func (k Keeper) HydrateTotalValues(ctx sdk.Context) error
- func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState)
- func (k Keeper) InitTotalValue(ctx sdk.Context, vault *types.VaultAccount) error
- func (k Keeper) IsVaultCreationGovOnly(ctx sdk.Context) (bool, error)
- func (k *Keeper) NAVEntryCount(ctx sdk.Context, vaultAddr sdk.AccAddress) (uint64, error)
- func (k Keeper) OpenKVStore(ctx sdk.Context) store.KVStore
- func (k Keeper) PerformVaultFeeTransfer(ctx sdk.Context, vault *types.VaultAccount) error
- func (k Keeper) PerformVaultInterestTransfer(ctx sdk.Context, vault *types.VaultAccount) error
- func (k Keeper) RecomputeTotalValue(ctx sdk.Context, vault types.VaultAccount) (math.Int, error)
- func (k *Keeper) RemoveVaultNAV(ctx sdk.Context, vault *types.VaultAccount, denom, signer string) error
- func (k Keeper) RescheduleFeeTimeout(ctx sdk.Context, vault *types.VaultAccount, oldTimeout int64) error
- func (k Keeper) ReschedulePayoutTimeout(ctx sdk.Context, vault *types.VaultAccount, oldTimeout int64) error
- func (k Keeper) SafeAddPayoutVerification(ctx sdk.Context, vault *types.VaultAccount) error
- func (k Keeper) SafeEnqueueFeeTimeout(ctx sdk.Context, vault *types.VaultAccount) error
- func (k Keeper) SafeEnqueuePayoutTimeout(ctx sdk.Context, vault *types.VaultAccount) error
- func (k *Keeper) SetMaxInterestRate(ctx sdk.Context, vault *types.VaultAccount, maxRate string) error
- func (k *Keeper) SetMaxSwapInValue(ctx sdk.Context, vault *types.VaultAccount, maxSwapIn string, authority string) error
- func (k *Keeper) SetMaxSwapOutValue(ctx sdk.Context, vault *types.VaultAccount, maxSwapOut string, ...) error
- func (k *Keeper) SetMinInterestRate(ctx sdk.Context, vault *types.VaultAccount, minRate string) error
- func (k *Keeper) SetMinSwapInValue(ctx sdk.Context, vault *types.VaultAccount, minSwapIn string, authority string) error
- func (k *Keeper) SetMinSwapOutValue(ctx sdk.Context, vault *types.VaultAccount, minSwapOut string, ...) error
- func (k *Keeper) SetNAVAuthority(ctx sdk.Context, vault *types.VaultAccount, newAuthority, signer string) error
- func (k *Keeper) SetSwapInEnable(ctx sdk.Context, vault *types.VaultAccount, enabled bool) error
- func (k *Keeper) SetSwapOutEnable(ctx sdk.Context, vault *types.VaultAccount, enabled bool) error
- func (k *Keeper) SetVaultAccount(ctx sdk.Context, vault *types.VaultAccount) error
- func (k *Keeper) SetVaultLookup(ctx context.Context, vault *types.VaultAccount) error
- func (k *Keeper) SetVaultNAV(ctx sdk.Context, vault *types.VaultAccount, nav types.VaultNAV, signer string) error
- func (k *Keeper) SetWithdrawalDelay(ctx sdk.Context, vault *types.VaultAccount, delaySeconds uint64, ...) error
- func (k *Keeper) SwapIn(ctx sdk.Context, vaultAddr, recipient sdk.AccAddress, asset sdk.Coin) (*sdk.Coin, error)
- func (k *Keeper) SwapOut(ctx sdk.Context, vaultAddr, owner sdk.AccAddress, shares sdk.Coin) (uint64, error)
- func (k Keeper) ToUnderlyingAssetAmount(ctx sdk.Context, vault types.VaultAccount, in sdk.Coin) (math.Int, error)
- func (k Keeper) UnitPriceFraction(ctx sdk.Context, srcDenom string, vault types.VaultAccount) (math.Int, math.Int, error)
- func (k Keeper) UpdateInterestRates(ctx sdk.Context, vault *types.VaultAccount, currentRate, desiredRate string) error
- func (k *Keeper) UpdateVaultAUMFeeBips(ctx sdk.Context, vault *types.VaultAccount, bips uint32, authority string) error
- func (k Keeper) ValidateInterestRateLimits(minRateStr, maxRateStr string) error
- func (k Keeper) WalkTotalValue(ctx sdk.Context, vault types.VaultAccount) (math.Int, error)
- type Migrator
- type VaultAttributer
Constants ¶
const ( // MaxSwapOutBatchSize is the maximum number of pending swap-out queue entries // visited per EndBlocker. Entries for paused vaults count against the budget // and are dequeued and refunded. This is a temporary value and we will need to // do more analysis on a proper batch size. // See https://github.com/ProvLabs/vault/issues/75. MaxSwapOutBatchSize = 100 // MaxInterestTimeoutsPerBlock is the maximum number of PayoutTimeoutQueue // entries visited per BeginBlocker. MaxInterestTimeoutsPerBlock = 100 // MaxFeeTimeoutsPerBlock is the maximum number of FeeTimeoutQueue entries // visited per BeginBlocker. MaxFeeTimeoutsPerBlock = 100 // MaxPayoutVerificationsPerBlock is the maximum number of PayoutVerificationSet // entries visited per EndBlocker. MaxPayoutVerificationsPerBlock = 100 // SwapOutImmediateRetries is the number of failures a pending swap out may accumulate // before its retries start being delayed by SwapOutRetryBackoffBase. SwapOutImmediateRetries = 1 // SwapOutRetryBackoffBase is the first delay (in seconds) applied to a repeatedly // failing swap out. The delay doubles with each further failure. SwapOutRetryBackoffBase = 600 // SwapOutRetryBackoffMax caps the retry delay (in seconds) so a permanently failing // swap out is still revisited, at a cost the batch budget can absorb. SwapOutRetryBackoffMax = 6 * interest.SecondsPerHour // SwapOutRetryJitterSpread is the window (in seconds) that delayed retries are spread across so // swap outs failing in the same block do not all come due again in the same block. SwapOutRetryJitterSpread = 600 )
const ( TotalValueInvariantRoute = "total-value" )
Crisis-module route names for the vault module's invariants.
const ( Supply = 0 NoFixedSupply = false NoForceTransfer = false NoGovControl = false )
const ( // AutoReconcilePayoutDuration is the time period (in seconds) used to forecast if a vault has // sufficient funds to cover future interest payments. AutoReconcilePayoutDuration = 24 * interest.SecondsPerHour )
const ( // AutoReconcileTimeout is the duration (in seconds) that a vault is considered // recently reconciled and is exempt from automatic interest checks. AutoReconcileTimeout = 20 * interest.SecondsPerHour )
Variables ¶
var ErrInternalNAVNotFound = errors.New("internal NAV entry not found")
ErrInternalNAVNotFound is returned by UnitPriceFraction (and any helper that composes it) when no Internal NAV entry exists for the requested denom on the target vault. Callers should match this with errors.Is to classify the failure (e.g. swap refund classification in getRefundReason) without relying on the formatted error string.
var ErrInternalNAVPriceCycle = errors.New("internal NAV price chain contains a cycle")
ErrInternalNAVPriceCycle is returned by UnitPriceFraction when a vault's Internal NAV table chains a denom's price back onto a denom already being resolved on the same path (a self-price or a longer loop). SetVaultNAV's accepted-denom validation makes this unreachable for normally-written state, but the engine detects it defensively so a NAV seeded outside that path (e.g. by a migration or a direct write) can never drive unbounded recursion.
var ErrNegativeTotalValue = errors.New("materialized total value would go negative")
ErrNegativeTotalValue is returned when a delta would drive a vault's materialized total below zero, meaning some path misreported its change.
var ErrNoMaterializedTotalValue = errors.New("vault has no materialized total value")
ErrNoMaterializedTotalValue is returned for a vault with no TotalValues entry. Seeding one is the job of creation, genesis import and the migration, so reaching this means the vault was skipped as unvaluable by one of them. See spec/02_state.md.
Functions ¶
func AllInvariants ¶ added in v1.2.4
AllInvariants runs every vault module invariant, stopping at the first one broken.
func EscrowedSharesInvariant ¶ added in v1.2.4
EscrowedSharesInvariant checks that a vault holds at least the shares its pending swap-outs claim to have escrowed. A shortfall means a payout can no longer be honored from escrow.
A surplus is not a violation: share transfers to the vault account are unrestricted, so anyone can create one with a bank send, and halting on that would be externally triggerable.
func NewMsgServer ¶
NewMsgServer creates a new MsgServer for the module.
func NewQueryServer ¶
func NewQueryServer(keeper *Keeper) types.QueryServer
func RegisterInvariants ¶ added in v1.2.4
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper)
RegisterInvariants registers the vault module's invariants.
func ShareSupplyInvariant ¶ added in v1.2.4
ShareSupplyInvariant checks that no vault's minted share supply exceeds its TotalShares.
TotalShares is the cross-chain supply-of-record: bridge mints are gated on the headroom between it and local supply, and a bridge burn deliberately leaves it untouched because those shares still exist on the remote chain. Local supply overtaking it means that headroom is corrupt and the bridge can mint shares nothing backs.
func TotalValueInvariant ¶ added in v1.2.4
TotalValueInvariant checks each vault's materialized total value against the value derived by walking its NAV table. A mismatch means some path moved a priced balance or changed a price without reporting it, so share pricing is running off a stale number.
Types ¶
type Keeper ¶
type Keeper struct {
AddressCodec address.Codec
AuthKeeper types.AccountKeeper
MarkerKeeper types.MarkerKeeper
MetadataKeeper types.MetadataKeeper
BankKeeper types.BankKeeper
NameKeeper types.NameKeeper
AttrKeeper types.AttributeKeeper
ExchangeKeeper types.ExchangeKeeper
ExchangeQueryServer types.ExchangeQueryServer
// Params holds the module-wide parameters.
Params collections.Item[types.Params]
// Vaults indexes every vault address; the vault itself lives in the auth account store.
Vaults collections.Map[sdk.AccAddress, []byte]
// NAVs prices each denom a vault holds, keyed by vault address and denom.
NAVs collections.Map[collections.Pair[sdk.AccAddress, string], types.VaultNAV]
// TotalValues materializes each vault's total value in its underlying asset.
TotalValues collections.Map[sdk.AccAddress, math.Int]
// NAVCounts tracks how many denoms each vault prices, so MaxVaultNAVEntries can be enforced
// without walking the table on every write.
NAVCounts collections.Map[sdk.AccAddress, uint64]
// PayoutVerificationSet holds the vaults awaiting a payout verification sweep, each entry doubling
// as that vault's retry token.
PayoutVerificationSet collections.KeySet[sdk.AccAddress]
// PayoutVerificationCursor is the address the next payout verification sweep resumes after.
PayoutVerificationCursor collections.Item[sdk.AccAddress]
// PayoutTimeoutQueue schedules the vaults due for an interest payout.
PayoutTimeoutQueue *queue.PayoutTimeoutQueue
// FeeTimeoutQueue schedules the vaults due for a fee collection.
FeeTimeoutQueue *queue.FeeTimeoutQueue
// PendingSwapOutQueue holds redemptions waiting out their configured delay.
PendingSwapOutQueue *queue.PendingSwapOutQueue
// contains filtered or unexported fields
}
func NewKeeper ¶
func NewKeeper( cdc codec.Codec, storeService store.KVStoreService, eventService event.Service, addressCodec address.Codec, authority []byte, authKeeper types.AccountKeeper, markerkeeper types.MarkerKeeper, metadatakeeper types.MetadataKeeper, bankkeeper types.BankKeeper, namekeeper types.NameKeeper, attributekeeper types.AttributeKeeper, exchangekeeper types.ExchangeKeeper, exchangeQueryServer types.ExchangeQueryServer, ) *Keeper
NewMsgServer creates a new Keeper for the module.
func (*Keeper) AllowSwapInAmount ¶ added in v1.1.0
func (k *Keeper) AllowSwapInAmount(ctx sdk.Context, swapInAsset sdk.Coin, vault types.VaultAccount) (bool, string, error)
AllowSwapInAmount checks whether a swap-in amount meets the minimum and maximum value requirements for a vault.
func (*Keeper) AllowSwapOutAmount ¶ added in v1.1.0
func (k *Keeper) AllowSwapOutAmount(ctx sdk.Context, assets sdk.Coin, vault types.VaultAccount) (bool, string, error)
AllowSwapOutAmount checks whether a swap-out amount meets the minimum and maximum value requirements for a vault.
func (*Keeper) BeginBlocker ¶
BeginBlocker is a hook that is called at the beginning of every block.
func (Keeper) CalculateAccruedAUMFee ¶ added in v1.1.0
func (k Keeper) CalculateAccruedAUMFee(ctx sdk.Context, vault types.VaultAccount, totalAssets sdkmath.Int) (sdkmath.Int, error)
CalculateAccruedAUMFee calculates the AUM fees that would have accrued for the vault from its FeePeriodStart to the current block time, based on the provided total assets. It returns the fee amount in the underlying asset and does not mutate state.
func (Keeper) CalculateAccruedAUMFeePayment ¶ added in v1.1.0
func (k Keeper) CalculateAccruedAUMFeePayment(ctx sdk.Context, vault types.VaultAccount, totalAssets sdkmath.Int) (sdk.Coin, error)
CalculateAccruedAUMFeePayment calculates the AUM fees that would have accrued for the vault from its FeePeriodStart to the current block time, as a coin in the vault's underlying asset.
func (Keeper) CalculateAccruedInterest ¶ added in v1.1.0
func (k Keeper) CalculateAccruedInterest(ctx sdk.Context, vault types.VaultAccount, principal sdk.Coin) (sdkmath.Int, error)
CalculateAccruedInterest calculates the interest that would have accrued for the vault from its PeriodStart to the current block time, based on the provided principal. It returns the interest amount (which can be negative) and does not mutate state.
func (Keeper) CalculateVaultTotalAssets ¶
func (k Keeper) CalculateVaultTotalAssets(ctx sdk.Context, vault *types.VaultAccount, principal sdk.Coin) (sdkmath.Int, error)
CalculateVaultTotalAssets returns the total value of the vault's assets, including the interest that would have accrued from PeriodStart to the current block time, and subtracting the AUM fees accrued since FeePeriodStart, without mutating state.
VALUATION LOGIC (Net TVV): This method subtracts the **OutstandingAumFee** from the gross total to ensure share pricing (NAV) reflects the actual equity owned by shareholders, excluding vault liabilities.
If no rate is set or accrual has not started, it returns the provided principal unchanged.
func (Keeper) CanPayInterestDuration ¶ added in v1.1.0
func (k Keeper) CanPayInterestDuration(ctx sdk.Context, vault *types.VaultAccount, duration int64) (bool, error)
CanPayInterestDuration determines whether the vault can fulfill the projected interest payment/refund over the given duration based on current reserves and principal TVV.
Interest is checked against vault reserves (positive interest) or principal marker underlying balance (negative interest).
It returns true only if interest checks pass.
func (Keeper) ConvertDepositToShares ¶ added in v1.2.0
func (k Keeper) ConvertDepositToShares(ctx sdk.Context, vault types.VaultAccount, in sdk.Coin) (sdk.Coin, error)
ConvertDepositToShares converts a deposit in the vault's underlying asset into the share amount it purchases, using the current net TVV and total share supply (pro-rata, floor arithmetic). Callers validate the deposit denom via ValidateAcceptedCoin, so no price conversion is required.
Returns a coin in the share denom. This function performs calculation only; callers must enforce liquidity/policy. Returns utils.ErrZeroAssetsWithSharesOutstanding when net TVV is zero while shares are outstanding; callers surface that as a rejection.
func (Keeper) ConvertSharesToRedeemCoin ¶
func (k Keeper) ConvertSharesToRedeemCoin(ctx sdk.Context, vault types.VaultAccount, shares math.Int) (sdk.Coin, error)
ConvertSharesToRedeemCoin converts a share amount into a payout coin in the vault's underlying asset — the only denom a vault redeems — using the current net TVV and total share supply (pro-rata, floor arithmetic).
This function performs calculation only; callers must enforce liquidity/policy. If shares <= 0, returns a zero-amount coin.
func (*Keeper) CreateVault ¶
func (k *Keeper) CreateVault(ctx sdk.Context, attributes VaultAttributer) (*types.VaultAccount, error)
CreateVault creates a new vault and its corresponding share marker atomically.
The process involves:
- Creating and persisting a new VaultAccount and its lookup entries.
- Initializing the fee timeout queue for the new vault.
- Creating, finalizing, and activating a restricted marker for the vault's shares.
- Performing a pre-flight check against the principal path by calling SendRestrictionFn with vault.PrincipalMarkerAddress() to ensure the fee collection address is permissioned to receive the underlying asset.
All steps are performed within a cache context. If any step fails, including the pre-flight permission check, all state changes are discarded to prevent the creation of inconsistent or "orphan" vaults.
func (*Keeper) EndBlocker ¶
EndBlocker is a hook that is called at the end of every block.
func (Keeper) EstimateTotalVaultValue ¶ added in v1.0.9
func (k Keeper) EstimateTotalVaultValue(ctx sdk.Context, vault *types.VaultAccount) (sdk.Coin, error)
EstimateTotalVaultValue returns an estimated Total Vault Value (TVV) as a Coin denominated in the vault's underlying asset. It composes two steps without mutating state:
- Reads the current principal-only TVV from on-chain balances at the principal (marker) account (excludes reserves and unpaid interest).
- Applies the vault's interest model to estimate unpaid interest through CalculateVaultTotalAssets, producing a best-effort TVV as of the query block. The result is floor-rounded and suitable for pro-rata calculations.
If the vault is paused, the estimation honors the keeper’s paused logic inside GetTVV.
Returns an sdk.Coin { Denom: vault.UnderlyingAsset, Amount: ... }.
func (Keeper) ExportGenesis ¶
func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState
ExportGenesis exports the current state of the vault module.
func (*Keeper) FindVaultAccount ¶
FindVaultAccount retrieves a vault by its address or share denomination.
func (Keeper) GetAUMFeeAddress ¶ added in v1.1.0
GetAUMFeeAddress returns the address where AUM fees are collected.
func (Keeper) GetAuthority ¶
GetAuthority returns the module's authority.
func (Keeper) GetAuthorityString ¶ added in v1.2.3
GetAuthorityString returns the module's authority as a bech32 address.
func (Keeper) GetNAVPerShare ¶ added in v1.2.0
GetNAVPerShare returns the floor NAV per share in units of vault.UnderlyingAsset.
Computation:
- TVV(underlying) is obtained from GetNetTVV (net of the OutstandingAumFee liability).
- totalShareSupply is taken from vault.TotalShares.Amount (the recorded share supply).
- If total shares == 0, returns 0. Otherwise returns TVV / totalShareSupply (floor).
For a paused vault, GetNetTVV supplies the frozen vault.PausedBalance.Amount, so the result is that frozen balance divided by the share supply.
func (Keeper) GetNetTVV ¶ added in v1.2.0
GetNetTVV returns the Total Vault Value (TVV) expressed in vault.UnderlyingAsset, net of the vault's OutstandingAumFee liability.
This is the authoritative valuation basis for share pricing and the published share NAV: it represents the equity actually owned by shareholders, excluding the AUM fee already owed to the fee collector but not yet transferred out of the principal marker.
Paused fast-path:
- If vault.Paused is true, this returns vault.PausedBalance.Amount directly. The paused balance is captured net of the OutstandingAumFee liability at pause time, so paused pricing stays frozen and NAV-independent.
When not paused, GetTVV supplies the gross sum of principal-marker balances; this method subtracts the OutstandingAumFee (already denominated in the underlying asset) and floors the result at zero.
func (Keeper) GetTVV ¶ added in v1.2.0
GetTVV returns the gross Total Vault Value (TVV) expressed in vault.UnderlyingAsset — every asset the vault's principal marker holds, before the OutstandingAumFee liability is deducted.
Gross and net are not interchangeable, and which one a caller wants is a policy decision:
- The AUM fee is assessed on gross, so the fee accrues on assets under management rather than on equity that already has the fee netted out (see PerformVaultFeeTransfer).
- Share pricing, share-NAV publication and interest accrual use GetNetTVV, because those must reflect equity actually owned by shareholders.
- Solvency and reserve checks use gross, since a liability owed does not change what is on hand to pay out with.
A paused vault returns vault.PausedBalance.Amount, which was captured net of the fee liability at pause time, so paused pricing stays frozen and NAV-independent.
Otherwise this is a single store read of the materialized total, never a walk of the vault's balances. WalkTotalValue defines the number, every path that moves a priced balance or changes a price reports its change, and the total-value invariant enforces that the two agree.
Because a held asset's internal NAV is set by the vault's NAV authority, repricing moves TVV and everything derived from it — a deliberate economic and trust surface.
func (Keeper) GetVault ¶
func (k Keeper) GetVault(ctx sdk.Context, address sdk.AccAddress) (*types.VaultAccount, error)
GetVault returns the vault account for the given address. This function will return nil if nothing exists at this address.
func (*Keeper) GetVaultNAV ¶ added in v1.2.0
func (k *Keeper) GetVaultNAV(ctx sdk.Context, vaultAddr sdk.AccAddress, denom string) (types.VaultNAV, error)
GetVaultNAV returns the internal NAV entry for the given vault address and denom. It returns collections.ErrNotFound when no entry exists.
func (Keeper) HydrateTotalValues ¶ added in v1.2.4
HydrateTotalValues derives and stores the materialized total for every vault in the lookup, resolving that lookup exactly as the total-value invariant does so the two cannot disagree about which vaults must end up with an entry. A vault that cannot be valued is logged and skipped, because aborting an upgrade or a genesis import over one bad vault is worse; the invariant passes over that vault too, having no reference of its own to compare against.
func (Keeper) InitGenesis ¶
func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState)
InitGenesis initializes the vault module state from genesis.
func (Keeper) InitTotalValue ¶ added in v1.2.4
InitTotalValue seeds a new vault's materialized total by deriving it rather than assuming zero, since its principal address may already hold a balance sent there before the vault existed. The walk is bounded here: a vault being created prices no denoms yet.
func (Keeper) IsVaultCreationGovOnly ¶ added in v1.2.4
IsVaultCreationGovOnly reports whether CreateVault may only be signed by the governance module account. Unset params fall back to the module default; any other read failure is surfaced so the gate never fails open on an unreadable store.
func (*Keeper) NAVEntryCount ¶ added in v1.2.4
NAVEntryCount returns how many denoms the vault prices. A vault with no recorded count prices nothing, so a missing entry reads as zero rather than an error.
func (Keeper) OpenKVStore ¶ added in v1.1.0
OpenKVStore returns a KVStore for the module.
func (Keeper) PerformVaultFeeTransfer ¶ added in v1.1.0
PerformVaultFeeTransfer computes and collects the AUM technology fee from the vault's principal marker account using its configured AumFeeBips.
The fee is calculated based on the **Gross TVV** (the literal sum of all assets in the marker) and collected in the vault's underlying asset.
This method implements a "collect-what-is-available" strategy: it attempts to transfer the total outstanding fee (accrued + previously unpaid), but caps the collection at the principal marker's current underlying-asset balance. Any uncollected remainder is recorded in OutstandingAumFee to be retried during the next reconciliation.
A rejected fee transfer is treated the same way as an insufficient balance: the error is logged, the full fee stays in OutstandingAumFee, and the fee period still advances. This keeps an uncollectable fee (for example a restricted underlying whose fee collector lost its required attribute) from failing reconciliation and bricking every vault operation. The outstanding total is capped at the gross TVV, so an uncollectable fee's excess is forfeited.
An EventVaultFeeCollected is emitted upon success.
func (Keeper) PerformVaultInterestTransfer ¶
PerformVaultInterestTransfer applies accrued interest between the vault and the marker account if the current block time is beyond PeriodStart.
Interest is settled exclusively in the vault's defined UnderlyingAsset. Interest is calculated based on the **Gross TVV** (the literal sum of all assets in the marker).
- Positive Interest: Paid from vault reserves to the marker. Fails if reserves are insufficient.
- Negative Interest: Refunded from marker principal to the vault. This is bounded by the available balance of the UnderlyingAsset in the marker account.
IMPORTANT: If the vault utilizes composite reserves (holding multiple token types), secondary assets are NOT liquidated or transferred to satisfy interest obligations. If the marker owes negative interest but lacks sufficient liquidity in the UnderlyingAsset, the transfer is capped at the available underlying balance, potentially resulting in a partial payment.
An EventVaultReconcile is emitted upon success. This method does not modify PeriodStart.
func (Keeper) RecomputeTotalValue ¶ added in v1.2.4
RecomputeTotalValue derives a vault's total value from state, stores it, and returns it.
This is a seeding path, not a repair path available to consensus code: the walk is unbounded in the number of denoms the vault prices. Callers are limited to genesis, the migration and vault creation. See spec/02_state.md.
func (*Keeper) RemoveVaultNAV ¶ added in v1.2.0
func (k *Keeper) RemoveVaultNAV(ctx sdk.Context, vault *types.VaultAccount, denom, signer string) error
RemoveVaultNAV deletes the internal net asset value entry for a denom on the given vault and emits an EventNAVRemoved carrying the last recorded price and volume, so a price the vault no longer stands behind stops driving valuation while its final value is still surfaced to downstream consumers.
It serves two callers: the outbound settlement path, which drops the entry once it has drained the vault's last unit of a denom, and the NAV authority, which revokes a price it set for a denom the vault never acquired. The signer is recorded on the event for attribution and is empty for the protocol-initiated settlement removal.
This method does NOT verify that signer is authorized to mutate the vault's NAV table, nor that the vault has stopped holding the denom; callers own both checks. It returns an error when no entry exists for the denom.
func (Keeper) RescheduleFeeTimeout ¶ added in v1.1.0
func (k Keeper) RescheduleFeeTimeout(ctx sdk.Context, vault *types.VaultAccount, oldTimeout int64) error
RescheduleFeeTimeout updates a vault's fee timeout to the next window (now + AutoReconcileTimeout) without resetting the FeePeriodStart. This is used for transient reconciliation failures to preserve accrued fees while preventing block-to-block retry loops.
The dequeue shares the atomic write, so a failure leaves the vault queued under its old timeout.
func (Keeper) ReschedulePayoutTimeout ¶ added in v1.1.0
func (k Keeper) ReschedulePayoutTimeout(ctx sdk.Context, vault *types.VaultAccount, oldTimeout int64) error
ReschedulePayoutTimeout updates a vault's payout timeout to the next window (now + AutoReconcileTimeout) without resetting the PeriodStart. This is used for transient reconciliation failures to preserve accrued interest while preventing block-to-block retry loops.
The dequeue shares the atomic write, so a failure leaves the vault queued under its old timeout.
func (Keeper) SafeAddPayoutVerification ¶ added in v1.1.0
SafeAddPayoutVerification clears any existing timeout entry for the given vault (if any), sets the vault's period start to the current block time, clears the period timeout, persists the vault, and stores the vault in the PayoutVerificationSet.
This ensures a vault is not present in both the verification set and timeout queues at the same time. Typically called after enabling interest or completing a reconciliation so the next accrual cycle begins cleanly.
func (Keeper) SafeEnqueueFeeTimeout ¶ added in v1.1.0
SafeEnqueueFeeTimeout clears any existing fee timeout entry for the given vault (if any), sets the vault's fee period start to the current block time, sets a new fee period timeout at (now + AutoReconcileTimeout), persists the vault, and enqueues the timeout entry in the FeeTimeoutQueue.
func (Keeper) SafeEnqueuePayoutTimeout ¶ added in v1.1.0
SafeEnqueuePayoutTimeout clears any existing timeout entry for the given vault (if any), sets the vault's period start to the current block time, sets a new period timeout at (now + AutoReconcileTimeout), persists the vault, and enqueues the timeout entry in the PayoutTimeoutQueue.
This ensures a vault is not present in both the timeout and verification queues at the same time. Typically called after a vault has been marked as payable so it will be revisited after the auto-reconcile window.
func (*Keeper) SetMaxInterestRate ¶
func (k *Keeper) SetMaxInterestRate(ctx sdk.Context, vault *types.VaultAccount, maxRate string) error
SetMaxInterestRate sets the maximum interest rate for a vault. An empty string disables the maximum rate check.
func (*Keeper) SetMaxSwapInValue ¶ added in v1.1.0
func (k *Keeper) SetMaxSwapInValue(ctx sdk.Context, vault *types.VaultAccount, maxSwapIn string, authority string) error
SetMaxSwapInValue updates the maximum swap-in value for a vault.
func (*Keeper) SetMaxSwapOutValue ¶ added in v1.1.0
func (k *Keeper) SetMaxSwapOutValue(ctx sdk.Context, vault *types.VaultAccount, maxSwapOut string, authority string) error
SetMaxSwapOutValue updates the maximum swap-out value for a vault.
func (*Keeper) SetMinInterestRate ¶
func (k *Keeper) SetMinInterestRate(ctx sdk.Context, vault *types.VaultAccount, minRate string) error
SetMinInterestRate sets the minimum interest rate for a vault. An empty string disables the minimum rate check.
func (*Keeper) SetMinSwapInValue ¶ added in v1.1.0
func (k *Keeper) SetMinSwapInValue(ctx sdk.Context, vault *types.VaultAccount, minSwapIn string, authority string) error
SetMinSwapInValue updates the minimum swap-in value for a vault.
func (*Keeper) SetMinSwapOutValue ¶ added in v1.1.0
func (k *Keeper) SetMinSwapOutValue(ctx sdk.Context, vault *types.VaultAccount, minSwapOut string, authority string) error
SetMinSwapOutValue updates the minimum swap-out value for a vault.
func (*Keeper) SetNAVAuthority ¶ added in v1.2.0
func (k *Keeper) SetNAVAuthority(ctx sdk.Context, vault *types.VaultAccount, newAuthority, signer string) error
SetNAVAuthority rotates the address authorized to mutate the vault's internal NAV table. The caller is responsible for verifying that signer is authorized to perform this rotation (typically via vault.ValidateAdmin); signer is recorded on the emitted EventNAVAuthorityUpdated for attribution only.
When newAuthority equals the current vault.NavAuthority this is a no-op: the vault is left unchanged and no event is emitted.
func (*Keeper) SetSwapInEnable ¶
SetSwapInEnable updates the SwapInEnabled flag for a given vault. It updates the vault account in the state and emits an EventToggleSwapIn event.
func (*Keeper) SetSwapOutEnable ¶
SetSwapOutEnable updates the SwapOutEnabled flag for a given vault. It updates the vault account in the state and emits an EventToggleSwapOut event.
func (*Keeper) SetVaultAccount ¶
SetVaultAccount validates and persists a VaultAccount using the auth keeper. Returns an error if validation fails.
func (*Keeper) SetVaultLookup ¶
SetVaultLookup stores a vault in the Vaults collection, keyed by its bech32 address. NOTE: should only be called by genesis and at vault creation. Returns an error if the vault is nil or the address cannot be parsed.
func (*Keeper) SetVaultNAV ¶ added in v1.2.0
func (k *Keeper) SetVaultNAV(ctx sdk.Context, vault *types.VaultAccount, nav types.VaultNAV, signer string) error
SetVaultNAV creates or updates the internal net asset value entry for a denom on the given vault. The denom need not be one the vault already holds: pricing an unheld denom is what authorizes the asset manager to acquire it, and the entry contributes nothing to total vault value until the asset arrives at the principal marker (see GetTVV). The nav argument supplies the denom, price, volume, and source; the updated block height and time are stamped from ctx before the entry is stored.
The denom may not be the vault's share denom, whose value is derived from the vault's total holdings rather than set externally, and may not be an IBC voucher denom (see types.ValidateNotIBCDenom). The denom must also name an asset that exists on-chain: a registered marker, or for a metadata value-owner denom (nft/<scope-id>) an existing metadata scope. The price must be a valid coin denominated in the vault's underlying asset. Its amount may be zero so the authority can write a worthless held asset down to zero. The volume must be positive.
This method does NOT verify that signer is authorized to mutate the vault's NAV table; signer is recorded for event attribution only. Callers must run vault.ValidateNAVAuthority (or an equivalent check) before invoking it.
An EventNAVUpdated event is emitted with signer recorded as the NAV authority that performed the update.
func (*Keeper) SetWithdrawalDelay ¶ added in v1.0.14
func (*Keeper) SwapIn ¶
func (k *Keeper) SwapIn(ctx sdk.Context, vaultAddr, recipient sdk.AccAddress, asset sdk.Coin) (*sdk.Coin, error)
SwapIn handles the process of depositing underlying assets into a vault in exchange for newly minted vault shares.
It performs the following steps:
- Retrieves the vault configuration for the given vault address.
- Verifies that swap-in is enabled for the vault.
- Reconciles the vault (interest and AUM fees) if due.
- Resolves the vault share marker address.
- Validates that the provided underlying asset matches the vault’s configured underlying denom.
- Rejects the deposit when the depositor is on the underlying marker’s deny list.
- Calculates the number of shares to mint based on the deposit, current supply, and vault balance, rejecting deposits that round down to zero shares, or that price against a zero net vault value with shares outstanding, before any funds move.
- Mints the computed amount of shares under the vault’s admin authority.
- Withdraws the minted shares from the vault to the recipient address.
10. Sends the underlying asset from the recipient to the vault’s marker account. 11. Emits a SwapIn event with metadata for indexing and audit.
Returns the minted share amount on success, or an error if any step fails.
func (*Keeper) SwapOut ¶
func (k *Keeper) SwapOut(ctx sdk.Context, vaultAddr, owner sdk.AccAddress, shares sdk.Coin) (uint64, error)
SwapOut validates a swap-out request, calculates the resulting assets in the vault's underlying asset, escrows the user's shares, and enqueues a pending withdrawal request to be processed by the EndBlocker. It returns the unique ID of the newly queued request.
The vault is reconciled before pricing so the swap-out limits gate the current net valuation. The limits are checked only at admission; the payout is re-priced at maturity without a second check.
func (Keeper) ToUnderlyingAssetAmount ¶
func (k Keeper) ToUnderlyingAssetAmount(ctx sdk.Context, vault types.VaultAccount, in sdk.Coin) (math.Int, error)
ToUnderlyingAssetAmount converts an input coin into its value expressed in vault.UnderlyingAsset using integer floor arithmetic.
Formula:
value_in_underlying = in.Amount * priceNumerator / priceDenominator
where (priceNumerator, priceDenominator) are from UnitPriceFraction(in.Denom → underlying). This performs a pure conversion based on NAV (or identity if denom==underlying). It does not enforce whether the denom is accepted by the vault; such policy checks are handled elsewhere.
func (Keeper) UnitPriceFraction ¶
func (k Keeper) UnitPriceFraction(ctx sdk.Context, srcDenom string, vault types.VaultAccount) (math.Int, math.Int, error)
UnitPriceFraction returns the unit price of srcDenom expressed in the vault's underlying asset as an integer fraction (numerator, denominator), sourced exclusively from the per-vault Internal NAV table.
Semantics ¶
The Internal NAV entry for a denom records the price of `volume` units of the denom denominated in the vault's underlying asset (held assets acquired via AcceptAsset settlement are priced this way):
1 srcDenom = nav.Price.Amount / nav.Volume nav.Price.Denom
When nav.Price.Denom is the underlying asset, the returned fraction is simply (nav.Price.Amount, nav.Volume). Should an entry's price denom chain onto another priced denom (possible only for state written outside SetVaultNAV's validation, e.g. by a migration or a direct write), the walk continues until the underlying is reached, and the fraction is the product of every entry's price over the product of every entry's volume along the chain srcDenom -> ... -> underlying:
1 srcDenom = (price_0 * price_1 * …) / (volume_0 * volume_1 * …) underlying
Suitable for floor(x * num / den) integer arithmetic.
Identity fast-path
- If srcDenom == vault.UnderlyingAsset, returns (1, 1) without a lookup.
Errors
- Wraps ErrInternalNAVNotFound when no entry exists for srcDenom on this vault. Callers should classify with errors.Is(err, ErrInternalNAVNotFound) rather than matching on the formatted error string.
- Returns wrapped errors for any other Internal NAV lookup failure.
- Defensive: rejects nav.Volume <= 0 or a negative nav.Price.Amount (these are already enforced at NAV-write time by validateVaultNAVFields). A zero price is permitted (a held asset written down to zero) and yields a zero unit price.
- Wraps ErrInternalNAVPriceCycle if the price chain ever revisits a denom already seen on the walk (a self-price or a longer loop). Walking a finite, non-repeating set of denoms is the hard termination guarantee.
The value is the product of every entry's price over the product of every entry's volume along the chain srcDenom -> ... -> underlying. The loop walks that chain, accumulating (num, den), and stops at the underlying. The visited set bounds the walk to the number of distinct denoms regardless of how the NAV table was seeded, so it terminates even for state written outside SetVaultNAV's accepted-denom validation. Under that validation real chains are a single hop (srcDenom -> underlying).
func (Keeper) UpdateInterestRates ¶
func (k Keeper) UpdateInterestRates(ctx sdk.Context, vault *types.VaultAccount, currentRate, desiredRate string) error
UpdateInterestRates sets the vault's current and desired interest rates and emits an EventVaultInterestChange. The modified account is persisted via the auth keeper.
func (*Keeper) UpdateVaultAUMFeeBips ¶ added in v1.1.0
func (k *Keeper) UpdateVaultAUMFeeBips(ctx sdk.Context, vault *types.VaultAccount, bips uint32, authority string) error
UpdateVaultAUMFeeBips reconciles outstanding AUM fees for the provided VaultAccount before updating the stored fee rate (in basis points).
This method ensures that all fees accrued under the old rate are accounted for before applying the new rate to future periods. It returns an error if the new bips value exceeds 10,000 (100%) or if reconciliation fails.
func (Keeper) ValidateInterestRateLimits ¶
ValidateInterestRateLimits checks that the provided minimum and maximum interest rates are valid decimal values, that neither exceeds the MaxAbsInterestRate ceiling in magnitude, and that the minimum rate is not greater than the maximum rate. The magnitude ceiling stops an admin from configuring bounds large enough to overflow the e^(rt) interest math and panic inside the block hooks. Empty values are treated as unset and pass validation.
func (Keeper) WalkTotalValue ¶ added in v1.2.4
WalkTotalValue derives a vault's total value by walking its NAV table, and is the definition the materialized total must match. It counts only the principal marker's balances, valuing the underlying at identity and each priced denom at its NAV. Iterating the NAV table rather than every principal balance keeps the cost proportional to the denoms the vault actually prices, and per-denom value comes from denomValue so the walk and the incremental deltas cannot disagree.
The share denom and the underlying are skipped up front. Neither entry should exist — the accumulator already holds the underlying, and validateVaultNAVFields rejects a NAV on the share denom — so this guards state that reached the table without passing that validation.
type Migrator ¶ added in v1.2.0
type Migrator struct {
// contains filtered or unexported fields
}
Migrator wraps the Keeper to expose versioned migration handlers registered with the module Configurator via cfg.RegisterMigration. Each Migrate*to* method corresponds to a single ConsensusVersion bump and is invoked by the SDK module manager during RunMigrations when the stored module version is behind module.ConsensusVersion.
func NewMigrator ¶ added in v1.2.0
NewMigrator constructs a Migrator that delegates to the supplied Keeper.
func (Migrator) Migrate1to2 ¶ added in v1.2.0
Migrate1to2 advances the vault module from ConsensusVersion 1 to 2 by flattening every vault to single-denom and enabling deposit protection on every vault's share marker. Both steps are idempotent across retries.
func (Migrator) Migrate2to3 ¶ added in v1.2.4
Migrate2to3 advances the vault module from ConsensusVersion 2 to 3 by enabling the gov_only_vault_creation param on mainnet, materializing every vault's total value, and deriving the NAV entry count MaxVaultNAVEntries is enforced against. The steps are independent and share a version because none of them has been released.
type VaultAttributer ¶
type VaultAttributer interface {
GetAdmin() string
GetUnderlyingAsset() string
GetWithdrawalDelaySeconds() uint64
GetMinSwapInValue() string
GetMinSwapOutValue() string
GetMaxSwapInValue() string
GetMaxSwapOutValue() string
}
VaultAttributer provides the attributes for creating a new vault.