diff --git a/.changelog/unreleased/deprecated/240-deprecation-sweep.md b/.changelog/unreleased/deprecated/240-deprecation-sweep.md new file mode 100644 index 00000000..93566dca --- /dev/null +++ b/.changelog/unreleased/deprecated/240-deprecation-sweep.md @@ -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). diff --git a/.changelog/unreleased/features/191-add-internal-nav-seed-migration.md b/.changelog/unreleased/features/191-add-internal-nav-seed-migration.md deleted file mode 100644 index ee6d96a1..00000000 --- a/.changelog/unreleased/features/191-add-internal-nav-seed-migration.md +++ /dev/null @@ -1 +0,0 @@ -* Add `MigrateInternalNAVSeedFromMarker` to seed the Internal NAV table from Marker NAV for vaults whose payment denom differs from underlying, and default `nav_authority` to the vault admin when unset. Bumps the vault module `ConsensusVersion` to 2 and registers a v1->v2 migration handler so the SDK module manager can drive the migration via `RunMigrations` during an upstream upgrade [#191](https://github.com/provlabs/vault/issues/191). diff --git a/.changelog/unreleased/improvements/239-disallow-multi-denom-vault.md b/.changelog/unreleased/improvements/239-disallow-multi-denom-vault.md new file mode 100644 index 00000000..03c81bc3 --- /dev/null +++ b/.changelog/unreleased/improvements/239-disallow-multi-denom-vault.md @@ -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). diff --git a/.changelog/unreleased/state-machine-breaking/240-remove-mixed-denom.md b/.changelog/unreleased/state-machine-breaking/240-remove-mixed-denom.md new file mode 100644 index 00000000..b5cb01df --- /dev/null +++ b/.changelog/unreleased/state-machine-breaking/240-remove-mixed-denom.md @@ -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). diff --git a/.golangci.yml b/.golangci.yml index 7d47d67f..9a8b2033 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -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 diff --git a/GEMINI.md b/GEMINI.md index d9eb2b0f..851f80da 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -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). --- diff --git a/README.md b/README.md index 26ef1dca..53c00fee 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..2556075b --- /dev/null +++ b/SECURITY.md @@ -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. diff --git a/api/provlabs/vault/v1/events.pulsar.go b/api/provlabs/vault/v1/events.pulsar.go index b027f07d..0f01e1e8 100644 --- a/api/provlabs/vault/v1/events.pulsar.go +++ b/api/provlabs/vault/v1/events.pulsar.go @@ -25633,7 +25633,8 @@ type EventSwapOutRequested struct { VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // owner is the bech32 address of the user who initiated the swap out. Owner string `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"` - // redeem_denom is the denomination of the asset to be redeemed. + // redeem_denom is the denomination of the asset to be redeemed. Always the + // vault's underlying_asset; retained for event-schema compatibility. RedeemDenom string `protobuf:"bytes,3,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` // shares is the amount of vault shares the user escrowed for this request. Shares string `protobuf:"bytes,4,opt,name=shares,proto3" json:"shares,omitempty"` @@ -25899,7 +25900,10 @@ type EventVaultPaused struct { VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // authority is the address (admin or asset manager) that paused the vault. Authority string `protobuf:"bytes,2,opt,name=authority,proto3" json:"authority,omitempty"` - // reason is the reason for pausing the vault. + // reason is the reason for pausing the vault. For a manual pause (PauseVault + // tx) this is the user-supplied reason. For an automated auto-pause triggered + // in the begin/end blocker, this carries the hard-coded reason describing the + // critical error that forced the pause. Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` // total_vault_value is the total value of the vault's assets at the time of pausing. TotalVaultValue string `protobuf:"bytes,4,opt,name=total_vault_value,json=totalVaultValue,proto3" json:"total_vault_value,omitempty"` @@ -25907,9 +25911,11 @@ type EventVaultPaused struct { // reconcile/valuation gate. False for a normal strict pause; true for a // forced manual pause and for automated auto-pauses. Forced bool `protobuf:"varint,5,opt,name=forced,proto3" json:"forced,omitempty"` - // forced_error records the reconcile and/or valuation error that was - // tolerated when forced is true. Empty when nothing failed. When non-empty, - // total_vault_value may be stale or zero. + // forced_error records the reconcile and/or valuation error tolerated by a + // manual force pause (PauseVault tx). Empty when nothing failed. When + // non-empty, total_vault_value may be stale or zero. Only the tx path sets + // this; automated auto-pauses leave it empty and instead encode their error + // in reason. ForcedError string `protobuf:"bytes,6,opt,name=forced_error,json=forcedError,proto3" json:"forced_error,omitempty"` } @@ -26992,7 +26998,7 @@ type EventAssetAccepted struct { // target_amount is the funds the vault paid the source, rendered as a coins string. TargetAmount string `protobuf:"bytes,5,opt,name=target_amount,json=targetAmount,proto3" json:"target_amount,omitempty"` // direction indicates whether the asset moved into the vault ("inbound") or - // out of the vault ("outbound") relative to the vault's payment denom. + // out of the vault ("outbound") relative to the vault's underlying asset. Direction string `protobuf:"bytes,6,opt,name=direction,proto3" json:"direction,omitempty"` } diff --git a/api/provlabs/vault/v1/query.pulsar.go b/api/provlabs/vault/v1/query.pulsar.go index 01b4d192..de365973 100644 --- a/api/provlabs/vault/v1/query.pulsar.go +++ b/api/provlabs/vault/v1/query.pulsar.go @@ -5825,7 +5825,6 @@ var ( md_QueryEstimateSwapOutRequest protoreflect.MessageDescriptor fd_QueryEstimateSwapOutRequest_vault_address protoreflect.FieldDescriptor fd_QueryEstimateSwapOutRequest_shares protoreflect.FieldDescriptor - fd_QueryEstimateSwapOutRequest_redeem_denom protoreflect.FieldDescriptor ) func init() { @@ -5833,7 +5832,6 @@ func init() { md_QueryEstimateSwapOutRequest = File_provlabs_vault_v1_query_proto.Messages().ByName("QueryEstimateSwapOutRequest") fd_QueryEstimateSwapOutRequest_vault_address = md_QueryEstimateSwapOutRequest.Fields().ByName("vault_address") fd_QueryEstimateSwapOutRequest_shares = md_QueryEstimateSwapOutRequest.Fields().ByName("shares") - fd_QueryEstimateSwapOutRequest_redeem_denom = md_QueryEstimateSwapOutRequest.Fields().ByName("redeem_denom") } var _ protoreflect.Message = (*fastReflection_QueryEstimateSwapOutRequest)(nil) @@ -5913,12 +5911,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) Range(f func(protoreflect.F return } } - if x.RedeemDenom != "" { - value := protoreflect.ValueOfString(x.RedeemDenom) - if !f(fd_QueryEstimateSwapOutRequest_redeem_denom, value) { - return - } - } } // Has reports whether a field is populated. @@ -5938,8 +5930,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) Has(fd protoreflect.FieldDe return x.VaultAddress != "" case "provlabs.vault.v1.QueryEstimateSwapOutRequest.shares": return x.Shares != "" - case "provlabs.vault.v1.QueryEstimateSwapOutRequest.redeem_denom": - return x.RedeemDenom != "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.QueryEstimateSwapOutRequest")) @@ -5960,8 +5950,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) Clear(fd protoreflect.Field x.VaultAddress = "" case "provlabs.vault.v1.QueryEstimateSwapOutRequest.shares": x.Shares = "" - case "provlabs.vault.v1.QueryEstimateSwapOutRequest.redeem_denom": - x.RedeemDenom = "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.QueryEstimateSwapOutRequest")) @@ -5984,9 +5972,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) Get(descriptor protoreflect case "provlabs.vault.v1.QueryEstimateSwapOutRequest.shares": value := x.Shares return protoreflect.ValueOfString(value) - case "provlabs.vault.v1.QueryEstimateSwapOutRequest.redeem_denom": - value := x.RedeemDenom - return protoreflect.ValueOfString(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.QueryEstimateSwapOutRequest")) @@ -6011,8 +5996,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) Set(fd protoreflect.FieldDe x.VaultAddress = value.Interface().(string) case "provlabs.vault.v1.QueryEstimateSwapOutRequest.shares": x.Shares = value.Interface().(string) - case "provlabs.vault.v1.QueryEstimateSwapOutRequest.redeem_denom": - x.RedeemDenom = value.Interface().(string) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.QueryEstimateSwapOutRequest")) @@ -6037,8 +6020,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) Mutable(fd protoreflect.Fie panic(fmt.Errorf("field vault_address of message provlabs.vault.v1.QueryEstimateSwapOutRequest is not mutable")) case "provlabs.vault.v1.QueryEstimateSwapOutRequest.shares": panic(fmt.Errorf("field shares of message provlabs.vault.v1.QueryEstimateSwapOutRequest is not mutable")) - case "provlabs.vault.v1.QueryEstimateSwapOutRequest.redeem_denom": - panic(fmt.Errorf("field redeem_denom of message provlabs.vault.v1.QueryEstimateSwapOutRequest is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.QueryEstimateSwapOutRequest")) @@ -6056,8 +6037,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) NewField(fd protoreflect.Fi return protoreflect.ValueOfString("") case "provlabs.vault.v1.QueryEstimateSwapOutRequest.shares": return protoreflect.ValueOfString("") - case "provlabs.vault.v1.QueryEstimateSwapOutRequest.redeem_denom": - return protoreflect.ValueOfString("") default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.QueryEstimateSwapOutRequest")) @@ -6135,10 +6114,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) ProtoMethods() *protoiface. if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } - l = len(x.RedeemDenom) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -6168,13 +6143,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) ProtoMethods() *protoiface. i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } - if len(x.RedeemDenom) > 0 { - i -= len(x.RedeemDenom) - copy(dAtA[i:], x.RedeemDenom) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.RedeemDenom))) - i-- - dAtA[i] = 0x1a - } if len(x.Shares) > 0 { i -= len(x.Shares) copy(dAtA[i:], x.Shares) @@ -6302,38 +6270,6 @@ func (x *fastReflection_QueryEstimateSwapOutRequest) ProtoMethods() *protoiface. } x.Shares = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field RedeemDenom", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - x.RedeemDenom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -13030,7 +12966,7 @@ type QueryEstimateSwapInRequest struct { // vault_address is the bech32 address of the vault to query. VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` - // assets is the amount of underlying or payment denom to swap in. + // assets is the amount of the underlying asset to swap in. Assets *v1beta11.Coin `protobuf:"bytes,2,opt,name=assets,proto3" json:"assets,omitempty"` } @@ -13133,8 +13069,6 @@ type QueryEstimateSwapOutRequest struct { VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // shares is the amount of shares to swap out. Shares string `protobuf:"bytes,2,opt,name=shares,proto3" json:"shares,omitempty"` - // redeem_denom is the payout denom to estimate; if empty, the underlying asset is used. - RedeemDenom string `protobuf:"bytes,3,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` } func (x *QueryEstimateSwapOutRequest) Reset() { @@ -13171,13 +13105,6 @@ func (x *QueryEstimateSwapOutRequest) GetShares() string { return "" } -func (x *QueryEstimateSwapOutRequest) GetRedeemDenom() string { - if x != nil { - return x.RedeemDenom - } - return "" -} - // QueryEstimateSwapOutResponse is the response message for the Query/EstimateSwapOut endpoint. type QueryEstimateSwapOutResponse struct { state protoimpl.MessageState @@ -13862,225 +13789,225 @@ var file_provlabs_vault_v1_query_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x08, 0xc8, 0xde, 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, - 0x22, 0x7d, 0x0a, 0x1b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, + 0x22, 0x6e, 0x0a, 0x1b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, - 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x22, - 0xa9, 0x01, 0x0a, 0x1c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, - 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x37, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, - 0x00, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x08, 0xc8, 0xde, 0x1f, - 0x00, 0x90, 0xdf, 0x1f, 0x01, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x4e, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, - 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x22, 0x6f, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, - 0x61, 0x76, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, - 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x98, 0x01, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, - 0x74, 0x4e, 0x61, 0x76, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, - 0x04, 0x6e, 0x61, 0x76, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x04, - 0x6e, 0x61, 0x76, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3c, 0x0a, - 0x14, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x4c, 0x0a, 0x15, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x03, 0x6e, 0x61, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x42, 0x04, - 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x03, 0x6e, 0x61, 0x76, 0x22, 0xf2, 0x02, 0x0a, 0x07, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, - 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x70, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x30, 0xc8, 0xde, 0x1f, 0x00, 0xaa, - 0xdf, 0x1f, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x0c, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x70, 0x0a, 0x0d, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x30, 0xc8, - 0xde, 0x1f, 0x00, 0xaa, 0xdf, 0x1f, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, - 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, - 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x22, 0x7d, - 0x0a, 0x18, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x22, 0x57, 0x0a, - 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x70, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x07, 0x70, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x73, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, - 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, - 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa3, 0x01, 0x0a, 0x1a, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x70, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x03, + 0x10, 0x04, 0x52, 0x0c, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, + 0x22, 0xa9, 0x01, 0x0a, 0x1c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, + 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, + 0x1f, 0x00, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x08, 0xc8, 0xde, + 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x14, 0x0a, 0x12, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x4e, 0x0a, 0x13, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x70, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x22, 0x6f, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, + 0x4e, 0x61, 0x76, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x46, 0x0a, 0x0a, 0x70, + 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x26, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0x98, 0x01, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, + 0x6c, 0x74, 0x4e, 0x61, 0x76, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, + 0x0a, 0x04, 0x6e, 0x61, 0x76, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x08, - 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x32, 0xcf, 0x0c, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x71, 0x0a, 0x06, 0x56, - 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, - 0x61, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, + 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, + 0x04, 0x6e, 0x61, 0x76, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3c, + 0x0a, 0x14, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x4c, 0x0a, 0x15, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x03, 0x6e, 0x61, 0x76, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x42, + 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x03, 0x6e, 0x61, 0x76, 0x22, 0xf2, 0x02, 0x0a, 0x07, 0x50, + 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x70, 0x0a, 0x0d, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x30, 0xc8, 0xde, 0x1f, 0x00, + 0xaa, 0xdf, 0x1f, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, + 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x0c, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x70, 0x0a, 0x0d, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, + 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x30, + 0xc8, 0xde, 0x1f, 0x00, 0xaa, 0xdf, 0x1f, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x73, + 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, + 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x22, + 0x7d, 0x0a, 0x18, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x30, 0x0a, 0x06, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, + 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1f, 0x0a, + 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x22, 0x57, + 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x70, + 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x73, - 0x0a, 0x05, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, - 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x07, + 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x73, 0x0a, 0x19, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x46, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa3, 0x01, 0x0a, + 0x1a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x70, + 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, + 0x08, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x70, 0x61, 0x67, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x32, 0xcf, 0x0c, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x71, 0x0a, 0x06, + 0x56, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x56, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x12, 0xaa, 0x01, 0x0a, 0x0e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, - 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x12, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, + 0x73, 0x0a, 0x05, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, + 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xaa, 0x01, 0x0a, 0x0e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, + 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x12, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x12, 0x31, + 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, + 0x2f, 0x7b, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, + 0x2f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, + 0x6e, 0x12, 0xae, 0x01, 0x0a, 0x0f, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, + 0x61, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, - 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x12, 0x31, 0x2f, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, - 0x7b, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x2f, - 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, - 0x12, 0xae, 0x01, 0x0a, 0x0f, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, - 0x70, 0x4f, 0x75, 0x74, 0x12, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x73, - 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x73, - 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x12, 0x32, 0x2f, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, - 0x7b, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x2f, - 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, - 0x74, 0x12, 0x97, 0x01, 0x0a, 0x0f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, - 0x70, 0x4f, 0x75, 0x74, 0x73, 0x12, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, - 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x73, 0x12, 0xb2, 0x01, 0x0a, 0x14, - 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, - 0x4f, 0x75, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, - 0x75, 0x6c, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, - 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x12, 0x27, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, - 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x70, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x73, - 0x12, 0x71, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x12, 0x12, 0x10, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x12, 0x84, 0x01, 0x0a, 0x09, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x61, 0x76, - 0x73, 0x12, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, - 0x4e, 0x61, 0x76, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x61, 0x76, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, 0x1a, + 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, + 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x34, 0x12, 0x32, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x6e, 0x61, 0x76, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x08, 0x4e, - 0x61, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, - 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x4e, 0x61, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x76, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x27, 0x12, 0x25, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, - 0x75, 0x6c, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x6e, 0x61, 0x76, 0x73, 0x2f, 0x7b, - 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x90, 0x01, 0x0a, 0x0c, 0x56, 0x61, - 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, + 0x2f, 0x7b, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, + 0x2f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, + 0x75, 0x74, 0x12, 0x97, 0x01, 0x0a, 0x0f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, + 0x61, 0x70, 0x4f, 0x75, 0x74, 0x73, 0x12, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, + 0x1b, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x73, 0x12, 0xb2, 0x01, 0x0a, + 0x14, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, + 0x70, 0x4f, 0x75, 0x74, 0x73, 0x12, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, + 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, + 0x61, 0x75, 0x6c, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, + 0x75, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, - 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, - 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x94, 0x01, 0x0a, - 0x0d, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2c, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70, + 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x12, 0x27, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, + 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, + 0x73, 0x12, 0x71, 0x0a, 0x06, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x25, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x12, 0x84, 0x01, 0x0a, 0x09, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x61, + 0x76, 0x73, 0x12, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, + 0x74, 0x4e, 0x61, 0x76, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x42, 0xc2, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x56, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x72, 0x6f, - 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x11, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x5c, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x5c, - 0x56, 0x31, 0xe2, 0x02, 0x1d, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x5c, 0x56, 0x61, - 0x75, 0x6c, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x3a, 0x3a, 0x56, - 0x61, 0x75, 0x6c, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x61, 0x76, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x12, + 0x1a, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x6e, 0x61, 0x76, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x08, + 0x4e, 0x61, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x4e, 0x61, 0x76, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, + 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4e, 0x61, 0x76, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x27, 0x12, 0x25, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, + 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x6e, 0x61, 0x76, 0x73, 0x2f, + 0x7b, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x3d, 0x2a, 0x2a, 0x7d, 0x12, 0x90, 0x01, 0x0a, 0x0c, 0x56, + 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2b, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, + 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, + 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x94, 0x01, + 0x0a, 0x0d, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, + 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x70, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x42, 0xc2, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x0a, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x73, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x76, + 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x56, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x72, + 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x56, 0x31, 0xca, + 0x02, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x5c, 0x56, 0x61, 0x75, 0x6c, 0x74, + 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1d, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x5c, 0x56, + 0x61, 0x75, 0x6c, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x3a, 0x3a, + 0x56, 0x61, 0x75, 0x6c, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/api/provlabs/vault/v1/tx.pulsar.go b/api/provlabs/vault/v1/tx.pulsar.go index 2a7ab6de..67e8e9e6 100644 --- a/api/provlabs/vault/v1/tx.pulsar.go +++ b/api/provlabs/vault/v1/tx.pulsar.go @@ -22,13 +22,11 @@ var ( fd_MsgCreateVaultRequest_admin protoreflect.FieldDescriptor fd_MsgCreateVaultRequest_share_denom protoreflect.FieldDescriptor fd_MsgCreateVaultRequest_underlying_asset protoreflect.FieldDescriptor - fd_MsgCreateVaultRequest_payment_denom protoreflect.FieldDescriptor fd_MsgCreateVaultRequest_withdrawal_delay_seconds protoreflect.FieldDescriptor fd_MsgCreateVaultRequest_min_swap_in_value protoreflect.FieldDescriptor fd_MsgCreateVaultRequest_min_swap_out_value protoreflect.FieldDescriptor fd_MsgCreateVaultRequest_max_swap_in_value protoreflect.FieldDescriptor fd_MsgCreateVaultRequest_max_swap_out_value protoreflect.FieldDescriptor - fd_MsgCreateVaultRequest_initial_payment_nav protoreflect.FieldDescriptor ) func init() { @@ -37,13 +35,11 @@ func init() { fd_MsgCreateVaultRequest_admin = md_MsgCreateVaultRequest.Fields().ByName("admin") fd_MsgCreateVaultRequest_share_denom = md_MsgCreateVaultRequest.Fields().ByName("share_denom") fd_MsgCreateVaultRequest_underlying_asset = md_MsgCreateVaultRequest.Fields().ByName("underlying_asset") - fd_MsgCreateVaultRequest_payment_denom = md_MsgCreateVaultRequest.Fields().ByName("payment_denom") fd_MsgCreateVaultRequest_withdrawal_delay_seconds = md_MsgCreateVaultRequest.Fields().ByName("withdrawal_delay_seconds") fd_MsgCreateVaultRequest_min_swap_in_value = md_MsgCreateVaultRequest.Fields().ByName("min_swap_in_value") fd_MsgCreateVaultRequest_min_swap_out_value = md_MsgCreateVaultRequest.Fields().ByName("min_swap_out_value") fd_MsgCreateVaultRequest_max_swap_in_value = md_MsgCreateVaultRequest.Fields().ByName("max_swap_in_value") fd_MsgCreateVaultRequest_max_swap_out_value = md_MsgCreateVaultRequest.Fields().ByName("max_swap_out_value") - fd_MsgCreateVaultRequest_initial_payment_nav = md_MsgCreateVaultRequest.Fields().ByName("initial_payment_nav") } var _ protoreflect.Message = (*fastReflection_MsgCreateVaultRequest)(nil) @@ -129,12 +125,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Range(f func(protoreflect.FieldDe return } } - if x.PaymentDenom != "" { - value := protoreflect.ValueOfString(x.PaymentDenom) - if !f(fd_MsgCreateVaultRequest_payment_denom, value) { - return - } - } if x.WithdrawalDelaySeconds != uint64(0) { value := protoreflect.ValueOfUint64(x.WithdrawalDelaySeconds) if !f(fd_MsgCreateVaultRequest_withdrawal_delay_seconds, value) { @@ -165,12 +155,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Range(f func(protoreflect.FieldDe return } } - if x.InitialPaymentNav != nil { - value := protoreflect.ValueOfMessage(x.InitialPaymentNav.ProtoReflect()) - if !f(fd_MsgCreateVaultRequest_initial_payment_nav, value) { - return - } - } } // Has reports whether a field is populated. @@ -192,8 +176,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Has(fd protoreflect.FieldDescript return x.ShareDenom != "" case "provlabs.vault.v1.MsgCreateVaultRequest.underlying_asset": return x.UnderlyingAsset != "" - case "provlabs.vault.v1.MsgCreateVaultRequest.payment_denom": - return x.PaymentDenom != "" case "provlabs.vault.v1.MsgCreateVaultRequest.withdrawal_delay_seconds": return x.WithdrawalDelaySeconds != uint64(0) case "provlabs.vault.v1.MsgCreateVaultRequest.min_swap_in_value": @@ -204,8 +186,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Has(fd protoreflect.FieldDescript return x.MaxSwapInValue != "" case "provlabs.vault.v1.MsgCreateVaultRequest.max_swap_out_value": return x.MaxSwapOutValue != "" - case "provlabs.vault.v1.MsgCreateVaultRequest.initial_payment_nav": - return x.InitialPaymentNav != nil default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgCreateVaultRequest")) @@ -228,8 +208,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Clear(fd protoreflect.FieldDescri x.ShareDenom = "" case "provlabs.vault.v1.MsgCreateVaultRequest.underlying_asset": x.UnderlyingAsset = "" - case "provlabs.vault.v1.MsgCreateVaultRequest.payment_denom": - x.PaymentDenom = "" case "provlabs.vault.v1.MsgCreateVaultRequest.withdrawal_delay_seconds": x.WithdrawalDelaySeconds = uint64(0) case "provlabs.vault.v1.MsgCreateVaultRequest.min_swap_in_value": @@ -240,8 +218,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Clear(fd protoreflect.FieldDescri x.MaxSwapInValue = "" case "provlabs.vault.v1.MsgCreateVaultRequest.max_swap_out_value": x.MaxSwapOutValue = "" - case "provlabs.vault.v1.MsgCreateVaultRequest.initial_payment_nav": - x.InitialPaymentNav = nil default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgCreateVaultRequest")) @@ -267,9 +243,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Get(descriptor protoreflect.Field case "provlabs.vault.v1.MsgCreateVaultRequest.underlying_asset": value := x.UnderlyingAsset return protoreflect.ValueOfString(value) - case "provlabs.vault.v1.MsgCreateVaultRequest.payment_denom": - value := x.PaymentDenom - return protoreflect.ValueOfString(value) case "provlabs.vault.v1.MsgCreateVaultRequest.withdrawal_delay_seconds": value := x.WithdrawalDelaySeconds return protoreflect.ValueOfUint64(value) @@ -285,9 +258,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Get(descriptor protoreflect.Field case "provlabs.vault.v1.MsgCreateVaultRequest.max_swap_out_value": value := x.MaxSwapOutValue return protoreflect.ValueOfString(value) - case "provlabs.vault.v1.MsgCreateVaultRequest.initial_payment_nav": - value := x.InitialPaymentNav - return protoreflect.ValueOfMessage(value.ProtoReflect()) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgCreateVaultRequest")) @@ -314,8 +284,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Set(fd protoreflect.FieldDescript x.ShareDenom = value.Interface().(string) case "provlabs.vault.v1.MsgCreateVaultRequest.underlying_asset": x.UnderlyingAsset = value.Interface().(string) - case "provlabs.vault.v1.MsgCreateVaultRequest.payment_denom": - x.PaymentDenom = value.Interface().(string) case "provlabs.vault.v1.MsgCreateVaultRequest.withdrawal_delay_seconds": x.WithdrawalDelaySeconds = value.Uint() case "provlabs.vault.v1.MsgCreateVaultRequest.min_swap_in_value": @@ -326,8 +294,6 @@ func (x *fastReflection_MsgCreateVaultRequest) Set(fd protoreflect.FieldDescript x.MaxSwapInValue = value.Interface().(string) case "provlabs.vault.v1.MsgCreateVaultRequest.max_swap_out_value": x.MaxSwapOutValue = value.Interface().(string) - case "provlabs.vault.v1.MsgCreateVaultRequest.initial_payment_nav": - x.InitialPaymentNav = value.Message().Interface().(*InitialVaultNAV) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgCreateVaultRequest")) @@ -348,19 +314,12 @@ func (x *fastReflection_MsgCreateVaultRequest) Set(fd protoreflect.FieldDescript // Mutable is a mutating operation and unsafe for concurrent use. func (x *fastReflection_MsgCreateVaultRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { switch fd.FullName() { - case "provlabs.vault.v1.MsgCreateVaultRequest.initial_payment_nav": - if x.InitialPaymentNav == nil { - x.InitialPaymentNav = new(InitialVaultNAV) - } - return protoreflect.ValueOfMessage(x.InitialPaymentNav.ProtoReflect()) case "provlabs.vault.v1.MsgCreateVaultRequest.admin": panic(fmt.Errorf("field admin of message provlabs.vault.v1.MsgCreateVaultRequest is not mutable")) case "provlabs.vault.v1.MsgCreateVaultRequest.share_denom": panic(fmt.Errorf("field share_denom of message provlabs.vault.v1.MsgCreateVaultRequest is not mutable")) case "provlabs.vault.v1.MsgCreateVaultRequest.underlying_asset": panic(fmt.Errorf("field underlying_asset of message provlabs.vault.v1.MsgCreateVaultRequest is not mutable")) - case "provlabs.vault.v1.MsgCreateVaultRequest.payment_denom": - panic(fmt.Errorf("field payment_denom of message provlabs.vault.v1.MsgCreateVaultRequest is not mutable")) case "provlabs.vault.v1.MsgCreateVaultRequest.withdrawal_delay_seconds": panic(fmt.Errorf("field withdrawal_delay_seconds of message provlabs.vault.v1.MsgCreateVaultRequest is not mutable")) case "provlabs.vault.v1.MsgCreateVaultRequest.min_swap_in_value": @@ -390,8 +349,6 @@ func (x *fastReflection_MsgCreateVaultRequest) NewField(fd protoreflect.FieldDes return protoreflect.ValueOfString("") case "provlabs.vault.v1.MsgCreateVaultRequest.underlying_asset": return protoreflect.ValueOfString("") - case "provlabs.vault.v1.MsgCreateVaultRequest.payment_denom": - return protoreflect.ValueOfString("") case "provlabs.vault.v1.MsgCreateVaultRequest.withdrawal_delay_seconds": return protoreflect.ValueOfUint64(uint64(0)) case "provlabs.vault.v1.MsgCreateVaultRequest.min_swap_in_value": @@ -402,9 +359,6 @@ func (x *fastReflection_MsgCreateVaultRequest) NewField(fd protoreflect.FieldDes return protoreflect.ValueOfString("") case "provlabs.vault.v1.MsgCreateVaultRequest.max_swap_out_value": return protoreflect.ValueOfString("") - case "provlabs.vault.v1.MsgCreateVaultRequest.initial_payment_nav": - m := new(InitialVaultNAV) - return protoreflect.ValueOfMessage(m.ProtoReflect()) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgCreateVaultRequest")) @@ -486,10 +440,6 @@ func (x *fastReflection_MsgCreateVaultRequest) ProtoMethods() *protoiface.Method if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } - l = len(x.PaymentDenom) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } if x.WithdrawalDelaySeconds != 0 { n += 1 + runtime.Sov(uint64(x.WithdrawalDelaySeconds)) } @@ -509,10 +459,6 @@ func (x *fastReflection_MsgCreateVaultRequest) ProtoMethods() *protoiface.Method if l > 0 { n += 1 + l + runtime.Sov(uint64(l)) } - if x.InitialPaymentNav != nil { - l = options.Size(x.InitialPaymentNav) - n += 1 + l + runtime.Sov(uint64(l)) - } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -542,20 +488,6 @@ func (x *fastReflection_MsgCreateVaultRequest) ProtoMethods() *protoiface.Method i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } - if x.InitialPaymentNav != nil { - encoded, err := options.Marshal(x.InitialPaymentNav) - if err != nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, err - } - i -= len(encoded) - copy(dAtA[i:], encoded) - i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) - i-- - dAtA[i] = 0x52 - } if len(x.MaxSwapOutValue) > 0 { i -= len(x.MaxSwapOutValue) copy(dAtA[i:], x.MaxSwapOutValue) @@ -589,13 +521,6 @@ func (x *fastReflection_MsgCreateVaultRequest) ProtoMethods() *protoiface.Method i-- dAtA[i] = 0x28 } - if len(x.PaymentDenom) > 0 { - i -= len(x.PaymentDenom) - copy(dAtA[i:], x.PaymentDenom) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.PaymentDenom))) - i-- - dAtA[i] = 0x22 - } if len(x.UnderlyingAsset) > 0 { i -= len(x.UnderlyingAsset) copy(dAtA[i:], x.UnderlyingAsset) @@ -762,38 +687,6 @@ func (x *fastReflection_MsgCreateVaultRequest) ProtoMethods() *protoiface.Method } x.UnderlyingAsset = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field PaymentDenom", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - x.PaymentDenom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex case 5: if wireType != 0 { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field WithdrawalDelaySeconds", wireType) @@ -941,42 +834,6 @@ func (x *fastReflection_MsgCreateVaultRequest) ProtoMethods() *protoiface.Method } x.MaxSwapOutValue = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 10: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field InitialPaymentNav", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if x.InitialPaymentNav == nil { - x.InitialPaymentNav = &InitialVaultNAV{} - } - if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.InitialPaymentNav); err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -3354,7 +3211,6 @@ var ( fd_MsgSwapOutRequest_owner protoreflect.FieldDescriptor fd_MsgSwapOutRequest_vault_address protoreflect.FieldDescriptor fd_MsgSwapOutRequest_assets protoreflect.FieldDescriptor - fd_MsgSwapOutRequest_redeem_denom protoreflect.FieldDescriptor ) func init() { @@ -3363,7 +3219,6 @@ func init() { fd_MsgSwapOutRequest_owner = md_MsgSwapOutRequest.Fields().ByName("owner") fd_MsgSwapOutRequest_vault_address = md_MsgSwapOutRequest.Fields().ByName("vault_address") fd_MsgSwapOutRequest_assets = md_MsgSwapOutRequest.Fields().ByName("assets") - fd_MsgSwapOutRequest_redeem_denom = md_MsgSwapOutRequest.Fields().ByName("redeem_denom") } var _ protoreflect.Message = (*fastReflection_MsgSwapOutRequest)(nil) @@ -3449,12 +3304,6 @@ func (x *fastReflection_MsgSwapOutRequest) Range(f func(protoreflect.FieldDescri return } } - if x.RedeemDenom != "" { - value := protoreflect.ValueOfString(x.RedeemDenom) - if !f(fd_MsgSwapOutRequest_redeem_denom, value) { - return - } - } } // Has reports whether a field is populated. @@ -3476,8 +3325,6 @@ func (x *fastReflection_MsgSwapOutRequest) Has(fd protoreflect.FieldDescriptor) return x.VaultAddress != "" case "provlabs.vault.v1.MsgSwapOutRequest.assets": return x.Assets != nil - case "provlabs.vault.v1.MsgSwapOutRequest.redeem_denom": - return x.RedeemDenom != "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgSwapOutRequest")) @@ -3500,8 +3347,6 @@ func (x *fastReflection_MsgSwapOutRequest) Clear(fd protoreflect.FieldDescriptor x.VaultAddress = "" case "provlabs.vault.v1.MsgSwapOutRequest.assets": x.Assets = nil - case "provlabs.vault.v1.MsgSwapOutRequest.redeem_denom": - x.RedeemDenom = "" default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgSwapOutRequest")) @@ -3527,9 +3372,6 @@ func (x *fastReflection_MsgSwapOutRequest) Get(descriptor protoreflect.FieldDesc case "provlabs.vault.v1.MsgSwapOutRequest.assets": value := x.Assets return protoreflect.ValueOfMessage(value.ProtoReflect()) - case "provlabs.vault.v1.MsgSwapOutRequest.redeem_denom": - value := x.RedeemDenom - return protoreflect.ValueOfString(value) default: if descriptor.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgSwapOutRequest")) @@ -3556,8 +3398,6 @@ func (x *fastReflection_MsgSwapOutRequest) Set(fd protoreflect.FieldDescriptor, x.VaultAddress = value.Interface().(string) case "provlabs.vault.v1.MsgSwapOutRequest.assets": x.Assets = value.Message().Interface().(*v1beta11.Coin) - case "provlabs.vault.v1.MsgSwapOutRequest.redeem_denom": - x.RedeemDenom = value.Interface().(string) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgSwapOutRequest")) @@ -3587,8 +3427,6 @@ func (x *fastReflection_MsgSwapOutRequest) Mutable(fd protoreflect.FieldDescript panic(fmt.Errorf("field owner of message provlabs.vault.v1.MsgSwapOutRequest is not mutable")) case "provlabs.vault.v1.MsgSwapOutRequest.vault_address": panic(fmt.Errorf("field vault_address of message provlabs.vault.v1.MsgSwapOutRequest is not mutable")) - case "provlabs.vault.v1.MsgSwapOutRequest.redeem_denom": - panic(fmt.Errorf("field redeem_denom of message provlabs.vault.v1.MsgSwapOutRequest is not mutable")) default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgSwapOutRequest")) @@ -3609,8 +3447,6 @@ func (x *fastReflection_MsgSwapOutRequest) NewField(fd protoreflect.FieldDescrip case "provlabs.vault.v1.MsgSwapOutRequest.assets": m := new(v1beta11.Coin) return protoreflect.ValueOfMessage(m.ProtoReflect()) - case "provlabs.vault.v1.MsgSwapOutRequest.redeem_denom": - return protoreflect.ValueOfString("") default: if fd.IsExtension() { panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.MsgSwapOutRequest")) @@ -3692,10 +3528,6 @@ func (x *fastReflection_MsgSwapOutRequest) ProtoMethods() *protoiface.Methods { l = options.Size(x.Assets) n += 1 + l + runtime.Sov(uint64(l)) } - l = len(x.RedeemDenom) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } if x.unknownFields != nil { n += len(x.unknownFields) } @@ -3725,13 +3557,6 @@ func (x *fastReflection_MsgSwapOutRequest) ProtoMethods() *protoiface.Methods { i -= len(x.unknownFields) copy(dAtA[i:], x.unknownFields) } - if len(x.RedeemDenom) > 0 { - i -= len(x.RedeemDenom) - copy(dAtA[i:], x.RedeemDenom) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.RedeemDenom))) - i-- - dAtA[i] = 0x22 - } if x.Assets != nil { encoded, err := options.Marshal(x.Assets) if err != nil { @@ -3909,38 +3734,6 @@ func (x *fastReflection_MsgSwapOutRequest) ProtoMethods() *protoiface.Methods { return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err } iNdEx = postIndex - case 4: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field RedeemDenom", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - x.RedeemDenom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := runtime.Skip(dAtA[iNdEx:]) @@ -29941,9 +29734,6 @@ type MsgCreateVaultRequest struct { ShareDenom string `protobuf:"bytes,2,opt,name=share_denom,json=shareDenom,proto3" json:"share_denom,omitempty"` // underlying_asset is the denomination of the asset supported by the vault. UnderlyingAsset string `protobuf:"bytes,3,opt,name=underlying_asset,json=underlyingAsset,proto3" json:"underlying_asset,omitempty"` - // payment_denom is the secondary denomination the vault can accept. - // if not specified, vault payment_denom will be set to underlying_asset. - PaymentDenom string `protobuf:"bytes,4,opt,name=payment_denom,json=paymentDenom,proto3" json:"payment_denom,omitempty"` // withdrawal_delay_seconds is the time period (in seconds) that a withdrawal // must wait in the pending queue before being processed. WithdrawalDelaySeconds uint64 `protobuf:"varint,5,opt,name=withdrawal_delay_seconds,json=withdrawalDelaySeconds,proto3" json:"withdrawal_delay_seconds,omitempty"` @@ -29963,13 +29753,6 @@ type MsgCreateVaultRequest struct { // - Values must be positive (> 0). // - An empty string "" indicates no maximum limit. MaxSwapOutValue string `protobuf:"bytes,9,opt,name=max_swap_out_value,json=maxSwapOutValue,proto3" json:"max_swap_out_value,omitempty"` - // initial_payment_nav seeds the per-vault Internal NAV entry for payment_denom - // at creation, ensuring fee accrual and payment-denom swap-outs are operational - // from block one. The entry's denom is implicitly payment_denom; the price - // denom must be underlying_asset. - // - Required when payment_denom is set and payment_denom != underlying_asset. - // - Must be omitted when payment_denom is empty or equal to underlying_asset. - InitialPaymentNav *InitialVaultNAV `protobuf:"bytes,10,opt,name=initial_payment_nav,json=initialPaymentNav,proto3" json:"initial_payment_nav,omitempty"` } func (x *MsgCreateVaultRequest) Reset() { @@ -30013,13 +29796,6 @@ func (x *MsgCreateVaultRequest) GetUnderlyingAsset() string { return "" } -func (x *MsgCreateVaultRequest) GetPaymentDenom() string { - if x != nil { - return x.PaymentDenom - } - return "" -} - func (x *MsgCreateVaultRequest) GetWithdrawalDelaySeconds() uint64 { if x != nil { return x.WithdrawalDelaySeconds @@ -30055,13 +29831,6 @@ func (x *MsgCreateVaultRequest) GetMaxSwapOutValue() string { return "" } -func (x *MsgCreateVaultRequest) GetInitialPaymentNav() *InitialVaultNAV { - if x != nil { - return x.InitialPaymentNav - } - return nil -} - // MsgCreateVaultResponse is the response message for the CreateVault endpoint. type MsgCreateVaultResponse struct { state protoimpl.MessageState @@ -30286,10 +30055,6 @@ type MsgSwapOutRequest struct { VaultAddress string `protobuf:"bytes,2,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // assets is the amount of underlying assets to withdraw. Assets *v1beta11.Coin `protobuf:"bytes,3,opt,name=assets,proto3" json:"assets,omitempty"` - // redeem_denom selects the payout coin. - // - If empty, defaults to the vault’s payment_denom. - // - Must be either the vault’s underlying_asset or its payment_denom. - RedeemDenom string `protobuf:"bytes,4,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` } func (x *MsgSwapOutRequest) Reset() { @@ -30333,13 +30098,6 @@ func (x *MsgSwapOutRequest) GetAssets() *v1beta11.Coin { return nil } -func (x *MsgSwapOutRequest) GetRedeemDenom() string { - if x != nil { - return x.RedeemDenom - } - return "" -} - // MsgSwapOutResponse is the response message for the SwapOut endpoint. type MsgSwapOutResponse struct { state protoimpl.MessageState @@ -32361,11 +32119,10 @@ type MsgUpdateVaultNAVRequest struct { // vault_address is the bech32 address of the vault whose NAV entry is being updated. VaultAddress string `protobuf:"bytes,2,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // denom is the asset denomination being priced. It must not be the vault's - // share denom. The underlying asset is a valid denom (e.g. to record its - // price in payment-denom terms). + // share denom. Denom string `protobuf:"bytes,3,opt,name=denom,proto3" json:"denom,omitempty"` // price is the total value of `volume` units of the denom, denominated in - // one of the vault's accepted denoms (underlying asset or payment denom). + // the vault's underlying asset. Price *v1beta11.Coin `protobuf:"bytes,4,opt,name=price,proto3" json:"price,omitempty"` // volume is the number of units of the denom that price covers. It must be positive. Volume string `protobuf:"bytes,5,opt,name=volume,proto3" json:"volume,omitempty"` @@ -32547,8 +32304,8 @@ func (*MsgUpdateNAVAuthorityResponse) Descriptor() ([]byte, []int) { // MsgAcceptAssetRequest is the request message for settling a pending exchange-module // payment whose target is the vault. The payment is identified by its source account and -// external_id. The vault settles only payments where one leg is the vault's payment_denom; -// the settlement direction (inbound or outbound) is derived from which leg that is. +// external_id. The vault settles only payments where one leg is the vault's underlying +// asset; the settlement direction (inbound or outbound) is derived from which leg that is. type MsgAcceptAssetRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -32750,7 +32507,7 @@ var file_provlabs_vault_v1_tx_proto_rawDesc = []byte{ 0x61, 0x62, 0x73, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xda, 0x04, 0x0a, 0x15, 0x4d, 0x73, 0x67, + 0x6c, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x91, 0x04, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, @@ -32759,723 +32516,718 @@ var file_provlabs_vault_v1_tx_proto_rawDesc = []byte{ 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x68, 0x61, 0x72, 0x65, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x29, 0x0a, 0x10, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x75, - 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x23, - 0x0a, 0x0d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, - 0x6e, 0x6f, 0x6d, 0x12, 0x38, 0x0a, 0x18, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, - 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, - 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x3f, 0x0a, - 0x11, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, - 0x6d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x41, - 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x3f, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, - 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x41, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, - 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, - 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x52, 0x0a, 0x13, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, - 0x5f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x76, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, - 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x56, 0x61, - 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x52, 0x11, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x76, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x3d, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x22, 0xf9, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x65, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x75, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x3a, 0xc8, 0xde, 0x1f, 0x00, 0xda, - 0xde, 0x1f, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, - 0x78, 0x2f, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, + 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x38, + 0x0a, 0x18, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, + 0x61, 0x79, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, + 0x79, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x3f, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x5f, + 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x6d, 0x69, 0x6e, 0x53, 0x77, + 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x41, 0x0a, 0x12, 0x6d, 0x69, 0x6e, + 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x69, 0x6e, + 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x11, + 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x6d, + 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x41, 0x0a, + 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x0f, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x04, + 0x10, 0x05, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x52, 0x13, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, + 0x5f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x76, 0x22, 0x3d, 0x0a, 0x16, + 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, + 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xf9, 0x01, 0x0a, 0x1f, + 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x44, 0x65, 0x6e, 0x6f, 0x6d, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x75, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x6e, 0x6b, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x42, 0x3a, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x78, 0x2f, 0x62, 0x61, 0x6e, 0x6b, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, + 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, + 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x53, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xac, 0x01, 0x0a, 0x10, + 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x2e, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, + 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, + 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x0a, + 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x11, 0x4d, 0x73, + 0x67, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x48, 0x0a, 0x0f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, + 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x0e, 0x73, 0x68, 0x61, 0x72, 0x65, + 0x73, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x22, 0xc1, 0x01, 0x0a, 0x11, 0x4d, 0x73, + 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x2e, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, + 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x44, - 0x65, 0x6e, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xac, 0x01, 0x0a, 0x10, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, - 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, - 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, - 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x11, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x73, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, - 0x1f, 0x00, 0x52, 0x0e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x64, 0x22, 0xd0, 0x01, 0x0a, 0x11, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, - 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, - 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, - 0x64, 0x65, 0x65, 0x6d, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0x33, 0x0a, 0x12, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, - 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x9d, 0x01, 0x0a, 0x1f, 0x4d, - 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, - 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, - 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, - 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x52, 0x61, 0x74, 0x65, 0x3a, 0x0a, - 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, - 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, - 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9d, - 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, - 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x52, 0x61, - 0x74, 0x65, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x22, - 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x1c, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x52, 0x61, 0x74, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, - 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x1f, 0x0a, 0x1d, 0x4d, - 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, - 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc8, 0x01, 0x0a, - 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, - 0x18, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, - 0x79, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, - 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, - 0x6c, 0x61, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xce, 0x01, 0x0a, 0x1e, - 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, - 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, - 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, + 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, + 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x0a, 0x82, + 0xe7, 0xb0, 0x2a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, + 0x0c, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x33, 0x0a, + 0x12, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x49, 0x64, 0x22, 0x9d, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4d, 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x11, 0x6d, - 0x69, 0x6e, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x6d, 0x69, - 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x0e, 0x82, 0xe7, - 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x21, 0x0a, 0x1f, - 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, - 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0xd1, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, - 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x41, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, - 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xce, 0x01, 0x0a, 0x1e, 0x4d, 0x73, 0x67, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, - 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x73, - 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, - 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, - 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x21, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x1f, - 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, - 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x12, - 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, - 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6d, + 0x69, 0x6e, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x69, 0x6e, 0x52, 0x61, 0x74, 0x65, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, + 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9d, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x52, 0x61, 0x74, 0x65, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, + 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x1c, 0x4d, + 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, + 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, + 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, + 0x72, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x52, + 0x61, 0x74, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x22, 0x1f, 0x0a, 0x1d, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc8, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, + 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, - 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, - 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, - 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, - 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, - 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, + 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0xce, 0x01, 0x0a, 0x1e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3a, 0x0a, 0x82, - 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, - 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x94, 0x01, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, - 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3a, - 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x4d, - 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc6, 0x01, 0x0a, 0x1e, 0x4d, 0x73, 0x67, 0x44, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, - 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, - 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, - 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, + 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, + 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x6d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x22, 0x21, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, + 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, + 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x53, + 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, + 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x20, 0x4d, + 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, + 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xce, 0x01, 0x0a, 0x1e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, + 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x3f, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x22, 0x21, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0xc7, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, + 0x22, 0x21, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, + 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, - 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, - 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x0e, 0x82, - 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, - 0x20, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0xc7, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, + 0x72, 0x65, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, + 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, + 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x16, + 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, + 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, + 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x94, 0x01, 0x0a, + 0x17, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, + 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, + 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xc6, 0x01, 0x0a, 0x1e, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, + 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x37, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, + 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x21, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, + 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc7, 0x01, 0x0a, 0x1f, + 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc7, 0x01, 0x0a, 0x1f, 0x4d, 0x73, + 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, + 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, + 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc8, 0x01, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x57, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, + 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, + 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x22, 0x23, 0x0a, 0x21, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x45, + 0x78, 0x70, 0x65, 0x64, 0x69, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, + 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x49, 0x64, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x22, 0x23, 0x0a, 0x21, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x70, 0x65, 0x64, 0x69, + 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x14, 0x4d, 0x73, 0x67, + 0x50, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, + 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x3a, 0x0e, 0x82, 0xe7, + 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x17, 0x0a, 0x15, + 0x4d, 0x73, 0x67, 0x50, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x70, + 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x0e, 0x82, + 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x19, 0x0a, + 0x17, 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x4d, 0x73, 0x67, + 0x53, 0x65, 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x0e, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0d, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x0a, 0x82, + 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x1d, 0x0a, 0x1b, 0x4d, 0x73, 0x67, + 0x53, 0x65, 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x16, 0x4d, 0x73, 0x67, + 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, + 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x19, + 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x42, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb9, 0x01, 0x0a, 0x1a, 0x4d, 0x73, + 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, + 0x6e, 0x67, 0x52, 0x06, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x37, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, + 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb9, 0x01, 0x0a, 0x1a, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, + 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x68, + 0x61, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x73, 0x68, 0x61, + 0x72, 0x65, 0x73, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x22, 0x1d, 0x0a, 0x1b, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x42, 0x75, 0x72, + 0x6e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xbb, 0x01, 0x0a, 0x19, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, + 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, + 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, + 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x73, 0x73, 0x12, 0x3d, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x1c, 0x0a, + 0x1a, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x99, 0x01, 0x0a, 0x16, + 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x37, + 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, + 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x1f, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x55, 0x4d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, + 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x75, 0x6d, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x62, + 0x69, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x61, 0x75, 0x6d, 0x46, 0x65, + 0x65, 0x42, 0x69, 0x70, 0x73, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x55, 0x4d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa8, 0x02, 0x0a, 0x18, 0x4d, 0x73, + 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, + 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, + 0x6e, 0x6f, 0x6d, 0x12, 0x35, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, - 0xde, 0x1f, 0x00, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, - 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x20, 0x4d, - 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, - 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0xc8, 0x01, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, - 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, + 0xde, 0x1f, 0x00, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x06, 0x76, 0x6f, + 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, + 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, + 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, + 0x67, 0x6e, 0x65, 0x72, 0x22, 0x1b, 0x0a, 0x19, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x1c, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, + 0x41, 0x56, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, + 0x67, 0x6e, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, + 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3d, 0x0a, 0x0d, 0x6e, 0x65, 0x77, + 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x1f, 0x0a, 0x1d, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4e, 0x41, 0x56, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd7, 0x01, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x41, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x30, 0x0a, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, + 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, + 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, + 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x22, 0x18, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd7, 0x01, 0x0a, 0x15, 0x4d, + 0x73, 0x67, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, - 0x1f, 0x00, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, - 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x23, 0x0a, 0x21, 0x4d, 0x73, - 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, - 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x89, 0x01, 0x0a, 0x20, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x70, 0x65, 0x64, 0x69, 0x74, 0x65, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, - 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x23, 0x0a, 0x21, 0x4d, - 0x73, 0x67, 0x45, 0x78, 0x70, 0x65, 0x64, 0x69, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0xb1, 0x01, 0x0a, 0x14, 0x4d, 0x73, 0x67, 0x50, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, - 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, - 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x14, - 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, - 0x6f, 0x72, 0x63, 0x65, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x22, 0x17, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x50, 0x61, 0x75, 0x73, 0x65, - 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x85, 0x01, - 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, - 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x70, 0x61, - 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, - 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, - 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, - 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x0e, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, - 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, - 0x6e, 0x22, 0x1d, 0x0a, 0x1b, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, - 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x93, 0x01, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x42, 0x72, - 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, - 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, - 0x67, 0x6c, 0x65, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0xb9, 0x01, 0x0a, 0x1a, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x4d, - 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x30, 0x0a, 0x06, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x62, 0x72, 0x69, 0x64, - 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, - 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, - 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x22, 0x1d, 0x0a, - 0x1b, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb9, 0x01, 0x0a, - 0x1a, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, - 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x62, - 0x72, 0x69, 0x64, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, - 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, - 0xde, 0x1f, 0x00, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x3a, 0x0b, 0x82, 0xe7, 0xb0, - 0x2a, 0x06, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x4d, 0x73, 0x67, 0x42, - 0x72, 0x69, 0x64, 0x67, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x19, 0x4d, 0x73, 0x67, 0x53, - 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, - 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3d, 0x0a, 0x0d, 0x61, 0x73, - 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, - 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x1c, 0x0a, 0x1a, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x99, 0x01, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, - 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x37, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, - 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, - 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, - 0x19, 0x0a, 0x17, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x1f, 0x4d, - 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x55, 0x4d, - 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, - 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x73, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x61, - 0x75, 0x6d, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x62, 0x69, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x0a, 0x61, 0x75, 0x6d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x3a, 0x0e, 0x82, - 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x22, 0x0a, - 0x20, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, - 0x55, 0x4d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0xa8, 0x02, 0x0a, 0x18, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, - 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, - 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, - 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, - 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x35, 0x0a, 0x05, 0x70, - 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x05, 0x70, 0x72, 0x69, - 0x63, 0x65, 0x12, 0x43, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, - 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, - 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, - 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x1b, 0x0a, 0x19, - 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, - 0x56, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x1c, 0x4d, 0x73, - 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x41, 0x56, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x69, - 0x67, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x3d, 0x0a, 0x0d, 0x6e, 0x65, 0x77, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x3a, 0x0b, 0x82, 0xe7, 0xb0, 0x2a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x1f, 0x0a, - 0x1d, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x41, 0x56, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd7, - 0x01, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, - 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, - 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x18, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x41, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0xd7, 0x01, 0x0a, 0x15, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x30, 0x0a, 0x06, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x65, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x3a, 0x0e, 0x82, 0xe7, - 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0x18, 0x0a, 0x16, - 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x98, 0x1d, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x62, - 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x28, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, - 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x44, - 0x65, 0x6e, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x32, 0x2e, 0x70, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x06, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, + 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x49, 0x64, 0x3a, 0x0e, 0x82, 0xe7, 0xb0, 0x2a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x22, 0x18, 0x0a, 0x16, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6a, 0x65, 0x63, + 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x98, + 0x1d, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x62, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x56, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, + 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, + 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x53, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x65, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, + 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, + 0x06, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, + 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x44, 0x65, 0x6e, 0x6f, - 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, - 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x06, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x12, - 0x23, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, - 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x07, 0x53, 0x77, - 0x61, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, - 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, + 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x56, 0x0a, 0x07, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x24, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, + 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, + 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, + 0x52, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, + 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, + 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, + 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x73, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, - 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, - 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, + 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x77, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, + 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, + 0x6c, 0x61, 0x79, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2f, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x32, 0x2e, 0x70, 0x72, + 0x65, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, + 0x65, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, + 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, + 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, + 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, + 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, + 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, + 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, + 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, + 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, - 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x31, 0x2e, 0x70, + 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, + 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x65, 0x0a, 0x0c, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, + 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, + 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x54, 0x6f, 0x67, 0x67, 0x6c, + 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, + 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, + 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x7d, 0x0a, 0x14, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, + 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, + 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, 0x61, - 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, - 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, - 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x2e, + 0x2e, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x80, 0x01, 0x0a, 0x15, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, + 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x50, + 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x53, 0x77, - 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x50, 0x72, 0x69, 0x6e, + 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, - 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x31, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x53, - 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, - 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, - 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x54, 0x6f, 0x67, 0x67, - 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, - 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, - 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, - 0x65, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x68, 0x0a, 0x0d, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, - 0x12, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, - 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x70, - 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x14, 0x44, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, - 0x73, 0x12, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, - 0x64, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, - 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, + 0x73, 0x12, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, + 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x46, 0x75, - 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, - 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, - 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x44, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, - 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, - 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, - 0x67, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, - 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, - 0x01, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, 0x72, 0x69, 0x6e, 0x63, - 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, + 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, + 0x16, 0x45, 0x78, 0x70, 0x65, 0x64, 0x69, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x45, + 0x78, 0x70, 0x65, 0x64, 0x69, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, + 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x70, 0x65, 0x64, 0x69, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0a, 0x50, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, + 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x50, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, + 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, - 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, - 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, + 0x67, 0x50, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, + 0x75, 0x6c, 0x74, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, + 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x70, 0x61, 0x75, + 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x50, 0x72, - 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x16, 0x45, 0x78, 0x70, 0x65, 0x64, 0x69, 0x74, - 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x12, - 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x70, 0x65, 0x64, 0x69, 0x74, 0x65, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x45, 0x78, 0x70, 0x65, - 0x64, 0x69, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, 0x4f, - 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0a, 0x50, 0x61, - 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, + 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x10, 0x53, 0x65, + 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2d, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, + 0x0c, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x29, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x42, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, + 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x10, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x4d, 0x69, + 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, - 0x50, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x50, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, - 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x55, - 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x29, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x73, 0x67, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, - 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x6e, - 0x70, 0x61, 0x75, 0x73, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x71, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, - 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, - 0x74, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, - 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x42, - 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, - 0x67, 0x6c, 0x65, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x42, 0x72, - 0x69, 0x64, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x10, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, - 0x12, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x4d, 0x69, - 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x4d, 0x69, 0x6e, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x71, 0x0a, 0x10, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, 0x61, - 0x72, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, - 0x65, 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, - 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, - 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, - 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x42, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x4d, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x10, 0x42, 0x72, 0x69, 0x64, 0x67, + 0x65, 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, 0x61, + 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x73, 0x67, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x42, 0x75, 0x72, 0x6e, 0x53, 0x68, 0x61, 0x72, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0f, 0x53, 0x65, + 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x55, 0x4d, 0x46, 0x65, 0x65, 0x42, - 0x69, 0x70, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x55, 0x4d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, - 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x55, 0x4d, 0x46, 0x65, 0x65, - 0x42, 0x69, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x0e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x12, 0x2b, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, - 0x74, 0x4e, 0x41, 0x56, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, + 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, - 0x56, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x12, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4e, 0x41, 0x56, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, - 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x41, 0x56, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x41, - 0x56, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x12, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, - 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x72, + 0x4d, 0x73, 0x67, 0x53, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x29, 0x2e, 0x70, 0x72, 0x6f, + 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, + 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, + 0x74, 0x41, 0x55, 0x4d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x12, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x73, 0x67, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, - 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6a, - 0x65, 0x63, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x73, 0x73, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, - 0x01, 0x42, 0xbf, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, - 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x07, 0x54, 0x78, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x76, - 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x76, 0x31, 0xa2, - 0x02, 0x03, 0x50, 0x56, 0x58, 0xaa, 0x02, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, - 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x11, 0x50, 0x72, 0x6f, 0x76, - 0x6c, 0x61, 0x62, 0x73, 0x5c, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1d, - 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x5c, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x5c, 0x56, - 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, - 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x3a, 0x3a, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x3a, - 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x55, + 0x4d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, + 0x6c, 0x74, 0x41, 0x55, 0x4d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, + 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, + 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, + 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x77, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x41, 0x56, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2f, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x41, 0x56, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x41, 0x56, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x41, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x28, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, + 0x67, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, + 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x41, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, + 0x0a, 0x0b, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x28, 0x2e, + 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, + 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x73, 0x67, 0x52, + 0x65, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, 0x01, 0x42, 0xbf, 0x01, 0x0a, 0x15, 0x63, 0x6f, + 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x2e, 0x76, 0x31, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x6c, + 0x61, 0x62, 0x73, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, + 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x76, 0x31, 0x3b, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x56, 0x58, 0xaa, 0x02, 0x11, + 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x56, + 0x31, 0xca, 0x02, 0x11, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x5c, 0x56, 0x61, 0x75, + 0x6c, 0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1d, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, + 0x5c, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x50, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, + 0x3a, 0x3a, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -33556,94 +33308,92 @@ var file_provlabs_vault_v1_tx_proto_goTypes = []interface{}{ (*MsgAcceptAssetResponse)(nil), // 61: provlabs.vault.v1.MsgAcceptAssetResponse (*MsgRejectAssetRequest)(nil), // 62: provlabs.vault.v1.MsgRejectAssetRequest (*MsgRejectAssetResponse)(nil), // 63: provlabs.vault.v1.MsgRejectAssetResponse - (*InitialVaultNAV)(nil), // 64: provlabs.vault.v1.InitialVaultNAV - (*v1beta1.Metadata)(nil), // 65: cosmos.bank.v1beta1.Metadata - (*v1beta11.Coin)(nil), // 66: cosmos.base.v1beta1.Coin - (*Params)(nil), // 67: provlabs.vault.v1.Params + (*v1beta1.Metadata)(nil), // 64: cosmos.bank.v1beta1.Metadata + (*v1beta11.Coin)(nil), // 65: cosmos.base.v1beta1.Coin + (*Params)(nil), // 66: provlabs.vault.v1.Params } var file_provlabs_vault_v1_tx_proto_depIdxs = []int32{ - 64, // 0: provlabs.vault.v1.MsgCreateVaultRequest.initial_payment_nav:type_name -> provlabs.vault.v1.InitialVaultNAV - 65, // 1: provlabs.vault.v1.MsgSetShareDenomMetadataRequest.metadata:type_name -> cosmos.bank.v1beta1.Metadata - 66, // 2: provlabs.vault.v1.MsgSwapInRequest.assets:type_name -> cosmos.base.v1beta1.Coin - 66, // 3: provlabs.vault.v1.MsgSwapInResponse.shares_received:type_name -> cosmos.base.v1beta1.Coin - 66, // 4: provlabs.vault.v1.MsgSwapOutRequest.assets:type_name -> cosmos.base.v1beta1.Coin - 66, // 5: provlabs.vault.v1.MsgDepositInterestFundsRequest.amount:type_name -> cosmos.base.v1beta1.Coin - 66, // 6: provlabs.vault.v1.MsgWithdrawInterestFundsRequest.amount:type_name -> cosmos.base.v1beta1.Coin - 66, // 7: provlabs.vault.v1.MsgDepositPrincipalFundsRequest.amount:type_name -> cosmos.base.v1beta1.Coin - 66, // 8: provlabs.vault.v1.MsgWithdrawPrincipalFundsRequest.amount:type_name -> cosmos.base.v1beta1.Coin - 66, // 9: provlabs.vault.v1.MsgBridgeMintSharesRequest.shares:type_name -> cosmos.base.v1beta1.Coin - 66, // 10: provlabs.vault.v1.MsgBridgeBurnSharesRequest.shares:type_name -> cosmos.base.v1beta1.Coin - 67, // 11: provlabs.vault.v1.MsgUpdateParamsRequest.params:type_name -> provlabs.vault.v1.Params - 66, // 12: provlabs.vault.v1.MsgUpdateVaultNAVRequest.price:type_name -> cosmos.base.v1beta1.Coin - 0, // 13: provlabs.vault.v1.Msg.CreateVault:input_type -> provlabs.vault.v1.MsgCreateVaultRequest - 2, // 14: provlabs.vault.v1.Msg.SetShareDenomMetadata:input_type -> provlabs.vault.v1.MsgSetShareDenomMetadataRequest - 4, // 15: provlabs.vault.v1.Msg.SwapIn:input_type -> provlabs.vault.v1.MsgSwapInRequest - 6, // 16: provlabs.vault.v1.Msg.SwapOut:input_type -> provlabs.vault.v1.MsgSwapOutRequest - 8, // 17: provlabs.vault.v1.Msg.UpdateMinInterestRate:input_type -> provlabs.vault.v1.MsgUpdateMinInterestRateRequest - 10, // 18: provlabs.vault.v1.Msg.UpdateMaxInterestRate:input_type -> provlabs.vault.v1.MsgUpdateMaxInterestRateRequest - 12, // 19: provlabs.vault.v1.Msg.UpdateInterestRate:input_type -> provlabs.vault.v1.MsgUpdateInterestRateRequest - 14, // 20: provlabs.vault.v1.Msg.UpdateWithdrawalDelay:input_type -> provlabs.vault.v1.MsgUpdateWithdrawalDelayRequest - 16, // 21: provlabs.vault.v1.Msg.UpdateMinSwapInValue:input_type -> provlabs.vault.v1.MsgUpdateMinSwapInValueRequest - 18, // 22: provlabs.vault.v1.Msg.UpdateMinSwapOutValue:input_type -> provlabs.vault.v1.MsgUpdateMinSwapOutValueRequest - 20, // 23: provlabs.vault.v1.Msg.UpdateMaxSwapInValue:input_type -> provlabs.vault.v1.MsgUpdateMaxSwapInValueRequest - 22, // 24: provlabs.vault.v1.Msg.UpdateMaxSwapOutValue:input_type -> provlabs.vault.v1.MsgUpdateMaxSwapOutValueRequest - 24, // 25: provlabs.vault.v1.Msg.ToggleSwapIn:input_type -> provlabs.vault.v1.MsgToggleSwapInRequest - 26, // 26: provlabs.vault.v1.Msg.ToggleSwapOut:input_type -> provlabs.vault.v1.MsgToggleSwapOutRequest - 28, // 27: provlabs.vault.v1.Msg.DepositInterestFunds:input_type -> provlabs.vault.v1.MsgDepositInterestFundsRequest - 30, // 28: provlabs.vault.v1.Msg.WithdrawInterestFunds:input_type -> provlabs.vault.v1.MsgWithdrawInterestFundsRequest - 32, // 29: provlabs.vault.v1.Msg.DepositPrincipalFunds:input_type -> provlabs.vault.v1.MsgDepositPrincipalFundsRequest - 34, // 30: provlabs.vault.v1.Msg.WithdrawPrincipalFunds:input_type -> provlabs.vault.v1.MsgWithdrawPrincipalFundsRequest - 36, // 31: provlabs.vault.v1.Msg.ExpeditePendingSwapOut:input_type -> provlabs.vault.v1.MsgExpeditePendingSwapOutRequest - 38, // 32: provlabs.vault.v1.Msg.PauseVault:input_type -> provlabs.vault.v1.MsgPauseVaultRequest - 40, // 33: provlabs.vault.v1.Msg.UnpauseVault:input_type -> provlabs.vault.v1.MsgUnpauseVaultRequest - 42, // 34: provlabs.vault.v1.Msg.SetBridgeAddress:input_type -> provlabs.vault.v1.MsgSetBridgeAddressRequest - 44, // 35: provlabs.vault.v1.Msg.ToggleBridge:input_type -> provlabs.vault.v1.MsgToggleBridgeRequest - 46, // 36: provlabs.vault.v1.Msg.BridgeMintShares:input_type -> provlabs.vault.v1.MsgBridgeMintSharesRequest - 48, // 37: provlabs.vault.v1.Msg.BridgeBurnShares:input_type -> provlabs.vault.v1.MsgBridgeBurnSharesRequest - 50, // 38: provlabs.vault.v1.Msg.SetAssetManager:input_type -> provlabs.vault.v1.MsgSetAssetManagerRequest - 52, // 39: provlabs.vault.v1.Msg.UpdateParams:input_type -> provlabs.vault.v1.MsgUpdateParamsRequest - 54, // 40: provlabs.vault.v1.Msg.UpdateVaultAUMFeeBips:input_type -> provlabs.vault.v1.MsgUpdateVaultAUMFeeBipsRequest - 56, // 41: provlabs.vault.v1.Msg.UpdateVaultNAV:input_type -> provlabs.vault.v1.MsgUpdateVaultNAVRequest - 58, // 42: provlabs.vault.v1.Msg.UpdateNAVAuthority:input_type -> provlabs.vault.v1.MsgUpdateNAVAuthorityRequest - 60, // 43: provlabs.vault.v1.Msg.AcceptAsset:input_type -> provlabs.vault.v1.MsgAcceptAssetRequest - 62, // 44: provlabs.vault.v1.Msg.RejectAsset:input_type -> provlabs.vault.v1.MsgRejectAssetRequest - 1, // 45: provlabs.vault.v1.Msg.CreateVault:output_type -> provlabs.vault.v1.MsgCreateVaultResponse - 3, // 46: provlabs.vault.v1.Msg.SetShareDenomMetadata:output_type -> provlabs.vault.v1.MsgSetShareDenomMetadataResponse - 5, // 47: provlabs.vault.v1.Msg.SwapIn:output_type -> provlabs.vault.v1.MsgSwapInResponse - 7, // 48: provlabs.vault.v1.Msg.SwapOut:output_type -> provlabs.vault.v1.MsgSwapOutResponse - 9, // 49: provlabs.vault.v1.Msg.UpdateMinInterestRate:output_type -> provlabs.vault.v1.MsgUpdateMinInterestRateResponse - 11, // 50: provlabs.vault.v1.Msg.UpdateMaxInterestRate:output_type -> provlabs.vault.v1.MsgUpdateMaxInterestRateResponse - 13, // 51: provlabs.vault.v1.Msg.UpdateInterestRate:output_type -> provlabs.vault.v1.MsgUpdateInterestRateResponse - 15, // 52: provlabs.vault.v1.Msg.UpdateWithdrawalDelay:output_type -> provlabs.vault.v1.MsgUpdateWithdrawalDelayResponse - 17, // 53: provlabs.vault.v1.Msg.UpdateMinSwapInValue:output_type -> provlabs.vault.v1.MsgUpdateMinSwapInValueResponse - 19, // 54: provlabs.vault.v1.Msg.UpdateMinSwapOutValue:output_type -> provlabs.vault.v1.MsgUpdateMinSwapOutValueResponse - 21, // 55: provlabs.vault.v1.Msg.UpdateMaxSwapInValue:output_type -> provlabs.vault.v1.MsgUpdateMaxSwapInValueResponse - 23, // 56: provlabs.vault.v1.Msg.UpdateMaxSwapOutValue:output_type -> provlabs.vault.v1.MsgUpdateMaxSwapOutValueResponse - 25, // 57: provlabs.vault.v1.Msg.ToggleSwapIn:output_type -> provlabs.vault.v1.MsgToggleSwapInResponse - 27, // 58: provlabs.vault.v1.Msg.ToggleSwapOut:output_type -> provlabs.vault.v1.MsgToggleSwapOutResponse - 29, // 59: provlabs.vault.v1.Msg.DepositInterestFunds:output_type -> provlabs.vault.v1.MsgDepositInterestFundsResponse - 31, // 60: provlabs.vault.v1.Msg.WithdrawInterestFunds:output_type -> provlabs.vault.v1.MsgWithdrawInterestFundsResponse - 33, // 61: provlabs.vault.v1.Msg.DepositPrincipalFunds:output_type -> provlabs.vault.v1.MsgDepositPrincipalFundsResponse - 35, // 62: provlabs.vault.v1.Msg.WithdrawPrincipalFunds:output_type -> provlabs.vault.v1.MsgWithdrawPrincipalFundsResponse - 37, // 63: provlabs.vault.v1.Msg.ExpeditePendingSwapOut:output_type -> provlabs.vault.v1.MsgExpeditePendingSwapOutResponse - 39, // 64: provlabs.vault.v1.Msg.PauseVault:output_type -> provlabs.vault.v1.MsgPauseVaultResponse - 41, // 65: provlabs.vault.v1.Msg.UnpauseVault:output_type -> provlabs.vault.v1.MsgUnpauseVaultResponse - 43, // 66: provlabs.vault.v1.Msg.SetBridgeAddress:output_type -> provlabs.vault.v1.MsgSetBridgeAddressResponse - 45, // 67: provlabs.vault.v1.Msg.ToggleBridge:output_type -> provlabs.vault.v1.MsgToggleBridgeResponse - 47, // 68: provlabs.vault.v1.Msg.BridgeMintShares:output_type -> provlabs.vault.v1.MsgBridgeMintSharesResponse - 49, // 69: provlabs.vault.v1.Msg.BridgeBurnShares:output_type -> provlabs.vault.v1.MsgBridgeBurnSharesResponse - 51, // 70: provlabs.vault.v1.Msg.SetAssetManager:output_type -> provlabs.vault.v1.MsgSetAssetManagerResponse - 53, // 71: provlabs.vault.v1.Msg.UpdateParams:output_type -> provlabs.vault.v1.MsgUpdateParamsResponse - 55, // 72: provlabs.vault.v1.Msg.UpdateVaultAUMFeeBips:output_type -> provlabs.vault.v1.MsgUpdateVaultAUMFeeBipsResponse - 57, // 73: provlabs.vault.v1.Msg.UpdateVaultNAV:output_type -> provlabs.vault.v1.MsgUpdateVaultNAVResponse - 59, // 74: provlabs.vault.v1.Msg.UpdateNAVAuthority:output_type -> provlabs.vault.v1.MsgUpdateNAVAuthorityResponse - 61, // 75: provlabs.vault.v1.Msg.AcceptAsset:output_type -> provlabs.vault.v1.MsgAcceptAssetResponse - 63, // 76: provlabs.vault.v1.Msg.RejectAsset:output_type -> provlabs.vault.v1.MsgRejectAssetResponse - 45, // [45:77] is the sub-list for method output_type - 13, // [13:45] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 64, // 0: provlabs.vault.v1.MsgSetShareDenomMetadataRequest.metadata:type_name -> cosmos.bank.v1beta1.Metadata + 65, // 1: provlabs.vault.v1.MsgSwapInRequest.assets:type_name -> cosmos.base.v1beta1.Coin + 65, // 2: provlabs.vault.v1.MsgSwapInResponse.shares_received:type_name -> cosmos.base.v1beta1.Coin + 65, // 3: provlabs.vault.v1.MsgSwapOutRequest.assets:type_name -> cosmos.base.v1beta1.Coin + 65, // 4: provlabs.vault.v1.MsgDepositInterestFundsRequest.amount:type_name -> cosmos.base.v1beta1.Coin + 65, // 5: provlabs.vault.v1.MsgWithdrawInterestFundsRequest.amount:type_name -> cosmos.base.v1beta1.Coin + 65, // 6: provlabs.vault.v1.MsgDepositPrincipalFundsRequest.amount:type_name -> cosmos.base.v1beta1.Coin + 65, // 7: provlabs.vault.v1.MsgWithdrawPrincipalFundsRequest.amount:type_name -> cosmos.base.v1beta1.Coin + 65, // 8: provlabs.vault.v1.MsgBridgeMintSharesRequest.shares:type_name -> cosmos.base.v1beta1.Coin + 65, // 9: provlabs.vault.v1.MsgBridgeBurnSharesRequest.shares:type_name -> cosmos.base.v1beta1.Coin + 66, // 10: provlabs.vault.v1.MsgUpdateParamsRequest.params:type_name -> provlabs.vault.v1.Params + 65, // 11: provlabs.vault.v1.MsgUpdateVaultNAVRequest.price:type_name -> cosmos.base.v1beta1.Coin + 0, // 12: provlabs.vault.v1.Msg.CreateVault:input_type -> provlabs.vault.v1.MsgCreateVaultRequest + 2, // 13: provlabs.vault.v1.Msg.SetShareDenomMetadata:input_type -> provlabs.vault.v1.MsgSetShareDenomMetadataRequest + 4, // 14: provlabs.vault.v1.Msg.SwapIn:input_type -> provlabs.vault.v1.MsgSwapInRequest + 6, // 15: provlabs.vault.v1.Msg.SwapOut:input_type -> provlabs.vault.v1.MsgSwapOutRequest + 8, // 16: provlabs.vault.v1.Msg.UpdateMinInterestRate:input_type -> provlabs.vault.v1.MsgUpdateMinInterestRateRequest + 10, // 17: provlabs.vault.v1.Msg.UpdateMaxInterestRate:input_type -> provlabs.vault.v1.MsgUpdateMaxInterestRateRequest + 12, // 18: provlabs.vault.v1.Msg.UpdateInterestRate:input_type -> provlabs.vault.v1.MsgUpdateInterestRateRequest + 14, // 19: provlabs.vault.v1.Msg.UpdateWithdrawalDelay:input_type -> provlabs.vault.v1.MsgUpdateWithdrawalDelayRequest + 16, // 20: provlabs.vault.v1.Msg.UpdateMinSwapInValue:input_type -> provlabs.vault.v1.MsgUpdateMinSwapInValueRequest + 18, // 21: provlabs.vault.v1.Msg.UpdateMinSwapOutValue:input_type -> provlabs.vault.v1.MsgUpdateMinSwapOutValueRequest + 20, // 22: provlabs.vault.v1.Msg.UpdateMaxSwapInValue:input_type -> provlabs.vault.v1.MsgUpdateMaxSwapInValueRequest + 22, // 23: provlabs.vault.v1.Msg.UpdateMaxSwapOutValue:input_type -> provlabs.vault.v1.MsgUpdateMaxSwapOutValueRequest + 24, // 24: provlabs.vault.v1.Msg.ToggleSwapIn:input_type -> provlabs.vault.v1.MsgToggleSwapInRequest + 26, // 25: provlabs.vault.v1.Msg.ToggleSwapOut:input_type -> provlabs.vault.v1.MsgToggleSwapOutRequest + 28, // 26: provlabs.vault.v1.Msg.DepositInterestFunds:input_type -> provlabs.vault.v1.MsgDepositInterestFundsRequest + 30, // 27: provlabs.vault.v1.Msg.WithdrawInterestFunds:input_type -> provlabs.vault.v1.MsgWithdrawInterestFundsRequest + 32, // 28: provlabs.vault.v1.Msg.DepositPrincipalFunds:input_type -> provlabs.vault.v1.MsgDepositPrincipalFundsRequest + 34, // 29: provlabs.vault.v1.Msg.WithdrawPrincipalFunds:input_type -> provlabs.vault.v1.MsgWithdrawPrincipalFundsRequest + 36, // 30: provlabs.vault.v1.Msg.ExpeditePendingSwapOut:input_type -> provlabs.vault.v1.MsgExpeditePendingSwapOutRequest + 38, // 31: provlabs.vault.v1.Msg.PauseVault:input_type -> provlabs.vault.v1.MsgPauseVaultRequest + 40, // 32: provlabs.vault.v1.Msg.UnpauseVault:input_type -> provlabs.vault.v1.MsgUnpauseVaultRequest + 42, // 33: provlabs.vault.v1.Msg.SetBridgeAddress:input_type -> provlabs.vault.v1.MsgSetBridgeAddressRequest + 44, // 34: provlabs.vault.v1.Msg.ToggleBridge:input_type -> provlabs.vault.v1.MsgToggleBridgeRequest + 46, // 35: provlabs.vault.v1.Msg.BridgeMintShares:input_type -> provlabs.vault.v1.MsgBridgeMintSharesRequest + 48, // 36: provlabs.vault.v1.Msg.BridgeBurnShares:input_type -> provlabs.vault.v1.MsgBridgeBurnSharesRequest + 50, // 37: provlabs.vault.v1.Msg.SetAssetManager:input_type -> provlabs.vault.v1.MsgSetAssetManagerRequest + 52, // 38: provlabs.vault.v1.Msg.UpdateParams:input_type -> provlabs.vault.v1.MsgUpdateParamsRequest + 54, // 39: provlabs.vault.v1.Msg.UpdateVaultAUMFeeBips:input_type -> provlabs.vault.v1.MsgUpdateVaultAUMFeeBipsRequest + 56, // 40: provlabs.vault.v1.Msg.UpdateVaultNAV:input_type -> provlabs.vault.v1.MsgUpdateVaultNAVRequest + 58, // 41: provlabs.vault.v1.Msg.UpdateNAVAuthority:input_type -> provlabs.vault.v1.MsgUpdateNAVAuthorityRequest + 60, // 42: provlabs.vault.v1.Msg.AcceptAsset:input_type -> provlabs.vault.v1.MsgAcceptAssetRequest + 62, // 43: provlabs.vault.v1.Msg.RejectAsset:input_type -> provlabs.vault.v1.MsgRejectAssetRequest + 1, // 44: provlabs.vault.v1.Msg.CreateVault:output_type -> provlabs.vault.v1.MsgCreateVaultResponse + 3, // 45: provlabs.vault.v1.Msg.SetShareDenomMetadata:output_type -> provlabs.vault.v1.MsgSetShareDenomMetadataResponse + 5, // 46: provlabs.vault.v1.Msg.SwapIn:output_type -> provlabs.vault.v1.MsgSwapInResponse + 7, // 47: provlabs.vault.v1.Msg.SwapOut:output_type -> provlabs.vault.v1.MsgSwapOutResponse + 9, // 48: provlabs.vault.v1.Msg.UpdateMinInterestRate:output_type -> provlabs.vault.v1.MsgUpdateMinInterestRateResponse + 11, // 49: provlabs.vault.v1.Msg.UpdateMaxInterestRate:output_type -> provlabs.vault.v1.MsgUpdateMaxInterestRateResponse + 13, // 50: provlabs.vault.v1.Msg.UpdateInterestRate:output_type -> provlabs.vault.v1.MsgUpdateInterestRateResponse + 15, // 51: provlabs.vault.v1.Msg.UpdateWithdrawalDelay:output_type -> provlabs.vault.v1.MsgUpdateWithdrawalDelayResponse + 17, // 52: provlabs.vault.v1.Msg.UpdateMinSwapInValue:output_type -> provlabs.vault.v1.MsgUpdateMinSwapInValueResponse + 19, // 53: provlabs.vault.v1.Msg.UpdateMinSwapOutValue:output_type -> provlabs.vault.v1.MsgUpdateMinSwapOutValueResponse + 21, // 54: provlabs.vault.v1.Msg.UpdateMaxSwapInValue:output_type -> provlabs.vault.v1.MsgUpdateMaxSwapInValueResponse + 23, // 55: provlabs.vault.v1.Msg.UpdateMaxSwapOutValue:output_type -> provlabs.vault.v1.MsgUpdateMaxSwapOutValueResponse + 25, // 56: provlabs.vault.v1.Msg.ToggleSwapIn:output_type -> provlabs.vault.v1.MsgToggleSwapInResponse + 27, // 57: provlabs.vault.v1.Msg.ToggleSwapOut:output_type -> provlabs.vault.v1.MsgToggleSwapOutResponse + 29, // 58: provlabs.vault.v1.Msg.DepositInterestFunds:output_type -> provlabs.vault.v1.MsgDepositInterestFundsResponse + 31, // 59: provlabs.vault.v1.Msg.WithdrawInterestFunds:output_type -> provlabs.vault.v1.MsgWithdrawInterestFundsResponse + 33, // 60: provlabs.vault.v1.Msg.DepositPrincipalFunds:output_type -> provlabs.vault.v1.MsgDepositPrincipalFundsResponse + 35, // 61: provlabs.vault.v1.Msg.WithdrawPrincipalFunds:output_type -> provlabs.vault.v1.MsgWithdrawPrincipalFundsResponse + 37, // 62: provlabs.vault.v1.Msg.ExpeditePendingSwapOut:output_type -> provlabs.vault.v1.MsgExpeditePendingSwapOutResponse + 39, // 63: provlabs.vault.v1.Msg.PauseVault:output_type -> provlabs.vault.v1.MsgPauseVaultResponse + 41, // 64: provlabs.vault.v1.Msg.UnpauseVault:output_type -> provlabs.vault.v1.MsgUnpauseVaultResponse + 43, // 65: provlabs.vault.v1.Msg.SetBridgeAddress:output_type -> provlabs.vault.v1.MsgSetBridgeAddressResponse + 45, // 66: provlabs.vault.v1.Msg.ToggleBridge:output_type -> provlabs.vault.v1.MsgToggleBridgeResponse + 47, // 67: provlabs.vault.v1.Msg.BridgeMintShares:output_type -> provlabs.vault.v1.MsgBridgeMintSharesResponse + 49, // 68: provlabs.vault.v1.Msg.BridgeBurnShares:output_type -> provlabs.vault.v1.MsgBridgeBurnSharesResponse + 51, // 69: provlabs.vault.v1.Msg.SetAssetManager:output_type -> provlabs.vault.v1.MsgSetAssetManagerResponse + 53, // 70: provlabs.vault.v1.Msg.UpdateParams:output_type -> provlabs.vault.v1.MsgUpdateParamsResponse + 55, // 71: provlabs.vault.v1.Msg.UpdateVaultAUMFeeBips:output_type -> provlabs.vault.v1.MsgUpdateVaultAUMFeeBipsResponse + 57, // 72: provlabs.vault.v1.Msg.UpdateVaultNAV:output_type -> provlabs.vault.v1.MsgUpdateVaultNAVResponse + 59, // 73: provlabs.vault.v1.Msg.UpdateNAVAuthority:output_type -> provlabs.vault.v1.MsgUpdateNAVAuthorityResponse + 61, // 74: provlabs.vault.v1.Msg.AcceptAsset:output_type -> provlabs.vault.v1.MsgAcceptAssetResponse + 63, // 75: provlabs.vault.v1.Msg.RejectAsset:output_type -> provlabs.vault.v1.MsgRejectAssetResponse + 44, // [44:76] is the sub-list for method output_type + 12, // [12:44] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_provlabs_vault_v1_tx_proto_init() } diff --git a/api/provlabs/vault/v1/tx_grpc.pb.go b/api/provlabs/vault/v1/tx_grpc.pb.go index 99750946..6dd98cf2 100644 --- a/api/provlabs/vault/v1/tx_grpc.pb.go +++ b/api/provlabs/vault/v1/tx_grpc.pb.go @@ -130,7 +130,7 @@ type MsgClient interface { // Must be signed by the vault admin. UpdateNAVAuthority(ctx context.Context, in *MsgUpdateNAVAuthorityRequest, opts ...grpc.CallOption) (*MsgUpdateNAVAuthorityResponse, error) // AcceptAsset settles a pending exchange-module payment whose target is the vault, - // exchanging an external asset for the vault's payment denom. + // exchanging an external asset for the vault's underlying asset. // Must be signed by the vault's asset manager; the admin cannot settle. AcceptAsset(ctx context.Context, in *MsgAcceptAssetRequest, opts ...grpc.CallOption) (*MsgAcceptAssetResponse, error) // RejectAsset declines a pending exchange-module payment whose target is the vault, @@ -544,7 +544,7 @@ type MsgServer interface { // Must be signed by the vault admin. UpdateNAVAuthority(context.Context, *MsgUpdateNAVAuthorityRequest) (*MsgUpdateNAVAuthorityResponse, error) // AcceptAsset settles a pending exchange-module payment whose target is the vault, - // exchanging an external asset for the vault's payment denom. + // exchanging an external asset for the vault's underlying asset. // Must be signed by the vault's asset manager; the admin cannot settle. AcceptAsset(context.Context, *MsgAcceptAssetRequest) (*MsgAcceptAssetResponse, error) // RejectAsset declines a pending exchange-module payment whose target is the vault, diff --git a/api/provlabs/vault/v1/vault.pulsar.go b/api/provlabs/vault/v1/vault.pulsar.go index a809f41d..cfeead01 100644 --- a/api/provlabs/vault/v1/vault.pulsar.go +++ b/api/provlabs/vault/v1/vault.pulsar.go @@ -2935,569 +2935,6 @@ func (x *fastReflection_VaultNAV) ProtoMethods() *protoiface.Methods { } } -var ( - md_InitialVaultNAV protoreflect.MessageDescriptor - fd_InitialVaultNAV_price protoreflect.FieldDescriptor - fd_InitialVaultNAV_volume protoreflect.FieldDescriptor - fd_InitialVaultNAV_source protoreflect.FieldDescriptor -) - -func init() { - file_provlabs_vault_v1_vault_proto_init() - md_InitialVaultNAV = File_provlabs_vault_v1_vault_proto.Messages().ByName("InitialVaultNAV") - fd_InitialVaultNAV_price = md_InitialVaultNAV.Fields().ByName("price") - fd_InitialVaultNAV_volume = md_InitialVaultNAV.Fields().ByName("volume") - fd_InitialVaultNAV_source = md_InitialVaultNAV.Fields().ByName("source") -} - -var _ protoreflect.Message = (*fastReflection_InitialVaultNAV)(nil) - -type fastReflection_InitialVaultNAV InitialVaultNAV - -func (x *InitialVaultNAV) ProtoReflect() protoreflect.Message { - return (*fastReflection_InitialVaultNAV)(x) -} - -func (x *InitialVaultNAV) slowProtoReflect() protoreflect.Message { - mi := &file_provlabs_vault_v1_vault_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -var _fastReflection_InitialVaultNAV_messageType fastReflection_InitialVaultNAV_messageType -var _ protoreflect.MessageType = fastReflection_InitialVaultNAV_messageType{} - -type fastReflection_InitialVaultNAV_messageType struct{} - -func (x fastReflection_InitialVaultNAV_messageType) Zero() protoreflect.Message { - return (*fastReflection_InitialVaultNAV)(nil) -} -func (x fastReflection_InitialVaultNAV_messageType) New() protoreflect.Message { - return new(fastReflection_InitialVaultNAV) -} -func (x fastReflection_InitialVaultNAV_messageType) Descriptor() protoreflect.MessageDescriptor { - return md_InitialVaultNAV -} - -// Descriptor returns message descriptor, which contains only the protobuf -// type information for the message. -func (x *fastReflection_InitialVaultNAV) Descriptor() protoreflect.MessageDescriptor { - return md_InitialVaultNAV -} - -// Type returns the message type, which encapsulates both Go and protobuf -// type information. If the Go type information is not needed, -// it is recommended that the message descriptor be used instead. -func (x *fastReflection_InitialVaultNAV) Type() protoreflect.MessageType { - return _fastReflection_InitialVaultNAV_messageType -} - -// New returns a newly allocated and mutable empty message. -func (x *fastReflection_InitialVaultNAV) New() protoreflect.Message { - return new(fastReflection_InitialVaultNAV) -} - -// Interface unwraps the message reflection interface and -// returns the underlying ProtoMessage interface. -func (x *fastReflection_InitialVaultNAV) Interface() protoreflect.ProtoMessage { - return (*InitialVaultNAV)(x) -} - -// Range iterates over every populated field in an undefined order, -// calling f for each field descriptor and value encountered. -// Range returns immediately if f returns false. -// While iterating, mutating operations may only be performed -// on the current field descriptor. -func (x *fastReflection_InitialVaultNAV) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - if x.Price != nil { - value := protoreflect.ValueOfMessage(x.Price.ProtoReflect()) - if !f(fd_InitialVaultNAV_price, value) { - return - } - } - if x.Volume != "" { - value := protoreflect.ValueOfString(x.Volume) - if !f(fd_InitialVaultNAV_volume, value) { - return - } - } - if x.Source != "" { - value := protoreflect.ValueOfString(x.Source) - if !f(fd_InitialVaultNAV_source, value) { - return - } - } -} - -// Has reports whether a field is populated. -// -// Some fields have the property of nullability where it is possible to -// distinguish between the default value of a field and whether the field -// was explicitly populated with the default value. Singular message fields, -// member fields of a oneof, and proto2 scalar fields are nullable. Such -// fields are populated only if explicitly set. -// -// In other cases (aside from the nullable cases above), -// a proto3 scalar field is populated if it contains a non-zero value, and -// a repeated field is populated if it is non-empty. -func (x *fastReflection_InitialVaultNAV) Has(fd protoreflect.FieldDescriptor) bool { - switch fd.FullName() { - case "provlabs.vault.v1.InitialVaultNAV.price": - return x.Price != nil - case "provlabs.vault.v1.InitialVaultNAV.volume": - return x.Volume != "" - case "provlabs.vault.v1.InitialVaultNAV.source": - return x.Source != "" - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.InitialVaultNAV")) - } - panic(fmt.Errorf("message provlabs.vault.v1.InitialVaultNAV does not contain field %s", fd.FullName())) - } -} - -// Clear clears the field such that a subsequent Has call reports false. -// -// Clearing an extension field clears both the extension type and value -// associated with the given field number. -// -// Clear is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_InitialVaultNAV) Clear(fd protoreflect.FieldDescriptor) { - switch fd.FullName() { - case "provlabs.vault.v1.InitialVaultNAV.price": - x.Price = nil - case "provlabs.vault.v1.InitialVaultNAV.volume": - x.Volume = "" - case "provlabs.vault.v1.InitialVaultNAV.source": - x.Source = "" - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.InitialVaultNAV")) - } - panic(fmt.Errorf("message provlabs.vault.v1.InitialVaultNAV does not contain field %s", fd.FullName())) - } -} - -// Get retrieves the value for a field. -// -// For unpopulated scalars, it returns the default value, where -// the default value of a bytes scalar is guaranteed to be a copy. -// For unpopulated composite types, it returns an empty, read-only view -// of the value; to obtain a mutable reference, use Mutable. -func (x *fastReflection_InitialVaultNAV) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { - switch descriptor.FullName() { - case "provlabs.vault.v1.InitialVaultNAV.price": - value := x.Price - return protoreflect.ValueOfMessage(value.ProtoReflect()) - case "provlabs.vault.v1.InitialVaultNAV.volume": - value := x.Volume - return protoreflect.ValueOfString(value) - case "provlabs.vault.v1.InitialVaultNAV.source": - value := x.Source - return protoreflect.ValueOfString(value) - default: - if descriptor.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.InitialVaultNAV")) - } - panic(fmt.Errorf("message provlabs.vault.v1.InitialVaultNAV does not contain field %s", descriptor.FullName())) - } -} - -// Set stores the value for a field. -// -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType. -// When setting a composite type, it is unspecified whether the stored value -// aliases the source's memory in any way. If the composite value is an -// empty, read-only value, then it panics. -// -// Set is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_InitialVaultNAV) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { - switch fd.FullName() { - case "provlabs.vault.v1.InitialVaultNAV.price": - x.Price = value.Message().Interface().(*v1beta11.Coin) - case "provlabs.vault.v1.InitialVaultNAV.volume": - x.Volume = value.Interface().(string) - case "provlabs.vault.v1.InitialVaultNAV.source": - x.Source = value.Interface().(string) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.InitialVaultNAV")) - } - panic(fmt.Errorf("message provlabs.vault.v1.InitialVaultNAV does not contain field %s", fd.FullName())) - } -} - -// Mutable returns a mutable reference to a composite type. -// -// If the field is unpopulated, it may allocate a composite value. -// For a field belonging to a oneof, it implicitly clears any other field -// that may be currently set within the same oneof. -// For extension fields, it implicitly stores the provided ExtensionType -// if not already stored. -// It panics if the field does not contain a composite type. -// -// Mutable is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_InitialVaultNAV) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "provlabs.vault.v1.InitialVaultNAV.price": - if x.Price == nil { - x.Price = new(v1beta11.Coin) - } - return protoreflect.ValueOfMessage(x.Price.ProtoReflect()) - case "provlabs.vault.v1.InitialVaultNAV.volume": - panic(fmt.Errorf("field volume of message provlabs.vault.v1.InitialVaultNAV is not mutable")) - case "provlabs.vault.v1.InitialVaultNAV.source": - panic(fmt.Errorf("field source of message provlabs.vault.v1.InitialVaultNAV is not mutable")) - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.InitialVaultNAV")) - } - panic(fmt.Errorf("message provlabs.vault.v1.InitialVaultNAV does not contain field %s", fd.FullName())) - } -} - -// NewField returns a new value that is assignable to the field -// for the given descriptor. For scalars, this returns the default value. -// For lists, maps, and messages, this returns a new, empty, mutable value. -func (x *fastReflection_InitialVaultNAV) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - switch fd.FullName() { - case "provlabs.vault.v1.InitialVaultNAV.price": - m := new(v1beta11.Coin) - return protoreflect.ValueOfMessage(m.ProtoReflect()) - case "provlabs.vault.v1.InitialVaultNAV.volume": - return protoreflect.ValueOfString("") - case "provlabs.vault.v1.InitialVaultNAV.source": - return protoreflect.ValueOfString("") - default: - if fd.IsExtension() { - panic(fmt.Errorf("proto3 declared messages do not support extensions: provlabs.vault.v1.InitialVaultNAV")) - } - panic(fmt.Errorf("message provlabs.vault.v1.InitialVaultNAV does not contain field %s", fd.FullName())) - } -} - -// WhichOneof reports which field within the oneof is populated, -// returning nil if none are populated. -// It panics if the oneof descriptor does not belong to this message. -func (x *fastReflection_InitialVaultNAV) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - switch d.FullName() { - default: - panic(fmt.Errorf("%s is not a oneof field in provlabs.vault.v1.InitialVaultNAV", d.FullName())) - } - panic("unreachable") -} - -// GetUnknown retrieves the entire list of unknown fields. -// The caller may only mutate the contents of the RawFields -// if the mutated bytes are stored back into the message with SetUnknown. -func (x *fastReflection_InitialVaultNAV) GetUnknown() protoreflect.RawFields { - return x.unknownFields -} - -// SetUnknown stores an entire list of unknown fields. -// The raw fields must be syntactically valid according to the wire format. -// An implementation may panic if this is not the case. -// Once stored, the caller must not mutate the content of the RawFields. -// An empty RawFields may be passed to clear the fields. -// -// SetUnknown is a mutating operation and unsafe for concurrent use. -func (x *fastReflection_InitialVaultNAV) SetUnknown(fields protoreflect.RawFields) { - x.unknownFields = fields -} - -// IsValid reports whether the message is valid. -// -// An invalid message is an empty, read-only value. -// -// An invalid message often corresponds to a nil pointer of the concrete -// message type, but the details are implementation dependent. -// Validity is not part of the protobuf data model, and may not -// be preserved in marshaling or other operations. -func (x *fastReflection_InitialVaultNAV) IsValid() bool { - return x != nil -} - -// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. -// This method may return nil. -// -// The returned methods type is identical to -// "google.golang.org/protobuf/runtime/protoiface".Methods. -// Consult the protoiface package documentation for details. -func (x *fastReflection_InitialVaultNAV) ProtoMethods() *protoiface.Methods { - size := func(input protoiface.SizeInput) protoiface.SizeOutput { - x := input.Message.Interface().(*InitialVaultNAV) - if x == nil { - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: 0, - } - } - options := runtime.SizeInputToOptions(input) - _ = options - var n int - var l int - _ = l - if x.Price != nil { - l = options.Size(x.Price) - n += 1 + l + runtime.Sov(uint64(l)) - } - l = len(x.Volume) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - l = len(x.Source) - if l > 0 { - n += 1 + l + runtime.Sov(uint64(l)) - } - if x.unknownFields != nil { - n += len(x.unknownFields) - } - return protoiface.SizeOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Size: n, - } - } - - marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { - x := input.Message.Interface().(*InitialVaultNAV) - if x == nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - options := runtime.MarshalInputToOptions(input) - _ = options - size := options.Size(x) - dAtA := make([]byte, size) - i := len(dAtA) - _ = i - var l int - _ = l - if x.unknownFields != nil { - i -= len(x.unknownFields) - copy(dAtA[i:], x.unknownFields) - } - if len(x.Source) > 0 { - i -= len(x.Source) - copy(dAtA[i:], x.Source) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Source))) - i-- - dAtA[i] = 0x1a - } - if len(x.Volume) > 0 { - i -= len(x.Volume) - copy(dAtA[i:], x.Volume) - i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Volume))) - i-- - dAtA[i] = 0x12 - } - if x.Price != nil { - encoded, err := options.Marshal(x.Price) - if err != nil { - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, err - } - i -= len(encoded) - copy(dAtA[i:], encoded) - i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) - i-- - dAtA[i] = 0xa - } - if input.Buf != nil { - input.Buf = append(input.Buf, dAtA...) - } else { - input.Buf = dAtA - } - return protoiface.MarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Buf: input.Buf, - }, nil - } - unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { - x := input.Message.Interface().(*InitialVaultNAV) - if x == nil { - return protoiface.UnmarshalOutput{ - NoUnkeyedLiterals: input.NoUnkeyedLiterals, - Flags: input.Flags, - }, nil - } - options := runtime.UnmarshalInputToOptions(input) - _ = options - dAtA := input.Buf - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: InitialVaultNAV: wiretype end group for non-group") - } - if fieldNum <= 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: InitialVaultNAV: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if x.Price == nil { - x.Price = &v1beta11.Coin{} - } - if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Price); err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Volume", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - x.Volume = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Source", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow - } - if iNdEx >= l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if postIndex > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - x.Source = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := runtime.Skip(dAtA[iNdEx:]) - if err != nil { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength - } - if (iNdEx + skippy) > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - if !options.DiscardUnknown { - x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) - } - iNdEx += skippy - } - } - - if iNdEx > l { - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF - } - return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil - } - return &protoiface.Methods{ - NoUnkeyedLiterals: struct{}{}, - Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, - Size: size, - Marshal: marshal, - Unmarshal: unmarshal, - Merge: nil, - CheckInitialized: nil, - } -} - var _ protoreflect.List = (*_AccountBalance_2_list)(nil) type _AccountBalance_2_list struct { @@ -3571,7 +3008,7 @@ func (x *AccountBalance) ProtoReflect() protoreflect.Message { } func (x *AccountBalance) slowProtoReflect() protoreflect.Message { - mi := &file_provlabs_vault_v1_vault_proto_msgTypes[3] + mi := &file_provlabs_vault_v1_vault_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4082,7 +3519,7 @@ func (x *PendingSwapOut) ProtoReflect() protoreflect.Message { } func (x *PendingSwapOut) slowProtoReflect() protoreflect.Message { - mi := &file_provlabs_vault_v1_vault_proto_msgTypes[4] + mi := &file_provlabs_vault_v1_vault_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4712,18 +4149,16 @@ type VaultAccount struct { // underlying_asset is the vault’s single principal collateral AND valuation/base unit. // - Exactly one denom. // - Total Vault Value (TVV) and NAV-per-share are computed and reported in this denom. - // - Interest accrual and internal accounting are measured in this denom. - // - Any other coin accepted for I/O (i.e. a distinct payment_denom) must have a NAV record priced INTO this denom. + // - Interest accrual, fees, and internal accounting are measured in this denom. + // - Held assets acquired via settlement must have an internal NAV record priced INTO this denom. UnderlyingAsset string `protobuf:"bytes,3,opt,name=underlying_asset,json=underlyingAsset,proto3" json:"underlying_asset,omitempty"` - // payment_denom is the external payment coin supported for user I/O alongside the underlying_asset. - // - Always populated. If not specified during creation, it defaults to underlying_asset. - // - If payment_denom equals underlying_asset, the vault operates as a single-denom vault. - // - If payment_denom differs from underlying_asset, swap-in/out accept either denom (one per call). - // - Default Swap-Out: If a user does not specify a redeem_denom during withdrawal, - // the vault defaults to paying out in this payment_denom. - // - NAV Requirement: If payment_denom differs from underlying_asset, it requires an on-chain NAV record - // mapping payment_denom -> underlying_asset to value deposits and redemptions. - // (Note: In current versions, this NAV check is strictly enforced unless payment_denom is 'uylds.fcc'). + // payment_denom always equals underlying_asset. Vaults are single-denom; the + // field is inert and retained only for wire compatibility. + // + // Deprecated: The mixed-denom vault concept has been flattened into a single + // underlying denom. Deletion of this field is deferred to a future major release. + // + // Deprecated: Do not use. PaymentDenom string `protobuf:"bytes,4,opt,name=payment_denom,json=paymentDenom,proto3" json:"payment_denom,omitempty"` // admin is the address that has administrative privileges over the vault. Admin string `protobuf:"bytes,5,opt,name=admin,proto3" json:"admin,omitempty"` @@ -4776,7 +4211,7 @@ type VaultAccount struct { FeePeriodTimeout int64 `protobuf:"varint,22,opt,name=fee_period_timeout,json=feePeriodTimeout,proto3" json:"fee_period_timeout,omitempty"` // outstanding_aum_fee is the amount of AUM fee that has been calculated but not yet collected // due to insufficient liquidity in the principal marker. This amount is always denominated - // in the vault's payment_denom, must be preserved, and is carried into valuation computations. + // in the vault's underlying_asset, must be preserved, and is carried into valuation computations. OutstandingAumFee *v1beta11.Coin `protobuf:"bytes,23,opt,name=outstanding_aum_fee,json=outstandingAumFee,proto3" json:"outstanding_aum_fee,omitempty"` // aum_fee_bips is the AUM fee rate (in basis points) for this specific vault. // Units: Basis Points (1 bps = 0.01%). @@ -4786,7 +4221,6 @@ type VaultAccount struct { AumFeeBips uint32 `protobuf:"varint,24,opt,name=aum_fee_bips,json=aumFeeBips,proto3" json:"aum_fee_bips,omitempty"` // min_swap_in_value is a string representing the minimum value required for a deposit. // - The value is measured in the underlying_asset. - // - Incoming payment_denom deposits are converted to this unit before checking. // - Values must be non-negative (>= 0). // - If empty ("") or "0", there is no minimum limit. MinSwapInValue string `protobuf:"bytes,25,opt,name=min_swap_in_value,json=minSwapInValue,proto3" json:"min_swap_in_value,omitempty"` @@ -4798,7 +4232,6 @@ type VaultAccount struct { MinSwapOutValue string `protobuf:"bytes,26,opt,name=min_swap_out_value,json=minSwapOutValue,proto3" json:"min_swap_out_value,omitempty"` // max_swap_in_value is a string representing the maximum value allowed for a deposit. // - The value is measured in the underlying_asset. - // - Incoming payment_denom deposits are converted to this unit before checking. // - Values must be positive (> 0). // - An empty string "" indicates no maximum limit. MaxSwapInValue string `protobuf:"bytes,27,opt,name=max_swap_in_value,json=maxSwapInValue,proto3" json:"max_swap_in_value,omitempty"` @@ -4855,6 +4288,7 @@ func (x *VaultAccount) GetUnderlyingAsset() string { return "" } +// Deprecated: Do not use. func (x *VaultAccount) GetPaymentDenom() string { if x != nil { return x.PaymentDenom @@ -5124,68 +4558,6 @@ func (x *VaultNAV) GetUpdatedTime() *timestamppb.Timestamp { return nil } -// InitialVaultNAV seeds a per-vault Internal NAV entry at vault creation time. -// It is the stateless subset of VaultNAV (no updated_block_height or -// updated_time, which are stamped by the keeper when the entry is persisted) -// and omits the denom, which is implied by the field that carries it on the -// containing message (e.g. payment_denom on MsgCreateVaultRequest). -type InitialVaultNAV struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // price is the total value of `volume` units of the priced denom, denominated - // in one of the vault's accepted denoms (typically the underlying asset). - Price *v1beta11.Coin `protobuf:"bytes,1,opt,name=price,proto3" json:"price,omitempty"` - // volume is the number of units of the priced denom that price covers. It - // must be positive; the per-unit value is price divided by volume. - Volume string `protobuf:"bytes,2,opt,name=volume,proto3" json:"volume,omitempty"` - // source identifies the origin of this NAV entry (for example an oracle name - // or the settlement path). - Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` -} - -func (x *InitialVaultNAV) Reset() { - *x = InitialVaultNAV{} - if protoimpl.UnsafeEnabled { - mi := &file_provlabs_vault_v1_vault_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InitialVaultNAV) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InitialVaultNAV) ProtoMessage() {} - -// Deprecated: Use InitialVaultNAV.ProtoReflect.Descriptor instead. -func (*InitialVaultNAV) Descriptor() ([]byte, []int) { - return file_provlabs_vault_v1_vault_proto_rawDescGZIP(), []int{2} -} - -func (x *InitialVaultNAV) GetPrice() *v1beta11.Coin { - if x != nil { - return x.Price - } - return nil -} - -func (x *InitialVaultNAV) GetVolume() string { - if x != nil { - return x.Volume - } - return "" -} - -func (x *InitialVaultNAV) GetSource() string { - if x != nil { - return x.Source - } - return "" -} - // AccountBalance represents the coin balance of a single account. type AccountBalance struct { state protoimpl.MessageState @@ -5201,7 +4573,7 @@ type AccountBalance struct { func (x *AccountBalance) Reset() { *x = AccountBalance{} if protoimpl.UnsafeEnabled { - mi := &file_provlabs_vault_v1_vault_proto_msgTypes[3] + mi := &file_provlabs_vault_v1_vault_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5215,7 +4587,7 @@ func (*AccountBalance) ProtoMessage() {} // Deprecated: Use AccountBalance.ProtoReflect.Descriptor instead. func (*AccountBalance) Descriptor() ([]byte, []int) { - return file_provlabs_vault_v1_vault_proto_rawDescGZIP(), []int{3} + return file_provlabs_vault_v1_vault_proto_rawDescGZIP(), []int{2} } func (x *AccountBalance) GetAddress() string { @@ -5244,14 +4616,17 @@ type PendingSwapOut struct { VaultAddress string `protobuf:"bytes,2,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // shares are the shares that were escrowed by the user. Shares *v1beta11.Coin `protobuf:"bytes,3,opt,name=shares,proto3" json:"shares,omitempty"` - // redeem_denom is the denomination of the asset to be redeemed. + // redeem_denom is the denomination of the asset to be redeemed. Always the + // vault's underlying_asset; retained for wire compatibility. + // + // Deprecated: Do not use. RedeemDenom string `protobuf:"bytes,4,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` } func (x *PendingSwapOut) Reset() { *x = PendingSwapOut{} if protoimpl.UnsafeEnabled { - mi := &file_provlabs_vault_v1_vault_proto_msgTypes[4] + mi := &file_provlabs_vault_v1_vault_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5265,7 +4640,7 @@ func (*PendingSwapOut) ProtoMessage() {} // Deprecated: Use PendingSwapOut.ProtoReflect.Descriptor instead. func (*PendingSwapOut) Descriptor() ([]byte, []int) { - return file_provlabs_vault_v1_vault_proto_rawDescGZIP(), []int{4} + return file_provlabs_vault_v1_vault_proto_rawDescGZIP(), []int{3} } func (x *PendingSwapOut) GetOwner() string { @@ -5289,6 +4664,7 @@ func (x *PendingSwapOut) GetShares() *v1beta11.Coin { return nil } +// Deprecated: Do not use. func (x *PendingSwapOut) GetRedeemDenom() string { if x != nil { return x.RedeemDenom @@ -5311,7 +4687,7 @@ var file_provlabs_vault_v1_vault_proto_rawDesc = []byte{ 0x6f, 0x67, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x0c, 0x0a, 0x0c, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x63, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcd, 0x0c, 0x0a, 0x0c, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x49, 0x0a, 0x0c, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, @@ -5324,147 +4700,137 @@ var file_provlabs_vault_v1_vault_proto_rawDesc = []byte{ 0x61, 0x72, 0x65, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, - 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, - 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, + 0x27, 0x0a, 0x0d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, 0x70, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x2e, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x48, 0x0a, 0x15, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x61, 0x74, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, + 0x74, 0x65, 0x12, 0x48, 0x0a, 0x15, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, + 0x63, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x40, 0x0a, 0x11, + 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x61, 0x74, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, + 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x40, + 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x72, + 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, + 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x0f, 0x6d, 0x61, 0x78, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, + 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x65, 0x72, + 0x69, 0x6f, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x77, + 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0d, 0x73, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x77, + 0x61, 0x70, 0x4f, 0x75, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x18, + 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, + 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, + 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x53, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, + 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x46, + 0x0a, 0x0e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, + 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x0d, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, + 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, + 0x61, 0x75, 0x73, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x0e, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x48, 0x0a, 0x15, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x44, 0x65, 0x63, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x13, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x48, - 0x0a, 0x15, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, - 0x73, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, - 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x44, 0x65, 0x63, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x52, 0x13, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x40, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x5f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x44, 0x65, 0x63, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x40, 0x0a, 0x11, 0x6d, 0x61, - 0x78, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, - 0x73, 0x2e, 0x44, 0x65, 0x63, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x61, 0x78, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x52, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, - 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, - 0x25, 0x0a, 0x0e, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x54, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, - 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0d, 0x73, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x28, - 0x0a, 0x10, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x73, 0x77, 0x61, 0x70, 0x4f, 0x75, - 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x77, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x73, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x77, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x0e, 0x70, 0x61, - 0x75, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, - 0xde, 0x1f, 0x00, 0x52, 0x0d, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x61, 0x75, 0x73, 0x65, - 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x0e, 0x62, 0x72, 0x69, 0x64, 0x67, - 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x62, 0x72, 0x69, 0x64, 0x67, - 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x62, 0x72, 0x69, 0x64, - 0x67, 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, - 0x3d, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, - 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x28, - 0x0a, 0x10, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x65, 0x65, 0x50, 0x65, 0x72, - 0x69, 0x6f, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x66, 0x65, 0x65, 0x5f, - 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x16, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x66, 0x65, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x54, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x4f, 0x0a, 0x13, 0x6f, 0x75, 0x74, 0x73, 0x74, 0x61, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x75, 0x6d, 0x5f, 0x66, 0x65, 0x65, 0x18, 0x17, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, - 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, - 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x11, 0x6f, 0x75, 0x74, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x41, 0x75, 0x6d, 0x46, 0x65, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x75, 0x6d, 0x5f, 0x66, - 0x65, 0x65, 0x5f, 0x62, 0x69, 0x70, 0x73, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x61, - 0x75, 0x6d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x12, 0x3f, 0x0a, 0x11, 0x6d, 0x69, 0x6e, - 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x19, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, - 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x6d, 0x69, 0x6e, 0x53, - 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x41, 0x0a, 0x12, 0x6d, 0x69, - 0x6e, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x69, - 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, - 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, 0x0e, + 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, + 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x66, 0x65, + 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x12, + 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x66, 0x65, 0x65, 0x50, 0x65, 0x72, + 0x69, 0x6f, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x4f, 0x0a, 0x13, 0x6f, 0x75, + 0x74, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x75, 0x6d, 0x5f, 0x66, 0x65, + 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, + 0x69, 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x11, 0x6f, 0x75, 0x74, 0x73, 0x74, 0x61, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x75, 0x6d, 0x46, 0x65, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x61, + 0x75, 0x6d, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x62, 0x69, 0x70, 0x73, 0x18, 0x18, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0a, 0x61, 0x75, 0x6d, 0x46, 0x65, 0x65, 0x42, 0x69, 0x70, 0x73, 0x12, 0x3f, 0x0a, + 0x11, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0e, - 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x41, - 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, + 0x6d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x41, + 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x3d, 0x0a, 0x0d, 0x6e, 0x61, 0x76, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x0c, 0x6e, 0x61, 0x76, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x22, 0xaf, 0x02, 0x0a, 0x08, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x12, 0x14, 0x0a, - 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, - 0x6e, 0x6f, 0x6d, 0x12, 0x35, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x3f, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x69, 0x6e, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, 0xd2, 0xb4, + 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x41, 0x0a, 0x12, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x6f, + 0x75, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x14, + 0xd2, 0xb4, 0x2d, 0x10, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0d, 0x6e, 0x61, 0x76, 0x5f, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, + 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x6e, 0x61, 0x76, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x22, 0xaf, 0x02, 0x0a, 0x08, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4e, 0x41, + 0x56, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x35, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, + 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, + 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x43, + 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, + 0xc8, 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, + 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, + 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, 0x76, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x47, 0x0a, + 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, + 0x08, 0xc8, 0xde, 0x1f, 0x00, 0x90, 0xdf, 0x1f, 0x01, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x0e, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x61, 0x0a, 0x05, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x30, 0xc8, + 0xde, 0x1f, 0x00, 0xaa, 0xdf, 0x1f, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2d, + 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, + 0x05, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, 0xe8, 0xa0, 0x1f, 0x00, + 0x22, 0xdf, 0x01, 0x0a, 0x0e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x77, 0x61, 0x70, + 0x4f, 0x75, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x42, 0x04, 0xc8, - 0xde, 0x1f, 0x00, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x06, 0x76, 0x6f, - 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, 0xde, 0x1f, 0x00, - 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, - 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x47, 0x0a, 0x0c, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x08, 0xc8, 0xde, 0x1f, - 0x00, 0x90, 0xdf, 0x1f, 0x01, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, - 0x6d, 0x65, 0x22, 0xa5, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x56, 0x61, - 0x75, 0x6c, 0x74, 0x4e, 0x41, 0x56, 0x12, 0x35, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, - 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, - 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, - 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2b, 0xc8, - 0xde, 0x1f, 0x00, 0xda, 0xde, 0x1f, 0x15, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, - 0x2e, 0x69, 0x6f, 0x2f, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x74, 0xd2, 0xb4, 0x2d, 0x0a, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, - 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x0e, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x61, 0x0a, 0x05, 0x63, 0x6f, 0x69, 0x6e, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, - 0x6e, 0x42, 0x30, 0xc8, 0xde, 0x1f, 0x00, 0xaa, 0xdf, 0x1f, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2f, 0x63, 0x6f, 0x73, - 0x6d, 0x6f, 0x73, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6f, - 0x69, 0x6e, 0x73, 0x52, 0x05, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x3a, 0x08, 0x88, 0xa0, 0x1f, 0x00, - 0xe8, 0xa0, 0x1f, 0x00, 0x22, 0xdb, 0x01, 0x0a, 0x0e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x53, 0x77, 0x61, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, - 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, - 0xd2, 0xb4, 0x2d, 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, - 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, - 0x6e, 0x42, 0x04, 0xc8, 0xde, 0x1f, 0x00, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, - 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x44, 0x65, 0x6e, + 0xde, 0x1f, 0x00, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0c, 0x72, + 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x42, 0xc2, 0x01, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x6c, 0x61, 0x62, 0x73, 0x2e, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, @@ -5492,32 +4858,30 @@ func file_provlabs_vault_v1_vault_proto_rawDescGZIP() []byte { return file_provlabs_vault_v1_vault_proto_rawDescData } -var file_provlabs_vault_v1_vault_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_provlabs_vault_v1_vault_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_provlabs_vault_v1_vault_proto_goTypes = []interface{}{ (*VaultAccount)(nil), // 0: provlabs.vault.v1.VaultAccount (*VaultNAV)(nil), // 1: provlabs.vault.v1.VaultNAV - (*InitialVaultNAV)(nil), // 2: provlabs.vault.v1.InitialVaultNAV - (*AccountBalance)(nil), // 3: provlabs.vault.v1.AccountBalance - (*PendingSwapOut)(nil), // 4: provlabs.vault.v1.PendingSwapOut - (*v1beta1.BaseAccount)(nil), // 5: cosmos.auth.v1beta1.BaseAccount - (*v1beta11.Coin)(nil), // 6: cosmos.base.v1beta1.Coin - (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp + (*AccountBalance)(nil), // 2: provlabs.vault.v1.AccountBalance + (*PendingSwapOut)(nil), // 3: provlabs.vault.v1.PendingSwapOut + (*v1beta1.BaseAccount)(nil), // 4: cosmos.auth.v1beta1.BaseAccount + (*v1beta11.Coin)(nil), // 5: cosmos.base.v1beta1.Coin + (*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp } var file_provlabs_vault_v1_vault_proto_depIdxs = []int32{ - 5, // 0: provlabs.vault.v1.VaultAccount.base_account:type_name -> cosmos.auth.v1beta1.BaseAccount - 6, // 1: provlabs.vault.v1.VaultAccount.total_shares:type_name -> cosmos.base.v1beta1.Coin - 6, // 2: provlabs.vault.v1.VaultAccount.paused_balance:type_name -> cosmos.base.v1beta1.Coin - 6, // 3: provlabs.vault.v1.VaultAccount.outstanding_aum_fee:type_name -> cosmos.base.v1beta1.Coin - 6, // 4: provlabs.vault.v1.VaultNAV.price:type_name -> cosmos.base.v1beta1.Coin - 7, // 5: provlabs.vault.v1.VaultNAV.updated_time:type_name -> google.protobuf.Timestamp - 6, // 6: provlabs.vault.v1.InitialVaultNAV.price:type_name -> cosmos.base.v1beta1.Coin - 6, // 7: provlabs.vault.v1.AccountBalance.coins:type_name -> cosmos.base.v1beta1.Coin - 6, // 8: provlabs.vault.v1.PendingSwapOut.shares:type_name -> cosmos.base.v1beta1.Coin - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 4, // 0: provlabs.vault.v1.VaultAccount.base_account:type_name -> cosmos.auth.v1beta1.BaseAccount + 5, // 1: provlabs.vault.v1.VaultAccount.total_shares:type_name -> cosmos.base.v1beta1.Coin + 5, // 2: provlabs.vault.v1.VaultAccount.paused_balance:type_name -> cosmos.base.v1beta1.Coin + 5, // 3: provlabs.vault.v1.VaultAccount.outstanding_aum_fee:type_name -> cosmos.base.v1beta1.Coin + 5, // 4: provlabs.vault.v1.VaultNAV.price:type_name -> cosmos.base.v1beta1.Coin + 6, // 5: provlabs.vault.v1.VaultNAV.updated_time:type_name -> google.protobuf.Timestamp + 5, // 6: provlabs.vault.v1.AccountBalance.coins:type_name -> cosmos.base.v1beta1.Coin + 5, // 7: provlabs.vault.v1.PendingSwapOut.shares:type_name -> cosmos.base.v1beta1.Coin + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_provlabs_vault_v1_vault_proto_init() } @@ -5551,18 +4915,6 @@ func file_provlabs_vault_v1_vault_proto_init() { } } file_provlabs_vault_v1_vault_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InitialVaultNAV); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_provlabs_vault_v1_vault_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AccountBalance); i { case 0: return &v.state @@ -5574,7 +4926,7 @@ func file_provlabs_vault_v1_vault_proto_init() { return nil } } - file_provlabs_vault_v1_vault_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_provlabs_vault_v1_vault_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PendingSwapOut); i { case 0: return &v.state @@ -5593,7 +4945,7 @@ func file_provlabs_vault_v1_vault_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_provlabs_vault_v1_vault_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/keeper/export_test.go b/keeper/export_test.go index 75742f3e..3d10be39 100644 --- a/keeper/export_test.go +++ b/keeper/export_test.go @@ -10,6 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/provenance-io/provenance/x/exchange" markertypes "github.com/provenance-io/provenance/x/marker/types" + "github.com/provlabs/vault/types" ) @@ -133,9 +134,9 @@ func (k Keeper) TestAccessor_publishAssetNAVToMarker(t *testing.T, ctx context.C } // TestAccessor_settlementLegCoins exposes the settlementLegCoins function for unit tests. -func (k Keeper) TestAccessor_settlementLegCoins(t *testing.T, payment *exchange.Payment, direction, paymentDenom string) (sdk.Coin, sdk.Coin, error) { +func (k Keeper) TestAccessor_settlementLegCoins(t *testing.T, payment *exchange.Payment, direction, underlyingDenom string) (sdk.Coin, sdk.Coin, error) { t.Helper() - return settlementLegCoins(payment, direction, paymentDenom) + return settlementLegCoins(payment, direction, underlyingDenom) } // TestAccessor_stageFromPrincipal exposes this keeper's stageFromPrincipal function for unit tests. diff --git a/keeper/genesis_test.go b/keeper/genesis_test.go index 652f672f..b0e41d5f 100644 --- a/keeper/genesis_test.go +++ b/keeper/genesis_test.go @@ -19,15 +19,7 @@ func (s *TestSuite) TestVaultGenesis_InitAndExport() { admin := s.adminAddr.String() vaultAddr := types.GetVaultAddress(shareDenom) - vault := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom, 0), - UnderlyingAsset: underlying, - PaymentDenom: underlying, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - } + vault := makeGenesisVaultAccount(shareDenom, underlying, admin) past := time.Now().Add(-5 * time.Minute).Unix() vault.PeriodTimeout = past @@ -86,15 +78,7 @@ func (s *TestSuite) TestVaultGenesis_InitAndExport() { func (s *TestSuite) TestInitGenesis_PanicOnInvalidTimeout() { vaultAddr := types.GetVaultAddress("panic-vault").String() - vault := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(types.GetVaultAddress("panic-vault")), - Admin: s.adminAddr.String(), - TotalShares: sdk.NewInt64Coin("panic-vault", 0), - UnderlyingAsset: "undercoin", - PaymentDenom: "undercoin", - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - } + vault := makeGenesisVaultAccount("panic-vault", "undercoin", s.adminAddr.String()) tests := []struct { name string @@ -146,6 +130,7 @@ func (s *TestSuite) TestInitGenesis_PanicOnInvalidTimeout() { }) } } + func (s *TestSuite) TestVaultGenesis_RoundTrip_FeeTimeoutAndParams() { shareDenom := "vaultshare_fee" underlying := "under_fee" @@ -156,16 +141,8 @@ func (s *TestSuite) TestVaultGenesis_RoundTrip_FeeTimeoutAndParams() { now := time.Now().Unix() future := now + 1000 - vault := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom, 0), - UnderlyingAsset: underlying, - PaymentDenom: underlying, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - FeePeriodTimeout: future, - } + vault := makeGenesisVaultAccount(shareDenom, underlying, admin) + vault.FeePeriodTimeout = future params := types.Params{ TechFeeAddress: aumFeeAddress.String(), @@ -209,27 +186,11 @@ func (s *TestSuite) TestVaultGenesis_RoundTrip_PastAndFutureTimeouts() { past := now.Add(-10 * time.Minute).Unix() future := now.Add(10 * time.Minute).Unix() - vault1 := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr1), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom1, 0), - UnderlyingAsset: underlying1, - PaymentDenom: underlying1, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - PeriodTimeout: past, - } + vault1 := makeGenesisVaultAccount(shareDenom1, underlying1, admin) + vault1.PeriodTimeout = past - vault2 := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr2), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom2, 0), - UnderlyingAsset: underlying2, - PaymentDenom: underlying2, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - PeriodTimeout: future, - } + vault2 := makeGenesisVaultAccount(shareDenom2, underlying2, admin) + vault2.PeriodTimeout = future genesis := &types.GenesisState{ Params: types.DefaultParams(), @@ -251,21 +212,12 @@ func (s *TestSuite) TestVaultGenesis_RoundTrip_PastAndFutureTimeouts() { func (s *TestSuite) TestVaultGenesis_InvalidTimeoutAddressPanics() { shareDenom := "vaultshare3" underlying := "under3" - vaultAddr := types.GetVaultAddress(shareDenom) admin := s.adminAddr.String() now := uint64(time.Now().Unix()) - vault := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom, 0), - UnderlyingAsset: underlying, - PaymentDenom: underlying, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - PeriodTimeout: int64(now), - } + vault := makeGenesisVaultAccount(shareDenom, underlying, admin) + vault.PeriodTimeout = int64(now) genesis := &types.GenesisState{ Params: types.DefaultParams(), @@ -290,15 +242,7 @@ func (s *TestSuite) TestVaultGenesis_ExistingAccountNumberCopied() { s.Require().NoError(existing.SetAccountNumber(999), "failed to set account number for existing account") s.k.AuthKeeper.SetAccount(s.ctx, existing) - vault := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom, 0), - UnderlyingAsset: underlying, - PaymentDenom: underlying, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - } + vault := makeGenesisVaultAccount(shareDenom, underlying, admin) genesis := &types.GenesisState{ Params: types.DefaultParams(), @@ -342,17 +286,8 @@ func (s *TestSuite) TestVaultGenesis_InitPanicsOnInvalidPendingSwapOut() { shareDenom := "vaultshare" underlying := "undercoin" admin := s.adminAddr.String() - vaultAddr := types.GetVaultAddress(shareDenom) - vault := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom, 0), - UnderlyingAsset: underlying, - PaymentDenom: underlying, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - } + vault := makeGenesisVaultAccount(shareDenom, underlying, admin) genesis := &types.GenesisState{ Params: types.DefaultParams(), @@ -381,18 +316,9 @@ func (s *TestSuite) TestVaultGenesis_InitPanicsWhenPendingSwapOutHasUnknownVault shareDenom := "vaultshare" underlying := "undercoin" admin := s.adminAddr.String() - vaultAddr := types.GetVaultAddress(shareDenom) badVaultAddr := types.GetVaultAddress("baddenom") - vault := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom, 0), - UnderlyingAsset: underlying, - PaymentDenom: underlying, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - } + vault := makeGenesisVaultAccount(shareDenom, underlying, admin) genesis := &types.GenesisState{ Params: types.DefaultParams(), @@ -421,17 +347,8 @@ func (s *TestSuite) TestVaultGenesis_InitPanicsWhenPendingSwapOutHasBadVaultAddr shareDenom := "vaultshare" underlying := "undercoin" admin := s.adminAddr.String() - vaultAddr := types.GetVaultAddress(shareDenom) - vault := types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(vaultAddr), - Admin: admin, - TotalShares: sdk.NewInt64Coin(shareDenom, 0), - UnderlyingAsset: underlying, - PaymentDenom: underlying, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - } + vault := makeGenesisVaultAccount(shareDenom, underlying, admin) genesis := &types.GenesisState{ Params: types.DefaultParams(), diff --git a/keeper/migrations.go b/keeper/migrations.go index 58ac7ed5..7a316a19 100644 --- a/keeper/migrations.go +++ b/keeper/migrations.go @@ -11,57 +11,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// MigrationNAVSeedSource is the value recorded on the source field of every -// VaultNAV entry created by migrateInternalNAVSeedFromMarker. It identifies the -// entry as a one-time seed from the Marker module's NAV table so indexers can -// distinguish migrated entries from oracle- or operator-supplied updates. -const MigrationNAVSeedSource = "x/vault internal NAV seed migration" - -// uyldsFccDenom is the temporary 1:1 peg denom. For non-identity vault pairs -// where payment_denom or underlying_asset is this denom, migration seeds an -// explicit (Price.Amount=1, Volume=1) Internal NAV entry so pricing reads from -// Internal NAV. Identity pairs (payment_denom == underlying_asset) are still -// skipped earlier because internal NAV denom/price-denom would collide. See -// https://github.com/ProvLabs/vault/issues/73. -const uyldsFccDenom = "uylds.fcc" - -// MigrateVaultAccountPaymentDenomDefaults updates legacy VaultAccount state created -// prior to v1.0.13 by normalizing empty payment denom fields. -// -// In versions <= v1.0.13, VaultAccount instances could be persisted with an empty -// PaymentDenom. Newer versions require a valid payment denom, which by default -// should be the vault’s underlying asset denom. -// -// This migration iterates all accounts in the auth store, identifies VaultAccount -// instances, and for any vault with an empty PaymentDenom sets it to UnderlyingAsset. -// Updated vault accounts are validated and re-persisted using the auth keeper. -// -// This function is intended to be executed once from an upgrade handler and is -// idempotent; running it multiple times will not modify already-migrated state. -func (k Keeper) MigrateVaultAccountPaymentDenomDefaults(ctx sdk.Context) error { - allAccounts := k.AuthKeeper.GetAllAccounts(ctx) - - for _, acc := range allAccounts { - v, ok := acc.(*types.VaultAccount) - if !ok { - continue - } - - if v.PaymentDenom == "" { - v.PaymentDenom = v.UnderlyingAsset - err := k.SetVaultAccount(ctx, v) - if err != nil { - return fmt.Errorf("failed to update vault account %s during migration: %w", v.Address, err) - } - } - } - - return nil -} - -// migrateInternalNAVSeedFromMarker seeds the Internal NAV table for every vault -// that will need an Internal NAV entry once the pricing engine switches to -// Internal-NAV-only reads. +// migrateFlattenMixedDenomVaults rewrites all vault state so every vault is +// strictly single-denom on its underlying asset. Mixed-denom vaults (a payment +// denom distinct from the underlying) predate the single-denom restriction; the +// live ones hold zero or dust balances, so no funds are moved — only their +// configuration is flattened. // // It is unexported on purpose: the only supported entry point is the // Migrator.Migrate1to2 handler registered with the SDK module manager via @@ -70,136 +24,151 @@ func (k Keeper) MigrateVaultAccountPaymentDenomDefaults(ctx sdk.Context) error { // fire exactly once per chain. // // For each VaultAccount in state the migration: -// 1. Defaults v.NavAuthority to v.Admin when empty. -// 2. Skips the vault if payment_denom == underlying_asset (identity fast-path -// in UnitPriceFraction; an Internal NAV entry is impossible here because -// denom and price denom would collide). -// 3. Skips the vault if an Internal NAV entry already exists for payment_denom -// so a re-run preserves operator-supplied values. -// 4. For vaults where payment_denom or underlying_asset is "uylds.fcc", writes -// a 1:1 Internal NAV (Price.Amount=1, Volume=1) so the new pricing engine -// reads an explicit entry rather than relying on the legacy peg fast-path. -// See https://github.com/ProvLabs/vault/issues/73. -// 5. Otherwise reads the forward (payment→underlying) and reverse -// (underlying→payment) Marker NAVs and, mirroring UnitPriceFraction, picks -// the entry with the greater UpdatedBlockHeight when both are present, or -// the single available entry. The chosen NAV is translated into the -// single-sided Internal NAV format (Denom=payment_denom, Price denominated -// in underlying_asset). -// -// All seeded entries are persisted via SetVaultNAV, which emits -// EventNAVUpdated for indexers. +// 1. Defaults v.NavAuthority to v.Admin when empty, matching how new vaults +// are created. +// 2. Sets PaymentDenom equal to UnderlyingAsset. The deprecated field remains +// on the wire for client compatibility, so it is normalized rather than +// cleared. +// 3. Re-denominates OutstandingAumFee into the underlying asset. A zero or +// empty fee is normalized directly. A non-zero fee in a foreign denom is +// converted through the vault's internal NAV table when an entry exists; +// when no price is available the fee is zeroed with an error-level log +// rather than failing the upgrade, because a halted chain is strictly +// worse than forfeiting a fee that live-state analysis shows is zero +// everywhere today. // -// If a vault has payment_denom != underlying_asset, is not on the uylds.fcc peg -// fast-path, has no pre-existing Internal NAV entry, and no forward or reverse -// Marker NAV is available, the migration returns an error naming the vault. -// Failing the migration is preferred over silently leaving the vault -// unpriceable post-upgrade. +// It then rewrites any pending swap-out whose redeem denom is not the owning +// vault's underlying asset, so queued payouts settle in the only denom the +// flattened vault can redeem. // -// The migration is idempotent on subsequent runs because pre-existing Internal -// NAV entries are preserved in step 3. -func (k Keeper) migrateInternalNAVSeedFromMarker(ctx sdk.Context) error { - accounts := k.AuthKeeper.GetAllAccounts(ctx) - - for _, acc := range accounts { +// The migration is idempotent: already-flattened vaults and conforming queue +// entries are left untouched. +func (k Keeper) migrateFlattenMixedDenomVaults(ctx sdk.Context) error { + for _, acc := range k.AuthKeeper.GetAllAccounts(ctx) { vault, ok := acc.(*types.VaultAccount) if !ok { continue } + changed := false if vault.NavAuthority == "" { vault.NavAuthority = vault.Admin - if err := k.SetVaultAccount(ctx, vault); err != nil { - return fmt.Errorf("failed to default nav_authority for vault %s: %w", vault.Address, err) - } + changed = true } - if vault.PaymentDenom == vault.UnderlyingAsset { - continue + if vault.PaymentDenom != vault.UnderlyingAsset { + k.getLogger(ctx).Info("flattening mixed-denom vault to single-denom", + "vault", vault.Address, + "underlying_asset", vault.UnderlyingAsset, + "payment_denom", vault.PaymentDenom, + ) + vault.PaymentDenom = vault.UnderlyingAsset + changed = true } - exists, err := k.NAVs.Has(ctx, collections.Join(vault.GetAddress(), vault.PaymentDenom)) - if err != nil { - return fmt.Errorf("failed to check internal NAV for vault %s: %w", vault.Address, err) - } - if exists { - continue - } + changed = k.normalizeOutstandingAumFee(ctx, vault) || changed - var nav types.VaultNAV - if vault.PaymentDenom == uyldsFccDenom || vault.UnderlyingAsset == uyldsFccDenom { - nav = types.VaultNAV{ - Denom: vault.PaymentDenom, - Price: sdk.NewCoin(vault.UnderlyingAsset, math.OneInt()), - Volume: math.OneInt(), - Source: MigrationNAVSeedSource, - } - } else { - nav, err = k.buildInternalNAVFromMarker(ctx, vault) - if err != nil { - return err + if changed { + if err := k.SetVaultAccount(ctx, vault); err != nil { + return fmt.Errorf("failed to persist flattened vault %s: %w", vault.Address, err) } } + } - if err := k.SetVaultNAV(ctx, vault, nav, vault.NavAuthority); err != nil { - return fmt.Errorf("failed to seed internal NAV for vault %s: %w", vault.Address, err) - } + if err := k.migratePendingSwapOutRedeemDenoms(ctx); err != nil { + return fmt.Errorf("failed to migrate pending swap-out redeem denoms: %w", err) } return nil } -// buildInternalNAVFromMarker reads the forward and reverse Marker NAVs for the -// vault's payment/underlying pair and returns the VaultNAV that should be -// written to the Internal NAV table. It mirrors UnitPriceFraction's selection -// rule: when both directions exist, the one with the greater UpdatedBlockHeight -// wins; when only one exists, that entry is used. -// -// Both directions are queried unconditionally so a transient error on one -// lookup does not prevent the migration from using a valid NAV from the other -// direction. An error is returned only when no usable NAV is available — that -// is, when both lookups return nil. In that case the surfaced error names the -// failing direction (if any) so operators can diagnose the underlying Marker -// store issue; if both lookups returned (nil, nil), the migration aborts with a -// "no marker NAV available" error naming the vault. +// normalizeOutstandingAumFee re-denominates a vault's OutstandingAumFee into the +// underlying asset, reporting whether the vault was modified. A zero or empty +// fee becomes the zero coin of the underlying. A non-zero fee in a foreign +// denom is converted through the vault's internal NAV table; when no price is +// available the fee is zeroed with an error-level log so the upgrade cannot +// halt over an unpriceable liability (live-state analysis shows every vault's +// outstanding fee is zero today). By construction no path fails: every outcome +// resolves to a concrete fee value, so the only signal is whether the vault +// was modified. +func (k Keeper) normalizeOutstandingAumFee(ctx sdk.Context, vault *types.VaultAccount) bool { + fee := vault.OutstandingAumFee + if fee.Denom == vault.UnderlyingAsset && !fee.Amount.IsNil() { + return false + } + + if fee.Amount.IsNil() || fee.Amount.IsZero() { + vault.OutstandingAumFee = sdk.NewCoin(vault.UnderlyingAsset, math.ZeroInt()) + return true + } + + converted, err := k.ToUnderlyingAssetAmount(ctx, *vault, fee) + if err != nil { + k.getLogger(ctx).Error("zeroing outstanding AUM fee with no internal NAV price", + "vault", vault.Address, + "fee", fee.String(), + "err", err, + ) + vault.OutstandingAumFee = sdk.NewCoin(vault.UnderlyingAsset, math.ZeroInt()) + return true + } + + k.getLogger(ctx).Info("re-denominated outstanding AUM fee into underlying asset", + "vault", vault.Address, + "old_fee", fee.String(), + "new_fee", sdk.NewCoin(vault.UnderlyingAsset, converted).String(), + ) + vault.OutstandingAumFee = sdk.NewCoin(vault.UnderlyingAsset, converted) + return true +} + +// migratePendingSwapOutRedeemDenoms rewrites every pending swap-out whose +// redeem denom differs from the owning vault's underlying asset. Entries are +// collected during the walk and written afterwards so the underlying iterator +// is never invalidated by a concurrent Set. // -// Also returns an error if the selected NAV has a zero price amount or zero -// volume. -func (k Keeper) buildInternalNAVFromMarker(ctx sdk.Context, vault *types.VaultAccount) (types.VaultNAV, error) { - fwd, errF := k.MarkerKeeper.GetNetAssetValue(ctx, vault.PaymentDenom, vault.UnderlyingAsset) - rev, errR := k.MarkerKeeper.GetNetAssetValue(ctx, vault.UnderlyingAsset, vault.PaymentDenom) - - if fwd == nil && rev == nil { - if errF != nil { - return types.VaultNAV{}, fmt.Errorf("failed to read forward marker NAV for vault %s (%s/%s): %w", vault.Address, vault.PaymentDenom, vault.UnderlyingAsset, errF) +// An entry whose vault cannot be loaded is skipped with an error-level log +// rather than failing the upgrade: the runtime queue processing tolerates the +// same state by dequeuing such entries, so halting the chain over one orphaned +// entry would be strictly worse. +func (k Keeper) migratePendingSwapOutRedeemDenoms(ctx sdk.Context) error { + type queuedRewrite struct { + key collections.Triple[int64, uint64, sdk.AccAddress] + req types.PendingSwapOut + } + + var rewrites []queuedRewrite + err := k.PendingSwapOutQueue.Walk(ctx, func(timestamp int64, id uint64, vaultAddr sdk.AccAddress, req types.PendingSwapOut) (bool, error) { + vault, ok := k.tryGetVault(ctx, vaultAddr) + if !ok { + k.getLogger(ctx).Error("skipping pending swap-out with no usable vault; queue processing dequeues such entries", + "vault", vaultAddr.String(), + "swap_out_id", id, + ) + return false, nil } - if errR != nil { - return types.VaultNAV{}, fmt.Errorf("failed to read reverse marker NAV for vault %s (%s/%s): %w", vault.Address, vault.UnderlyingAsset, vault.PaymentDenom, errR) + if req.RedeemDenom == vault.UnderlyingAsset { + return false, nil } - return types.VaultNAV{}, fmt.Errorf("no marker NAV available to seed internal NAV for vault %s (payment %s, underlying %s)", vault.Address, vault.PaymentDenom, vault.UnderlyingAsset) + k.getLogger(ctx).Info("rewriting pending swap-out redeem denom to underlying asset", + "vault", vault.Address, + "swap_out_id", id, + "redeem_denom", req.RedeemDenom, + "underlying_asset", vault.UnderlyingAsset, + ) + req.RedeemDenom = vault.UnderlyingAsset + rewrites = append(rewrites, queuedRewrite{key: collections.Join3(timestamp, id, vaultAddr), req: req}) + return false, nil + }) + if err != nil { + return fmt.Errorf("failed to walk pending swap-out queue: %w", err) } - useForward := fwd != nil && (rev == nil || fwd.UpdatedBlockHeight >= rev.UpdatedBlockHeight) - - var priceAmt, volume math.Int - if useForward { - if fwd.Volume == 0 || fwd.Price.Amount.IsZero() { - return types.VaultNAV{}, fmt.Errorf("invalid forward marker NAV for vault %s (%s/%s): price=%s volume=%d", vault.Address, vault.PaymentDenom, vault.UnderlyingAsset, fwd.Price.Amount, fwd.Volume) + for _, rewrite := range rewrites { + if err := k.PendingSwapOutQueue.IndexedMap.Set(ctx, rewrite.key, rewrite.req); err != nil { + return fmt.Errorf("failed to rewrite pending swap-out %d: %w", rewrite.key.K2(), err) } - priceAmt = fwd.Price.Amount - volume = math.NewIntFromUint64(fwd.Volume) - } else { - if rev.Volume == 0 || rev.Price.Amount.IsZero() { - return types.VaultNAV{}, fmt.Errorf("invalid reverse marker NAV for vault %s (%s/%s): price=%s volume=%d", vault.Address, vault.UnderlyingAsset, vault.PaymentDenom, rev.Price.Amount, rev.Volume) - } - priceAmt = math.NewIntFromUint64(rev.Volume) - volume = rev.Price.Amount } - return types.VaultNAV{ - Denom: vault.PaymentDenom, - Price: sdk.NewCoin(vault.UnderlyingAsset, priceAmt), - Volume: volume, - Source: MigrationNAVSeedSource, - }, nil + return nil } diff --git a/keeper/migrations_test.go b/keeper/migrations_test.go index 543fddd6..4cd9fcc2 100644 --- a/keeper/migrations_test.go +++ b/keeper/migrations_test.go @@ -4,459 +4,215 @@ import ( "cosmossdk.io/collections" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/provlabs/vault/keeper" "github.com/provlabs/vault/types" ) -func (s *TestSuite) TestKeeper_MigrateVaultAccountPaymentDenomDefaults() { - createVault := func(shareDenom, underlying, payment string) (sdk.AccAddress, *types.VaultAccount) { - addr := types.GetVaultAddress(shareDenom) - - vault := &types.VaultAccount{ - BaseAccount: authtypes.NewBaseAccountWithAddress(addr), - Admin: s.adminAddr.String(), - TotalShares: sdk.NewCoin(shareDenom, sdkmath.ZeroInt()), - UnderlyingAsset: underlying, - PaymentDenom: payment, - CurrentInterestRate: types.ZeroInterestRate, - DesiredInterestRate: types.ZeroInterestRate, - SwapInEnabled: true, - SwapOutEnabled: true, - WithdrawalDelaySeconds: 0, - Paused: false, - PausedBalance: sdk.Coin{}, - BridgeEnabled: false, - BridgeAddress: "", - } - - acct := s.simApp.AccountKeeper.NewAccount(s.ctx, vault) - vaultAcct, ok := acct.(*types.VaultAccount) - s.Require().True(ok, "new account should return a *types.VaultAccount for a VaultAccount prototype") - - s.simApp.AccountKeeper.SetAccount(s.ctx, vaultAcct) - - return addr, vaultAcct +func (s *TestSuite) TestKeeper_MigrateFlattenMixedDenomVaults() { + underlying := "ylds" + payment := "usdc" + + runMigration := func() { + s.Require().NoError(keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx), "flatten migration should succeed") } - vaultAddrA, _ := createVault("vaultsharesA", "uylds.fcc", "") - vaultAddrB, _ := createVault("vaultsharesB", "uusdc", "custompay") - - nonVaultAddr := sdk.AccAddress([]byte("non-vault-account-addr____")) - nonVault := s.simApp.AccountKeeper.NewAccountWithAddress(s.ctx, nonVaultAddr) - s.simApp.AccountKeeper.SetAccount(s.ctx, nonVault) - - err := s.simApp.VaultKeeper.MigrateVaultAccountPaymentDenomDefaults(s.ctx) - s.Require().NoError(err, "migration should not return an error") - - gotA := s.simApp.AccountKeeper.GetAccount(s.ctx, vaultAddrA) - s.Require().NotNil(gotA, "vault A account should exist after migration") - gotVaultA, ok := gotA.(*types.VaultAccount) - s.Require().True(ok, "vault A account should be a VaultAccount type") - s.Require().Equal("uylds.fcc", gotVaultA.PaymentDenom, "vault A PaymentDenom should default to UnderlyingAsset when empty") - - gotB := s.simApp.AccountKeeper.GetAccount(s.ctx, vaultAddrB) - s.Require().NotNil(gotB, "vault B account should exist after migration") - gotVaultB, ok := gotB.(*types.VaultAccount) - s.Require().True(ok, "vault B account should be a VaultAccount type") - s.Require().Equal("custompay", gotVaultB.PaymentDenom, "vault B PaymentDenom should remain unchanged when already set") - - gotNonVault := s.simApp.AccountKeeper.GetAccount(s.ctx, nonVaultAddr) - s.Require().NotNil(gotNonVault, "non-vault account should still exist after migration") - _, ok = gotNonVault.(*types.VaultAccount) - s.Require().False(ok, "non-vault account should not be converted to a VaultAccount during migration") - - err = s.simApp.VaultKeeper.MigrateVaultAccountPaymentDenomDefaults(s.ctx) - s.Require().NoError(err, "migration should be idempotent and not error when run a second time") - - gotA2 := s.simApp.AccountKeeper.GetAccount(s.ctx, vaultAddrA) - s.Require().NotNil(gotA2, "vault A account should still exist after second migration run") - gotVaultA2, ok := gotA2.(*types.VaultAccount) - s.Require().True(ok, "vault A account should still be a VaultAccount type after second migration run") - s.Require().Equal("uylds.fcc", gotVaultA2.PaymentDenom, "vault A PaymentDenom should remain set to UnderlyingAsset after second migration run") -} + getVault := func(addr sdk.AccAddress) *types.VaultAccount { + acct := s.simApp.AccountKeeper.GetAccount(s.ctx, addr) + s.Require().NotNil(acct, "vault account should exist after migration") + vault, ok := acct.(*types.VaultAccount) + s.Require().True(ok, "account at %s should be a VaultAccount", addr) + return vault + } -// TestKeeper_MigrateInternalNAVSeedFromMarker exercises the migration that seeds -// the Internal NAV table from Marker NAVs for vaults whose payment_denom differs -// from underlying_asset. Each subtest sets up a fresh fleet so cross-test state -// from the suite-level SetupTest does not leak between cases. -func (s *TestSuite) TestKeeper_MigrateInternalNAVSeedFromMarker() { - s.Run("forward marker NAV seeds internal NAV", func() { + s.Run("unpaused mixed vault with outstanding shares flattens in place", func() { s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare1" - - vault := s.setupLegacyPaymentDenomVault(underlying, share, payment, 3, 2) - - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration should succeed when forward marker NAV exists") - - got, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "internal NAV entry should be seeded for payment denom") - s.Require().Equal(payment, got.Denom, "internal NAV denom should be payment denom") - s.Require().Equal(underlying, got.Price.Denom, "internal NAV price denom should be underlying") - s.Require().Equal(sdkmath.NewInt(3), got.Price.Amount, "internal NAV price amount should be forward marker price amount") - s.Require().Equal(sdkmath.NewInt(2), got.Volume, "internal NAV volume should be forward marker volume") - s.Require().Equal(keeper.MigrationNAVSeedSource, got.Source, "internal NAV source should mark this entry as a migration seed") - }) + legacy := s.createLegacyVaultAccount("vsharemixed", underlying, payment) + legacy.TotalShares = sdk.NewCoin("vsharemixed", sdkmath.NewInt(999_748_457_017)) + legacy.OutstandingAumFee = sdk.Coin{Denom: "", Amount: sdkmath.ZeroInt()} + s.simApp.AccountKeeper.SetAccount(s.ctx, legacy) - s.Run("reverse marker NAV seeds internal NAV when only reverse exists", func() { - s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare2" + nonVaultAddr := sdk.AccAddress([]byte("non-vault-account-addr____")) + s.simApp.AccountKeeper.SetAccount(s.ctx, s.simApp.AccountKeeper.NewAccountWithAddress(s.ctx, nonVaultAddr)) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 2_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 2_000_000), s.adminAddr) - vault := s.createLegacyVaultAccount(share, underlying, payment) - s.setReverseNAV(underlying, payment, 5, 7) - - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration should succeed when only reverse marker NAV exists") - - got, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "internal NAV entry should be seeded for payment denom") - s.Require().Equal(payment, got.Denom, "internal NAV denom should be payment denom") - s.Require().Equal(underlying, got.Price.Denom, "internal NAV price denom should be underlying") - s.Require().Equal(sdkmath.NewInt(7), got.Price.Amount, "reverse marker volume should become internal NAV price amount") - s.Require().Equal(sdkmath.NewInt(5), got.Volume, "reverse marker price amount should become internal NAV volume") - }) + runMigration() - s.Run("newer reverse NAV wins when both directions exist", func() { - s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare3" + got := getVault(legacy.GetAddress()) + s.Equal(underlying, got.PaymentDenom, "payment denom should collapse onto the underlying asset") + s.Equal(sdk.NewCoin(underlying, sdkmath.ZeroInt()), got.OutstandingAumFee, "empty outstanding AUM fee should normalize to the zero coin of the underlying") + s.Equal(sdkmath.NewInt(999_748_457_017), got.TotalShares.Amount, "total shares of record must be preserved by the flatten") + s.False(got.Paused, "an unpaused vault should stay unpaused through the flatten") - vault := s.setupLegacyPaymentDenomVault(underlying, share, payment, 3, 2) - s.bumpHeight() - s.setReverseNAV(underlying, payment, 11, 5) + gotNonVault := s.simApp.AccountKeeper.GetAccount(s.ctx, nonVaultAddr) + s.Require().NotNil(gotNonVault, "non-vault account should still exist after migration") + _, isVault := gotNonVault.(*types.VaultAccount) + s.False(isVault, "non-vault account must not be converted by the migration") - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration should succeed when both directions exist") - - got, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "internal NAV entry should be seeded") - s.Require().Equal(sdkmath.NewInt(5), got.Price.Amount, "newer reverse volume should become internal NAV price amount") - s.Require().Equal(sdkmath.NewInt(11), got.Volume, "newer reverse price amount should become internal NAV volume") + runMigration() + got = getVault(legacy.GetAddress()) + s.Equal(underlying, got.PaymentDenom, "second run should be idempotent: payment denom stays flattened") }) - s.Run("payment equals underlying skips seeding but defaults nav_authority", func() { + s.Run("paused mixed vault keeps pause state and paused balance snapshot", func() { s.SetupTest() - underlying := "ylds" - share := "vshare4" + legacy := s.createLegacyVaultAccount("vsharepaused", underlying, payment) + legacy.Paused = true + legacy.PausedReason = "withdraw interest funds" + legacy.PausedBalance = sdk.NewCoin(underlying, sdkmath.NewInt(69_526_395)) + s.simApp.AccountKeeper.SetAccount(s.ctx, legacy) + + runMigration() - vault := s.setupBaseVault(underlying, share) - vault.NavAuthority = "" - s.simApp.AccountKeeper.SetAccount(s.ctx, vault) + got := getVault(legacy.GetAddress()) + s.Equal(underlying, got.PaymentDenom, "payment denom should collapse onto the underlying asset") + s.True(got.Paused, "pause state must survive the flatten") + s.Equal("withdraw interest funds", got.PausedReason, "pause reason must survive the flatten") + s.Equal(sdkmath.NewInt(69_526_395), got.PausedBalance.Amount, "paused balance snapshot must survive the flatten") + }) - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration should succeed when payment equals underlying") + s.Run("nav authority defaults to admin when unset", func() { + s.SetupTest() + legacy := s.createLegacyVaultAccount("vsharenavauth", underlying, payment) + legacy.NavAuthority = "" + s.simApp.AccountKeeper.SetAccount(s.ctx, legacy) - has, err := s.simApp.VaultKeeper.NAVs.Has(s.ctx, collections.Join(vault.GetAddress(), vault.PaymentDenom)) - s.Require().NoError(err, "internal NAV lookup should not error") - s.Require().False(has, "no internal NAV entry should be created when payment == underlying") + runMigration() - got, err := s.simApp.VaultKeeper.GetVault(s.ctx, vault.GetAddress()) - s.Require().NoError(err, "should fetch vault after migration") - s.Require().Equal(vault.Admin, got.NavAuthority, "nav_authority should default to admin when empty") + got := getVault(legacy.GetAddress()) + s.Equal(got.Admin, got.NavAuthority, "unset nav authority should default to the vault admin") }) - s.Run("uylds.fcc payment seeds a 1:1 internal NAV without marker NAV", func() { + s.Run("already-single-denom vault is untouched", func() { s.SetupTest() - underlying := "ylds" - payment := "uylds.fcc" - share := "vshare5" + conforming := s.createLegacyVaultAccount("vsharesingle", underlying, underlying) + conforming.OutstandingAumFee = sdk.NewCoin(underlying, sdkmath.ZeroInt()) + s.simApp.AccountKeeper.SetAccount(s.ctx, conforming) + before := *getVault(conforming.GetAddress()) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 2_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 2_000_000), s.adminAddr) - vault := s.createLegacyVaultAccount(share, underlying, payment) - - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration must not error on uylds.fcc peg vault even without marker NAV") - - got, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "1:1 internal NAV entry should be seeded for uylds.fcc payment peg vault") - s.Require().Equal(payment, got.Denom, "1:1 NAV denom should be payment denom") - s.Require().Equal(underlying, got.Price.Denom, "1:1 NAV price denom should be underlying") - s.Require().Equal(sdkmath.OneInt(), got.Price.Amount, "1:1 NAV price amount should be one") - s.Require().Equal(sdkmath.OneInt(), got.Volume, "1:1 NAV volume should be one") - s.Require().Equal(keeper.MigrationNAVSeedSource, got.Source, "1:1 NAV source should mark this entry as a migration seed") + runMigration() + + after := *getVault(conforming.GetAddress()) + s.Equal(before, after, "a vault already flattened must not be modified by the migration") }) - s.Run("uylds.fcc underlying seeds a 1:1 internal NAV without marker NAV", func() { + s.Run("non-zero outstanding AUM fee converts through the internal NAV table", func() { s.SetupTest() - underlying := "uylds.fcc" - payment := "usdc" - share := "vshare6" - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 2_000_000), s.adminAddr) s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 2_000_000), s.adminAddr) - vault := s.createLegacyVaultAccount(share, underlying, payment) + legacy := s.createLegacyVaultAccount("vsharefeenav", underlying, payment) + legacy.OutstandingAumFee = sdk.NewCoin(payment, sdkmath.NewInt(10)) + s.simApp.AccountKeeper.SetAccount(s.ctx, legacy) - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration must not error on uylds.fcc peg vault even without marker NAV") + nav := types.NewVaultNAV(payment, sdk.NewInt64Coin(underlying, 2), sdkmath.OneInt(), "test") + s.Require().NoError(s.simApp.VaultKeeper.SetVaultNAV(s.ctx, legacy, nav, legacy.Admin), "seeding a payment-denom NAV entry must succeed") - got, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "1:1 internal NAV entry should be seeded for uylds.fcc underlying peg vault") - s.Require().Equal(payment, got.Denom, "1:1 NAV denom should be payment denom") - s.Require().Equal(underlying, got.Price.Denom, "1:1 NAV price denom should be underlying") - s.Require().Equal(sdkmath.OneInt(), got.Price.Amount, "1:1 NAV price amount should be one") - s.Require().Equal(sdkmath.OneInt(), got.Volume, "1:1 NAV volume should be one") + runMigration() + + got := getVault(legacy.GetAddress()) + s.Equal(sdk.NewCoin(underlying, sdkmath.NewInt(20)), got.OutstandingAumFee, "10%s at 2%s each should re-denominate to 20%s", payment, underlying, underlying) }) - s.Run("missing marker NAV fails migration loudly with vault id", func() { + s.Run("non-zero outstanding AUM fee with no NAV price is zeroed rather than halting", func() { s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare7" + legacy := s.createLegacyVaultAccount("vsharefeezero", underlying, payment) + legacy.OutstandingAumFee = sdk.NewCoin(payment, sdkmath.NewInt(10)) + s.simApp.AccountKeeper.SetAccount(s.ctx, legacy) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 2_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 2_000_000), s.adminAddr) - vault := s.createLegacyVaultAccount(share, underlying, payment) + runMigration() - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().Error(err, "migration must fail when no marker NAV exists for a non-peg vault") - s.Require().Contains(err.Error(), vault.Address, "error message should name the unpriced vault") - s.Require().Contains(err.Error(), "no marker NAV available", "error message should explain the cause") + got := getVault(legacy.GetAddress()) + s.Equal(sdk.NewCoin(underlying, sdkmath.ZeroInt()), got.OutstandingAumFee, "an unpriceable fee should be zeroed in the underlying, never failing the upgrade") }) - s.Run("preserves pre-existing internal NAV entries", func() { + s.Run("pending swap-outs in the old payment denom are rewritten to the underlying", func() { s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare8" - - vault := s.setupLegacyPaymentDenomVault(underlying, share, payment, 3, 2) - - existing := types.VaultNAV{ - Denom: payment, - Price: sdk.NewInt64Coin(underlying, 99), - Volume: sdkmath.NewInt(100), - Source: "operator-supplied", - } - s.Require().NoError(s.simApp.VaultKeeper.SetVaultNAV(s.ctx, vault, existing, vault.Admin), "seeding existing NAV must succeed") - - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration should succeed when pre-existing NAV entry exists") - - got, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "internal NAV entry should still be present after re-run") - s.Require().Equal(sdkmath.NewInt(99), got.Price.Amount, "pre-existing internal NAV price must not be overwritten") - s.Require().Equal(sdkmath.NewInt(100), got.Volume, "pre-existing internal NAV volume must not be overwritten") - s.Require().Equal("operator-supplied", got.Source, "pre-existing internal NAV source must not be overwritten") - }) + legacy := s.createLegacyVaultAccount("vshareswaps", underlying, payment) + owner := sdk.AccAddress([]byte("swap-out-owner-addr_______")) + shares := sdk.NewCoin("vshareswaps", sdkmath.NewInt(100)) - s.Run("migration is idempotent across consecutive runs", func() { - s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare9" - - vault := s.setupLegacyPaymentDenomVault(underlying, share, payment, 3, 2) - - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "first migration run should succeed") - first, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "seeded NAV should be readable after first run") - - err = keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "second migration run should succeed") - second, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "seeded NAV should still be readable after second run") - s.Require().Equal(first, second, "internal NAV should not change between consecutive migration runs") - }) + mixedReq := types.NewPendingSwapOut(owner, legacy.GetAddress(), shares, payment) + mixedID, err := s.simApp.VaultKeeper.PendingSwapOutQueue.Enqueue(s.ctx, 1_000, &mixedReq) + s.Require().NoError(err, "enqueueing a payment-denom swap-out fixture must succeed") - s.Run("nav_authority is left intact when already set", func() { - s.SetupTest() - underlying := "ylds" - share := "vshare10" + conformingReq := types.NewPendingSwapOut(owner, legacy.GetAddress(), shares, underlying) + conformingID, err := s.simApp.VaultKeeper.PendingSwapOutQueue.Enqueue(s.ctx, 2_000, &conformingReq) + s.Require().NoError(err, "enqueueing an underlying-denom swap-out fixture must succeed") - vault := s.setupBaseVault(underlying, share) - other := sdk.AccAddress([]byte("other-nav-authority_______")).String() - vault.NavAuthority = other - s.simApp.AccountKeeper.SetAccount(s.ctx, vault) + runMigration() - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration should succeed for identity-denom vault with nav_authority set") + gotTime, gotMixed, err := s.simApp.VaultKeeper.PendingSwapOutQueue.GetByID(s.ctx, mixedID) + s.Require().NoError(err, "rewritten swap-out %d should still be readable by id", mixedID) + s.Equal(underlying, gotMixed.RedeemDenom, "payment-denom swap-out should redeem in the underlying after migration") + s.Equal(int64(1_000), gotTime, "rewritten swap-out must keep its payout timestamp") + s.Equal(shares, gotMixed.Shares, "rewritten swap-out must keep its escrowed shares") - got, err := s.simApp.VaultKeeper.GetVault(s.ctx, vault.GetAddress()) - s.Require().NoError(err, "should fetch vault after migration") - s.Require().Equal(other, got.NavAuthority, "non-empty nav_authority should not be overwritten") + _, gotConforming, err := s.simApp.VaultKeeper.PendingSwapOutQueue.GetByID(s.ctx, conformingID) + s.Require().NoError(err, "conforming swap-out %d should still be readable by id", conformingID) + s.Equal(underlying, gotConforming.RedeemDenom, "conforming swap-out should be left redeeming the underlying") }) - s.Run("mixed fleet processes each vault under its own rule", func() { + s.Run("pending swap-out with no vault account is skipped instead of failing the upgrade", func() { s.SetupTest() - // identity-denom vault: needs only nav_authority default. - identityUnderlying := "asset0" - identityShare := "share0" - identityVault := s.setupBaseVault(identityUnderlying, identityShare) - identityVault.NavAuthority = "" - s.simApp.AccountKeeper.SetAccount(s.ctx, identityVault) - - // uylds.fcc peg vault: must receive a 1:1 internal NAV entry. - pegUnderlying := "asset1" - pegPayment := "uylds.fcc" - pegShare := "share1" - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(pegUnderlying, 2_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(pegPayment, 2_000_000), s.adminAddr) - pegVault := s.createLegacyVaultAccount(pegShare, pegUnderlying, pegPayment) - - // mismatched-denom vault with forward NAV: must be seeded. - seededUnderlying := "asset2" - seededPayment := "asset2pay" - seededShare := "share2" - seededVault := s.setupLegacyPaymentDenomVault(seededUnderlying, seededShare, seededPayment, 3, 2) - - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "mixed-fleet migration should succeed") - - gotIdentity, err := s.simApp.VaultKeeper.GetVault(s.ctx, identityVault.GetAddress()) - s.Require().NoError(err, "identity vault should be readable") - s.Require().Equal(identityVault.Admin, gotIdentity.NavAuthority, "identity vault nav_authority should default to admin") - hasIdentityNAV, err := s.simApp.VaultKeeper.NAVs.Has(s.ctx, collections.Join(identityVault.GetAddress(), identityVault.PaymentDenom)) - s.Require().NoError(err, "identity vault NAV lookup should not error") - s.Require().False(hasIdentityNAV, "identity vault should not have an internal NAV entry") - - gotPegNAV, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(pegVault.GetAddress(), pegPayment)) - s.Require().NoError(err, "peg vault should have a 1:1 internal NAV entry") - s.Require().Equal(sdkmath.OneInt(), gotPegNAV.Price.Amount, "peg vault NAV price amount should be one") - s.Require().Equal(sdkmath.OneInt(), gotPegNAV.Volume, "peg vault NAV volume should be one") - s.Require().Equal(pegUnderlying, gotPegNAV.Price.Denom, "peg vault NAV price denom should be underlying") - - gotSeeded, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(seededVault.GetAddress(), seededPayment)) - s.Require().NoError(err, "seeded vault NAV should be readable") - s.Require().Equal(sdkmath.NewInt(3), gotSeeded.Price.Amount, "seeded vault price amount mismatch") - s.Require().Equal(sdkmath.NewInt(2), gotSeeded.Volume, "seeded vault volume mismatch") - }) + legacy := s.createLegacyVaultAccount("vshareorphan", underlying, payment) + owner := sdk.AccAddress([]byte("swap-out-owner-addr_______")) + orphanVaultAddr := types.GetVaultAddress("vsharemissing") - s.Run("migration emits EventNAVUpdated for each seeded entry", func() { - s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare11" - - vault := s.setupLegacyPaymentDenomVault(underlying, share, payment, 3, 2) - - em := sdk.NewEventManager() - s.ctx = s.ctx.WithEventManager(em) - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "migration should succeed") - - var saw bool - for _, ev := range normalizeEvents(em.Events()) { - if ev.Type != "provlabs.vault.v1.EventNAVUpdated" { - continue - } - if getAttribute(ev, "vault_address") == vault.Address && - getAttribute(ev, "denom") == payment { - saw = true - break - } - } - s.Require().True(saw, "expected EventNAVUpdated for vault=%s denom=%s", vault.Address, payment) - }) + orphanReq := types.NewPendingSwapOut(owner, orphanVaultAddr, sdk.NewCoin("vsharemissing", sdkmath.NewInt(50)), payment) + orphanID, err := s.simApp.VaultKeeper.PendingSwapOutQueue.Enqueue(s.ctx, 1_000, &orphanReq) + s.Require().NoError(err, "enqueueing a swap-out for a non-existent vault must succeed") - s.Run("non-vault accounts are skipped", func() { - s.SetupTest() - other := sdk.AccAddress([]byte("plain-account_____________")) - s.simApp.AccountKeeper.SetAccount(s.ctx, s.simApp.AccountKeeper.NewAccountWithAddress(s.ctx, other)) - - // Mixed-fleet check that the migration walks past plain accounts. - underlying := "ylds" - payment := "usdc" - share := "vshare12" - vault := s.setupLegacyPaymentDenomVault(underlying, share, payment, 3, 2) - - err := keeper.NewMigrator(s.simApp.VaultKeeper).Migrate1to2(s.ctx) - s.Require().NoError(err, "non-vault accounts should not break migration") - - has, err := s.simApp.VaultKeeper.NAVs.Has(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "internal NAV lookup should not error") - s.Require().True(has, "vault should still be seeded when an unrelated account exists") - - gotOther := s.simApp.AccountKeeper.GetAccount(s.ctx, other) - s.Require().NotNil(gotOther, "non-vault account should still exist after migration") - _, ok := gotOther.(*types.VaultAccount) - s.Require().False(ok, "non-vault account should not be converted by migration") + mixedReq := types.NewPendingSwapOut(owner, legacy.GetAddress(), sdk.NewCoin("vshareorphan", sdkmath.NewInt(100)), payment) + mixedID, err := s.simApp.VaultKeeper.PendingSwapOutQueue.Enqueue(s.ctx, 2_000, &mixedReq) + s.Require().NoError(err, "enqueueing a payment-denom swap-out fixture must succeed") + + runMigration() + + _, gotOrphan, err := s.simApp.VaultKeeper.PendingSwapOutQueue.GetByID(s.ctx, orphanID) + s.Require().NoError(err, "orphaned swap-out %d should still be readable by id", orphanID) + s.Equal(payment, gotOrphan.RedeemDenom, "orphaned swap-out should be left untouched for queue processing to dequeue") + + _, gotMixed, err := s.simApp.VaultKeeper.PendingSwapOutQueue.GetByID(s.ctx, mixedID) + s.Require().NoError(err, "rewritten swap-out %d should still be readable by id", mixedID) + s.Equal(underlying, gotMixed.RedeemDenom, "the walk must continue past the orphan and still rewrite mixed-denom entries") }) } -// TestVaultModule_RunMigrations exercises the registered v1->v2 migration -// end-to-end through the SDK module manager, the same path an upstream upgrade -// handler uses via runModuleMigrations / app.mm.RunMigrations. The first -// subtest fails if module.go stops calling cfg.RegisterMigration for vault -// v1->v2: in that case RunMigrations returns "no migrations found for module -// vault" and the version map advance never happens. func (s *TestSuite) TestVaultModule_RunMigrations() { - s.Run("vault pinned to v1 runs the registered v1->v2 migration and seeds internal NAV", func() { + underlying := "ylds" + payment := "usdc" + + s.Run("vault pinned to v1 runs the registered v1->v2 flatten migration", func() { s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare-mm-v1" - vault := s.setupLegacyPaymentDenomVault(underlying, share, payment, 3, 2) + legacy := s.createLegacyVaultAccount("vsharemmv1", underlying, payment) fromVM := s.simApp.ModuleManager.GetVersionMap() fromVM[types.ModuleName] = 1 newVM, err := s.simApp.ModuleManager.RunMigrations(s.ctx, s.simApp.Configurator(), fromVM) - s.Require().NoError(err, "RunMigrations must succeed; vault v1->v2 handler must be registered for vault %s", vault.Address) + s.Require().NoError(err, "RunMigrations must succeed; vault v1->v2 handler must be registered for vault %s", legacy.Address) s.Require().Equal(uint64(2), newVM[types.ModuleName], "vault module version should advance to ConsensusVersion 2") - got, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "internal NAV should be seeded for vault %s denom %s by the v1->v2 migration", vault.Address, payment) - s.Equal(payment, got.Denom, "seeded NAV denom should be payment denom %s", payment) - s.Equal(underlying, got.Price.Denom, "seeded NAV price denom should be underlying %s", underlying) - s.Equal(sdkmath.NewInt(3), got.Price.Amount, "seeded NAV price amount should match forward marker price for vault %s", vault.Address) - s.Equal(sdkmath.NewInt(2), got.Volume, "seeded NAV volume should match forward marker volume for vault %s", vault.Address) - s.Equal(keeper.MigrationNAVSeedSource, got.Source, "seeded NAV source should mark this entry as a migration seed for vault %s", vault.Address) + acct := s.simApp.AccountKeeper.GetAccount(s.ctx, legacy.GetAddress()) + got, ok := acct.(*types.VaultAccount) + s.Require().True(ok, "account at %s should remain a VaultAccount", legacy.Address) + s.Equal(underlying, got.PaymentDenom, "the v1->v2 migration should flatten the mixed vault %s", legacy.Address) + + _, err = s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(legacy.GetAddress(), payment)) + s.Require().ErrorIs(err, collections.ErrNotFound, "the flatten migration must not seed internal NAV entries") }) - s.Run("version map already at current ConsensusVersion is a no-op and preserves operator-supplied NAV", func() { + s.Run("version map already at current ConsensusVersion is a no-op", func() { s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare-mm-noop" - vault := s.setupLegacyPaymentDenomVault(underlying, share, payment, 3, 2) - - existing := types.VaultNAV{ - Denom: payment, - Price: sdk.NewInt64Coin(underlying, 99), - Volume: sdkmath.NewInt(100), - Source: "operator-supplied", - } - s.Require().NoError(s.simApp.VaultKeeper.SetVaultNAV(s.ctx, vault, existing, vault.Admin), "seeding operator-supplied NAV must succeed for vault %s", vault.Address) + legacy := s.createLegacyVaultAccount("vsharemmnoop", underlying, payment) fromVM := s.simApp.ModuleManager.GetVersionMap() newVM, err := s.simApp.ModuleManager.RunMigrations(s.ctx, s.simApp.Configurator(), fromVM) - s.Require().NoError(err, "RunMigrations should succeed when versions match for vault %s", vault.Address) + s.Require().NoError(err, "RunMigrations should succeed when versions match") s.Require().Equal(fromVM[types.ModuleName], newVM[types.ModuleName], "vault module version should remain unchanged") - got, err := s.simApp.VaultKeeper.NAVs.Get(s.ctx, collections.Join(vault.GetAddress(), payment)) - s.Require().NoError(err, "operator-supplied NAV should still be readable for vault %s denom %s", vault.Address, payment) - s.Equal(sdkmath.NewInt(99), got.Price.Amount, "operator-supplied NAV price must not be overwritten for vault %s", vault.Address) - s.Equal(sdkmath.NewInt(100), got.Volume, "operator-supplied NAV volume must not be overwritten for vault %s", vault.Address) - s.Equal("operator-supplied", got.Source, "operator-supplied NAV source must not be overwritten for vault %s", vault.Address) - }) - - s.Run("RunMigrations surfaces the inner migration error when a vault has no marker NAV", func() { - s.SetupTest() - underlying := "ylds" - payment := "usdc" - share := "vshare-mm-err" - - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 2_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 2_000_000), s.adminAddr) - vault := s.createLegacyVaultAccount(share, underlying, payment) - - fromVM := s.simApp.ModuleManager.GetVersionMap() - fromVM[types.ModuleName] = 1 - - _, err := s.simApp.ModuleManager.RunMigrations(s.ctx, s.simApp.Configurator(), fromVM) - s.Require().Error(err, "RunMigrations should propagate the inner migration error for unpriceable vault %s", vault.Address) - s.ErrorContains(err, vault.Address, "propagated error should name the unpriceable vault") - s.ErrorContains(err, "no marker NAV available", "propagated error should explain the cause") + acct := s.simApp.AccountKeeper.GetAccount(s.ctx, legacy.GetAddress()) + got, ok := acct.(*types.VaultAccount) + s.Require().True(ok, "account at %s should remain a VaultAccount", legacy.Address) + s.Equal(payment, got.PaymentDenom, "a matching version map must not trigger the flatten") }) } diff --git a/keeper/migrator.go b/keeper/migrator.go index 113fbbb4..5f0d99b5 100644 --- a/keeper/migrator.go +++ b/keeper/migrator.go @@ -19,9 +19,12 @@ func NewMigrator(k *Keeper) Migrator { } // Migrate1to2 advances the vault module from ConsensusVersion 1 to 2 by -// seeding the Internal NAV table from Marker NAVs and defaulting nav_authority -// to the vault admin when unset. The work is delegated to the unexported -// migrateInternalNAVSeedFromMarker, which is idempotent across retries. +// flattening every vault to single-denom: payment denoms collapse onto the +// underlying asset, outstanding AUM fees are re-denominated into the +// underlying, pending swap-outs redeem in the underlying, and nav_authority +// defaults to the vault admin when unset. The work is delegated to the +// unexported migrateFlattenMixedDenomVaults, which is idempotent across +// retries. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return m.keeper.migrateInternalNAVSeedFromMarker(ctx) + return m.keeper.migrateFlattenMixedDenomVaults(ctx) } diff --git a/keeper/msg_server.go b/keeper/msg_server.go index 066ce431..50e96871 100644 --- a/keeper/msg_server.go +++ b/keeper/msg_server.go @@ -90,7 +90,7 @@ func (k msgServer) SwapOut(goCtx context.Context, msg *types.MsgSwapOutRequest) vaultAddr := sdk.MustAccAddressFromBech32(msg.VaultAddress) ownerAddr := sdk.MustAccAddressFromBech32(msg.Owner) - requestID, err := k.Keeper.SwapOut(ctx, vaultAddr, ownerAddr, msg.Assets, msg.RedeemDenom) + requestID, err := k.Keeper.SwapOut(ctx, vaultAddr, ownerAddr, msg.Assets) if err != nil { return nil, fmt.Errorf("failed to swap out: %w", err) } @@ -892,7 +892,7 @@ func (k msgServer) UpdateNAVAuthority(goCtx context.Context, msg *types.MsgUpdat } // AcceptAsset settles a pending exchange-module payment whose target is the vault, -// exchanging an external asset for the vault's payment denom. Only the vault's asset +// exchanging an external asset for the vault's underlying asset. Only the vault's asset // manager may sign it; the admin cannot settle. // // The exchange module's AcceptPayment operates on the caller's primary account, so the @@ -903,7 +903,7 @@ func (k msgServer) UpdateNAVAuthority(goCtx context.Context, msg *types.MsgUpdat // // All steps run in the message handler; any failure reverts the whole transaction. The // settlement direction (inbound or outbound) is derived from which payment leg carries -// the vault's payment denom. +// the vault's underlying asset. func (k msgServer) AcceptAsset(goCtx context.Context, msg *types.MsgAcceptAssetRequest) (*types.MsgAcceptAssetResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) @@ -936,9 +936,9 @@ func (k msgServer) AcceptAsset(goCtx context.Context, msg *types.MsgAcceptAssetR return nil, err } - assetCoin, paymentCoin, err := settlementLegCoins(payment, direction, vault.PaymentDenom) + assetCoin, paymentCoin, err := settlementLegCoins(payment, direction, vault.UnderlyingAsset) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to resolve settlement leg coins: %w", err) } if err := k.checkSettlementNAVGuardrail(ctx, vault, assetCoin, paymentCoin); err != nil { return nil, err @@ -1003,30 +1003,30 @@ func (k msgServer) RejectAsset(goCtx context.Context, msg *types.MsgRejectAssetR } // assetSettlementDirection determines whether a payment settles inbound or outbound for a -// vault, based on which leg carries the vault's payment denom. The vault settles payments -// where its payment denom is exactly one of the two legs: it pays the payment denom out -// (inbound, target leg) or receives it in (outbound, source leg). A payment with the -// payment denom on both legs cannot be settled. +// vault, based on which leg carries the vault's underlying asset. The vault settles +// payments where its underlying asset is exactly one of the two legs: it pays the +// underlying out (inbound, target leg) or receives it in (outbound, source leg). A payment +// with the underlying on both legs cannot be settled. // -// A zero-priced asset carries the payment denom on neither leg (the zero coin is stripped), +// A zero-priced asset carries the underlying on neither leg (the zero coin is stripped), // so direction is inferred from the leg holding the asset: an asset on the source leg moves // into the vault (inbound), an asset on the target leg moves out (outbound). A zero-priced // payment with an asset on both legs, or on neither, cannot be settled. func assetSettlementDirection(vault *types.VaultAccount, payment *exchange.Payment) (string, error) { - paymentDenom := vault.PaymentDenom - sourceHasPayment := payment.SourceAmount.AmountOf(paymentDenom).IsPositive() - targetHasPayment := payment.TargetAmount.AmountOf(paymentDenom).IsPositive() + underlying := vault.UnderlyingAsset + sourceHasUnderlying := payment.SourceAmount.AmountOf(underlying).IsPositive() + targetHasUnderlying := payment.TargetAmount.AmountOf(underlying).IsPositive() switch { - case targetHasPayment && !sourceHasPayment: + case targetHasUnderlying && !sourceHasUnderlying: return types.AssetDirectionInbound, nil - case sourceHasPayment && !targetHasPayment: + case sourceHasUnderlying && !targetHasUnderlying: return types.AssetDirectionOutbound, nil - case sourceHasPayment && targetHasPayment: - return "", fmt.Errorf("payment must carry vault payment denom %q on exactly one leg: source_amount=%q target_amount=%q", paymentDenom, payment.SourceAmount, payment.TargetAmount) + case sourceHasUnderlying && targetHasUnderlying: + return "", fmt.Errorf("payment must carry vault underlying asset %q on exactly one leg: source_amount=%q target_amount=%q", underlying, payment.SourceAmount, payment.TargetAmount) } - // Neither leg carries the payment denom: a zero-priced settlement. Infer direction + // Neither leg carries the underlying asset: a zero-priced settlement. Infer direction // from the leg holding the asset. switch { case payment.TargetAmount.IsZero() && !payment.SourceAmount.IsZero(): diff --git a/keeper/msg_server_security_test.go b/keeper/msg_server_security_test.go index 3490a5cd..502b2370 100644 --- a/keeper/msg_server_security_test.go +++ b/keeper/msg_server_security_test.go @@ -84,7 +84,7 @@ func (s *TestSuite) TestMsgServer_SmallFirstSwapIn_HugeDonation_SwapOut() { s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) s.ctx = s.ctx.WithBlockTime(time.Now()) sharesToBurn := sdk.NewCoin(shareDenom, respIn.Amount) - _, err = s.k.SwapOut(s.ctx, vaultAddr, owner, sharesToBurn, "") + _, err = s.k.SwapOut(s.ctx, vaultAddr, owner, sharesToBurn) s.Require().NoError(err, "swap-out of all tiny depositor shares should succeed") s.simApp.VaultKeeper.TestAccessor_processPendingSwapOuts(s.T(), s.ctx, keeper.MaxSwapOutBatchSize) diff --git a/keeper/msg_server_test.go b/keeper/msg_server_test.go index 7b9e0a43..322dd311 100644 --- a/keeper/msg_server_test.go +++ b/keeper/msg_server_test.go @@ -977,7 +977,7 @@ func (s *TestSuite) TestMsgServer_ToggleSwapOut() { }, expectedErrSubstrs: []string{ "failed to set swap out enable", - "invalid payment denom: \"!TABLES!\": invalid denom: !TABLES!", + "must be empty or equal underlying asset", }, }, } @@ -1747,7 +1747,7 @@ func (s *TestSuite) TestMsgServer_ToggleSwapIn() { }, expectedErrSubstrs: []string{ "failed to set swap in enable", - "invalid payment denom: \"!TABLES!\": invalid denom: !TABLES!", + "must be empty or equal underlying asset", }, }, } @@ -4448,16 +4448,11 @@ func (s *TestSuite) TestMsgServer_PauseVault_ForceVsStrict() { } brokenTVVSetup := func() (sdk.AccAddress, string) { - underlying := "ylds" - share := "vshare" - payment := "usdc" - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 1_000_000), s.adminAddr) - vault := s.setupBaseVault(underlying, share, payment) - s.Require().NoError(s.k.NAVs.Remove(s.ctx, collections.Join(vault.GetAddress(), payment)), - "removing the bootstrap payment NAV should surface the conversion failure") - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, vault.PrincipalMarkerAddress(), - sdk.NewCoins(sdk.NewInt64Coin(payment, 10))), - "funding the principal with an unpriced accepted denom should make TVV conversion error") + vault, _, underlying, heldDenom := s.setupOversizedNAVVault() + s.seedOversizedNAV(vault, heldDenom, underlying, maxValidNAVPrice(), math.OneInt()) + s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), + sdk.NewCoins(sdk.NewInt64Coin(heldDenom, 2))), + "funding the principal with a held asset priced at the 256-bit ceiling should make TVV conversion overflow") s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) return vault.GetAddress(), underlying } @@ -4954,7 +4949,6 @@ func (s *TestSuite) TestMsgServer_ToggleBridge() { vault.BridgeAddress = s.adminAddr.String() s.k.AuthKeeper.SetAccount(s.ctx, vault) s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) - } tc := msgServerTestCase[types.MsgToggleBridgeRequest, postCheckArgs]{ @@ -6248,19 +6242,22 @@ func (s *TestSuite) TestMsgServer_UpdateNAVAuthority_NoOpWhenUnchanged() { } func (s *TestSuite) TestMsgServer_AcceptAsset_Inbound() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" externalID := "p2p-inbound" - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - s.requireSimpleMarker(asset) - - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5))), "failed to fund principal with payment denom") - sourceAmount := sdk.NewCoins(sdk.NewInt64Coin(asset, 10)) - targetAmount := sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)) - s.createPayment(source, vaultAddr, sourceAmount, targetAmount, externalID) + targetAmount := sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)) + vault, principalAddr, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + assetMarker: asset, + fundSource: sourceAmount, + fundPrincipal: targetAmount, + sourceAmount: sourceAmount, + targetAmount: targetAmount, + externalID: externalID, + }) + vaultAddr := vault.GetAddress() s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) resp, err := keeper.NewMsgServer(s.simApp.VaultKeeper).AcceptAsset(s.ctx, &types.MsgAcceptAssetRequest{ @@ -6273,29 +6270,32 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Inbound() { s.Assert().Equal(&types.MsgAcceptAssetResponse{}, resp, "AcceptAsset inbound response") s.assertBalance(source, asset, sdkmath.NewInt(0)) - s.assertBalance(source, paymentDenom, sdkmath.NewInt(5)) + s.assertBalance(source, underlying, sdkmath.NewInt(5)) s.assertBalance(principalAddr, asset, sdkmath.NewInt(10)) - s.assertBalance(principalAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(principalAddr, underlying, sdkmath.NewInt(0)) s.assertBalance(vaultAddr, asset, sdkmath.NewInt(0)) - s.assertBalance(vaultAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(vaultAddr, underlying, sdkmath.NewInt(0)) s.requireTypedEventEmitted(types.NewEventAssetAccepted(vaultAddr.String(), source.String(), externalID, sourceAmount, targetAmount, types.AssetDirectionInbound)) } func (s *TestSuite) TestMsgServer_AcceptAsset_Outbound() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" externalID := "p2p-outbound" - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - s.requireSimpleMarker(asset) - - source := s.CreateAndFundAccount(sdk.NewInt64Coin(paymentDenom, 5)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10))), "failed to fund principal with asset") - - sourceAmount := sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)) + sourceAmount := sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)) targetAmount := sdk.NewCoins(sdk.NewInt64Coin(asset, 10)) - s.createPayment(source, vaultAddr, sourceAmount, targetAmount, externalID) + vault, principalAddr, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + assetMarker: asset, + fundSource: sourceAmount, + fundPrincipal: targetAmount, + sourceAmount: sourceAmount, + targetAmount: targetAmount, + externalID: externalID, + }) + vaultAddr := vault.GetAddress() s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) resp, err := keeper.NewMsgServer(s.simApp.VaultKeeper).AcceptAsset(s.ctx, &types.MsgAcceptAssetRequest{ @@ -6307,12 +6307,12 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Outbound() { s.Require().NoError(err, "AcceptAsset outbound should succeed") s.Assert().Equal(&types.MsgAcceptAssetResponse{}, resp, "AcceptAsset outbound response") - s.assertBalance(source, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(source, underlying, sdkmath.NewInt(0)) s.assertBalance(source, asset, sdkmath.NewInt(10)) s.assertBalance(principalAddr, asset, sdkmath.NewInt(0)) - s.assertBalance(principalAddr, paymentDenom, sdkmath.NewInt(5)) + s.assertBalance(principalAddr, underlying, sdkmath.NewInt(5)) s.assertBalance(vaultAddr, asset, sdkmath.NewInt(0)) - s.assertBalance(vaultAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(vaultAddr, underlying, sdkmath.NewInt(0)) s.requireTypedEventEmitted(types.NewEventAssetAccepted(vaultAddr.String(), source.String(), externalID, sourceAmount, targetAmount, types.AssetDirectionOutbound)) @@ -6323,19 +6323,22 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Outbound() { } func (s *TestSuite) TestMsgServer_AcceptAsset_ZeroPriceOutbound() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" externalID := "p2p-outbound-zero" - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - s.requireSimpleMarker(asset) - - source := s.CreateAndFundAccount(sdk.NewInt64Coin(underlying, 1)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10))), "failed to fund principal with asset") - sourceAmount := sdk.NewCoins() targetAmount := sdk.NewCoins(sdk.NewInt64Coin(asset, 10)) - s.createPayment(source, vaultAddr, sourceAmount, targetAmount, externalID) + vault, principalAddr, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + assetMarker: asset, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(underlying, 1)), + fundPrincipal: targetAmount, + sourceAmount: sourceAmount, + targetAmount: targetAmount, + externalID: externalID, + }) + vaultAddr := vault.GetAddress() s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) resp, err := keeper.NewMsgServer(s.simApp.VaultKeeper).AcceptAsset(s.ctx, &types.MsgAcceptAssetRequest{ @@ -6348,33 +6351,36 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_ZeroPriceOutbound() { s.Assert().Equal(&types.MsgAcceptAssetResponse{}, resp, "AcceptAsset zero-price outbound response") s.assertBalance(source, asset, sdkmath.NewInt(10)) - s.assertBalance(source, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(source, underlying, sdkmath.NewInt(1)) s.assertBalance(principalAddr, asset, sdkmath.NewInt(0)) - s.assertBalance(principalAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(principalAddr, underlying, sdkmath.NewInt(0)) s.assertBalance(vaultAddr, asset, sdkmath.NewInt(0)) - s.assertBalance(vaultAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(vaultAddr, underlying, sdkmath.NewInt(0)) s.requireTypedEventEmitted(types.NewEventAssetAccepted(vaultAddr.String(), source.String(), externalID, sourceAmount, targetAmount, types.AssetDirectionOutbound)) - drainedNAV := types.NewVaultNAV(asset, sdk.NewInt64Coin(paymentDenom, 0), targetAmount[0].Amount, vaultAddr.String()) + drainedNAV := types.NewVaultNAV(asset, sdk.NewInt64Coin(underlying, 0), targetAmount[0].Amount, vaultAddr.String()) s.requireTypedEventEmitted(types.NewEventNAVRemoved(vaultAddr.String(), drainedNAV)) _, err = s.k.GetVaultNAV(s.ctx, vaultAddr, asset) s.Assert().ErrorIs(err, collections.ErrNotFound, "NAV entry for %s should be removed after the draining zero-price outbound settlement", asset) } func (s *TestSuite) TestMsgServer_AcceptAsset_ZeroPriceInbound() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" externalID := "p2p-inbound-zero" - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - s.requireSimpleMarker(asset) - - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - sourceAmount := sdk.NewCoins(sdk.NewInt64Coin(asset, 10)) targetAmount := sdk.NewCoins() - s.createPayment(source, vaultAddr, sourceAmount, targetAmount, externalID) + vault, principalAddr, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + assetMarker: asset, + fundSource: sourceAmount, + sourceAmount: sourceAmount, + targetAmount: targetAmount, + externalID: externalID, + }) + vaultAddr := vault.GetAddress() s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) resp, err := keeper.NewMsgServer(s.simApp.VaultKeeper).AcceptAsset(s.ctx, &types.MsgAcceptAssetRequest{ @@ -6387,22 +6393,22 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_ZeroPriceInbound() { s.Assert().Equal(&types.MsgAcceptAssetResponse{}, resp, "AcceptAsset zero-price inbound response") s.assertBalance(source, asset, sdkmath.NewInt(0)) - s.assertBalance(source, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(source, underlying, sdkmath.NewInt(0)) s.assertBalance(principalAddr, asset, sdkmath.NewInt(10)) - s.assertBalance(principalAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(principalAddr, underlying, sdkmath.NewInt(0)) s.assertBalance(vaultAddr, asset, sdkmath.NewInt(0)) - s.assertBalance(vaultAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(vaultAddr, underlying, sdkmath.NewInt(0)) s.requireTypedEventEmitted(types.NewEventAssetAccepted(vaultAddr.String(), source.String(), externalID, sourceAmount, targetAmount, types.AssetDirectionInbound)) stored, err := s.k.GetVaultNAV(s.ctx, vaultAddr, asset) s.Require().NoError(err, "NAV entry for %s should exist after the zero-price inbound settlement", asset) - s.Assert().Equal(sdk.NewInt64Coin(paymentDenom, 0), stored.Price, "stored NAV price should be the zero payment coin") + s.Assert().Equal(sdk.NewInt64Coin(underlying, 0), stored.Price, "stored NAV price should be the zero underlying coin") s.Assert().Equal(sourceAmount[0].Amount, stored.Volume, "stored NAV volume should be the asset amount") } func (s *TestSuite) TestMsgServer_AcceptAsset_RestrictedMarker() { - underlying, share, paymentDenom, restrictedDenom := "under", "vshare", "pay", "restrictedrwa" + underlying, share, restrictedDenom := "under", "vshare", "restrictedrwa" externalID := "p2p-restricted" tests := []struct { @@ -6433,9 +6439,9 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_RestrictedMarker() { defer func() { s.ctx = origCtx }() s.ctx, _ = s.ctx.CacheContext() - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, principalAddr := s.setupAssetSettlementVault(underlying, share) vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(underlying, 1)) + source := s.CreateAndFundAccount(sdk.NewInt64Coin("stake", 1)) grants := []markertypes.AccessGrant{ {Address: s.adminAddr.String(), Permissions: markertypes.AccessList{ @@ -6460,10 +6466,10 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_RestrictedMarker() { ) s.Require().NoError(s.simApp.MarkerKeeper.AddFinalizeAndActivateMarker(s.ctx, restrictedMarker), "failed to create restricted marker %s", restrictedDenom) s.Require().NoError(s.simApp.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, source, restrictedDenom, sdk.NewCoins(sdk.NewInt64Coin(restrictedDenom, 10))), "failed to fund source %s with restricted marker denom %s", source, restrictedDenom) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5))), "failed to fund principal %s with payment denom %s", principalAddr, paymentDenom) + s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(underlying, 5))), "failed to fund principal %s with underlying asset %s", principalAddr, underlying) sourceAmount := sdk.NewCoins(sdk.NewInt64Coin(restrictedDenom, 10)) - targetAmount := sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)) + targetAmount := sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)) s.createPayment(source, vaultAddr, sourceAmount, targetAmount, externalID) s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) @@ -6487,11 +6493,11 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_RestrictedMarker() { s.Assert().Equal(&types.MsgAcceptAssetResponse{}, resp, "AcceptAsset restricted marker response") s.assertBalance(source, restrictedDenom, sdkmath.NewInt(0)) - s.assertBalance(source, paymentDenom, sdkmath.NewInt(5)) + s.assertBalance(source, underlying, sdkmath.NewInt(5)) s.assertBalance(principalAddr, restrictedDenom, sdkmath.NewInt(10)) - s.assertBalance(principalAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(principalAddr, underlying, sdkmath.NewInt(0)) s.assertBalance(vaultAddr, restrictedDenom, sdkmath.NewInt(0)) - s.assertBalance(vaultAddr, paymentDenom, sdkmath.NewInt(0)) + s.assertBalance(vaultAddr, underlying, sdkmath.NewInt(0)) s.requireTypedEventEmitted(types.NewEventAssetAccepted(vaultAddr.String(), source.String(), externalID, sourceAmount, targetAmount, types.AssetDirectionInbound)) }) @@ -6499,7 +6505,7 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_RestrictedMarker() { } func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" tests := []struct { name string @@ -6524,15 +6530,19 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { { name: "unauthorized signer", setup: func() *types.MsgAcceptAssetRequest { - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: "unauth", + }) stranger := s.CreateAndFundAccount(sdk.NewInt64Coin(underlying, 1)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5))), "fund principal") - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "unauth") return &types.MsgAcceptAssetRequest{ Authority: stranger.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "unauth", } @@ -6542,14 +6552,18 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { { name: "admin cannot settle, only the asset manager may", setup: func() *types.MsgAcceptAssetRequest { - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5))), "fund principal") - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "admin-settle") + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: "admin-settle", + }) return &types.MsgAcceptAssetRequest{ Authority: s.adminAddr.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "admin-settle", } @@ -6559,7 +6573,15 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { { name: "vault without an asset manager cannot settle", setup: func() *types.MsgAcceptAssetRequest { - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: "no-mgr", + }) vaultAddr := vault.GetAddress() _, err := keeper.NewMsgServer(s.simApp.VaultKeeper).SetAssetManager(s.ctx, &types.MsgSetAssetManagerRequest{ Admin: s.adminAddr.String(), @@ -6567,9 +6589,6 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { AssetManager: "", }) s.Require().NoError(err, "failed to clear asset manager on vault %s", vaultAddr) - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5))), "fund principal") - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "no-mgr") return &types.MsgAcceptAssetRequest{ Authority: s.adminAddr.String(), VaultAddress: vaultAddr.String(), @@ -6582,12 +6601,15 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { { name: "payment not found", setup: func() *types.MsgAcceptAssetRequest { - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + omitPayment: true, + }) return &types.MsgAcceptAssetRequest{ Authority: s.assetManagerAddr.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "ghost", } @@ -6597,14 +6619,17 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { { name: "payment target mismatch", setup: func() *types.MsgAcceptAssetRequest { - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + omitPayment: true, + }) other := s.CreateAndFundAccount(sdk.NewInt64Coin(underlying, 1)) - s.createPayment(source, other, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "mismatch") + s.createPayment(source, other, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), "mismatch") return &types.MsgAcceptAssetRequest{ Authority: s.assetManagerAddr.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "mismatch", } @@ -6612,15 +6637,19 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { expectedErrSubstrs: []string{"is not vault"}, }, { - name: "payment denom on neither leg", + name: "underlying asset on neither leg", setup: func() *types.MsgAcceptAssetRequest { - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), "noleg") + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin("stake", 5)), + externalID: "noleg", + }) return &types.MsgAcceptAssetRequest{ Authority: s.assetManagerAddr.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "noleg", } @@ -6628,15 +6657,19 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { expectedErrSubstrs: []string{"exactly one leg"}, }, { - name: "payment denom on both legs", + name: "underlying asset on both legs", setup: func() *types.MsgAcceptAssetRequest { - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(paymentDenom, 5)) - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 3), sdk.NewInt64Coin(asset, 2)), "bothlegs") + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 3), sdk.NewInt64Coin(asset, 2)), + externalID: "bothlegs", + }) return &types.MsgAcceptAssetRequest{ Authority: s.assetManagerAddr.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "bothlegs", } @@ -6646,14 +6679,18 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { { name: "insufficient principal balance", setup: func() *types.MsgAcceptAssetRequest { - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 4))), "fund principal short") - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "short") + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 4)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: "short", + }) return &types.MsgAcceptAssetRequest{ Authority: s.assetManagerAddr.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "short", } @@ -6663,11 +6700,16 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { { name: "rejects settlement while vault is paused", setup: func() *types.MsgAcceptAssetRequest { - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: "paused", + }) vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5))), "fund principal") - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "paused") paused, err := s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err, "failed to get vault %s for paused setup", vaultAddr) paused.Paused = true @@ -6703,7 +6745,7 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Failures() { } func (s *TestSuite) TestMsgServer_AcceptAsset_NAVGuardrail() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" externalID := "guardrail" tests := []struct { @@ -6717,84 +6759,75 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_NAVGuardrail() { }{ { name: "inbound settlement at the exact NAV price passes the guardrail", - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 5), Volume: sdkmath.NewInt(10)}, + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 5), Volume: sdkmath.NewInt(10)}, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), }, { name: "inbound settlement off the NAV price is rejected", - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 6), Volume: sdkmath.NewInt(10)}, + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 6), Volume: sdkmath.NewInt(10)}, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), - expectedErrSubstrs: []string{"does not match internal NAV", "10rwacoin", "5pay", "6pay"}, + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + expectedErrSubstrs: []string{"does not match internal NAV", "10rwacoin", "5under", "6under"}, }, { name: "no NAV entry skips the guardrail for a first acquisition", fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), }, { name: "outbound settlement at the exact NAV price passes the guardrail", - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 5), Volume: sdkmath.NewInt(10)}, - fundSource: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 5), Volume: sdkmath.NewInt(10)}, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), targetAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), }, { name: "outbound settlement off the NAV price is rejected", - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 5), Volume: sdkmath.NewInt(10)}, - fundSource: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 4)), + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 5), Volume: sdkmath.NewInt(10)}, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(underlying, 4)), fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 4)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 4)), targetAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - expectedErrSubstrs: []string{"does not match internal NAV", "10rwacoin", "4pay", "5pay"}, + expectedErrSubstrs: []string{"does not match internal NAV", "10rwacoin", "4under", "5under"}, }, { name: "fractional NAV price that floor math would accept is rejected", - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 3), Volume: sdkmath.NewInt(2)}, + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 3), Volume: sdkmath.NewInt(2)}, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 3)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 4)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 4)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 3)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 4)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 4)), expectedErrSubstrs: []string{"does not match internal NAV"}, }, { name: "fractional NAV price settled at an exact multiple passes the guardrail", - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 3), Volume: sdkmath.NewInt(2)}, + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 3), Volume: sdkmath.NewInt(2)}, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 4)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 6)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 6)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 4)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 6)), - }, - { - name: "NAV priced in a denom other than the settlement payment is rejected", - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 5), Volume: sdkmath.NewInt(10)}, - fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), - sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), - expectedErrSubstrs: []string{"is priced in"}, + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 6)), }, { name: "asset leg with multiple coins cannot be priced and is rejected", fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10), sdk.NewInt64Coin("othercoin", 5)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10), sdk.NewInt64Coin("othercoin", 5)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), expectedErrSubstrs: []string{"one asset coin"}, }, { name: "empty asset leg cannot be priced and is rejected", - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), expectedErrSubstrs: []string{"one asset coin"}, }, } @@ -6808,7 +6841,6 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_NAVGuardrail() { vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ underlying: underlying, share: share, - paymentDenom: paymentDenom, assetMarker: asset, seedNav: tc.seedNav, fundSource: tc.fundSource, @@ -6844,7 +6876,6 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_NAVGuardrail() { func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV() { underlying := "under" share := "vshare" - paymentDenom := "pay" asset := "rwacoin" externalID := "settle-nav" @@ -6865,53 +6896,53 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV() { name: "inbound first acquisition seeds the internal NAV from the settlement price", registerAssetMarker: true, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), - expectedNavPrice: sdk.NewInt64Coin(paymentDenom, 5), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + expectedNavPrice: sdk.NewInt64Coin(underlying, 5), expectedNavVolume: sdkmath.NewInt(10), }, { name: "inbound settlement at the NAV price re-prices the entry from the settlement legs", registerAssetMarker: true, - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 1), Volume: sdkmath.NewInt(2)}, + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 1), Volume: sdkmath.NewInt(2)}, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 4)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 2)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 2)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 4)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 2)), - expectedNavPrice: sdk.NewInt64Coin(paymentDenom, 2), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 2)), + expectedNavPrice: sdk.NewInt64Coin(underlying, 2), expectedNavVolume: sdkmath.NewInt(4), }, { name: "fractional first acquisition stores the exact settlement price and volume", registerAssetMarker: true, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 3)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 10)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 10)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 3)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 10)), - expectedNavPrice: sdk.NewInt64Coin(paymentDenom, 10), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 10)), + expectedNavPrice: sdk.NewInt64Coin(underlying, 10), expectedNavVolume: sdkmath.NewInt(3), }, { name: "outbound settlement leaving a principal balance keeps the NAV entry", registerAssetMarker: true, - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 5), Volume: sdkmath.NewInt(10)}, - fundSource: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 5), Volume: sdkmath.NewInt(10)}, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(asset, 20)), - sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), targetAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - expectedNavPrice: sdk.NewInt64Coin(paymentDenom, 5), + expectedNavPrice: sdk.NewInt64Coin(underlying, 5), expectedNavVolume: sdkmath.NewInt(10), }, { name: "outbound settlement draining the principal removes the NAV entry", registerAssetMarker: true, - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 5), Volume: sdkmath.NewInt(10)}, - fundSource: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 5), Volume: sdkmath.NewInt(10)}, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), targetAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - expectedNavPrice: sdk.NewInt64Coin(paymentDenom, 5), + expectedNavPrice: sdk.NewInt64Coin(underlying, 5), expectedNavVolume: sdkmath.NewInt(10), expectNavRemoved: true, }, @@ -6919,9 +6950,9 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV() { name: "asset denom that is not a registered marker fails the settlement", registerAssetMarker: false, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), expectedErrContains: "is not a registered marker", }, } @@ -6939,7 +6970,6 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV() { vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ underlying: underlying, share: share, - paymentDenom: paymentDenom, assetMarker: assetMarker, seedNav: tc.seedNav, fundSource: tc.fundSource, @@ -7005,7 +7035,6 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV() { func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV_MetadataDenom() { underlying := "under" share := "vshare" - paymentDenom := "pay" asset := metadatatypes.ScopeMetadataAddress(uuid.MustParse("00000000-0000-4000-8000-000000000001")).Denom() externalID := "settle-nav-nft" @@ -7016,11 +7045,10 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV_MetadataDenom() { vault, principalAddr, source := s.setupAcceptAssetScenario(acceptAssetScenario{ underlying: underlying, share: share, - paymentDenom: paymentDenom, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), externalID: externalID, }) vaultAddr := vault.GetAddress() @@ -7036,7 +7064,7 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV_MetadataDenom() { stored, err := s.k.GetVaultNAV(s.ctx, vaultAddr, asset) s.Require().NoError(err, "internal NAV entry for nft/ denom %s should exist after settlement", asset) - s.Assert().Equal(sdk.NewInt64Coin(paymentDenom, 5), stored.Price, "stored NAV price for nft/ denom") + s.Assert().Equal(sdk.NewInt64Coin(underlying, 5), stored.Price, "stored NAV price for nft/ denom") s.Assert().Equal(sdkmath.NewInt(10), stored.Volume, "stored NAV volume for nft/ denom") s.Assert().Equal(vaultAddr.String(), stored.Source, "stored NAV source should be the vault address") s.requireTypedEventEmitted(types.NewEventNAVUpdated(vaultAddr.String(), stored, s.assetManagerAddr.String())) @@ -7049,8 +7077,8 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_SettlementNAV_MetadataDenom() { const secondID = "settle-nav-nft-2" s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, source, sdk.NewCoins(sdk.NewInt64Coin(asset, 10))), "fund source for second settlement") - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 6))), "fund principal for second settlement") - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 6)), secondID) + s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(underlying, 6))), "fund principal for second settlement") + s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(underlying, 6)), secondID) _, err = keeper.NewMsgServer(s.simApp.VaultKeeper).AcceptAsset(s.ctx, &types.MsgAcceptAssetRequest{ Authority: s.assetManagerAddr.String(), @@ -7102,7 +7130,6 @@ func (s *TestSuite) TestMsgServer_UpdateVaultNAV_MetadataDenom() { func (s *TestSuite) TestMsgServer_AcceptAsset_Reconcile() { underlying := "under" share := "vshare" - paymentDenom := "pay" asset := "rwacoin" externalID := "settle-reconcile" @@ -7121,7 +7148,7 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Reconcile() { { name: "settlement rejected by the NAV guardrail does not reconcile", interestRate: "4.20", - seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(paymentDenom, 9), Volume: sdkmath.NewInt(10)}, + seedNav: &types.VaultNAV{Denom: asset, Price: sdk.NewInt64Coin(underlying, 9), Volume: sdkmath.NewInt(10)}, expectedErrContains: "does not match internal NAV", expectedReconciles: 0, }, @@ -7142,13 +7169,12 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Reconcile() { vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ underlying: underlying, share: share, - paymentDenom: paymentDenom, assetMarker: asset, seedNav: tc.seedNav, fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), - targetAmount: sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), externalID: externalID, }) vaultAddr := vault.GetAddress() @@ -7195,16 +7221,20 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_Reconcile() { } func (s *TestSuite) TestMsgServer_AcceptAsset_InsufficientPrincipalDoesNotSettle() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" externalID := "short-noop" - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, principalAddr, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + fundPrincipal: sdk.NewCoins(sdk.NewInt64Coin(underlying, 4)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: externalID, + }) vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 4))), "fund principal short") - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), externalID) - _, err := keeper.NewMsgServer(s.simApp.VaultKeeper).AcceptAsset(s.ctx, &types.MsgAcceptAssetRequest{ Authority: s.assetManagerAddr.String(), VaultAddress: vaultAddr.String(), @@ -7217,19 +7247,23 @@ func (s *TestSuite) TestMsgServer_AcceptAsset_InsufficientPrincipalDoesNotSettle s.Require().NoError(getErr, "GetPayment after failed settle") s.Require().NotNil(stored, "payment should remain in escrow after a failed settle") s.assertBalance(source, asset, sdkmath.NewInt(10)) - s.assertBalance(principalAddr, paymentDenom, sdkmath.NewInt(4)) + s.assertBalance(principalAddr, underlying, sdkmath.NewInt(4)) } func (s *TestSuite) TestMsgServer_RejectAsset() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" externalID := "p2p-reject" - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: externalID, + }) vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), externalID) - s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) resp, err := keeper.NewMsgServer(s.simApp.VaultKeeper).RejectAsset(s.ctx, &types.MsgRejectAssetRequest{ Authority: s.assetManagerAddr.String(), @@ -7249,7 +7283,7 @@ func (s *TestSuite) TestMsgServer_RejectAsset() { } func (s *TestSuite) TestMsgServer_RejectAsset_Failures() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" tests := []struct { name string @@ -7272,14 +7306,18 @@ func (s *TestSuite) TestMsgServer_RejectAsset_Failures() { { name: "unauthorized signer", setup: func() *types.MsgRejectAssetRequest { - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: "unauth", + }) stranger := s.CreateAndFundAccount(sdk.NewInt64Coin(underlying, 1)) - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "unauth") return &types.MsgRejectAssetRequest{ Authority: stranger.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "unauth", } @@ -7289,13 +7327,17 @@ func (s *TestSuite) TestMsgServer_RejectAsset_Failures() { { name: "admin cannot reject, only the asset manager may", setup: func() *types.MsgRejectAssetRequest { - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "admin-reject") + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: "admin-reject", + }) return &types.MsgRejectAssetRequest{ Authority: s.adminAddr.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "admin-reject", } @@ -7305,7 +7347,14 @@ func (s *TestSuite) TestMsgServer_RejectAsset_Failures() { { name: "vault without an asset manager cannot reject", setup: func() *types.MsgRejectAssetRequest { - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + sourceAmount: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + targetAmount: sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), + externalID: "no-mgr", + }) vaultAddr := vault.GetAddress() _, err := keeper.NewMsgServer(s.simApp.VaultKeeper).SetAssetManager(s.ctx, &types.MsgSetAssetManagerRequest{ Admin: s.adminAddr.String(), @@ -7313,8 +7362,6 @@ func (s *TestSuite) TestMsgServer_RejectAsset_Failures() { AssetManager: "", }) s.Require().NoError(err, "failed to clear asset manager on vault %s", vaultAddr) - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), "no-mgr") return &types.MsgRejectAssetRequest{ Authority: s.adminAddr.String(), VaultAddress: vaultAddr.String(), @@ -7327,12 +7374,15 @@ func (s *TestSuite) TestMsgServer_RejectAsset_Failures() { { name: "payment does not exist", setup: func() *types.MsgRejectAssetRequest { - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) - vaultAddr := vault.GetAddress() - source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) + vault, _, source := s.setupAcceptAssetScenario(acceptAssetScenario{ + underlying: underlying, + share: share, + fundSource: sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), + omitPayment: true, + }) return &types.MsgRejectAssetRequest{ Authority: s.assetManagerAddr.String(), - VaultAddress: vaultAddr.String(), + VaultAddress: vault.GetAddress().String(), Source: source.String(), ExternalId: "ghost", } diff --git a/keeper/nav.go b/keeper/nav.go index 0d5647b3..b67e01c9 100644 --- a/keeper/nav.go +++ b/keeper/nav.go @@ -36,11 +36,8 @@ func validateVaultNAVFields(vault *types.VaultAccount, nav types.VaultNAV) error if err := nav.Price.Validate(); err != nil { return fmt.Errorf("invalid NAV price: %w", err) } - if vault.IsAcceptedDenom(nav.Denom) && !nav.Price.Amount.IsPositive() { - return fmt.Errorf("NAV price amount for accepted denom %q must be positive, got %s", nav.Denom, nav.Price.Amount) - } - if !vault.IsAcceptedDenom(nav.Price.Denom) { - return fmt.Errorf("NAV price denom %q must be an accepted vault denom %v", nav.Price.Denom, vault.AcceptedDenoms()) + if nav.Price.Denom != vault.UnderlyingAsset { + return fmt.Errorf("NAV price denom %q must be the vault underlying asset %q", nav.Price.Denom, vault.UnderlyingAsset) } if nav.Volume.IsNil() || !nav.Volume.IsPositive() { return fmt.Errorf("NAV volume must be positive") @@ -60,11 +57,9 @@ func validateVaultNAVFields(vault *types.VaultAccount, nav types.VaultNAV) error // the vault's total holdings rather than set externally. The denom must also // be a registered marker on-chain, except for metadata value-owner denoms // (nft/), which are legitimate vault assets but cannot be markers. -// The price must be a valid coin denominated in one of the vault's accepted -// denoms (underlying asset or payment denom). Its amount must be positive when -// the priced denom is itself an accepted denom (e.g. the payment denom), but -// may be zero for a held, non-accepted denom so the authority can write a -// worthless asset down to zero. The volume must be positive. +// 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 diff --git a/keeper/nav_test.go b/keeper/nav_test.go index 7cf331b6..dbd6d839 100644 --- a/keeper/nav_test.go +++ b/keeper/nav_test.go @@ -8,10 +8,10 @@ import ( "cosmossdk.io/collections" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/google/uuid" markertypes "github.com/provenance-io/provenance/x/marker/types" metadatatypes "github.com/provenance-io/provenance/x/metadata/types" + "github.com/provlabs/vault/types" ) @@ -156,8 +156,8 @@ func (s *TestSuite) TestKeeper_SetVaultNAV_OverwriteReStamps() { // TestKeeper_SetVaultNAV_RejectsInvalidInput verifies SetVaultNAV rejects every // invalid input before persisting an entry: the vault share denom, an invalid -// price coin, a negative price amount, a price denom outside the vault's -// accepted denoms, a nil or non-positive volume, and a denom that is not a +// price coin, a negative price amount, a price denom that is not the vault +// underlying asset, a nil or non-positive volume, and a denom that is not a // registered marker. func (s *TestSuite) TestKeeper_SetVaultNAV_RejectsInvalidInput() { underlying := "under" @@ -200,13 +200,13 @@ func (s *TestSuite) TestKeeper_SetVaultNAV_RejectsInvalidInput() { expectedErrSubstr: "invalid NAV price", }, { - name: "rejects a price denom outside the vault accepted denoms", + name: "rejects a price denom that is not the vault underlying asset", nav: types.VaultNAV{ Denom: registeredDenom, - Price: sdk.NewInt64Coin("notaccepted", 100), + Price: sdk.NewInt64Coin("notunderlying", 100), Volume: sdkmath.NewInt(1), }, - expectedErrSubstr: "must be an accepted vault denom", + expectedErrSubstr: "must be the vault underlying asset", }, { name: "rejects a nil volume", @@ -311,32 +311,6 @@ func (s *TestSuite) TestKeeper_SetVaultNAV_AllowsZeroPriceForHeldDenom() { s.Assert().True(stored.Price.Amount.IsZero(), "stored NAV price for held denom should be zero, got %s", stored.Price.Amount) } -// TestKeeper_SetVaultNAV_RejectsZeroPriceForAcceptedDenom verifies the > 0 rule -// is still enforced for accepted denoms (here the payment denom), so the -// redemption and AUM-fee conversion math never sees a zero accepted-denom price. -func (s *TestSuite) TestKeeper_SetVaultNAV_RejectsZeroPriceForAcceptedDenom() { - underlying := "under" - share := "vaultshares" - payment := "pay" - vault := s.setupSinglePaymentDenomVault(underlying, share, payment, 1, 1) - vaultAddr := types.GetVaultAddress(share) - - s.Require().True(vault.IsAcceptedDenom(payment), "%q must be an accepted denom for this test", payment) - - nav := types.VaultNAV{ - Denom: payment, - Price: sdk.NewInt64Coin(underlying, 0), - Volume: sdkmath.NewInt(1), - } - err := s.k.SetVaultNAV(s.ctx, vault, nav, s.adminAddr.String()) - s.Require().Error(err, "SetVaultNAV should reject a zero price for an accepted denom") - s.Assert().Contains(err.Error(), `NAV price amount for accepted denom "pay" must be positive`, "error should name the accepted denom") - - stored, getErr := s.k.GetVaultNAV(s.ctx, vaultAddr, payment) - s.Require().NoError(getErr, "the pre-seeded positive payment NAV should still be present") - s.Assert().True(stored.Price.Amount.IsPositive(), "the rejected zero write must not overwrite the existing payment NAV") -} - func (s *TestSuite) TestKeeper_SetVaultNAV_MetadataDenomSkipsMarkerCheck() { underlying := "under" share := "vaultshares" @@ -548,7 +522,6 @@ func (s *TestSuite) TestKeeper_CheckSettlementNAVGuardrail() { func (s *TestSuite) TestKeeper_PublishAssetNAVToMarker() { underlying := "under" share := "vshare" - paymentDenom := "pay" asset := "rwacoin" tests := []struct { @@ -586,13 +559,13 @@ func (s *TestSuite) TestKeeper_PublishAssetNAVToMarker() { defer func() { s.ctx = origCtx }() s.ctx, _ = s.ctx.CacheContext() - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, _ := s.setupAssetSettlementVault(underlying, share) if tc.registerAssetMarker { s.requireSimpleMarker(asset) } nav := types.VaultNAV{ Denom: asset, - Price: sdk.NewInt64Coin(paymentDenom, 5), + Price: sdk.NewInt64Coin(underlying, 5), Volume: tc.volume, Source: vault.Address, } @@ -606,9 +579,9 @@ func (s *TestSuite) TestKeeper_PublishAssetNAVToMarker() { } s.Require().NoError(err, "publishAssetNAVToMarker should succeed for denom %s volume %s", nav.Denom, nav.Volume) - stored, err := s.k.MarkerKeeper.GetNetAssetValue(s.ctx, asset, paymentDenom) - s.Require().NoError(err, "failed to read marker NAV for %s priced in %s", asset, paymentDenom) - s.Require().NotNil(stored, "marker NAV for %s priced in %s should exist after publish", asset, paymentDenom) + stored, err := s.k.MarkerKeeper.GetNetAssetValue(s.ctx, asset, underlying) + s.Require().NoError(err, "failed to read marker NAV for %s priced in %s", asset, underlying) + s.Require().NotNil(stored, "marker NAV for %s priced in %s should exist after publish", asset, underlying) s.Assert().Equal(nav.Price, stored.Price, "marker NAV price should match the internal NAV price for %s", asset) s.Assert().Equal(nav.Volume.Uint64(), stored.Volume, "marker NAV volume should match the internal NAV volume for %s", asset) s.requireTypedEventEmitted(markertypes.NewEventSetNetAssetValue(asset, nav.Price, nav.Volume.Uint64(), vault.Address)) diff --git a/keeper/payout.go b/keeper/payout.go index 38f80f0a..374ff082 100644 --- a/keeper/payout.go +++ b/keeper/payout.go @@ -168,7 +168,7 @@ func (k *Keeper) processSingleWithdrawal(ctx sdk.Context, id uint64, req types.P return fmt.Errorf("%w: failed to reconcile vault: %w", types.ErrReconcileFailure, err) } - assets, err := k.ConvertSharesToRedeemCoin(ctx, vault, req.Shares.Amount, req.RedeemDenom) + assets, err := k.ConvertSharesToRedeemCoin(ctx, vault, req.Shares.Amount) if err != nil { return fmt.Errorf("failed to convert shares to redeem coin for single withdrawal: %w", err) } diff --git a/keeper/payout_restrictions_test.go b/keeper/payout_restrictions_test.go index e8eb0667..88d2fb92 100644 --- a/keeper/payout_restrictions_test.go +++ b/keeper/payout_restrictions_test.go @@ -5,7 +5,6 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" - attrtypes "github.com/provenance-io/provenance/x/attribute/types" ) @@ -38,7 +37,7 @@ func (s *TestSuite) TestCheckPayoutRestrictions() { for i, tc := range tests { s.Run(tc.name, func() { - // s.SetupTest() is called by the suite before each Test* method, + // s.SetupTest() is called by the suite before each Test* method, // but s.Run subtests might need their own isolation if they share state. // However, requireAddFinalizeAndActivateMarker will fail if denom is reused. underlyingDenom := fmt.Sprintf("underlying%d", i) diff --git a/keeper/payout_test.go b/keeper/payout_test.go index a88410b9..0fb3409d 100644 --- a/keeper/payout_test.go +++ b/keeper/payout_test.go @@ -8,7 +8,6 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - markertypes "github.com/provenance-io/provenance/x/marker/types" "github.com/provlabs/vault/keeper" @@ -323,7 +322,7 @@ func (s *TestSuite) TestKeeper_ProcessPendingSwapOuts() { batchSize: keeper.MaxSwapOutBatchSize, }, { - name: "refund when calculating redeem denom fails", + name: "stale foreign redeem denom in queue entry pays out in the underlying", setup: func(shareDenom string, vaultAddr sdk.AccAddress, shares sdk.Coin) (sdk.AccAddress, uint64) { ownerAddr := s.CreateAndFundAccount(assets) vault := s.setupBaseVault(underlyingDenom, shareDenom) @@ -343,19 +342,11 @@ func (s *TestSuite) TestKeeper_ProcessPendingSwapOuts() { return ownerAddr, id }, posthandler: func(ownerAddr sdk.AccAddress, reqID uint64, shareDenom string, vaultAddr sdk.AccAddress, principalAddress sdk.AccAddress, shares sdk.Coin, testBlockTime time.Time) { - s.assertBalance(ownerAddr, shareDenom, shares.Amount) - reason := types.RefundReasonNavNotFound - - expectedEvents := sdk.Events{} - expectedEvents = append(expectedEvents, createSendCoinEvents(vaultAddr.String(), ownerAddr.String(), shares.String())...) - expectedEvent, err := sdk.TypedEventToEvent(types.NewEventSwapOutRefunded(vaultAddr.String(), ownerAddr.String(), shares, reqID, reason)) - s.Require().NoError(err, "should not error converting typed EventSwapOutRefunded") - expectedEvents = append(expectedEvents, expectedEvent) - s.Assert().Equal( - normalizeEvents(expectedEvents), - normalizeEvents(s.ctx.EventManager().Events()), - "a single EventSwapOutRefunded should be emitted", - ) + payout := s.k.BankKeeper.GetBalance(s.ctx, ownerAddr, underlyingDenom) + s.Require().True(payout.Amount.IsPositive(), "owner should be paid in the underlying asset even when the stored redeem denom is foreign") + s.assertBalance(ownerAddr, "badredeemdenom", math.ZeroInt()) + supply := s.k.BankKeeper.GetSupply(s.ctx, shareDenom) + s.Require().True(supply.Amount.IsZero(), "escrowed shares should be burned after the underlying payout") }, batchSize: keeper.MaxSwapOutBatchSize, }, @@ -808,22 +799,6 @@ func (s *TestSuite) TestKeeper_ProcessSingleWithdrawal_TypedSentinels() { expectedSentinel: types.ErrReconcileFailure, expectedReason: types.RefundReasonReconcileFailure, }, - { - name: "missing redeem NAV surfaces the typed ErrInternalNAVNotFound sentinel", - setup: func() (types.PendingSwapOut, types.VaultAccount) { - shareDenom := "vsharenav" - vaultAddr := types.GetVaultAddress(shareDenom) - vault, ownerAddr, minted := escrowVault(shareDenom, vaultAddr) - return types.PendingSwapOut{ - Owner: ownerAddr.String(), - VaultAddress: vaultAddr.String(), - RedeemDenom: "badredeemdenom", - Shares: minted, - }, *vault - }, - expectedSentinel: keeper.ErrInternalNAVNotFound, - expectedReason: types.RefundReasonNavNotFound, - }, } for _, tc := range tests { diff --git a/keeper/query_server.go b/keeper/query_server.go index 2453a1d1..fcc27177 100644 --- a/keeper/query_server.go +++ b/keeper/query_server.go @@ -140,14 +140,6 @@ func (k queryServer) EstimateSwapIn(goCtx context.Context, req *types.QueryEstim return nil, status.Error(codes.FailedPrecondition, "swap-in disabled or vault paused") } - priceNum, priceDen, err := k.UnitPriceFraction(ctx, req.Assets.Denom, *vault) - if err != nil { - return nil, status.Errorf(codes.InvalidArgument, "no NAV for %s/%s: %v", req.Assets.Denom, vault.UnderlyingAsset, err) - } - if priceDen.IsZero() { - return nil, status.Errorf(codes.InvalidArgument, "invalid NAV: zero volume for %s/%s", req.Assets.Denom, vault.UnderlyingAsset) - } - totalShares := vault.TotalShares.Amount estimatedTVV, err := k.EstimateTotalVaultValue(ctx, vault) @@ -155,10 +147,8 @@ func (k queryServer) EstimateSwapIn(goCtx context.Context, req *types.QueryEstim return nil, status.Errorf(codes.Internal, "failed to estimate total assets: %v", err) } - amountNum := req.Assets.Amount.Mul(priceNum) - estimatedShares, err := utils.CalculateSharesProRataFraction( - amountNum, - priceDen, + estimatedShares, err := utils.CalculateSharesProRata( + req.Assets.Amount, estimatedTVV.Amount, totalShares, vault.TotalShares.Denom, @@ -174,7 +164,7 @@ func (k queryServer) EstimateSwapIn(goCtx context.Context, req *types.QueryEstim }, nil } -// EstimateSwapOut estimates the amount of payout assets (underlying or payout denom) received for a given amount of shares. +// EstimateSwapOut estimates the amount of underlying assets received for a given amount of shares. func (k queryServer) EstimateSwapOut(goCtx context.Context, req *types.QueryEstimateSwapOutRequest) (*types.QueryEstimateSwapOutResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") @@ -199,14 +189,6 @@ func (k queryServer) EstimateSwapOut(goCtx context.Context, req *types.QueryEsti return nil, status.Error(codes.FailedPrecondition, "swap-out disabled or vault paused") } - redeemDenom := req.RedeemDenom - if redeemDenom == "" { - redeemDenom = vault.UnderlyingAsset - } - if !vault.IsAcceptedDenom(redeemDenom) { - return nil, status.Errorf(codes.InvalidArgument, "unsupported redeem denom: %q", redeemDenom) - } - totalShares := vault.TotalShares.Amount estimatedTVV, err := k.EstimateTotalVaultValue(ctx, vault) @@ -214,26 +196,19 @@ func (k queryServer) EstimateSwapOut(goCtx context.Context, req *types.QueryEsti return nil, status.Errorf(codes.Internal, "failed to estimate total assets: %v", err) } - priceNum, priceDen, err := k.UnitPriceFraction(ctx, redeemDenom, *vault) - if err != nil { - return nil, status.Errorf(codes.InvalidArgument, "no NAV for %s/%s: %v", redeemDenom, vault.UnderlyingAsset, err) - } - if priceNum.IsZero() { - return nil, status.Errorf(codes.InvalidArgument, "zero price for %s/%s", redeemDenom, vault.UnderlyingAsset) - } - shares, ok := math.NewIntFromString(req.Shares) if !ok { return nil, status.Errorf(codes.InvalidArgument, "invalid shares amount \"%s\" : must be a valid integer", req.Shares) } + if shares.IsNegative() { + return nil, status.Errorf(codes.InvalidArgument, "invalid shares amount \"%s\" : must not be negative", req.Shares) + } - estimatedPayout, err := utils.CalculateRedeemProRataFraction( + estimatedPayout, err := utils.CalculateRedeemProRata( shares, totalShares, estimatedTVV.Amount, - priceNum, - priceDen, - redeemDenom, + vault.UnderlyingAsset, ) if err != nil { return nil, status.Errorf(codes.Internal, "failed to calculate redeem estimate: %v", err) diff --git a/keeper/query_server_test.go b/keeper/query_server_test.go index f246535a..e9146972 100644 --- a/keeper/query_server_test.go +++ b/keeper/query_server_test.go @@ -42,7 +42,7 @@ func (s *TestSuite) TestQueryServer_Vault() { } underlying := "uylds.fcc" - payment := "usdc" + heldAsset := "usdc" shareDenom1 := "vault1" addr1 := types.GetVaultAddress(shareDenom1) @@ -55,31 +55,27 @@ func (s *TestSuite) TestQueryServer_Vault() { setupVaults := func() { s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 1), s.adminAddr) - initNAV := &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlying, 1), - Volume: math.OneInt(), - } - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{Admin: admin, ShareDenom: shareDenom1, UnderlyingAsset: underlying, PaymentDenom: payment, InitialPaymentNav: initNAV}) - s.Require().NoError(err, "create vault1 should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{Admin: admin, ShareDenom: shareDenom2, UnderlyingAsset: underlying, PaymentDenom: payment, InitialPaymentNav: initNAV}) - s.Require().NoError(err, "create vault2 should succeed") + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldAsset, 1), s.adminAddr) + vault1 := s.createSingleDenomVault(vaultAttrs{admin: admin, share: shareDenom1, underlying: underlying}) + vault2 := s.createSingleDenomVault(vaultAttrs{admin: admin, share: shareDenom2, underlying: underlying}) + s.setVaultNAV(vault1, heldAsset, sdk.NewInt64Coin(underlying, 1), 1) + s.setVaultNAV(vault2, heldAsset, sdk.NewInt64Coin(underlying, 1), 1) s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin(underlying, 40))), "fund reserves for vault1 should succeed") - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr1, sdk.NewCoins(sdk.NewInt64Coin(underlying, 100), sdk.NewInt64Coin(payment, 250))), "fund principal (marker) for vault1 should succeed") + s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr1, sdk.NewCoins(sdk.NewInt64Coin(underlying, 100), sdk.NewInt64Coin(heldAsset, 250))), "fund principal (marker) for vault1 should succeed") s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, addr2, sdk.NewCoins(sdk.NewInt64Coin(underlying, 20))), "fund reserves for vault2 should succeed") - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr2, sdk.NewCoins(sdk.NewInt64Coin(underlying, 200), sdk.NewInt64Coin(payment, 100))), "fund principal (marker) for vault2 should succeed") + s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr2, sdk.NewCoins(sdk.NewInt64Coin(underlying, 200), sdk.NewInt64Coin(heldAsset, 100))), "fund principal (marker) for vault2 should succeed") } tests := []querytest.TestCase[types.QueryVaultRequest, types.QueryVaultResponse]{ { - Name: "vault found by address (multi-denom principal, uylds.fcc underlying)", + Name: "vault found by address (held asset priced via internal NAV)", Setup: setupVaults, Req: &types.QueryVaultRequest{Id: addr1.String()}, ExpectedResp: &types.QueryVaultResponse{ - Vault: *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, underlying, payment, 0, 15, "", "", "", ""), + Vault: *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, underlying, 0, 15, "", "", "", ""), Principal: types.AccountBalance{ Address: markerAddr1.String(), - Coins: sdk.NewCoins(sdk.NewInt64Coin(underlying, 100), sdk.NewInt64Coin(payment, 250)), + Coins: sdk.NewCoins(sdk.NewInt64Coin(underlying, 100), sdk.NewInt64Coin(heldAsset, 250)), }, Reserves: types.AccountBalance{ Address: addr1.String(), @@ -89,14 +85,14 @@ func (s *TestSuite) TestQueryServer_Vault() { }, }, { - Name: "vault found by share denom (multi-denom principal, uylds.fcc underlying)", + Name: "vault found by share denom (held asset priced via internal NAV)", Setup: setupVaults, Req: &types.QueryVaultRequest{Id: shareDenom2}, ExpectedResp: &types.QueryVaultResponse{ - Vault: *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, underlying, payment, 0, 15, "", "", "", ""), + Vault: *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, underlying, 0, 15, "", "", "", ""), Principal: types.AccountBalance{ Address: markerAddr2.String(), - Coins: sdk.NewCoins(sdk.NewInt64Coin(underlying, 200), sdk.NewInt64Coin(payment, 100)), + Coins: sdk.NewCoins(sdk.NewInt64Coin(underlying, 200), sdk.NewInt64Coin(heldAsset, 100)), }, Reserves: types.AccountBalance{ Address: addr2.String(), @@ -202,131 +198,53 @@ func (s *TestSuite) TestQueryServer_Vaults() { shareDenom3 := "vault3" addr3 := types.GetVaultAddress(shareDenom3) + setupThreeVaults := func() { + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("stake2", 1), s.adminAddr) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("nhash", 1), s.adminAddr) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdf", 1), s.adminAddr) + s.CreateVaultWithParams(shareDenom1, "stake2") + s.CreateVaultWithParams(shareDenom2, "nhash") + s.CreateVaultWithParams(shareDenom3, "usdf") + } + tests := []querytest.TestCase[types.QueryVaultsRequest, types.QueryVaultsResponse]{ { Name: "happy path - single vault", Setup: func() { s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("stake2", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdc", 1), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom1, - UnderlyingAsset: "stake2", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("stake2", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") + s.CreateVaultWithParams(shareDenom1, "stake2") }, Req: &types.QueryVaultsRequest{}, ExpectedResp: &types.QueryVaultsResponse{ Vaults: []types.VaultAccount{ - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", "usdc", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", 0, 15, "", "", "", ""), }, Pagination: &query.PageResponse{Total: 1}, }, }, { - Name: "happy path - multiple vaults", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("stake2", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("nhash", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdf", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdc", 1), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom1, - UnderlyingAsset: "stake2", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("stake2", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom2, - UnderlyingAsset: "nhash", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("nhash", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom3, - UnderlyingAsset: "usdf", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("usdf", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - }, - Req: &types.QueryVaultsRequest{}, + Name: "happy path - multiple vaults", + Setup: setupThreeVaults, + Req: &types.QueryVaultsRequest{}, ExpectedResp: &types.QueryVaultsResponse{ Vaults: []types.VaultAccount{ - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", "usdc", 0, 15, "", "", "", ""), - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", "usdc", 0, 15, "", "", "", ""), - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr3), admin, shareDenom3, "usdf", "usdc", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr3), admin, shareDenom3, "usdf", 0, 15, "", "", "", ""), }, Pagination: &query.PageResponse{Total: 3}, }, }, { - Name: "pagination - limits the number of outputs", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("stake2", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("nhash", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdf", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdc", 1), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom1, - UnderlyingAsset: "stake2", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("stake2", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom2, - UnderlyingAsset: "nhash", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("nhash", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom3, - UnderlyingAsset: "usdf", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("usdf", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "pagination - limits the number of outputs", + Setup: setupThreeVaults, Req: &types.QueryVaultsRequest{ Pagination: &query.PageRequest{Limit: 2}, }, ExpectedResp: &types.QueryVaultsResponse{ Vaults: []types.VaultAccount{ - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr3), admin, shareDenom3, "usdf", "usdc", 0, 15, "", "", "", ""), - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", "usdc", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr3), admin, shareDenom3, "usdf", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", 0, 15, "", "", "", ""), }, Pagination: &query.PageResponse{ NextKey: []byte("not nil"), @@ -334,209 +252,57 @@ func (s *TestSuite) TestQueryServer_Vaults() { }, }, { - Name: "pagination - offset starts at correct location", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("stake2", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("nhash", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdf", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdc", 1), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom1, - UnderlyingAsset: "stake2", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("stake2", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom2, - UnderlyingAsset: "nhash", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("nhash", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom3, - UnderlyingAsset: "usdf", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("usdf", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "pagination - offset starts at correct location", + Setup: setupThreeVaults, Req: &types.QueryVaultsRequest{ Pagination: &query.PageRequest{Offset: 1}, }, ExpectedResp: &types.QueryVaultsResponse{ Vaults: []types.VaultAccount{ - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", "usdc", 0, 15, "", "", "", ""), - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", "usdc", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", 0, 15, "", "", "", ""), }, Pagination: &query.PageResponse{Total: 3}, }, }, { - Name: "pagination - offset starts at correct location and enforces limit", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("stake2", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("nhash", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdf", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdc", 1), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom1, - UnderlyingAsset: "stake2", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("stake2", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom2, - UnderlyingAsset: "nhash", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("nhash", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom3, - UnderlyingAsset: "usdf", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("usdf", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "pagination - offset starts at correct location and enforces limit", + Setup: setupThreeVaults, Req: &types.QueryVaultsRequest{ Pagination: &query.PageRequest{Offset: 2, Limit: 1}, }, ExpectedResp: &types.QueryVaultsResponse{ Vaults: []types.VaultAccount{ - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", "usdc", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", 0, 15, "", "", "", ""), }, Pagination: &query.PageResponse{}, }, }, { - Name: "pagination - enabled count total", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("stake2", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("nhash", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdf", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdc", 1), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom1, - UnderlyingAsset: "stake2", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("stake2", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom2, - UnderlyingAsset: "nhash", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("nhash", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom3, - UnderlyingAsset: "usdf", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("usdf", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "pagination - enabled count total", + Setup: setupThreeVaults, Req: &types.QueryVaultsRequest{ Pagination: &query.PageRequest{CountTotal: true}, }, ExpectedResp: &types.QueryVaultsResponse{ Vaults: []types.VaultAccount{ - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", "usdc", 0, 15, "", "", "", ""), - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", "usdc", 0, 15, "", "", "", ""), - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr3), admin, shareDenom3, "usdf", "usdc", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr3), admin, shareDenom3, "usdf", 0, 15, "", "", "", ""), }, Pagination: &query.PageResponse{Total: 3}, }, }, { - Name: "pagination - reverse provides the results in reverse order", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("stake2", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("nhash", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdf", 1), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin("usdc", 1), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom1, - UnderlyingAsset: "stake2", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("stake2", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom2, - UnderlyingAsset: "nhash", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("nhash", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - _, err = s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: shareDenom3, - UnderlyingAsset: "usdf", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("usdf", 1), - Volume: math.OneInt(), - }, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "pagination - reverse provides the results in reverse order", + Setup: setupThreeVaults, Req: &types.QueryVaultsRequest{ Pagination: &query.PageRequest{Reverse: true, Limit: 2}, }, ExpectedResp: &types.QueryVaultsResponse{ Vaults: []types.VaultAccount{ - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", "usdc", 0, 15, "", "", "", ""), - *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", "usdc", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr2), admin, shareDenom2, "nhash", 0, 15, "", "", "", ""), + *types.NewVaultAccount(authtypes.NewBaseAccountWithAddress(addr1), admin, shareDenom1, "stake2", 0, 15, "", "", "", ""), }, Pagination: &query.PageResponse{ NextKey: []byte("not nil"), @@ -579,25 +345,19 @@ func (s *TestSuite) TestQueryServer_EstimateSwapIn() { } underlyingDenom := "uylds.fcc" - paymentDenom := "usdc" shareDenom := "vaultshares" vaultAddr := types.GetVaultAddress(shareDenom) - admin := s.adminAddr.String() assetsUnderlying := sdk.NewInt64Coin(underlyingDenom, 100) - assetsPayment := sdk.NewInt64Coin(paymentDenom, 100) + + setupVault := func() { + s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) + s.CreateVaultWithParams(shareDenom, underlyingDenom) + } tests := []querytest.TestCase[types.QueryEstimateSwapInRequest, types.QueryEstimateSwapInResponse]{ { - Name: "happy path underlying deposit (peg)", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "happy path underlying deposit (peg)", + Setup: setupVault, Req: &types.QueryEstimateSwapInRequest{ VaultAddress: vaultAddr.String(), Assets: assetsUnderlying, @@ -606,36 +366,10 @@ func (s *TestSuite) TestQueryServer_EstimateSwapIn() { Assets: sdk.NewCoin(shareDenom, assetsUnderlying.Amount.Mul(utils.ShareScalar)), }, }, - { - Name: "happy path payment deposit with 1:1 internal NAV", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") - s.seedVaultNAV(vaultAddr, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) - }, - Req: &types.QueryEstimateSwapInRequest{ - VaultAddress: vaultAddr.String(), - Assets: assetsPayment, - }, - ExpectedResp: &types.QueryEstimateSwapInResponse{ - Assets: sdk.NewCoin(shareDenom, assetsPayment.Amount.Mul(utils.ShareScalar)), - }, - }, { Name: "fails if vault is paused", Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") + setupVault() vault, err := s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err, "getting vault should succeed") vault.Paused = true @@ -650,13 +384,7 @@ func (s *TestSuite) TestQueryServer_EstimateSwapIn() { { Name: "fails if swap-in is disabled", Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") + setupVault() vault, err := s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err, "getting vault should succeed") vault.SwapInEnabled = false @@ -689,16 +417,8 @@ func (s *TestSuite) TestQueryServer_EstimateSwapIn() { ExpectedErrSubstrs: []string{"vault with address", "not found"}, }, { - Name: "unsupported denom", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "unsupported denom", + Setup: setupVault, Req: &types.QueryEstimateSwapInRequest{ VaultAddress: vaultAddr.String(), Assets: sdk.NewInt64Coin("otherdenom", 100), @@ -726,33 +446,32 @@ func (s *TestSuite) TestQueryServer_EstimateSwapOut() { } underlyingDenom := "uylds.fcc" - paymentDenom := "usdc" shareDenom := "vaultshares" vaultAddr := types.GetVaultAddress(shareDenom) - admin := s.adminAddr.String() sharesToSwap := sdk.NewCoin(shareDenom, math.NewInt(100).Mul(utils.ShareScalar)) + setupVault := func() { + s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) + s.CreateVaultWithParams(shareDenom, underlyingDenom) + } + + setupFundedVault := func() { + setupVault() + err := FundAccount(s.ctx, s.simApp.BankKeeper, markertypes.MustGetMarkerAddress(shareDenom), sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 100))) + s.Require().NoError(err, "fund marker with underlying should succeed") + err = FundAccount(s.ctx, s.simApp.BankKeeper, s.adminAddr, sdk.NewCoins(sharesToSwap)) + s.Require().NoError(err, "fund owner with shares should succeed") + vault, err := s.k.GetVault(s.ctx, vaultAddr) + s.Require().NoError(err, "get vault should succeed") + s.Require().NotNil(vault, "vault should not be nil") + vault.TotalShares = sharesToSwap + s.k.AuthKeeper.SetAccount(s.ctx, vault) + } + tests := []querytest.TestCase[types.QueryEstimateSwapOutRequest, types.QueryEstimateSwapOutResponse]{ { - Name: "happy path redeem to underlying (peg)", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") - err = FundAccount(s.ctx, s.simApp.BankKeeper, markertypes.MustGetMarkerAddress(shareDenom), sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 100))) - s.Require().NoError(err, "fund marker with underlying should succeed") - err = FundAccount(s.ctx, s.simApp.BankKeeper, s.adminAddr, sdk.NewCoins(sharesToSwap)) - s.Require().NoError(err, "fund owner with shares should succeed") - vault, err := s.k.GetVault(s.ctx, vaultAddr) - s.Require().NoError(err, "get vault should succeed") - s.Require().NotNil(vault, "vault should not be nil") - vault.TotalShares = sharesToSwap - s.k.AuthKeeper.SetAccount(s.ctx, vault) - }, + Name: "happy path redeem to underlying (peg)", + Setup: setupFundedVault, Req: &types.QueryEstimateSwapOutRequest{ VaultAddress: vaultAddr.String(), Shares: sharesToSwap.Amount.String(), @@ -761,46 +480,10 @@ func (s *TestSuite) TestQueryServer_EstimateSwapOut() { Assets: sdk.NewInt64Coin(underlyingDenom, 100), }, }, - { - Name: "happy path redeem to payment denom with 1:1 internal NAV", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") - err = FundAccount(s.ctx, s.simApp.BankKeeper, markertypes.MustGetMarkerAddress(shareDenom), sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 100))) - s.Require().NoError(err, "fund marker with underlying should succeed") - err = FundAccount(s.ctx, s.simApp.BankKeeper, s.adminAddr, sdk.NewCoins(sharesToSwap)) - s.Require().NoError(err, "fund owner with shares should succeed") - vault, err := s.k.GetVault(s.ctx, vaultAddr) - s.Require().NoError(err, "get vault should succeed") - s.Require().NotNil(vault, "vault should not be nil") - vault.TotalShares = sharesToSwap - s.k.AuthKeeper.SetAccount(s.ctx, vault) - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) - }, - Req: &types.QueryEstimateSwapOutRequest{ - VaultAddress: vaultAddr.String(), - Shares: sharesToSwap.Amount.String(), - RedeemDenom: paymentDenom, - }, - ExpectedResp: &types.QueryEstimateSwapOutResponse{ - Assets: sdk.NewInt64Coin(paymentDenom, 100), - }, - }, { Name: "fails if vault is paused", Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") + setupVault() vault, err := s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err, "getting vault should succeed") vault.Paused = true @@ -815,13 +498,7 @@ func (s *TestSuite) TestQueryServer_EstimateSwapOut() { { Name: "fails if swap-out is disabled", Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") + setupVault() vault, err := s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err, "getting vault should succeed") vault.SwapOutEnabled = false @@ -854,39 +531,22 @@ func (s *TestSuite) TestQueryServer_EstimateSwapOut() { ExpectedErrSubstrs: []string{"vault with address", "not found"}, }, { - Name: "unsupported redeem denom", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "fails with incorrect shares string", + Setup: setupVault, Req: &types.QueryEstimateSwapOutRequest{ VaultAddress: vaultAddr.String(), - Shares: math.NewInt(100).String(), - RedeemDenom: "wrongdenom", + Shares: "bogus", }, - ExpectedErrSubstrs: []string{"unsupported redeem denom"}, + ExpectedErrSubstrs: []string{"invalid shares amount \"bogus\" : must be a valid integer"}, }, { - Name: "fails with incorrect shares string", - Setup: func() { - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(underlyingDenom, math.NewInt(1000)), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewCoin(paymentDenom, math.NewInt(1000)), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: admin, ShareDenom: shareDenom, UnderlyingAsset: underlyingDenom, PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.OneInt()}, - }) - s.Require().NoError(err, "vault creation should succeed") - }, + Name: "fails with negative shares", + Setup: setupVault, Req: &types.QueryEstimateSwapOutRequest{ VaultAddress: vaultAddr.String(), - Shares: "bogus", + Shares: "-100", }, - ExpectedErrSubstrs: []string{"invalid shares amount \"bogus\" : must be a valid integer"}, + ExpectedErrSubstrs: []string{"invalid shares amount \"-100\" : must not be negative", "InvalidArgument"}, }, } @@ -1449,14 +1109,14 @@ func (s *TestSuite) TestQueryServer_NavValue() { // TestQueryServer_VaultPayment verifies the VaultPayment query returns a single // payment targeting the vault and reports NotFound for unknown or mistargeted payments. func (s *TestSuite) TestQueryServer_VaultPayment() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, _ := s.setupAssetSettlementVault(underlying, share) vaultAddr := vault.GetAddress() source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) sourceAmount := sdk.NewCoins(sdk.NewInt64Coin(asset, 10)) - targetAmount := sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)) + targetAmount := sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)) s.createPayment(source, vaultAddr, sourceAmount, targetAmount, "invoice-1") otherSource := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) @@ -1594,15 +1254,15 @@ func (s *TestSuite) TestQueryServer_VaultPayment() { // TestQueryServer_VaultPayments verifies the VaultPayments query returns every payment // targeting the vault, excludes payments for other targets, and paginates the results. func (s *TestSuite) TestQueryServer_VaultPayments() { - underlying, share, paymentDenom, asset := "under", "vshare", "pay", "rwacoin" + underlying, share, asset := "under", "vshare", "rwacoin" - vault, _ := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, _ := s.setupAssetSettlementVault(underlying, share) vaultAddr := vault.GetAddress() externalIDs := []string{"p-1", "p-2", "p-3", "p-4", "p-5"} for _, externalID := range externalIDs { source := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) - s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 5)), externalID) + s.createPayment(source, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(asset, 10)), sdk.NewCoins(sdk.NewInt64Coin(underlying, 5)), externalID) } otherSource := s.CreateAndFundAccount(sdk.NewInt64Coin(asset, 10)) diff --git a/keeper/queue_test.go b/keeper/queue_test.go index 5a4edf7a..a4e46e51 100644 --- a/keeper/queue_test.go +++ b/keeper/queue_test.go @@ -6,12 +6,12 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/stretchr/testify/require" kpr "github.com/provlabs/vault/keeper" "github.com/provlabs/vault/types" "github.com/provlabs/vault/utils" "github.com/provlabs/vault/utils/mocks" - "github.com/stretchr/testify/require" ) func TestSafeAddPayoutVerification_UpdatesVaultAndQueues(t *testing.T) { diff --git a/keeper/reconcile.go b/keeper/reconcile.go index 444d9b8e..9581cb12 100644 --- a/keeper/reconcile.go +++ b/keeper/reconcile.go @@ -304,11 +304,11 @@ func (k Keeper) PerformVaultInterestTransfer(ctx sdk.Context, vault *types.Vault // 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 configured PaymentDenom. +// 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 PaymentDenom balance. Any uncollected remainder is +// the principal marker's current underlying-asset balance. Any uncollected remainder is // recorded in OutstandingAumFee to be retried during the next reconciliation. // // An EventVaultFeeCollected is emitted upon success. @@ -332,7 +332,7 @@ func (k Keeper) PerformVaultFeeTransfer(ctx sdk.Context, vault *types.VaultAccou if err != nil { return fmt.Errorf("failed to add new fee payment %s to outstanding AUM fee %s: %w", newFeePayment, vault.OutstandingAumFee, err) } - totalOutstanding := sdk.NewCoin(vault.PaymentDenom, totalOutstandingAmount) + totalOutstanding := sdk.NewCoin(vault.UnderlyingAsset, totalOutstandingAmount) if totalOutstanding.IsZero() { vault.FeePeriodStart = currentBlockTime return nil @@ -344,7 +344,7 @@ func (k Keeper) PerformVaultFeeTransfer(ctx sdk.Context, vault *types.VaultAccou } principalAddress := vault.PrincipalMarkerAddress() - balance := k.BankKeeper.GetBalance(ctx, principalAddress, vault.PaymentDenom) + balance := k.BankKeeper.GetBalance(ctx, principalAddress, vault.UnderlyingAsset) toCollect := totalOutstanding if balance.Amount.LT(totalOutstanding.Amount) { @@ -472,29 +472,13 @@ func (k Keeper) CalculateAccruedAUMFee(ctx sdk.Context, vault types.VaultAccount } // CalculateAccruedAUMFeePayment calculates the AUM fees that would have accrued for the vault -// from its FeePeriodStart to the current block time, converted to the vault's PaymentDenom. +// from its FeePeriodStart to the current block time, as a coin in the vault's underlying asset. func (k Keeper) CalculateAccruedAUMFeePayment(ctx sdk.Context, vault types.VaultAccount, totalAssets sdkmath.Int) (sdk.Coin, error) { feeUnderlying, err := k.CalculateAccruedAUMFee(ctx, vault, totalAssets) if err != nil { return sdk.Coin{}, fmt.Errorf("failed to calculate accrued AUM fee: %w", err) } - if feeUnderlying.IsZero() { - return sdk.NewCoin(vault.PaymentDenom, sdkmath.ZeroInt()), nil - } - feePayment, err := k.FromUnderlyingAssetAmount(ctx, vault, feeUnderlying, vault.PaymentDenom) - if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to convert accrued fee to payment denom: %w", err) - } - return sdk.NewCoin(vault.PaymentDenom, feePayment), nil -} - -// CalculateOutstandingFeeUnderlying converts the vault's outstanding AUM fees into -// the equivalent amount of the underlying asset. -func (k Keeper) CalculateOutstandingFeeUnderlying(ctx sdk.Context, vault types.VaultAccount) (sdkmath.Int, error) { - if vault.OutstandingAumFee.IsZero() { - return sdkmath.ZeroInt(), nil - } - return k.ToUnderlyingAssetAmount(ctx, vault, vault.OutstandingAumFee) + return sdk.NewCoin(vault.UnderlyingAsset, feeUnderlying), nil } // CalculateVaultTotalAssets returns the total value of the vault's assets, including the interest @@ -519,11 +503,7 @@ func (k Keeper) CalculateVaultTotalAssets(ctx sdk.Context, vault *types.VaultAcc } estimated = estimated.Sub(feeAccrued) - outstandingUnderlying, err := k.CalculateOutstandingFeeUnderlying(ctx, *vault) - if err != nil { - return sdkmath.Int{}, fmt.Errorf("error converting outstanding fee: %w", err) - } - estimated = estimated.Sub(outstandingUnderlying) + estimated = estimated.Sub(vault.OutstandingAumFee.Amount) if estimated.IsNegative() { estimated = sdkmath.ZeroInt() @@ -627,7 +607,7 @@ func (k Keeper) reschedulePayoutTimeout(ctx sdk.Context, vault *types.VaultAccou } // tryGetVault returns the vault if found, or false if the vault is missing or invalid. -// It should only be used in BeginBlocker/EndBlocker logic where failure is non-critical. +// It should only be used in BeginBlocker/EndBlocker or migration logic where failure is non-critical. func (k Keeper) tryGetVault(ctx sdk.Context, addr sdk.AccAddress) (*types.VaultAccount, bool) { vault, err := k.GetVault(ctx, addr) if err != nil { diff --git a/keeper/reconcile_test.go b/keeper/reconcile_test.go index bb67a906..2bce4153 100644 --- a/keeper/reconcile_test.go +++ b/keeper/reconcile_test.go @@ -6,7 +6,6 @@ import ( "math/big" "time" - "cosmossdk.io/collections" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" markertypes "github.com/provenance-io/provenance/x/marker/types" @@ -23,7 +22,11 @@ func (s *TestSuite) TestKeeper_ReconcileVault() { vaultAddress := types.GetVaultAddress(shareDenom) testBlockTime := time.Now() futureTime := testBlockTime.Add(100 * time.Second) - pastTime := testBlockTime.Add(-60 * 24 * time.Hour) // ~2 months + pastTime := testBlockTime.Add(-60 * 24 * time.Hour) + interestEarnedAtPositiveRate := sdkmath.NewInt(41_952_013) + feeOnTVVAfterPositiveInterest := sdkmath.NewInt(256_919) + interestPaidAtNegativeRate := sdkmath.NewInt(40_262_904) + feeOnTVVAfterNegativeInterest := sdkmath.NewInt(236_647) tests := []struct { name string @@ -53,16 +56,11 @@ func (s *TestSuite) TestKeeper_ReconcileVault() { inPayoutQueue: true, }, { - name: "interest period has elasped, should pay interest and update period start", - interestRate: "0.25", - periodStart: pastTime.Unix(), - // Fee is calculated on TVV AFTER interest transfer. - // Initial TVV: 1,000,000,000. Interest: 41,952,013. - // TVV after interest: 1,041,952,013. - // Fee: 1,041,952,013 * 0.0015 * 5,184,000 / 31,536,000 = 256,919 - // Total marker change: 41,952,013 - 256,919 = 41,695,094 - expectedVaultAmt: sdkmath.NewInt(958_047_987), - expectedMarkerAmt: sdkmath.NewInt(1_041_695_094), + name: "interest period has elasped, should pay interest and update period start", + interestRate: "0.25", + periodStart: pastTime.Unix(), + expectedVaultAmt: underlying.Amount.Sub(interestEarnedAtPositiveRate), + expectedMarkerAmt: underlying.Amount.Add(interestEarnedAtPositiveRate).Sub(feeOnTVVAfterPositiveInterest), inPayoutQueue: true, expectedEvents: func() sdk.Events { markerAddr := markertypes.MustGetMarkerAddress(shareDenom) @@ -91,7 +89,7 @@ func (s *TestSuite) TestKeeper_ReconcileVault() { nav := createMarkerSetNAV( shareDenom, - sdk.NewCoin(underlying.Denom, sdkmath.NewInt(1_041_695_094)), // NAV updated with fee + sdk.NewCoin(underlying.Denom, sdkmath.NewInt(1_041_695_094)), "vault", totalShares.Amount.Uint64(), ) @@ -101,17 +99,11 @@ func (s *TestSuite) TestKeeper_ReconcileVault() { }, }, { - name: "interest period has elasped, should pay negative interest and update period start", - interestRate: "-0.25", - periodStart: pastTime.Unix(), - // Initial TVV: 1,000,000,000. Interest: -40,262,904. - // TVV after interest: 959,737,096. - // Fee: 959,737,096 * 0.0015 * 5,184,000 / 31,536,000 = 236,647 - // Total marker change: -40,262,904 - 236,647 = -40,499,551 - // Marker: 1,000,000,000 - 40,499,551 = 959,500,449 - // Vault: 1,000,000,000 + 40,262,904 = 1,040,262,904 - expectedVaultAmt: sdkmath.NewInt(1_040_262_904), - expectedMarkerAmt: sdkmath.NewInt(959_500_449), + name: "interest period has elasped, should pay negative interest and update period start", + interestRate: "-0.25", + periodStart: pastTime.Unix(), + expectedVaultAmt: underlying.Amount.Add(interestPaidAtNegativeRate), + expectedMarkerAmt: underlying.Amount.Sub(interestPaidAtNegativeRate).Sub(feeOnTVVAfterNegativeInterest), inPayoutQueue: true, expectedEvents: func() sdk.Events { markerAddr := markertypes.MustGetMarkerAddress(shareDenom) @@ -140,7 +132,7 @@ func (s *TestSuite) TestKeeper_ReconcileVault() { nav := createMarkerSetNAV( shareDenom, - sdk.NewCoin(underlying.Denom, sdkmath.NewInt(959_500_449)), // NAV updated with fee + sdk.NewCoin(underlying.Denom, sdkmath.NewInt(959_500_449)), "vault", totalShares.Amount.Uint64(), ) @@ -201,19 +193,18 @@ func (s *TestSuite) TestKeeper_ReconcileVault() { func (s *TestSuite) TestKeeper_PerformVaultReconcile_CompositeWithOutstandingFee() { shareDenom := "composite.shares" underlyingDenom := "underlying" - paymentDenom := "payment" + heldDenom := "held" vaultAddress := types.GetVaultAddress(shareDenom) testBlockTime := time.Date(2024, 3, 1, 0, 0, 0, 0, time.UTC) sixtyDays := 60 * 24 * time.Hour pastTime := testBlockTime.Add(-sixtyDays) - // Local helper for complex composite setup - setup := func(outstanding sdk.Coin, markerLiquidity sdk.Coins, navPrice *sdk.Coin) *types.VaultAccount { + setupVaultWithHeldAssetAndOutstandingFee := func(outstanding sdk.Coin, markerLiquidity sdk.Coins, heldNavPrice *sdk.Coin) *types.VaultAccount { s.SetupTest() s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlyingDenom, 10_000_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 10_000_000_000), s.adminAddr) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 10_000_000_000), s.adminAddr) - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom) + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) vault.CurrentInterestRate = "0.25" vault.DesiredInterestRate = "0.25" vault.PeriodStart = pastTime.Unix() @@ -223,35 +214,31 @@ func (s *TestSuite) TestKeeper_PerformVaultReconcile_CompositeWithOutstandingFee markerAddr := markertypes.MustGetMarkerAddress(shareDenom) s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr, markerLiquidity), "failed to fund marker account with liquidity") - // Fund reserves to pay interest s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, vaultAddress, sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 1_000_000_000))), "failed to fund vault reserves") - if navPrice == nil { - navPrice = &sdk.Coin{Denom: underlyingDenom, Amount: sdkmath.NewInt(1)} + if heldNavPrice == nil { + heldNavPrice = &sdk.Coin{Denom: underlyingDenom, Amount: sdkmath.NewInt(1)} } - s.setVaultNAV(vault, paymentDenom, *navPrice, 1) + s.setVaultNAV(vault, heldDenom, *heldNavPrice, 1) s.ctx = s.ctx.WithBlockTime(testBlockTime).WithEventManager(sdk.NewEventManager()) return vault } s.Run("Case 1: Full Collection (Sufficient Liquidity)", func() { - outstanding := sdk.NewInt64Coin(paymentDenom, 100_000) + outstanding := sdk.NewInt64Coin(underlyingDenom, 100_000) markerLiquidity := sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1_000_000_000), - sdk.NewInt64Coin(paymentDenom, 1_000_000), // Plenty of payment tokens + sdk.NewInt64Coin(heldDenom, 1_000_000), ) - vault := setup(outstanding, markerLiquidity, nil) // 1:1 Fast-path + vault := setupVaultWithHeldAssetAndOutstandingFee(outstanding, markerLiquidity, nil) - // Interest on GROSS TVV (1,000,000,000 + 1,000,000 = 1,001,000,000) - // 1,001,000,000 * (e^(0.25 * 5184000/31536000) - 1) = 41,993,965 expectedInterest := sdkmath.NewInt(41_993_965) err := s.k.TestAccessor_reconcileVault(s.T(), s.ctx, vault) s.Require().NoError(err, "reconcileVault should not error for case: Full Collection") - // Verify event shows Gross principal events := normalizeEvents(s.ctx.EventManager().Events()) var reconcileEv *sdk.Event for i := range events { @@ -262,7 +249,7 @@ func (s *TestSuite) TestKeeper_PerformVaultReconcile_CompositeWithOutstandingFee } s.Require().NotNil(reconcileEv, "EventVaultReconcile should be emitted in Case 1 (events: %v)", events) s.Require().Equal("1001000000underlying", getAttribute(*reconcileEv, "principal_before"), "principal_before mismatch in Case 1") - s.Require().Equal(expectedInterest.String()+"underlying", getAttribute(*reconcileEv, "interest_earned"), "interest_earned mismatch in Case 1") + s.Require().Equal(expectedInterest.String()+"underlying", getAttribute(*reconcileEv, "interest_earned"), "interest_earned should be 0.25 on gross TVV 1,001,000,000 (underlying + held) over 60 days = 41,993,965 in Case 1") updatedVault, err := s.k.GetVault(s.ctx, vaultAddress) s.Require().NoError(err, "failed to get updated vault") @@ -270,52 +257,39 @@ func (s *TestSuite) TestKeeper_PerformVaultReconcile_CompositeWithOutstandingFee provlabsAddr, err := s.k.GetAUMFeeAddress(s.ctx) s.Require().NoError(err, "failed to get AUM fee address") - // TVV after interest = 1,001,000,000 + 41,993,965 = 1,042,993,965 - // Current Fee (15bps): 1,042,993,965 * 0.0015 * 5184000/31536000 = 257,176 - // Total Debt = 257,176 (current) + 100,000 (outstanding) = 357,176 - s.assertBalance(provlabsAddr, paymentDenom, sdkmath.NewInt(357_176)) + currentFeeOnTVVAfterInterest := sdkmath.NewInt(257_176) + s.assertBalance(provlabsAddr, underlyingDenom, currentFeeOnTVVAfterInterest.Add(outstanding.Amount)) }) - s.Run("Case 2: Partial Collection (Insufficient Liquidity)", func() { - outstanding := sdk.NewInt64Coin(paymentDenom, 1_000_000) - markerLiquidity := sdk.NewCoins( - sdk.NewInt64Coin(underlyingDenom, 1_000_000_000), - sdk.NewInt64Coin(paymentDenom, 100_000), // Only 100k available - ) - vault := setup(outstanding, markerLiquidity, nil) + s.Run("Case 2: Partial Collection (Insufficient Underlying Liquidity)", func() { + outstanding := sdk.NewInt64Coin(underlyingDenom, 1_000_000) + markerLiquidity := sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 100_000)) + vault := setupVaultWithHeldAssetAndOutstandingFee(outstanding, markerLiquidity, nil) + vault.CurrentInterestRate = "0" + vault.DesiredInterestRate = "0" + vault.AumFeeBips = 0 + s.k.AuthKeeper.SetAccount(s.ctx, vault) err := s.k.TestAccessor_reconcileVault(s.T(), s.ctx, vault) s.Require().NoError(err, "reconcileVault should not error for case: Partial Collection") - // TVV = 1,000,100,000 - // Interest on 1,000,100,000 = 41,956,208 - // Updated TVV = 1,042,056,208 - // Fee = 1,042,056,208 * 0.0015 * 5184000/31536000 = 256,945 - // Total Debt = 256,945 (current on Gross) + 1,000_000 (old) = 1,256,945 - // Collected = 100,000 (all available) - // Remaining = 1,156,945 updatedVault, err := s.k.GetVault(s.ctx, vaultAddress) s.Require().NoError(err, "failed to get updated vault") - s.Require().Equal(sdkmath.NewInt(1_156_945), updatedVault.OutstandingAumFee.Amount, "outstanding fee balance mismatch in Case 2") + s.Require().Equal(sdkmath.NewInt(900_000), updatedVault.OutstandingAumFee.Amount, "outstanding fee should be the 1,000,000 liability minus the marker's 100,000 of underlying liquidity collected in Case 2") provlabsAddr, err := s.k.GetAUMFeeAddress(s.ctx) s.Require().NoError(err, "failed to get AUM fee address") - s.assertBalance(provlabsAddr, paymentDenom, sdkmath.NewInt(100_000)) + s.assertBalance(provlabsAddr, underlyingDenom, sdkmath.NewInt(100_000)) }) s.Run("Case 3: Interest Accrual on Debted Assets (Verify Gross Logic)", func() { - // Vault has 1,000,000,000 underlying - // It OWES 500,000,000 payment (Outstanding fee = 500m underlying value) - // But those 500m are STILL in the marker (Gross = 1.5b) - outstanding := sdk.NewInt64Coin(paymentDenom, 500_000_000) + outstanding := sdk.NewInt64Coin(underlyingDenom, 500_000_000) markerLiquidity := sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1_000_000_000), - sdk.NewInt64Coin(paymentDenom, 500_000_000), + sdk.NewInt64Coin(heldDenom, 500_000_000), ) - vault := setup(outstanding, markerLiquidity, nil) + vault := setupVaultWithHeldAssetAndOutstandingFee(outstanding, markerLiquidity, nil) - // Interest on 1.5b (Gross), not 1.0b (Net) - // 1,500,000,000 * (e^(0.25 * 5184000/31536000) - 1) = 62,928,020 expectedInterest := sdkmath.NewInt(62_928_020) err := s.k.TestAccessor_reconcileVault(s.T(), s.ctx, vault) @@ -331,43 +305,33 @@ func (s *TestSuite) TestKeeper_PerformVaultReconcile_CompositeWithOutstandingFee } s.Require().NotNil(reconcileEv, "EventVaultReconcile should be emitted in Case 3 (events: %v)", events) s.Require().Equal("1500000000underlying", getAttribute(*reconcileEv, "principal_before"), "principal_before mismatch in Case 3") - s.Require().Equal(expectedInterest.String()+"underlying", getAttribute(*reconcileEv, "interest_earned"), "interest_earned mismatch in Case 3") + s.Require().Equal(expectedInterest.String()+"underlying", getAttribute(*reconcileEv, "interest_earned"), "interest_earned should accrue on gross TVV 1,500,000,000 (not net of the 500,000,000 fee debt) = 62,928,020 in Case 3") }) s.Run("Case 4: Net Valuation for Share Pricing", func() { - outstanding := sdk.NewInt64Coin(paymentDenom, 100_000_000) + outstanding := sdk.NewInt64Coin(underlyingDenom, 100_000_000) markerLiquidity := sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 1_000_000_000)) - vault := setup(outstanding, markerLiquidity, nil) - - // GROSS = 1,000,000,000 - // NET = 1,000,000,000 - 100,000,000 = 900,000_000 + vault := setupVaultWithHeldAssetAndOutstandingFee(outstanding, markerLiquidity, nil) tvv, err := s.k.GetTVVInUnderlyingAsset(s.ctx, *vault) s.Require().NoError(err, "failed to get TVV in underlying asset") s.Require().Equal(sdkmath.NewInt(1_000_000_000), tvv, "GetTVV returns Gross") - // Valuation should return Net - // Interest on Gross (1b) = 41,952,013 - // Fee on Updated Gross (1,041,952,013) = 256,919 - // Debt = 100,000,000 - // Net Valuation = (1,000,000,000 + 41,952,013) - 256,919 - 100,000,000 = 941,695,094 expectedNetValuation := sdkmath.NewInt(941_695_094) val, err := s.k.CalculateVaultTotalAssets(s.ctx, vault, sdk.NewInt64Coin(underlyingDenom, 1_000_000_000)) s.Require().NoError(err, "CalculateVaultTotalAssets should not error for case: Net Valuation for Share Pricing") - s.Require().Equal(expectedNetValuation, val, "valuation should be Net of outstanding fees") + s.Require().Equal(expectedNetValuation, val, "valuation should be net of outstanding fees: gross 1,000,000,000 + interest 41,952,013 - fee 256,919 - debt 100,000,000 = 941,695,094") }) s.Run("Case 5: Negative Interest with Liabilities", func() { - outstanding := sdk.NewInt64Coin(paymentDenom, 100_000) + outstanding := sdk.NewInt64Coin(underlyingDenom, 100_000) markerLiquidity := sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 1_000_000_000)) - vault := setup(outstanding, markerLiquidity, nil) + vault := setupVaultWithHeldAssetAndOutstandingFee(outstanding, markerLiquidity, nil) vault.CurrentInterestRate = "-0.25" vault.DesiredInterestRate = "-0.25" s.k.AuthKeeper.SetAccount(s.ctx, vault) - // Negative Interest on Gross (1,000,000,000) - // 1,000,000,000 * (e^(-0.25 * 5184000/31536000) - 1) = -40,262,904 expectedRefund := sdkmath.NewInt(40_262_904) err := s.k.TestAccessor_reconcileVault(s.T(), s.ctx, vault) @@ -382,73 +346,44 @@ func (s *TestSuite) TestKeeper_PerformVaultReconcile_CompositeWithOutstandingFee } } s.Require().NotNil(reconcileEv, "EventVaultReconcile should be emitted in Case 5 (events: %v)", events) - s.Require().Equal(expectedRefund.Neg().String()+"underlying", getAttribute(*reconcileEv, "interest_earned"), "interest_earned mismatch in Case 5") + s.Require().Equal(expectedRefund.Neg().String()+"underlying", getAttribute(*reconcileEv, "interest_earned"), "interest_earned should be -0.25 on gross TVV 1,000,000,000 over 60 days = -40,262,904 in Case 5") - // Vault reserves should increase by refund - s.assertBalance(vaultAddress, underlyingDenom, sdkmath.NewInt(1_040_262_904)) - }) - - s.Run("Case 6: Non-1:1 NAV Composite Conversion", func() { - // Outstanding in Payment tokens - // NAV: 1 payment = 2 underlying - outstanding := sdk.NewInt64Coin(paymentDenom, 50_000_000) // Value 100m underlying - markerLiquidity := sdk.NewCoins( - sdk.NewInt64Coin(underlyingDenom, 500_000_000), - sdk.NewInt64Coin(paymentDenom, 250_000_000), // Value 500m underlying - ) - // Gross TVV = 500m + (250m * 2) = 1,000,000,000 - vault := setup(outstanding, markerLiquidity, &sdk.Coin{Denom: underlyingDenom, Amount: sdkmath.NewInt(2)}) - - // Accruals on Gross (1b) - // Interest = 41,952,013 - // Fee = 256,919 - // Debt (Net of NAV) = 50,000,000 * 2 = 100,000,000 - // Net Valuation = (1,000,000,000 + 41,952,013) - 256,919 - 100,000,000 = 941,695,094 - - val, err := s.k.CalculateVaultTotalAssets(s.ctx, vault, sdk.NewInt64Coin(underlyingDenom, 1_000_000_000)) - s.Require().NoError(err, "CalculateVaultTotalAssets should not error for case: Non-1:1 NAV Composite Conversion") - s.Require().Equal(sdkmath.NewInt(941_695_094), val, "valuation should correctly convert secondary debt via NAV") + s.assertBalance(vaultAddress, underlyingDenom, sdkmath.NewInt(1_000_000_000).Add(expectedRefund)) }) } func (s *TestSuite) TestKeeper_ReconcileLeavesUncollectedFee_PricesOffNetTVV() { shareDenom := "underfunded.shares" underlyingDenom := "underlying" - paymentDenom := "payment" + heldDenom := "held" vaultAddress := types.GetVaultAddress(shareDenom) testBlockTime := time.Date(2024, 3, 1, 0, 0, 0, 0, time.UTC) pastTime := testBlockTime.Add(-60 * 24 * time.Hour) s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlyingDenom, 10_000_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 10_000_000_000), s.adminAddr) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 10_000_000_000), s.adminAddr) - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom) + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) vault.CurrentInterestRate = "0" vault.DesiredInterestRate = "0" vault.AumFeeBips = 0 vault.PeriodStart = pastTime.Unix() vault.FeePeriodStart = pastTime.Unix() - vault.OutstandingAumFee = sdk.NewInt64Coin(paymentDenom, 100_000_000) + vault.OutstandingAumFee = sdk.NewInt64Coin(underlyingDenom, 100_000_000) totalShares := sdk.NewInt64Coin(shareDenom, 1_000_000) vault.TotalShares = totalShares s.k.AuthKeeper.SetAccount(s.ctx, vault) s.Require().NoError(s.k.MarkerKeeper.MintCoin(s.ctx, vault.GetAddress(), totalShares), "should mint share supply") - paymentMarkerAddr := markertypes.MustGetMarkerAddress(paymentDenom) - paymentMarkerAccount, err := s.k.MarkerKeeper.GetMarker(s.ctx, paymentMarkerAddr) - s.Require().NoError(err, "should fetch payment marker for NAV setup") - s.Require().NoError(s.k.MarkerKeeper.SetNetAssetValue(s.ctx, paymentMarkerAccount, markertypes.NetAssetValue{ - Price: sdk.NewInt64Coin(underlyingDenom, 1), - Volume: 1, - }, "test"), "should set payment->underlying NAV at 1:1") + s.setVaultNAV(vault, heldDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, vault.PrincipalMarkerAddress(), sdk.NewCoins( - sdk.NewInt64Coin(underlyingDenom, 1_000_000_000), - )), "should fund principal marker with underlying only, leaving no payment-denom liquidity to pay the fee") + sdk.NewInt64Coin(heldDenom, 1_000_000_000), + )), "should fund principal marker with the held asset only, leaving no underlying liquidity to pay the fee") s.SetCtxBlockTime(testBlockTime) - err = s.k.TestAccessor_reconcileVault(s.T(), s.ctx, vault) + err := s.k.TestAccessor_reconcileVault(s.T(), s.ctx, vault) s.Require().NoError(err, "reconcileVault should not error") reconciled, err := s.k.GetVault(s.ctx, vaultAddress) @@ -457,7 +392,7 @@ func (s *TestSuite) TestKeeper_ReconcileLeavesUncollectedFee_PricesOffNetTVV() { s.Require().Equal(sdkmath.NewInt(100_000_000), reconciled.OutstandingAumFee.Amount, "fee could not be collected, so the full liability survives reconcile") provlabsAddr, err := s.k.GetAUMFeeAddress(s.ctx) s.Require().NoError(err, "should get AUM fee address") - s.assertBalance(provlabsAddr, paymentDenom, sdkmath.ZeroInt()) + s.assertBalance(provlabsAddr, underlyingDenom, sdkmath.ZeroInt()) grossTVV, err := s.k.GetTVVInUnderlyingAsset(s.ctx, *reconciled) s.Require().NoError(err, "should compute gross TVV") @@ -467,7 +402,7 @@ func (s *TestSuite) TestKeeper_ReconcileLeavesUncollectedFee_PricesOffNetTVV() { s.Require().Equal(sdkmath.NewInt(900_000_000), netTVV, "net TVV = gross 1,000,000,000 minus outstanding fee 100,000,000, so gross > net even after reconcile") grossView := *reconciled - grossView.OutstandingAumFee = sdk.NewInt64Coin(paymentDenom, 0) + grossView.OutstandingAumFee = sdk.NewInt64Coin(underlyingDenom, 0) navNet, err := s.k.GetNAVPerShareInUnderlyingAsset(s.ctx, *reconciled) s.Require().NoError(err, "should compute net NAV per share") @@ -484,9 +419,9 @@ func (s *TestSuite) TestKeeper_ReconcileLeavesUncollectedFee_PricesOffNetTVV() { s.Require().True(netMint.Amount.GT(grossMint.Amount), "net pricing mints more shares per deposit than gross would (gross overstates TVV)") redeemShares := sdkmath.NewInt(100_000) - netRedeem, err := s.k.ConvertSharesToRedeemCoin(s.ctx, *reconciled, redeemShares, underlyingDenom) + netRedeem, err := s.k.ConvertSharesToRedeemCoin(s.ctx, *reconciled, redeemShares) s.Require().NoError(err, "net redeem conversion should succeed") - grossRedeem, err := s.k.ConvertSharesToRedeemCoin(s.ctx, grossView, redeemShares, underlyingDenom) + grossRedeem, err := s.k.ConvertSharesToRedeemCoin(s.ctx, grossView, redeemShares) s.Require().NoError(err, "gross redeem conversion should succeed") s.Require().True(netRedeem.Amount.LT(grossRedeem.Amount), "net pricing pays out less per share than gross would (gross overstates TVV)") } @@ -496,7 +431,7 @@ func (s *TestSuite) TestKeeper_CalculateVaultTotalAssets() { underlying := sdk.NewInt64Coin("underlying", 1_000_000_000) vaultAddress := types.GetVaultAddress(shareDenom) testBlockTime := time.Now() - pastTime := testBlockTime.Add(-60 * 24 * time.Hour) // ~2 months + pastTime := testBlockTime.Add(-60 * 24 * time.Hour) setup := func(interestRate string, periodStartSeconds int64) *types.VaultAccount { s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) @@ -774,12 +709,9 @@ func (s *TestSuite) TestKeeper_HandleReconciledVaults() { expectedEvents sdk.Events }{ { - name: "no vaults in store", - setup: func() { - // No setup needed, store is empty - }, + name: "no vaults in store", + setup: func() {}, postCheck: func() { - // No vaults to check vaults, err := s.k.GetVaults(s.ctx) s.Require().NoError(err, "no vaults: GetVaults should not error") s.Require().Empty(vaults, "no vaults: vaults should be empty") @@ -819,9 +751,7 @@ func (s *TestSuite) TestKeeper_HandleReconciledVaults() { { name: "two vaults reconciled, one payable, one depleted", setup: func() { - // Vault 1: payable createVaultWithInterest(s, v1, "0.1", testBlockTime.Unix(), testBlockTime.Unix(), true, true) - // Vault 2: depleted createVaultWithInterest(s, v2, "0.1", testBlockTime.Unix(), testBlockTime.Unix(), false, true) }, postCheck: func() { @@ -846,7 +776,7 @@ func (s *TestSuite) TestKeeper_HandleReconciledVaults() { s.k.AuthKeeper.SetAccount(s.ctx, vault) }, postCheck: func() { - s.assertInPayoutVerificationQueue(v1.vaultAddr, true) // Should still be in the queue + s.assertInPayoutVerificationQueue(v1.vaultAddr, true) }, expectErr: false, expectedEvents: sdk.Events{}, @@ -1259,41 +1189,28 @@ func (s *TestSuite) TestKeeper_CanPayInterestDuration_NegativeInterest_Composite shareDenom := "vaultshares.composite" underlyingDenom := "uylds.fcc.receipt.token" - paymentDenom := "uylds.fcc" + heldDenom := "uylds.fcc" underlying := sdk.NewInt64Coin(underlyingDenom, 1_000_000_000) vaultAddr := types.GetVaultAddress(shareDenom) markerAddr := markertypes.MustGetMarkerAddress(shareDenom) s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 10_000_000_000_000), s.adminAddr) - - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: s.adminAddr.String(), - ShareDenom: shareDenom, - UnderlyingAsset: underlyingDenom, - PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlyingDenom, 1), - Volume: sdkmath.OneInt(), - }, - }) - s.Require().NoError(err, "failed to create composite vault in TestKeeper_CanPayInterestDuration_NegativeInterest_Composite_InsufficientUnderlying") + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 10_000_000_000_000), s.adminAddr) - vault, err := s.k.GetVault(s.ctx, vaultAddr) - s.Require().NoError(err, "failed to get composite vault in TestKeeper_CanPayInterestDuration_NegativeInterest_Composite_InsufficientUnderlying") + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) + s.setVaultNAV(vault, heldDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) vault.CurrentInterestRate = "-0.5" vault.DesiredInterestRate = "-0.5" s.k.AuthKeeper.SetAccount(s.ctx, vault) - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, vaultAddr, sdk.NewCoins(sdk.NewCoin(underlyingDenom, sdkmath.NewInt(1_000_000)))), "failed to fund composite vault in TestKeeper_CanPayInterestDuration_NegativeInterest_Composite_InsufficientUnderlying") tinyUnderlying := sdkmath.NewInt(10_000_000) - hugePayment := sdkmath.NewInt(10_000_000_000_000) + hugeHeld := sdkmath.NewInt(10_000_000_000_000) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr, sdk.NewCoins(sdk.NewCoin(underlyingDenom, tinyUnderlying), sdk.NewCoin(paymentDenom, hugePayment))), "failed to fund marker account") + s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr, sdk.NewCoins(sdk.NewCoin(underlyingDenom, tinyUnderlying), sdk.NewCoin(heldDenom, hugeHeld))), "failed to fund marker account") year := int64(365 * 24 * time.Hour / time.Second) @@ -1369,12 +1286,12 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_PositiveInterest_Use endVault := s.simApp.BankKeeper.GetBalance(s.ctx, vaultAddr, underlying.Denom).Amount endMarker := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, underlying.Denom).Amount + sixtyDayAumFee := sdkmath.NewInt(256_919) expectedVault := startVault.Sub(interestEarned) - // Fee for 1,041,952,013 TVV for 60 days is 256,919. - expectedMarker := startMarker.Add(interestEarned).Sub(sdkmath.NewInt(256_919)) + expectedMarker := startMarker.Add(interestEarned).Sub(sixtyDayAumFee) s.Require().Equal(expectedVault, endVault, "vault reserves mismatch") - s.Require().Equal(sdkmath.NewInt(1_041_695_094), endMarker, "marker principal mismatch") + s.Require().Equal(sdkmath.NewInt(1_041_695_094), endMarker, "marker principal should be 1,000,000,000 plus interest 41,952,013 minus the 60-day AUM fee 256,919") s.assertVaultAndMarkerBalances( vaultAddr, @@ -1432,7 +1349,7 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_PositiveInterest_Use shareDenom := "nvylds.shares.composite" underlying := sdk.NewInt64Coin("uylds.fcc.receipt.token", 1_000_000_000) - paymentDenom := "uylds.fcc" + heldDenom := "uylds.fcc" vaultAddr := types.GetVaultAddress(shareDenom) markerAddr := markertypes.MustGetMarkerAddress(shareDenom) @@ -1440,29 +1357,16 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_PositiveInterest_Use periodStart := now.Add(-60 * 24 * time.Hour).Unix() s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000_000), s.adminAddr) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 1_000_000_000), s.adminAddr) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: s.adminAddr.String(), - ShareDenom: shareDenom, - UnderlyingAsset: underlying.Denom, - PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlying.Denom, 1), - Volume: sdkmath.OneInt(), - }, - }) - s.Require().NoError(err, "expected CreateVault to succeed") - - vault, err := s.k.GetVault(s.ctx, vaultAddr) - s.Require().NoError(err, "expected GetVault to succeed after CreateVault") + vault := s.CreateVaultWithParams(shareDenom, underlying.Denom) + s.setVaultNAV(vault, heldDenom, sdk.NewInt64Coin(underlying.Denom, 1), 1) vault.CurrentInterestRate = "0.25" vault.DesiredInterestRate = "0.25" vault.PeriodStart = periodStart vault.FeePeriodStart = periodStart s.k.AuthKeeper.SetAccount(s.ctx, vault) - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlying.Denom, 1), 1) s.Require().NoError( FundAccount(s.ctx, s.simApp.BankKeeper, vaultAddr, sdk.NewCoins(underlying)), @@ -1470,12 +1374,12 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_PositiveInterest_Use ) receiptPortion := sdkmath.NewInt(950_000_000) - paymentPortion := sdkmath.NewInt(50_000_000) + heldPortion := sdkmath.NewInt(50_000_000) s.Require().NoError( FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr, sdk.NewCoins( sdk.NewCoin(underlying.Denom, receiptPortion), - sdk.NewCoin(paymentDenom, paymentPortion), + sdk.NewCoin(heldDenom, heldPortion), )), "expected funding composite principal to succeed", ) @@ -1484,11 +1388,11 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_PositiveInterest_Use startVault := s.simApp.BankKeeper.GetBalance(s.ctx, vaultAddr, underlying.Denom).Amount startMarkerUnderlying := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, underlying.Denom).Amount - startMarkerPayment := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, paymentDenom).Amount + startMarkerHeld := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, heldDenom).Amount s.Require().Equal(underlying.Amount, startVault, "expected initial vault reserves to equal funded amount") s.Require().Equal(receiptPortion, startMarkerUnderlying, "expected marker underlying balance to equal receipt portion") - s.Require().Equal(paymentPortion, startMarkerPayment, "expected marker payment balance to equal payment portion") + s.Require().Equal(heldPortion, startMarkerHeld, "expected marker held-asset balance to equal held portion") principalTvv, err := s.k.GetTVVInUnderlyingAsset(s.ctx, *vault) s.Require().NoError(err, "expected GetTVVInUnderlyingAsset to succeed") @@ -1506,15 +1410,15 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_PositiveInterest_Use endVault := s.simApp.BankKeeper.GetBalance(s.ctx, vaultAddr, underlying.Denom).Amount endMarkerUnderlying := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, underlying.Denom).Amount - endMarkerPayment := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, paymentDenom).Amount + endMarkerHeld := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, heldDenom).Amount + sixtyDayAumFee := sdkmath.NewInt(256_919) expectedVault := startVault.Sub(interestEarned) - expectedMarkerUnderlying := startMarkerUnderlying.Add(interestEarned) - // Fee: 1,041,952,013 * 0.0015 * 5,184,000 / 31,536,000 = 256,920 + expectedMarkerUnderlying := startMarkerUnderlying.Add(interestEarned).Sub(sixtyDayAumFee) s.Require().Equal(expectedVault, endVault, "expected vault reserves to decrease by TVV-based interest") - s.Require().Equal(expectedMarkerUnderlying, endMarkerUnderlying, "expected marker underlying balance to increase by TVV-based interest") - s.Require().Equal(sdkmath.NewInt(49_743_081), endMarkerPayment, "expected marker payment token balance to decrease by AUM fee") + s.Require().Equal(expectedMarkerUnderlying, endMarkerUnderlying, "expected marker underlying balance to rise by interest and fall by the 15bps 60-day AUM fee of 256,919 on post-interest TVV") + s.Require().Equal(heldPortion, endMarkerHeld, "expected marker held-asset balance to be untouched by the underlying-denominated fee") s.assertVaultAndMarkerBalances( vaultAddr, @@ -1544,7 +1448,6 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_PositiveInterest_Use } expectedPrincipalBefore := sdk.NewCoin(underlying.Denom, principalTvv) - // principal_after in EventVaultReconcile reflects state AFTER interest but BEFORE AUM fees. expectedPrincipalAfter := expectedPrincipalBefore.Add(sdk.NewCoin(underlying.Denom, interestEarned)) s.Require().Equal( @@ -1556,7 +1459,7 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_PositiveInterest_Use s.Require().Equal( expectedPrincipalAfter.String(), principalAfterStr, - "expected principal_after to reflect TVV-based principal after transfer", + "expected principal_after to reflect TVV-based principal after interest but before AUM fees", ) s.Require().Equal( @@ -1645,7 +1548,7 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_NegativeInterest_Com shareDenom := "nvylds.shares.composite.neg" underlyingDenom := "uylds.fcc.receipt" - paymentDenom := "uylds.fcc" + heldDenom := "uylds.fcc" vaultAddr := types.GetVaultAddress(shareDenom) markerAddr := markertypes.MustGetMarkerAddress(shareDenom) @@ -1653,54 +1556,38 @@ func (s *TestSuite) TestKeeper_PerformVaultInterestTransfer_NegativeInterest_Com periodStart := now.Add(-365 * 24 * time.Hour).Unix() s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlyingDenom, 1000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000_000), s.adminAddr) - - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: s.adminAddr.String(), - ShareDenom: shareDenom, - UnderlyingAsset: underlyingDenom, - PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlyingDenom, 1), - Volume: sdkmath.OneInt(), - }, - }) - s.Require().NoError(err, "CreateVault with composite structure should succeed") + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 1_000_000_000), s.adminAddr) - vault, err := s.k.GetVault(s.ctx, vaultAddr) - s.Require().NoError(err, "GetVault should return the created vault") + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) + s.setVaultNAV(vault, heldDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) vault.CurrentInterestRate = "-0.5" vault.DesiredInterestRate = "-0.5" vault.PeriodStart = periodStart vault.FeePeriodStart = periodStart s.k.AuthKeeper.SetAccount(s.ctx, vault) - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, vaultAddr, sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 1_000_000))), "Funding vault should succeed") - hugeOtherBalance := sdk.NewInt64Coin(paymentDenom, 1_000_000_000) + hugeHeldBalance := sdk.NewInt64Coin(heldDenom, 1_000_000_000) tinyUnderlyingBalance := sdk.NewInt64Coin(underlyingDenom, 10) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr, sdk.NewCoins(hugeOtherBalance, tinyUnderlyingBalance)), "Funding marker with composite assets should succeed") + s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, markerAddr, sdk.NewCoins(hugeHeldBalance, tinyUnderlyingBalance)), "Funding marker with composite assets should succeed") s.ctx = s.ctx.WithBlockTime(now).WithEventManager(sdk.NewEventManager()) tvv, err := s.k.GetTVVInUnderlyingAsset(s.ctx, *vault) s.Require().NoError(err, "GetTVVInUnderlyingAsset should succeed") - s.Require().True(tvv.GT(sdkmath.NewInt(100_000)), "TVV should be significantly higher than the underlying balance due to secondary assets") + s.Require().True(tvv.GT(sdkmath.NewInt(100_000)), "TVV should be significantly higher than the underlying balance due to the held asset") err = s.k.TestAccessor_reconcileVault(s.T(), s.ctx, vault) s.Require().NoError(err, "ReconcileVault should not error even if underlying liquidity is insufficient for full negative interest") endUnderlying := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, underlyingDenom) - endOther := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, paymentDenom) + endHeld := s.simApp.BankKeeper.GetBalance(s.ctx, markerAddr, heldDenom) - s.Require().True(endUnderlying.IsZero(), "Underlying asset should be fully depleted") - // TVV: 1,000,000,000 other + 10 underlying = 1,000,000,010 - // Fee = 1,000,000,010 * 0.0015 * 1 year / 1 year = 1,500,000 - expectedOther := hugeOtherBalance.Amount.Sub(sdkmath.NewInt(1_500_000)) - s.Require().Equal(expectedOther, endOther.Amount, "Secondary asset balance should decrease by AUM fee") + s.Require().True(endUnderlying.IsZero(), "Underlying asset should be fully depleted by the capped negative interest") + s.Require().Equal(hugeHeldBalance.Amount, endHeld.Amount, "Held asset should be untouched by the underlying-denominated fee once underlying is depleted") } func (s *TestSuite) TestKeeper_setShareDenomNAV() { @@ -2029,7 +1916,6 @@ func (s *TestSuite) TestKeeper_publishShareNav_NAVLifecycle() { func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { tests := []struct { name string - paymentDenom string aumFeeBips uint32 initialLiquidity sdkmath.Int expectedFeeTotal sdkmath.Int @@ -2041,7 +1927,6 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { }{ { name: "partial collection then full (default 15 bps)", - paymentDenom: "uylds.fcc", aumFeeBips: 15, initialLiquidity: sdkmath.NewInt(100_000), expectedFeeTotal: sdkmath.NewInt(246_600), @@ -2053,7 +1938,6 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { }, { name: "partial collection then full (100 bps)", - paymentDenom: "uylds.fcc", aumFeeBips: 100, initialLiquidity: sdkmath.NewInt(100_000), expectedFeeTotal: sdkmath.NewInt(1_644_000), @@ -2065,7 +1949,6 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { }, { name: "zero fee collection", - paymentDenom: "uylds.fcc", aumFeeBips: 0, initialLiquidity: sdkmath.NewInt(100_000), expectedFeeTotal: sdkmath.NewInt(0), @@ -2082,20 +1965,21 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { s.SetupTest() shareDenom := "fee.shares" underlyingDenom := "uylds.fcc.receipt" - underlying := sdk.NewInt64Coin(underlyingDenom, 1_000_000_000) + heldDenom := "uylds.fcc" + heldAmount := sdkmath.NewInt(1_000_000_000) vaultAddr := types.GetVaultAddress(shareDenom) now := s.ctx.BlockTime() twoMonthsAgo := now.Add(-60 * 24 * time.Hour) - s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(tc.paymentDenom, 1_000_000_000), s.adminAddr) - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, tc.paymentDenom) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlyingDenom, 1_000_000_000), s.adminAddr) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 1_000_000_000), s.adminAddr) + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) vault.AumFeeBips = tc.aumFeeBips s.SetVaultRatesAndPeriod(vault, "0.0", "0.0", twoMonthsAgo.Unix(), 0) - s.setVaultNAV(vault, tc.paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) + s.setVaultNAV(vault, heldDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) - s.FundMarker(shareDenom, sdk.NewCoins(underlying)) - s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewCoin(tc.paymentDenom, tc.initialLiquidity))) + s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewCoin(heldDenom, heldAmount))) + s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewCoin(underlyingDenom, tc.initialLiquidity))) s.SetCtxBlockTime(now) @@ -2103,14 +1987,12 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { s.Require().NoError(err, "PerformVaultFeeTransfer should not error during initial collection") s.Require().NoError(s.k.SetVaultAccount(s.ctx, vault), "SetVaultAccount should succeed after initial collection") - // Verify partial collection provlabsAddr, err := s.k.GetAUMFeeAddress(s.ctx) s.Require().NoError(err, "failed to get AUM fee address from GetAUMFeeAddress") - s.assertBalance(provlabsAddr, tc.paymentDenom, tc.expectedCollected) + s.assertBalance(provlabsAddr, underlyingDenom, tc.expectedCollected) s.Require().Equal(tc.expectedOutstanding, vault.OutstandingAumFee.Amount, "outstanding fee balance mismatch") - // Check event events := normalizeEvents(s.ctx.EventManager().Events()) found := false for _, ev := range events { @@ -2121,12 +2003,12 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { expectedEv := createVaultFeeCollectedEvent( vaultAddr, snapshot, - sdk.NewCoin(tc.paymentDenom, tc.expectedCollected), - sdk.NewCoin(tc.paymentDenom, tc.expectedFeeTotal), - sdk.NewCoin(tc.paymentDenom, tc.expectedOutstanding), + sdk.NewCoin(underlyingDenom, tc.expectedCollected), + sdk.NewCoin(underlyingDenom, tc.expectedFeeTotal), + sdk.NewCoin(underlyingDenom, tc.expectedOutstanding), int64(60*24*time.Hour/time.Second), ) - s.Assert().Equal(normalizeEvent(expectedEv), ev, "EventVaultFeeCollected mismatch") + s.Assert().Equal(normalizeEvent(expectedEv), ev, "EventVaultFeeCollected mismatch: aum snapshot should equal gross TVV (held 1,000,000,000 priced 1:1 plus underlying liquidity)") } } s.Require().Equal(!tc.expectedFeeTotal.IsZero(), found, "EventVaultFeeCollected emission mismatch") @@ -2135,9 +2017,8 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { return } - // Second collection s.SetCtxBlockTime(now.Add(time.Second)) - s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewCoin(tc.paymentDenom, tc.secondLiquidity))) + s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewCoin(underlyingDenom, tc.secondLiquidity))) err = s.k.PerformVaultFeeTransfer(s.ctx, vault) s.Require().NoError(err, "PerformVaultFeeTransfer should not error during second collection") @@ -2147,19 +2028,19 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer() { s.Require().NoError(err, "failed to get vault for share denom %s", shareDenom) s.Require().Equal(s.ctx.BlockTime().Unix(), vault.FeePeriodStart, "FeePeriodStart should be updated") s.Require().True(vault.OutstandingAumFee.IsZero(), "outstanding fee should be cleared") - s.assertBalance(markertypes.MustGetMarkerAddress(shareDenom), tc.paymentDenom, tc.expectedFinalMarker) + s.assertBalance(markertypes.MustGetMarkerAddress(shareDenom), underlyingDenom, tc.expectedFinalMarker) }) } } func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer_OversizedTVVDegradesToError() { - vault, _, underlyingDenom, paymentDenom := s.setupOversizedNAVVault() - s.seedOversizedNAV(vault, paymentDenom, underlyingDenom, maxValidNAVPrice(), sdkmath.OneInt()) + vault, _, underlyingDenom, heldDenom := s.setupOversizedNAVVault() + s.seedOversizedNAV(vault, heldDenom, underlyingDenom, maxValidNAVPrice(), sdkmath.OneInt()) principalAddress := vault.PrincipalMarkerAddress() s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, principalAddress, sdk.NewCoins( - sdk.NewInt64Coin(paymentDenom, 1), - )), "funding principal with one payment unit should drive TVV to the 256-bit ceiling") + sdk.NewInt64Coin(heldDenom, 1), + )), "funding principal with one held-asset unit should drive TVV to the 256-bit ceiling") now := s.ctx.BlockTime() twoMonthsAgo := now.Add(-60 * 24 * time.Hour) @@ -2176,20 +2057,17 @@ func (s *TestSuite) TestKeeper_PerformVaultFeeTransfer_OutstandingFeeOverflowDeg s.SetupTest() shareDenom := "fee.shares" underlyingDenom := "uylds.fcc.receipt" - paymentDenom := "uylds.fcc" underlying := sdk.NewInt64Coin(underlyingDenom, 1_000_000_000) now := s.ctx.BlockTime() twoMonthsAgo := now.Add(-60 * 24 * time.Hour) s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000_000), s.adminAddr) - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom) + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) vault.AumFeeBips = 100 - vault.OutstandingAumFee = sdk.NewCoin(paymentDenom, maxValidNAVPrice()) + vault.OutstandingAumFee = sdk.NewCoin(underlyingDenom, maxValidNAVPrice()) s.SetVaultRatesAndPeriod(vault, "0.0", "0.0", twoMonthsAgo.Unix(), 0) s.FundMarker(shareDenom, sdk.NewCoins(underlying)) - s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewCoin(paymentDenom, sdkmath.NewInt(100_000)))) s.SetCtxBlockTime(now) err := s.k.PerformVaultFeeTransfer(s.ctx, vault) @@ -2201,12 +2079,10 @@ func (s *TestSuite) TestKeeper_CanPayInterestDuration_WithAUMFee() { s.SetupTest() shareDenom := "fee.payout.shares" underlyingDenom := "underlying" - paymentDenom := "uylds.fcc" underlying := sdk.NewInt64Coin(underlyingDenom, 1_000_000_000) s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000_000), s.adminAddr) - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom) + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) s.SetVaultRatesAndPeriod(vault, "0.0", "", 0, 0) s.FundMarker(shareDenom, sdk.NewCoins(underlying)) @@ -2214,14 +2090,13 @@ func (s *TestSuite) TestKeeper_CanPayInterestDuration_WithAUMFee() { ok, err := s.k.CanPayInterestDuration(s.ctx, vault, year) s.Require().NoError(err, "CanPayInterestDuration returned error for vault=%s year=%d", vault.Address, year) - s.Require().True(ok, "should succeed even when no payment denom liquidity for fees (deferred)") + s.Require().True(ok, "should succeed because a zero interest rate never requires reserves regardless of AUM fees") } func (s *TestSuite) TestKeeper_HandleVaultFeeTimeouts() { s.SetupTest() shareDenom := "fee.timeout.shares" underlyingDenom := "underlying" - paymentDenom := "uylds.fcc" underlying := sdk.NewInt64Coin(underlyingDenom, 1_000_000_000) vaultAddr := types.GetVaultAddress(shareDenom) @@ -2229,11 +2104,9 @@ func (s *TestSuite) TestKeeper_HandleVaultFeeTimeouts() { twoMonthsAgo := now.Add(-60 * 24 * time.Hour) s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000_000), s.adminAddr) - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom) + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) s.SetVaultRatesAndPeriod(vault, "0.0", "0.0", twoMonthsAgo.Unix(), twoMonthsAgo.Unix()) - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 1) - s.FundMarker(shareDenom, sdk.NewCoins(underlying, sdk.NewInt64Coin(paymentDenom, 10_000_000))) + s.FundMarker(shareDenom, sdk.NewCoins(underlying)) s.Require().NoError(s.k.FeeTimeoutQueue.Enqueue(s.ctx, twoMonthsAgo.Unix(), vaultAddr), "failed to enqueue vault in FeeTimeoutQueue") @@ -2243,7 +2116,7 @@ func (s *TestSuite) TestKeeper_HandleVaultFeeTimeouts() { provlabsAddr, err := s.k.GetAUMFeeAddress(s.ctx) s.Require().NoError(err, "failed to get AUM fee address from GetAUMFeeAddress") - feeCollected := s.simApp.BankKeeper.GetBalance(s.ctx, provlabsAddr, paymentDenom).Amount + feeCollected := s.simApp.BankKeeper.GetBalance(s.ctx, provlabsAddr, underlyingDenom).Amount s.Require().True(feeCollected.IsPositive(), "fee should be collected for address %s", provlabsAddr) found := false @@ -2373,97 +2246,32 @@ func (s *TestSuite) TestKeeper_AccrualCalculations() { } }) - s.Run("CalculateOutstandingFeeUnderlying", func() { - s.SetupTest() - vault := setup() - - tests := []struct { - name string - paymentDenom string - navPrice int64 - navVolume int64 - outstanding sdk.Coin - expected sdkmath.Int - }{ - { - name: "no outstanding fee, should return zero", - outstanding: sdk.NewInt64Coin(underlyingDenom, 0), - expected: sdkmath.ZeroInt(), - }, - { - name: "outstanding fee in underlying denom, should return same amount", - outstanding: sdk.NewInt64Coin(underlyingDenom, 500), - expected: sdkmath.NewInt(500), - }, - { - name: "outstanding fee in payment denom with 1:1 internal NAV, should return 1:1 amount", - paymentDenom: "uylds.fcc", - navPrice: 1, - navVolume: 1, - outstanding: sdk.NewInt64Coin("uylds.fcc", 1000), - expected: sdkmath.NewInt(1000), - }, - } - - for _, tc := range tests { - s.Run(tc.name, func() { - if tc.paymentDenom != "" { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(tc.paymentDenom, 1_000_000), s.adminAddr) - s.setVaultPaymentDenomWithNAV(vault, tc.paymentDenom, sdk.NewInt64Coin(underlyingDenom, tc.navPrice), tc.navVolume) - } - vault.OutstandingAumFee = tc.outstanding - amt, err := s.k.CalculateOutstandingFeeUnderlying(s.ctx, *vault) - s.Require().NoError(err, "outstanding fee conversion failed for case: %s", tc.name) - s.Require().Equal(tc.expected, amt, "outstanding fee underlying amount mismatch for case: %s", tc.name) - }) - } - }) - s.Run("CalculateAccruedAUMFeePayment", func() { s.SetupTest() vault := setup() tests := []struct { - name string - start int64 - paymentDenom string - setupNav bool - expected sdk.Coin + name string + start int64 + expected sdk.Coin }{ { - name: "no fee period start, should return zero coin", - start: 0, - paymentDenom: underlyingDenom, - expected: sdk.NewInt64Coin(underlyingDenom, 0), - }, - { - name: "valid period with 1:1 payment denom, should return same amount", - start: pastTime.Unix(), - paymentDenom: underlyingDenom, - expected: sdk.NewInt64Coin(underlyingDenom, 246_575), + name: "no fee period start, should return zero coin", + start: 0, + expected: sdk.NewInt64Coin(underlyingDenom, 0), }, { - name: "valid period with 1:2 NAV record, should return doubled amount", - start: pastTime.Unix(), - paymentDenom: "usdc", - setupNav: true, - expected: sdk.NewInt64Coin("usdc", 493_150), + name: "valid period, should return the fee in the underlying asset", + start: pastTime.Unix(), + expected: sdk.NewInt64Coin(underlyingDenom, 246_575), }, } for _, tc := range tests { s.Run(tc.name, func() { vault.FeePeriodStart = tc.start - vault.PaymentDenom = tc.paymentDenom s.k.AuthKeeper.SetAccount(s.ctx, vault) - if tc.setupNav { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(tc.paymentDenom, 1_000_000), s.adminAddr) - // price=1 underlying per volume=2 payment → 1 payment redeems for 0.5 underlying, - // so 1 underlying converts to 2 payment. - s.setVaultNAV(vault, tc.paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 2) - } - amt, err := s.k.CalculateAccruedAUMFeePayment(s.ctx, *vault, underlying.Amount) s.Require().NoError(err, "accrued AUM fee payment calculation failed for case: %s", tc.name) s.Require().Equal(tc.expected, amt, "accrued AUM fee payment coin mismatch for case: %s", tc.name) @@ -2520,7 +2328,7 @@ func (s *TestSuite) TestKeeper_HandleVaultFeeTimeouts_RetryOnFailure() { s.SetupTest() shareDenom := "fee.timeout.shares" underlyingDenom := "underlying" - paymentDenom := "other" // not uylds.fcc, so it needs a NAV + heldDenom := "other" underlying := sdk.NewInt64Coin(underlyingDenom, 1_000_000_000) vaultAddr := types.GetVaultAddress(shareDenom) @@ -2528,37 +2336,26 @@ func (s *TestSuite) TestKeeper_HandleVaultFeeTimeouts_RetryOnFailure() { twoMonthsAgo := now.Add(-60 * 24 * time.Hour) s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000_000), s.adminAddr) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 1_000_000_000), s.adminAddr) - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom) - // Remove the bootstrap NAV so PerformVaultFeeTransfer hits the missing-NAV path. - s.Require().NoError(s.k.NAVs.Remove(s.ctx, collections.Join(vault.GetAddress(), paymentDenom)), - "removing bootstrap NAV for %q should succeed", paymentDenom) + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) - // CreateVaultWithParams enqueues an initial timeout, we must remove it to have a clean test - s.Require().NoError(s.k.FeeTimeoutQueue.Dequeue(s.ctx, vault.FeePeriodTimeout, vaultAddr), "failed to dequeue vault from FeeTimeoutQueue") + s.Require().NoError(s.k.FeeTimeoutQueue.Dequeue(s.ctx, vault.FeePeriodTimeout, vaultAddr), "failed to dequeue the initial fee timeout enqueued by CreateVaultWithParams") s.SetVaultRatesAndPeriod(vault, "0.0", "0.0", twoMonthsAgo.Unix(), twoMonthsAgo.Unix()) - // Fund marker with some underlying so TVV is positive s.FundMarker(shareDenom, sdk.NewCoins(underlying)) - // Enqueue it s.Require().NoError(s.k.FeeTimeoutQueue.Enqueue(s.ctx, twoMonthsAgo.Unix(), vaultAddr), "failed to enqueue vault in FeeTimeoutQueue") - // Call handleVaultFeeTimeouts. - // PerformVaultFeeTransfer calls GetTVVInUnderlyingAsset. - // GetTVVInUnderlyingAsset calls ToUnderlyingAssetAmount for all balances. - // If we have a balance in paymentDenom ("other"), it will try to find a NAV to underlyingDenom. - // Since there is no NAV, it should fail. - - // We don't fund the marker with 'other' denom here because that would make GetTVVInUnderlyingAsset fail. - // Instead, we rely on the missing NAV for 'other' during fee payment conversion in PerformVaultFeeTransfer. + // An oversized held-asset NAV plus a nonzero balance overflows the 256-bit SafeMul during + // valuation, simulating a transient PerformVaultFeeTransfer failure. + s.seedOversizedNAV(vault, heldDenom, underlyingDenom, maxValidNAVPrice(), sdkmath.OneInt()) + s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewInt64Coin(heldDenom, 2))) err := s.k.TestAccessor_handleVaultFeeTimeouts(s.T(), s.ctx) s.Require().NoError(err, "handleVaultFeeTimeouts should not return error even if a vault fails") - // Verify the vault is RE-ENQUEUED with a NEW timeout because we don't continue on PerformVaultFeeTransfer failure expectedTimeout := uint64(s.ctx.BlockTime().Unix() + keeper.AutoReconcileTimeout) found := false err = s.k.FeeTimeoutQueue.Walk(s.ctx, func(timeout uint64, addr sdk.AccAddress) (bool, error) { @@ -2569,9 +2366,8 @@ func (s *TestSuite) TestKeeper_HandleVaultFeeTimeouts_RetryOnFailure() { return false, nil }) s.Require().NoError(err, "FeeTimeoutQueue.Walk returned unexpected error during retry verification") - s.Require().True(found, "vault should be in the fee timeout queue with new timeout") + s.Require().True(found, "vault should be re-enqueued in the fee timeout queue after the transient failure") - // Verify FeePeriodStart is preserved updatedVault, err := s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err) s.Require().Equal(twoMonthsAgo.Unix(), updatedVault.FeePeriodStart, "FeePeriodStart should be preserved on transient failure") @@ -2581,7 +2377,6 @@ func (s *TestSuite) TestKeeper_HandleVaultFeeTimeouts_Success() { s.SetupTest() shareDenom := "fee.success.shares" underlyingDenom := "underlying" - paymentDenom := "uylds.fcc" underlying := sdk.NewInt64Coin(underlyingDenom, 1_000_000_000) vaultAddr := types.GetVaultAddress(shareDenom) @@ -2589,26 +2384,20 @@ func (s *TestSuite) TestKeeper_HandleVaultFeeTimeouts_Success() { twoMonthsAgo := now.Add(-60 * 24 * time.Hour) s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000_000), s.adminAddr) - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom) + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) - // CreateVaultWithParams enqueues an initial timeout, we must remove it to have a clean test - s.Require().NoError(s.k.FeeTimeoutQueue.Dequeue(s.ctx, vault.FeePeriodTimeout, vaultAddr), "failed to dequeue vault from FeeTimeoutQueue") + s.Require().NoError(s.k.FeeTimeoutQueue.Dequeue(s.ctx, vault.FeePeriodTimeout, vaultAddr), "failed to dequeue the initial fee timeout enqueued by CreateVaultWithParams") s.SetVaultRatesAndPeriod(vault, "0.0", "0.0", twoMonthsAgo.Unix(), twoMonthsAgo.Unix()) - // Fund marker with some underlying so TVV is positive s.FundMarker(shareDenom, sdk.NewCoins(underlying)) - // Enqueue it s.Require().NoError(s.k.FeeTimeoutQueue.Enqueue(s.ctx, twoMonthsAgo.Unix(), vaultAddr), "failed to enqueue vault in FeeTimeoutQueue") - // Call handleVaultFeeTimeouts. Success this time (uylds.fcc doesn't need NAV) err := s.k.TestAccessor_handleVaultFeeTimeouts(s.T(), s.ctx) s.Require().NoError(err, "handleVaultFeeTimeouts should succeed") - // Verify the vault is DEQUEUED from old timeout and ENQUEUED with new timeout foundOld := false foundNew := false err = s.k.FeeTimeoutQueue.Walk(s.ctx, func(timeout uint64, addr sdk.AccAddress) (bool, error) { @@ -2630,7 +2419,7 @@ func (s *TestSuite) TestKeeper_HandleVaultInterestTimeouts_RetryOnFailure() { s.SetupTest() shareDenom := "interest.timeout.shares" underlyingDenom := "underlying" - paymentDenom := "other" // not uylds.fcc, so it needs a NAV + heldDenom := "other" underlying := sdk.NewInt64Coin(underlyingDenom, 1_000_000_000) vaultAddr := types.GetVaultAddress(shareDenom) @@ -2638,37 +2427,29 @@ func (s *TestSuite) TestKeeper_HandleVaultInterestTimeouts_RetryOnFailure() { twoMonthsAgo := now.Add(-60 * 24 * time.Hour) s.requireAddFinalizeAndActivateMarker(underlying, s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000_000), s.adminAddr) - - vault := s.CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom) - // Remove the bootstrap NAV so CanPayInterestDuration hits the missing-NAV path - // when GetTVVInUnderlyingAsset iterates the principal balance. - s.Require().NoError(s.k.NAVs.Remove(s.ctx, collections.Join(vault.GetAddress(), paymentDenom)), - "removing bootstrap NAV for %q should succeed", paymentDenom) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 1_000_000_000), s.adminAddr) - // CreateVaultWithParams enqueues an initial fee timeout, and also sets up the vault. - // We want to test interest timeouts, which use PayoutTimeoutQueue. + vault := s.CreateVaultWithParams(shareDenom, underlyingDenom) + // The initial fee timeout from CreateVaultWithParams is left in place; this test exercises + // the interest PayoutTimeoutQueue. s.SetVaultRatesAndPeriod(vault, "0.1", "0.1", twoMonthsAgo.Unix(), twoMonthsAgo.Unix()) vault.PeriodStart = twoMonthsAgo.Unix() vault.PeriodTimeout = twoMonthsAgo.Unix() s.k.AuthKeeper.SetAccount(s.ctx, vault) - // Fund marker with some underlying so TVV is positive s.FundMarker(shareDenom, sdk.NewCoins(underlying)) - // Enqueue it in PayoutTimeoutQueue s.Require().NoError(s.k.PayoutTimeoutQueue.Enqueue(s.ctx, twoMonthsAgo.Unix(), vaultAddr), "failed to enqueue vault") - // Trigger an error in CanPayInterestDuration by funding the principal marker with a denom - // that lacks a NAV conversion rate to the underlying asset. - // This simulates a transient error without making the VaultAccount itself invalid. - s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 1000))) + // An oversized held-asset NAV plus a nonzero balance overflows the 256-bit SafeMul during + // valuation, simulating a transient failure without making the VaultAccount itself invalid. + s.seedOversizedNAV(vault, heldDenom, underlyingDenom, maxValidNAVPrice(), sdkmath.OneInt()) + s.FundMarker(shareDenom, sdk.NewCoins(sdk.NewInt64Coin(heldDenom, 2))) err := s.k.TestAccessor_handleVaultInterestTimeouts(s.T(), s.ctx) s.Require().NoError(err, "handleVaultInterestTimeouts should not return error") - // Verify the vault is RE-ENQUEUED with a NEW timeout because we reschedule on failure expectedTimeout := uint64(s.ctx.BlockTime().Unix() + keeper.AutoReconcileTimeout) found := false err = s.k.PayoutTimeoutQueue.Walk(s.ctx, func(timeout uint64, addr sdk.AccAddress) (bool, error) { @@ -2679,9 +2460,8 @@ func (s *TestSuite) TestKeeper_HandleVaultInterestTimeouts_RetryOnFailure() { return false, nil }) s.Require().NoError(err, "PayoutTimeoutQueue.Walk returned unexpected error during retry verification") - s.Require().True(found, "vault should be in the interest timeout queue with new timeout") + s.Require().True(found, "vault should be re-enqueued in the interest timeout queue after the transient failure") - // Verify PeriodStart is preserved updatedVault, err := s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err) s.Require().Equal(twoMonthsAgo.Unix(), updatedVault.PeriodStart, "PeriodStart should be preserved on transient failure") @@ -2694,24 +2474,19 @@ func (s *TestSuite) TestReconcileVault_BootstrapFeePeriod() { testBlockTime := time.Now() periodStart := testBlockTime.Add(-1 * time.Hour).Unix() - // Setup vault with PeriodStart set but FeePeriodStart = 0 vaultAddr, vault := s.setupReconcileVault("0.25", periodStart, false, underlying, shareDenom, totalShares, testBlockTime) - // Manually set FeePeriodStart to 0 to simulate the bug scenario vault.FeePeriodStart = 0 vault.FeePeriodTimeout = 0 s.k.AuthKeeper.SetAccount(s.ctx, vault) - // Verify initial state v, err := s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err) s.Require().Equal(int64(0), v.FeePeriodStart, "FeePeriodStart should be 0 initially") - // Call reconcileVault err = s.k.TestAccessor_reconcileVault(s.T(), s.ctx, v) s.Require().NoError(err) - // Verify FeePeriodStart is bootstrapped (should be equal to current block time) v, err = s.k.GetVault(s.ctx, vaultAddr) s.Require().NoError(err) s.Require().NotEqual(int64(0), v.FeePeriodStart, "FeePeriodStart should have been bootstrapped") diff --git a/keeper/settlement.go b/keeper/settlement.go index 091ffe33..98327f35 100644 --- a/keeper/settlement.go +++ b/keeper/settlement.go @@ -71,12 +71,12 @@ func (k *Keeper) applySettlementNAV(ctx sdk.Context, vault *types.VaultAccount, } // settlementLegCoins resolves a payment's legs into the single asset coin and the -// single payment-denom coin for the given settlement direction. The NAV guardrail +// single underlying-asset coin for the given settlement direction. The NAV guardrail // and upsert price exactly one asset coin against one payment coin, so the asset leg // with zero or multiple coins is rejected. A zero-priced settlement carries no coin on // the payment leg (the zero coin is stripped); an empty payment leg yields a zero coin -// of paymentDenom, but a payment leg carrying more than one coin is rejected. -func settlementLegCoins(payment *exchange.Payment, direction, paymentDenom string) (assetCoin, paymentCoin sdk.Coin, err error) { +// of underlyingDenom, but a payment leg carrying more than one coin is rejected. +func settlementLegCoins(payment *exchange.Payment, direction, underlyingDenom string) (assetCoin, paymentCoin sdk.Coin, err error) { assetLeg, paymentLeg := payment.TargetAmount, payment.SourceAmount if direction == types.AssetDirectionInbound { assetLeg, paymentLeg = payment.SourceAmount, payment.TargetAmount @@ -84,7 +84,7 @@ func settlementLegCoins(payment *exchange.Payment, direction, paymentDenom strin if len(assetLeg) != 1 || len(paymentLeg) > 1 { return sdk.Coin{}, sdk.Coin{}, fmt.Errorf("payment legs must carry one asset coin and at most one payment coin to settle against the vault NAV: source_amount=%q target_amount=%q", payment.SourceAmount, payment.TargetAmount) } - paymentCoin = sdk.NewInt64Coin(paymentDenom, 0) + paymentCoin = sdk.NewInt64Coin(underlyingDenom, 0) if len(paymentLeg) == 1 { paymentCoin = paymentLeg[0] } diff --git a/keeper/settlement_test.go b/keeper/settlement_test.go index c7b83750..7e989d2a 100644 --- a/keeper/settlement_test.go +++ b/keeper/settlement_test.go @@ -6,16 +6,15 @@ import ( "cosmossdk.io/collections" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/provenance-io/provenance/x/exchange" markertypes "github.com/provenance-io/provenance/x/marker/types" + "github.com/provlabs/vault/types" ) func (s *TestSuite) TestKeeper_ApplySettlementNAV() { underlying := "under" share := "vshare" - paymentDenom := "pay" asset := "rwacoin" tests := []struct { @@ -69,7 +68,7 @@ func (s *TestSuite) TestKeeper_ApplySettlementNAV() { defer func() { s.ctx = origCtx }() s.ctx, _ = s.ctx.CacheContext() - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, principalAddr := s.setupAssetSettlementVault(underlying, share) vaultAddr := vault.GetAddress() if tc.registerAssetMarker { s.requireSimpleMarker(asset) @@ -79,7 +78,7 @@ func (s *TestSuite) TestKeeper_ApplySettlementNAV() { } assetCoin := sdk.NewCoin(asset, tc.assetAmount) - paymentCoin := sdk.NewInt64Coin(paymentDenom, 5) + paymentCoin := sdk.NewInt64Coin(underlying, 5) s.ctx = s.ctx.WithEventManager(sdk.NewEventManager()) err := s.k.TestAccessor_applySettlementNAV(s.T(), s.ctx, vault, assetCoin, paymentCoin, tc.direction, s.adminAddr.String()) @@ -190,7 +189,7 @@ func (s *TestSuite) TestSettlementLegCoins() { } func (s *TestSuite) TestKeeper_StageAndReturnPrincipal() { - underlying, share, paymentDenom := "under", "vshare", "pay" + underlying, share := "under", "vshare" restricted, free := "restrictedrwa", "freerwa" tests := []struct { @@ -254,7 +253,7 @@ func (s *TestSuite) TestKeeper_StageAndReturnPrincipal() { defer func() { s.ctx = origCtx }() s.ctx, _ = s.ctx.CacheContext() - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, principalAddr := s.setupAssetSettlementVault(underlying, share) vaultAddr := vault.GetAddress() from, to := principalAddr, vaultAddr @@ -281,13 +280,13 @@ func (s *TestSuite) TestKeeper_StageAndReturnPrincipal() { } func (s *TestSuite) TestKeeper_ReturnToPrincipal_BypassIsLoadBearing() { - underlying, share, paymentDenom, restricted := "under", "vshare", "pay", "restrictedrwa" + underlying, share, restricted := "under", "vshare", "restrictedrwa" origCtx := s.ctx defer func() { s.ctx = origCtx }() s.ctx, _ = s.ctx.CacheContext() - vault, principalAddr := s.setupAssetSettlementVault(underlying, share, paymentDenom) + vault, principalAddr := s.setupAssetSettlementVault(underlying, share) vaultAddr := vault.GetAddress() s.requireRestrictedMarker(restricted) diff --git a/keeper/suite_test.go b/keeper/suite_test.go index a3378467..f9ced007 100644 --- a/keeper/suite_test.go +++ b/keeper/suite_test.go @@ -282,26 +282,21 @@ func (s *TestSuite) requireRestrictedMarker(denom string) { s.Require().NoError(s.simApp.MarkerKeeper.AddFinalizeAndActivateMarker(s.ctx, marker), "failed to create restricted marker %s", denom) } -// setupAssetSettlementVault creates a vault whose payment denom differs from its underlying -// asset. Both the underlying and payment denoms are non-restricted Coin markers (CreateVault's -// fee-collector preflight requires the payment denom to be a marker). Settlement messages are -// asset-manager-only, so the suite's assetManagerAddr is assigned to the vault. It returns the -// vault and its principal marker address. -func (s *TestSuite) setupAssetSettlementVault(underlying, share, paymentDenom string) (*types.VaultAccount, sdk.AccAddress) { +// setupAssetSettlementVault creates a single-denom vault (underlying asset only) and assigns +// the suite's assetManagerAddr as its asset manager, since settlement messages +// (AcceptAsset/RejectAsset) are asset-manager-only and must never be signed by the admin. +// The external asset a settlement trades against the underlying is a separate marker denom +// the caller registers and prices via the vault's internal NAV. It returns the vault and its +// principal marker address. +func (s *TestSuite) setupAssetSettlementVault(underlying, share string) (*types.VaultAccount, sdk.AccAddress) { s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 1_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000), s.adminAddr) - vault, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: s.adminAddr.String(), - ShareDenom: share, - UnderlyingAsset: underlying, - PaymentDenom: paymentDenom, - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlying, 1), - Volume: sdkmath.OneInt(), - }, + vault, err := s.k.CreateVault(s.ctx, vaultAttrs{ + admin: s.adminAddr.String(), + share: share, + underlying: underlying, }) - s.Require().NoError(err, "failed to create asset settlement vault") + s.Require().NoError(err, "failed to create settlement vault for share denom %s", share) _, err = keeper.NewMsgServer(s.simApp.VaultKeeper).SetAssetManager(s.ctx, &types.MsgSetAssetManagerRequest{ Admin: s.adminAddr.String(), @@ -335,7 +330,6 @@ func (s *TestSuite) createPayment(source, target sdk.AccAddress, sourceAmount, t type acceptAssetScenario struct { underlying string share string - paymentDenom string assetMarker string // external asset denom to register as a simple marker; empty skips registration seedNav *types.VaultNAV // internal NAV to seed before settlement; nil skips seeding fundSource sdk.Coins // coins minted to the payment source; zero skips funding @@ -343,14 +337,16 @@ type acceptAssetScenario struct { sourceAmount sdk.Coins // payment source leg targetAmount sdk.Coins // payment target leg externalID string + omitPayment bool // skip staging the payment; the test stages its own or exercises a missing payment } // setupAcceptAssetScenario builds the common AcceptAsset test fixture: an asset-settlement // vault, the optional asset marker and seeded NAV, a funded source account (which always -// carries a stake coin) and principal, and a staged payment from the source to the vault. +// carries a stake coin) and principal, and a staged payment from the source to the vault +// (unless omitPayment is set). // It returns the vault, its principal marker address, and the payment source address. func (s *TestSuite) setupAcceptAssetScenario(sc acceptAssetScenario) (*types.VaultAccount, sdk.AccAddress, sdk.AccAddress) { - vault, principalAddr := s.setupAssetSettlementVault(sc.underlying, sc.share, sc.paymentDenom) + vault, principalAddr := s.setupAssetSettlementVault(sc.underlying, sc.share) if sc.assetMarker != "" { s.requireSimpleMarker(sc.assetMarker) } @@ -370,7 +366,9 @@ func (s *TestSuite) setupAcceptAssetScenario(sc acceptAssetScenario) (*types.Vau s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principalAddr, sc.fundPrincipal), "failed to fund principal with %s", sc.fundPrincipal) } - s.createPayment(source, vault.GetAddress(), sc.sourceAmount, sc.targetAmount, sc.externalID) + if !sc.omitPayment { + s.createPayment(source, vault.GetAddress(), sc.sourceAmount, sc.targetAmount, sc.externalID) + } return vault, principalAddr, source } @@ -500,107 +498,66 @@ type vaultAttrs struct { admin string share string underlying string - payment string withdrawalDelaySeconds uint64 minSwapIn string minSwapOut string maxSwapIn string maxSwapOut string - initialPaymentNav *types.InitialVaultNAV expected types.VaultAccount } -func (v vaultAttrs) GetAdmin() string { return v.admin } -func (v vaultAttrs) GetShareDenom() string { return v.share } -func (v vaultAttrs) GetUnderlyingAsset() string { return v.underlying } -func (v vaultAttrs) GetPaymentDenom() string { return v.payment } -func (v vaultAttrs) GetWithdrawalDelaySeconds() uint64 { return v.withdrawalDelaySeconds } -func (v vaultAttrs) GetMinSwapInValue() string { return v.minSwapIn } -func (v vaultAttrs) GetMinSwapOutValue() string { return v.minSwapOut } -func (v vaultAttrs) GetMaxSwapInValue() string { return v.maxSwapIn } -func (v vaultAttrs) GetMaxSwapOutValue() string { return v.maxSwapOut } -func (v vaultAttrs) GetInitialPaymentNav() *types.InitialVaultNAV { return v.initialPaymentNav } - -// initialPaymentNAVOrDefault returns the supplied initial NAV when set; -// otherwise it returns a 1:1 placeholder priced in underlyingDenom suitable -// for setupBaseVault helpers. Returns nil when the vault does not require a -// payment-denom NAV (paymentDenom is empty or equals the underlying asset). -func initialPaymentNAVOrDefault(initial *types.InitialVaultNAV, paymentDenom, underlyingDenom string) *types.InitialVaultNAV { - if paymentDenom == "" || paymentDenom == underlyingDenom { - return nil - } - if initial != nil { - return initial - } - return &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlyingDenom, 1), - Volume: sdkmath.OneInt(), - Source: "test-bootstrap", - } +func (v vaultAttrs) GetAdmin() string { return v.admin } +func (v vaultAttrs) GetShareDenom() string { return v.share } +func (v vaultAttrs) GetUnderlyingAsset() string { return v.underlying } +func (v vaultAttrs) GetWithdrawalDelaySeconds() uint64 { return v.withdrawalDelaySeconds } +func (v vaultAttrs) GetMinSwapInValue() string { return v.minSwapIn } +func (v vaultAttrs) GetMinSwapOutValue() string { return v.minSwapOut } +func (v vaultAttrs) GetMaxSwapInValue() string { return v.maxSwapIn } +func (v vaultAttrs) GetMaxSwapOutValue() string { return v.maxSwapOut } + +// createSingleDenomVault creates a single-denom vault via keeper.CreateVault. It is the +// shared workhorse behind the base-vault helpers now that vaults are single-denom. +func (s *TestSuite) createSingleDenomVault(cfg vaultAttrs) *types.VaultAccount { + vault, err := s.k.CreateVault(s.ctx, cfg) + s.Require().NoError(err, "vault creation should succeed for share denom %s", cfg.share) + return vault } -// setupBaseVaultRestricted creates a vault with a restricted underlying asset. -// It establishes a marker for the underlying asset, requiring a specific attribute for transfers. -// An optional paymentDenom can be provided for the vault's configuration. -// It returns the newly created vault account. -func (s *TestSuite) setupBaseVaultRestricted(underlyingDenom, shareDenom string, paymentDenom ...string) *types.VaultAccount { +// setupBaseVaultRestricted creates a single-denom vault with a restricted underlying asset. +// It establishes a marker for the underlying asset, requiring a specific attribute for +// transfers, and returns the newly created vault account. +func (s *TestSuite) setupBaseVaultRestricted(underlyingDenom, shareDenom string) *types.VaultAccount { s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlyingDenom, 2_000_000), s.adminAddr, simulation.RequiredMarkerAttribute) - var pDenom string - if len(paymentDenom) > 0 { - pDenom = paymentDenom[0] - } - - vaultCfg := vaultAttrs{ - admin: s.adminAddr.String(), - share: shareDenom, - underlying: underlyingDenom, - payment: pDenom, - initialPaymentNav: initialPaymentNAVOrDefault(nil, pDenom, underlyingDenom), - } - vault, err := s.k.CreateVault(s.ctx, vaultCfg) - s.Require().NoError(err, "vault creation should succeed") - - return vault + return s.createSingleDenomVault(vaultAttrs{ + admin: s.adminAddr.String(), + share: shareDenom, + underlying: underlyingDenom, + }) } -// setupBaseVault creates and activates markers for the underlying and share denoms, -// withdraws some underlying coins to the admin, and creates the vault. -// It can optionally accept a paymentDenom for the vault's configuration. -// It returns the newly created vault account. -func (s *TestSuite) setupBaseVault(underlyingDenom, shareDenom string, paymentDenom ...string) *types.VaultAccount { +// setupBaseVault creates and activates the marker for the underlying denom, withdraws some +// underlying coins to the admin, and creates a single-denom vault. It returns the newly +// created vault account. +func (s *TestSuite) setupBaseVault(underlyingDenom, shareDenom string) *types.VaultAccount { s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlyingDenom, 2_000_000), s.adminAddr) s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, underlyingDenom, sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 100_000))) - var pDenom string - if len(paymentDenom) > 0 { - pDenom = paymentDenom[0] - } - - vaultCfg := vaultAttrs{ - admin: s.adminAddr.String(), - share: shareDenom, - underlying: underlyingDenom, - payment: pDenom, - initialPaymentNav: initialPaymentNAVOrDefault(nil, pDenom, underlyingDenom), - } - vault, err := s.k.CreateVault(s.ctx, vaultCfg) - s.Require().NoError(err, "vault creation should succeed") - - return vault + return s.createSingleDenomVault(vaultAttrs{ + admin: s.adminAddr.String(), + share: shareDenom, + underlying: underlyingDenom, + }) } -// CreateVaultWithParams creates a vault with the given parameters and returns the vault account. -func (s *TestSuite) CreateVaultWithParams(shareDenom, underlyingDenom, paymentDenom string) *types.VaultAccount { - vault, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: s.adminAddr.String(), - ShareDenom: shareDenom, - UnderlyingAsset: underlyingDenom, - PaymentDenom: paymentDenom, - InitialPaymentNav: initialPaymentNAVOrDefault(nil, paymentDenom, underlyingDenom), +// CreateVaultWithParams creates a single-denom vault with the given share and underlying +// denoms and returns the vault account. The underlying marker must already exist. +func (s *TestSuite) CreateVaultWithParams(shareDenom, underlyingDenom string) *types.VaultAccount { + return s.createSingleDenomVault(vaultAttrs{ + admin: s.adminAddr.String(), + share: shareDenom, + underlying: underlyingDenom, }) - s.Require().NoError(err, "CreateVault should succeed for %s", shareDenom) - return vault } // CreateAndActivateVault creates a marker for the underlying asset and then creates the vault itself. @@ -810,29 +767,26 @@ func createSwapInEvents(owner, vaultAddr, markerAddr sdk.AccAddress, asset, shar return allEvents } -// setupSinglePaymentDenomVault is a comprehensive helper that creates a vault with -// an underlying asset, a share denom, and a single payment denom. It creates all -// markers, withdraws funds to the admin, creates the vault with the paymentDenom -// configured, and seeds an Internal NAV entry pricing one paymentDenom unit at -// price/volume underlying. -func (s *TestSuite) setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom string, price, volume int64) *types.VaultAccount { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 2_000_000), s.adminAddr) - s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, paymentDenom, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 100_000))) - vault := s.setupBaseVault(underlyingDenom, shareDenom, paymentDenom) - - if paymentDenom != underlyingDenom { - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, price), volume) - } - +// setupHeldAssetVault creates a single-denom vault (underlying + share) and gives it an +// external held asset: it registers the heldDenom marker, withdraws some to the admin, and +// seeds the vault's internal NAV pricing volume units of heldDenom at price units of the +// underlying asset. This models a vault that has acquired a non-underlying asset via +// settlement and prices it through the internal NAV chain, which is how the valuation engine +// values held assets under the single-denom design. heldDenom must differ from the underlying. +func (s *TestSuite) setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom string, price, volume int64) *types.VaultAccount { + vault := s.setupBaseVault(underlyingDenom, shareDenom) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 2_000_000), s.adminAddr) + s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, heldDenom, sdk.NewCoins(sdk.NewInt64Coin(heldDenom, 100_000))) + s.setVaultNAV(vault, heldDenom, sdk.NewInt64Coin(underlyingDenom, price), volume) return vault } // createLegacyVaultAccount stores a *types.VaultAccount directly via the // AccountKeeper, bypassing keeper.CreateVault entirely. Use this in migration -// tests that need to simulate a pre-v2 vault in state: one that was persisted -// before the InitialPaymentNAV requirement existed and therefore has no -// Internal NAV entry for its payment denom. The caller is responsible for -// registering any markers the vault depends on (e.g. payment + underlying). +// tests that need to simulate a pre-v2 vault in state: one that may still +// carry a payment denom that differs from its underlying asset. The caller is +// responsible for registering any markers the vault depends on (e.g. payment +// + underlying). func (s *TestSuite) createLegacyVaultAccount(shareDenom, underlyingDenom, paymentDenom string) *types.VaultAccount { addr := types.GetVaultAddress(shareDenom) if paymentDenom == "" { @@ -855,64 +809,17 @@ func (s *TestSuite) createLegacyVaultAccount(shareDenom, underlyingDenom, paymen return vaultAcct } -// setForwardMarkerNAV sets a payment->underlying net asset value on the payment -// denom marker. Used by migration tests so Migrate1to2 can -// read a forward marker NAV via MarkerKeeper.GetNetAssetValue. -func (s *TestSuite) setForwardMarkerNAV(paymentDenom, underlyingDenom string, price, volume int64) { - paymentMarkerAddr := markertypes.MustGetMarkerAddress(paymentDenom) - paymentMarkerAccount, err := s.k.MarkerKeeper.GetMarker(s.ctx, paymentMarkerAddr) - s.Require().NoError(err, "should fetch payment marker for forward NAV setup") - s.Require().NoError(s.k.MarkerKeeper.SetNetAssetValue(s.ctx, paymentMarkerAccount, markertypes.NetAssetValue{ - Price: sdk.NewInt64Coin(underlyingDenom, price), - Volume: uint64(volume), - }, "test"), "should set forward marker NAV %s->%s=%d/%d", paymentDenom, underlyingDenom, price, volume) -} - -// setupOversizedNAVVault builds a single-payment-denom vault primed for the NAV -// overflow guard tests. It returns the vault, the suite keeper (fully wired, -// including the internal NAV table the valuation engine reads), and the -// underlying and payment denoms used to stage oversized NAVs. +// setupOversizedNAVVault builds a single-denom vault holding an external asset primed for +// the NAV overflow guard tests. It returns the vault, the suite keeper (fully wired, including +// the internal NAV table the valuation engine reads), the underlying denom, and the held-asset +// denom whose internal NAV the overflow tests overwrite with oversized price/volume via +// seedOversizedNAV. func (s *TestSuite) setupOversizedNAVVault() (*types.VaultAccount, keeper.Keeper, string, string) { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) - return vault, s.k, underlyingDenom, paymentDenom -} - -// setReverseNAV sets a reverse net asset value on the underlying denom marker, -// allowing the vault to value the underlying in terms of the payment denom. -func (s *TestSuite) setReverseNAV(underlyingDenom, paymentDenom string, price, volume int64) { - underlyingMarkerAddr := markertypes.MustGetMarkerAddress(underlyingDenom) - underlyingMarkerAccount, err := s.k.MarkerKeeper.GetMarker(s.ctx, underlyingMarkerAddr) - s.Require().NoError(err, "should fetch underlying marker for reverse NAV setup") - s.Require().NoError(s.k.MarkerKeeper.SetNetAssetValue(s.ctx, underlyingMarkerAccount, markertypes.NetAssetValue{ - Price: sdk.NewInt64Coin(paymentDenom, price), - Volume: uint64(volume), - }, "test-reverse"), "should set reverse marker NAV %s->%s=%d/%d", underlyingDenom, paymentDenom, price, volume) -} - -// setupLegacyPaymentDenomVault wires up a pre-v2 fixture for migration tests: -// registers payment + underlying markers, persists a VaultAccount directly via -// AccountKeeper so no InitialPaymentNAV is required, and sets a forward -// payment->underlying marker NAV. The returned vault has no Internal NAV entry -// so Migrate1to2 has work to do. -func (s *TestSuite) setupLegacyPaymentDenomVault(underlyingDenom, shareDenom, paymentDenom string, price, volume int64) *types.VaultAccount { - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlyingDenom, 2_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 2_000_000), s.adminAddr) - vault := s.createLegacyVaultAccount(shareDenom, underlyingDenom, paymentDenom) - s.setForwardMarkerNAV(paymentDenom, underlyingDenom, price, volume) - return vault -} - -// seedVaultNAV looks up the vault by address and seeds an Internal NAV entry on -// it for denom, pricing volume units at price. Combines the common -// GetVault + setVaultNAV pair used across table-driven tests. -func (s *TestSuite) seedVaultNAV(addr sdk.AccAddress, denom string, price sdk.Coin, volume int64) *types.VaultAccount { - vault, err := s.k.GetVault(s.ctx, addr) - s.Require().NoError(err, "get vault %s should succeed for NAV seeding", addr) - s.setVaultNAV(vault, denom, price, volume) - return vault + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) + return vault, s.k, underlyingDenom, heldDenom } // setVaultNAV seeds an Internal NAV entry on the given vault for denom, pricing @@ -924,18 +831,6 @@ func (s *TestSuite) setVaultNAV(vault *types.VaultAccount, denom string, price s "should set internal NAV %s -> %s=%s/%d", denom, price.Denom, price.Amount, volume) } -// setVaultPaymentDenomWithNAV mutates the vault to use paymentDenom, persists -// the account, and seeds the corresponding Internal NAV entry pricing one -// paymentDenom unit at (price.Amount / volume) underlying. Use this in tests -// that need to attach a payment denom to an already-created vault and price -// it against the underlying in a single step (replaces the inline -// `vault.PaymentDenom = X; SetAccount; setVaultNAV` triplet). -func (s *TestSuite) setVaultPaymentDenomWithNAV(vault *types.VaultAccount, paymentDenom string, price sdk.Coin, volume int64) { - vault.PaymentDenom = paymentDenom - s.k.AuthKeeper.SetAccount(s.ctx, vault) - s.setVaultNAV(vault, paymentDenom, price, volume) -} - // bumpHeight increments the suite's context block height by 1. func (s *TestSuite) bumpHeight() { s.ctx = s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1) @@ -1138,6 +1033,7 @@ func makeGenesisVaultAccount(shareDenom, underlying, admin string) types.VaultAc PaymentDenom: underlying, CurrentInterestRate: types.ZeroInterestRate, DesiredInterestRate: types.ZeroInterestRate, + OutstandingAumFee: sdk.NewInt64Coin(underlying, 0), } } diff --git a/keeper/valuation_engine.go b/keeper/valuation_engine.go index 977e9f3f..778c9b59 100644 --- a/keeper/valuation_engine.go +++ b/keeper/valuation_engine.go @@ -35,18 +35,18 @@ var ErrInternalNAVPriceCycle = errors.New("internal NAV price chain contains a c // # Semantics // // The Internal NAV entry for a denom records the price of `volume` units of the -// denom denominated in one of the vault's accepted denoms (the underlying asset -// or the payment denom): +// 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). When it is the payment denom (only possible -// when payment_denom != underlying, e.g. a held nft/scope… asset settled against -// the payment denom), the chain continues through the payment denom's own price -// so the result is always expressed in the underlying asset. The fraction is the -// product of every entry's price over the product of every entry's volume along -// the chain srcDenom -> ... -> underlying: +// (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 // @@ -54,7 +54,6 @@ var ErrInternalNAVPriceCycle = errors.New("internal NAV price chain contains a c // // Identity fast-path // - If srcDenom == vault.UnderlyingAsset, returns (1, 1) without a lookup. -// This also covers single-denom vaults where payment_denom == underlying. // // Errors // - Wraps ErrInternalNAVNotFound when no entry exists for srcDenom on this @@ -75,7 +74,7 @@ var ErrInternalNAVPriceCycle = errors.New("internal NAV price chain contains a c // 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 -> payment -> underlying). +// (srcDenom -> underlying). func (k Keeper) UnitPriceFraction(ctx sdk.Context, srcDenom string, vault types.VaultAccount) (math.Int, math.Int, error) { num, den := math.NewInt(1), math.NewInt(1) visited := make(map[string]struct{}) @@ -156,29 +155,6 @@ func (k Keeper) ToUnderlyingAssetAmount(ctx sdk.Context, vault types.VaultAccoun return product.Quo(volume), nil } -// FromUnderlyingAssetAmount converts an amount of vault.UnderlyingAsset into -// the equivalent value in targetDenom using integer floor arithmetic. -// -// Formula: -// -// value_in_target = inAmount * priceDenominator / priceNumerator -// -// where (priceNumerator, priceDenominator) are from UnitPriceFraction(targetDenom → underlying). -func (k Keeper) FromUnderlyingAssetAmount(ctx sdk.Context, vault types.VaultAccount, inAmount math.Int, targetDenom string) (math.Int, error) { - priceNum, priceDen, err := k.UnitPriceFraction(ctx, targetDenom, vault) - if err != nil { - return math.Int{}, fmt.Errorf("failed to get unit price fraction: %w", err) - } - if priceNum.IsZero() { - return math.Int{}, fmt.Errorf("zero price for %s/%s", targetDenom, vault.UnderlyingAsset) - } - product, err := inAmount.SafeMul(priceDen) - if err != nil { - return math.Int{}, fmt.Errorf("failed to multiply amount %s by price denominator %s: %w", inAmount, priceDen, err) - } - return product.Quo(priceNum), nil -} - // GetTVVInUnderlyingAsset returns the Total Vault Value (TVV) expressed in // vault.UnderlyingAsset using floor arithmetic. // @@ -193,15 +169,11 @@ func (k Keeper) FromUnderlyingAssetAmount(ctx sdk.Context, vault types.VaultAcco // // Computation (when not paused), valuing only the denoms the vault actually prices // rather than everything parked at the principal marker: -// - First, value each accepted denom (underlying, and payment when configured) from -// its principal balance via ToUnderlyingAssetAmount. The underlying takes the -// identity price; the payment denom takes its internal NAV. An accepted denom that -// holds a balance but carries no NAV is a misconfiguration and propagates as an -// error (the underlying never needs a NAV thanks to the identity fast-path). +// - First, count the principal's underlying-asset balance at its identity price. // - Then, iterate this vault's internal NAV entries and value any held denom // (e.g. nft/scope… acquired via AcceptAsset) from its principal balance at its -// internal NAV. Accepted denoms and the share denom are skipped here because the -// accepted denoms are already valued above and the share denom is never priced. +// internal NAV. The underlying and the share denom are skipped here because the +// underlying is already counted above and the share denom is never priced. // - Sum the converted amounts (floor at each multiplication/division step). // // Iterating the NAV table (a protocol-controlled key set written only by SetVaultNAV @@ -219,27 +191,12 @@ func (k Keeper) GetTVVInUnderlyingAsset(ctx sdk.Context, vault types.VaultAccoun } principal := vault.PrincipalMarkerAddress() - total := math.ZeroInt() - - for _, denom := range vault.AcceptedDenoms() { - balance := k.BankKeeper.GetBalance(ctx, principal, denom) - if balance.IsZero() { - continue - } - val, err := k.ToUnderlyingAssetAmount(ctx, vault, balance) - if err != nil { - return math.Int{}, fmt.Errorf("failed to convert accepted denom %q balance to underlying: %w", denom, err) - } - total, err = total.SafeAdd(val) - if err != nil { - return math.Int{}, fmt.Errorf("failed to add balance %s to total vault value: %w", val, err) - } - } + total := k.BankKeeper.GetBalance(ctx, principal, vault.UnderlyingAsset).Amount navRange := collections.NewPrefixedPairRange[sdk.AccAddress, string](vault.GetAddress()) err := k.NAVs.Walk(ctx, navRange, func(key collections.Pair[sdk.AccAddress, string], _ types.VaultNAV) (bool, error) { denom := key.K2() - if denom == vault.TotalShares.Denom || vault.IsAcceptedDenom(denom) { + if denom == vault.TotalShares.Denom || denom == vault.UnderlyingAsset { return false, nil } balance := k.BankKeeper.GetBalance(ctx, principal, denom) @@ -276,8 +233,8 @@ func (k Keeper) GetTVVInUnderlyingAsset(ctx sdk.Context, vault types.VaultAccoun // pricing stays frozen and NAV-independent. // // When not paused, GetTVVInUnderlyingAsset supplies the gross sum of principal-marker -// balances; this method subtracts the OutstandingAumFee converted to underlying units and -// floors the result at zero. +// balances; this method subtracts the OutstandingAumFee (already denominated in the +// underlying asset) and floors the result at zero. func (k Keeper) GetNetTVVInUnderlyingAsset(ctx sdk.Context, vault types.VaultAccount) (math.Int, error) { gross, err := k.GetTVVInUnderlyingAsset(ctx, vault) if err != nil { @@ -286,11 +243,7 @@ func (k Keeper) GetNetTVVInUnderlyingAsset(ctx sdk.Context, vault types.VaultAcc if vault.Paused { return gross, nil } - outstanding, err := k.CalculateOutstandingFeeUnderlying(ctx, vault) - if err != nil { - return math.Int{}, fmt.Errorf("failed to calculate outstanding AUM fee: %w", err) - } - net := gross.Sub(outstanding) + net := gross.Sub(vault.OutstandingAumFee.Amount) if net.IsNegative() { return math.ZeroInt(), nil } @@ -320,61 +273,36 @@ func (k Keeper) GetNAVPerShareInUnderlyingAsset(ctx sdk.Context, vault types.Vau return tvv.Quo(vault.TotalShares.Amount), nil } -// ConvertSharesToRedeemCoin converts a share amount into a payout coin in redeemDenom -// using the current TVV and total share supply (pro-rata, single-floor arithmetic). -// -// Steps: -// 1. Look up the unit price fraction for redeemDenom → underlying via UnitPriceFraction. -// 2. Compute the payout in one step using -// CalculateRedeemProRataFraction(shares, totalShares, TVV, priceNum, priceDen) -// where TVV is from principal (marker) balances. +// ConvertDepositToSharesInUnderlyingAsset 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 redeemDenom. This function performs calculation only; callers -// must enforce liquidity/policy. If shares <= 0, returns a zero-amount coin. +// Returns a coin in the share denom. This function performs calculation only; +// callers must enforce liquidity/policy. func (k Keeper) ConvertDepositToSharesInUnderlyingAsset(ctx sdk.Context, vault types.VaultAccount, in sdk.Coin) (sdk.Coin, error) { - priceNum, priceDen, err := k.UnitPriceFraction(ctx, in.Denom, vault) - if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to get unit price fraction: %w", err) - } tvv, err := k.GetNetTVVInUnderlyingAsset(ctx, vault) if err != nil { return sdk.Coin{}, fmt.Errorf("failed to get TVV: %w", err) } - amountNumerator, err := in.Amount.SafeMul(priceNum) - if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to multiply amount %s by price numerator %s: %w", in.Amount, priceNum, err) - } - return utils.CalculateSharesProRataFraction(amountNumerator, priceDen, tvv, vault.TotalShares.Amount, vault.TotalShares.Denom) + return utils.CalculateSharesProRata(in.Amount, tvv, vault.TotalShares.Amount, vault.TotalShares.Denom) } -// ConvertSharesToRedeemCoin converts a share amount into a payout coin in redeemDenom -// using the current TVV and total share supply (both pro-rata, floor arithmetic). +// 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). // -// Steps: -// 1. Convert shares → underlying via -// CalculateAssetsFromShares(shares, totalShares, TVV) -// where TVV is from principal (marker) balances. -// 2. Convert the resulting underlying amount to redeemDenom via FromUnderlyingAssetAmount -// (identity fast-path if redeemDenom == vault.UnderlyingAsset). -// -// Returns a coin in redeemDenom. This function performs calculation only; callers -// must enforce liquidity/policy. If shares <= 0, returns a zero-amount coin. -func (k Keeper) ConvertSharesToRedeemCoin(ctx sdk.Context, vault types.VaultAccount, shares math.Int, redeemDenom string) (sdk.Coin, error) { +// This function performs calculation only; callers must enforce liquidity/policy. +// If shares <= 0, returns a zero-amount coin. +func (k Keeper) ConvertSharesToRedeemCoin(ctx sdk.Context, vault types.VaultAccount, shares math.Int) (sdk.Coin, error) { if !shares.IsPositive() { - return sdk.NewCoin(redeemDenom, math.ZeroInt()), nil + return sdk.NewCoin(vault.UnderlyingAsset, math.ZeroInt()), nil } tvv, err := k.GetNetTVVInUnderlyingAsset(ctx, vault) if err != nil { return sdk.Coin{}, fmt.Errorf("failed to get TVV: %w", err) } - priceNum, priceDen, err := k.UnitPriceFraction(ctx, redeemDenom, vault) - if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to get unit price fraction: %w", err) - } - if priceNum.IsZero() { - return sdk.Coin{}, fmt.Errorf("zero price for %s/%s", redeemDenom, vault.UnderlyingAsset) - } - return utils.CalculateRedeemProRataFraction(shares, vault.TotalShares.Amount, tvv, priceNum, priceDen, redeemDenom) + return utils.CalculateRedeemProRata(shares, vault.TotalShares.Amount, tvv, vault.UnderlyingAsset) } // EstimateTotalVaultValue returns an estimated Total Vault Value (TVV) as a Coin diff --git a/keeper/valuation_engine_test.go b/keeper/valuation_engine_test.go index 7b0f6938..ad0a13c7 100644 --- a/keeper/valuation_engine_test.go +++ b/keeper/valuation_engine_test.go @@ -17,10 +17,10 @@ import ( func (s *TestSuite) TestUnitPriceFraction_Table() { underlyingDenom := "underlying" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" heldAsset := metadatatypes.ScopeMetadataAddress(uuid.MustParse("00000000-0000-4000-8000-0000000000e5")).Denom() - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) cases := []struct { name string @@ -38,8 +38,8 @@ func (s *TestSuite) TestUnitPriceFraction_Table() { expectedDenominator: 1, }, { - name: "payment denom converts to underlying via its internal NAV", - fromDenom: paymentDenom, + name: "held denom converts to underlying via its internal NAV", + fromDenom: heldDenom, expectedNumerator: 1, expectedDenominator: 2, }, @@ -50,22 +50,34 @@ func (s *TestSuite) TestUnitPriceFraction_Table() { expectedSentinel: keeper.ErrInternalNAVNotFound, }, { - name: "payment priced asset chains through the payment denom NAV to underlying", + // A multi-hop price chain (heldAsset -> heldDenom -> underlying) can only + // exist in state written outside SetVaultNAV's validation (which forces every + // price denom to be the underlying), e.g. a migration or a direct write. The + // engine still walks such a chain, so seed both legs directly to exercise it. + name: "held asset chains through an intermediate denom NAV to underlying", fromDenom: heldAsset, setup: func() { s.bumpHeight() - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 2) - s.setVaultNAV(vault, heldAsset, sdk.NewInt64Coin(paymentDenom, 6), 1) + s.Require().NoError(s.k.NAVs.Set( + s.ctx, + collections.Join(vault.GetAddress(), heldDenom), + types.VaultNAV{Denom: heldDenom, Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.NewInt(2)}, + ), "should write the intermediate leg of the price chain directly to storage") + s.Require().NoError(s.k.NAVs.Set( + s.ctx, + collections.Join(vault.GetAddress(), heldAsset), + types.VaultNAV{Denom: heldAsset, Price: sdk.NewInt64Coin(heldDenom, 6), Volume: math.NewInt(1)}, + ), "should write the held-asset leg of the price chain directly to storage") }, expectedNumerator: 6, expectedDenominator: 2, }, { name: "overwritten internal NAV uses the latest entry", - fromDenom: paymentDenom, + fromDenom: heldDenom, setup: func() { s.bumpHeight() - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 5), 7) + s.setVaultNAV(vault, heldDenom, sdk.NewInt64Coin(underlyingDenom, 5), 7) }, expectedNumerator: 5, expectedDenominator: 7, @@ -76,14 +88,14 @@ func (s *TestSuite) TestUnitPriceFraction_Table() { // is ever corrupted (e.g. by a future migration). Bypass write-side // validation by writing directly to the NAVs collection. name: "non-positive internal NAV volume is rejected by the defensive guard", - fromDenom: paymentDenom, + fromDenom: heldDenom, setup: func() { s.bumpHeight() s.Require().NoError(s.k.NAVs.Set( s.ctx, - collections.Join(vault.GetAddress(), paymentDenom), + collections.Join(vault.GetAddress(), heldDenom), types.VaultNAV{ - Denom: paymentDenom, + Denom: heldDenom, Price: sdk.NewInt64Coin(underlyingDenom, 1), Volume: math.ZeroInt(), }, @@ -95,14 +107,14 @@ func (s *TestSuite) TestUnitPriceFraction_Table() { // A zero price is a legitimate write-down of a held asset to zero. The // engine must accept it and yield a zero unit price rather than erroring. name: "zero internal NAV price yields a zero unit price", - fromDenom: paymentDenom, + fromDenom: heldDenom, setup: func() { s.bumpHeight() s.Require().NoError(s.k.NAVs.Set( s.ctx, - collections.Join(vault.GetAddress(), paymentDenom), + collections.Join(vault.GetAddress(), heldDenom), types.VaultNAV{ - Denom: paymentDenom, + Denom: heldDenom, Price: sdk.NewInt64Coin(underlyingDenom, 0), Volume: math.NewInt(1), }, @@ -115,14 +127,14 @@ func (s *TestSuite) TestUnitPriceFraction_Table() { // Defensive guard: a negative price can only arise from corrupted state // and must be rejected. name: "negative internal NAV price is rejected by the defensive guard", - fromDenom: paymentDenom, + fromDenom: heldDenom, setup: func() { s.bumpHeight() s.Require().NoError(s.k.NAVs.Set( s.ctx, - collections.Join(vault.GetAddress(), paymentDenom), + collections.Join(vault.GetAddress(), heldDenom), types.VaultNAV{ - Denom: paymentDenom, + Denom: heldDenom, Price: sdk.Coin{Denom: underlyingDenom, Amount: math.NewInt(-1)}, Volume: math.NewInt(1), }, @@ -134,14 +146,14 @@ func (s *TestSuite) TestUnitPriceFraction_Table() { // A nil price amount round-trips through storage as zero, so it is read // back as a legitimate zero-value NAV rather than tripping the guard. name: "nil internal NAV price normalizes to zero through storage", - fromDenom: paymentDenom, + fromDenom: heldDenom, setup: func() { s.bumpHeight() s.Require().NoError(s.k.NAVs.Set( s.ctx, - collections.Join(vault.GetAddress(), paymentDenom), + collections.Join(vault.GetAddress(), heldDenom), types.VaultNAV{ - Denom: paymentDenom, + Denom: heldDenom, Price: sdk.Coin{Denom: underlyingDenom, Amount: math.Int{}}, Volume: math.NewInt(1), }, @@ -219,21 +231,21 @@ func (s *TestSuite) TestUnitPriceFraction_Table() { func (s *TestSuite) TestToUnderlyingAssetAmount() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) testKeeper := s.k - val, err := testKeeper.ToUnderlyingAssetAmount(s.ctx, *vault, sdk.NewInt64Coin(paymentDenom, 4)) + val, err := testKeeper.ToUnderlyingAssetAmount(s.ctx, *vault, sdk.NewInt64Coin(heldDenom, 4)) s.Require().NoError(err, "to-underlying should succeed for valid NAV") s.Require().Equal(math.NewInt(2), val, "4 usdc at 1/2 should be 2 ylds") - valFloor, err := testKeeper.ToUnderlyingAssetAmount(s.ctx, *vault, sdk.NewInt64Coin(paymentDenom, 5)) + valFloor, err := testKeeper.ToUnderlyingAssetAmount(s.ctx, *vault, sdk.NewInt64Coin(heldDenom, 5)) s.Require().NoError(err, "to-underlying with floor should succeed") s.Require().Equal(math.NewInt(2), valFloor, "5 usdc at 1/2 should floor to 2 ylds (not 2.5)") - valZero, err := testKeeper.ToUnderlyingAssetAmount(s.ctx, *vault, sdk.NewInt64Coin(paymentDenom, 0)) + valZero, err := testKeeper.ToUnderlyingAssetAmount(s.ctx, *vault, sdk.NewInt64Coin(heldDenom, 0)) s.Require().NoError(err, "to-underlying with zero amount should succeed") s.Require().Equal(math.ZeroInt(), valZero, "0 usdc should convert to 0 ylds") @@ -242,67 +254,18 @@ func (s *TestSuite) TestToUnderlyingAssetAmount() { s.Require().Contains(err.Error(), "no internal NAV entry for denom", "error should mention missing internal NAV") } -func (s *TestSuite) TestFromUnderlyingAssetAmount() { - underlyingDenom := "ylds" - paymentDenom := "usdc" - shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) - - testKeeper := s.k - - // 1 Underlying = 1/2 Payment (PriceNum=1, PriceDen=2) - // FromUnderlying(2 ylds) = 2 * 2 / 1 = 4 usdc - val, err := testKeeper.FromUnderlyingAssetAmount(s.ctx, *vault, math.NewInt(2), paymentDenom) - s.Require().NoError(err, "from-underlying should succeed for valid NAV") - s.Require().Equal(math.NewInt(4), val, "2 ylds at 1/2 should be 4 usdc") - - // Identity path - valIdentity, err := testKeeper.FromUnderlyingAssetAmount(s.ctx, *vault, math.NewInt(100), underlyingDenom) - s.Require().NoError(err, "identity from-underlying should succeed") - s.Require().Equal(math.NewInt(100), valIdentity, "100 ylds should be 100 ylds") - - // Missing NAV - _, err = testKeeper.FromUnderlyingAssetAmount(s.ctx, *vault, math.NewInt(5), "unknown") - s.Require().Error(err, "should error when NAV missing for target denom") - s.Require().Contains(err.Error(), "no internal NAV entry for denom", "error should mention missing internal NAV") -} - func (s *TestSuite) TestNAVConversion_OversizedNAVReturnsErrorNotPanic() { - vault, testKeeper, underlyingDenom, paymentDenom := s.setupOversizedNAVVault() + vault, testKeeper, underlyingDenom, heldDenom := s.setupOversizedNAVVault() tests := []struct { name string run func() error }{ { - name: "valuing a payment balance in underlying overflows the forward NAV multiply", - run: func() error { - s.seedOversizedNAV(vault, paymentDenom, underlyingDenom, oversizedNAVPrice(), math.OneInt()) - _, err := testKeeper.ToUnderlyingAssetAmount(s.ctx, *vault, sdk.NewCoin(paymentDenom, oversizedNAVPrice())) - return err - }, - }, - { - name: "valuing underlying in a payment denom overflows the reverse NAV multiply", - run: func() error { - s.seedOversizedNAV(vault, paymentDenom, underlyingDenom, math.OneInt(), oversizedNAVPrice()) - _, err := testKeeper.FromUnderlyingAssetAmount(s.ctx, *vault, oversizedNAVPrice(), paymentDenom) - return err - }, - }, - { - name: "converting an oversized deposit to shares overflows the forward NAV multiply", - run: func() error { - s.seedOversizedNAV(vault, paymentDenom, underlyingDenom, oversizedNAVPrice(), math.OneInt()) - _, err := testKeeper.ConvertDepositToSharesInUnderlyingAsset(s.ctx, *vault, sdk.NewCoin(paymentDenom, oversizedNAVPrice())) - return err - }, - }, - { - name: "redeeming shares to a payout coin overflows the reverse NAV multiply", + name: "valuing a held-asset balance in underlying overflows the forward NAV multiply", run: func() error { - s.seedOversizedNAV(vault, paymentDenom, underlyingDenom, math.OneInt(), oversizedNAVPrice()) - _, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, oversizedNAVPrice(), paymentDenom) + s.seedOversizedNAV(vault, heldDenom, underlyingDenom, oversizedNAVPrice(), math.OneInt()) + _, err := testKeeper.ToUnderlyingAssetAmount(s.ctx, *vault, sdk.NewCoin(heldDenom, oversizedNAVPrice())) return err }, }, @@ -330,15 +293,15 @@ func (s *TestSuite) TestToUnderlyingAssetAmount_IdentityFastPath() { func (s *TestSuite) TestGetTVVInUnderlyingAsset_ExcludesSharesAndSumsInAsset() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) principalAddress := vault.PrincipalMarkerAddress() s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, principalAddress, sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1000), - sdk.NewInt64Coin(paymentDenom, 10), - )), "should fund vault with base and payment coins") + sdk.NewInt64Coin(heldDenom, 10), + )), "should fund vault with underlying and held-asset coins") testKeeper := s.k totalVaultValueInAsset, err := testKeeper.GetTVVInUnderlyingAsset(s.ctx, *vault) @@ -365,34 +328,14 @@ func (s *TestSuite) TestGetTVVInUnderlyingAsset_EmptyAndSharesOnly() { s.Require().Equal(math.ZeroInt(), tvvSharesOnly, "TVV of shares-only vault should be zero") } -func (s *TestSuite) TestGetTVVInUnderlyingAsset_ErrorPropagation() { - underlyingDenom := "ylds" - paymentDenom := "usdc" - shareDenom := "vshare" - - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000), s.adminAddr) - vault := s.setupBaseVault(underlyingDenom, shareDenom, paymentDenom) - s.Require().NoError(s.k.NAVs.Remove(s.ctx, collections.Join(vault.GetAddress(), paymentDenom)), - "removing bootstrap NAV should succeed so the no-NAV path is exercised") - - s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, paymentDenom, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 10))) - s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 10))), "funding principal should succeed") - - testKeeper := s.k - _, err := testKeeper.GetTVVInUnderlyingAsset(s.ctx, *vault) - - s.Require().Error(err, "get TVV should error when accepted payment denom lacks NAV") - s.Require().Contains(err.Error(), "no internal NAV entry for denom \"usdc\"", "error should propagate from missing internal NAV") -} - func (s *TestSuite) TestGetTVVInUnderlyingAsset_AccumulatorOverflowReturnsErrorNotPanic() { - vault, testKeeper, underlyingDenom, paymentDenom := s.setupOversizedNAVVault() - s.seedOversizedNAV(vault, paymentDenom, underlyingDenom, maxValidNAVPrice(), math.OneInt()) + vault, testKeeper, underlyingDenom, heldDenom := s.setupOversizedNAVVault() + s.seedOversizedNAV(vault, heldDenom, underlyingDenom, maxValidNAVPrice(), math.OneInt()) principalAddress := vault.PrincipalMarkerAddress() s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, principalAddress, sdk.NewCoins( - sdk.NewInt64Coin(paymentDenom, 1), - )), "funding principal with one payment unit should succeed") + sdk.NewInt64Coin(heldDenom, 1), + )), "funding principal with one held-asset unit should succeed") s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, principalAddress, sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 100), )), "funding principal with a small underlying balance should succeed") @@ -422,27 +365,6 @@ func (s *TestSuite) TestGetTVVInUnderlyingAsset_IncludesUnderlyingPricedHeldAsse s.Require().Equal(math.NewInt(115), tvv, "TVV should be 100 underlying + floor(10 * 3 / 2) = 115") } -func (s *TestSuite) TestGetTVVInUnderlyingAsset_IncludesPaymentPricedHeldAsset() { - underlyingDenom := "ylds" - paymentDenom := "usdc" - shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 3, 1) - - heldAsset := metadatatypes.ScopeMetadataAddress(uuid.MustParse("00000000-0000-4000-8000-0000000000b2")).Denom() - s.setVaultNAV(vault, heldAsset, sdk.NewInt64Coin(paymentDenom, 5), 2) - - principal := vault.PrincipalMarkerAddress() - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, principal, sdk.NewCoins( - sdk.NewInt64Coin(underlyingDenom, 100), - sdk.NewInt64Coin(paymentDenom, 4), - sdk.NewInt64Coin(heldAsset, 10), - )), "funding principal with underlying, payment, and a payment-priced held asset should succeed") - - tvv, err := s.k.GetTVVInUnderlyingAsset(s.ctx, *vault) - s.Require().NoError(err, "TVV should chain a payment-priced held asset through to the underlying without error") - s.Require().Equal(math.NewInt(187), tvv, "TVV should be 100 underlying + (4 usdc * 3) + (10 asset * 5/2 usdc * 3) = 100 + 12 + 75 = 187") -} - func (s *TestSuite) TestGetTVVInUnderlyingAsset_SkipsHeldAssetWithoutNAV() { underlyingDenom := "ylds" shareDenom := "vshare" @@ -463,15 +385,15 @@ func (s *TestSuite) TestGetTVVInUnderlyingAsset_SkipsHeldAssetWithoutNAV() { func (s *TestSuite) TestGetTVVInUnderlyingAsset_UnvaluedPrincipalDenomsDoNotChangeValue() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) principal := vault.PrincipalMarkerAddress() s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, principal, sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1000), - sdk.NewInt64Coin(paymentDenom, 10), - )), "funding the principal with the valued underlying and payment balances should succeed") + sdk.NewInt64Coin(heldDenom, 10), + )), "funding the principal with the valued underlying and held-asset balances should succeed") spy := &countingBankKeeper{BankKeeper: s.k.BankKeeper} spyKeeper := s.k @@ -504,24 +426,6 @@ func (s *TestSuite) TestGetTVVInUnderlyingAsset_UnvaluedPrincipalDenomsDoNotChan "balance lookups must stay bounded to the valued denoms and not scale with the %d parked unvalued denoms", parkedUnvaluedDenoms) } -func (s *TestSuite) TestGetTVVInUnderlyingAsset_AcceptedDenomMissingNAVStillErrors() { - underlyingDenom := "ylds" - paymentDenom := "usdc" - shareDenom := "vshare" - - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000), s.adminAddr) - vault := s.setupBaseVault(underlyingDenom, shareDenom, paymentDenom) - s.Require().NoError(s.k.NAVs.Remove(s.ctx, collections.Join(vault.GetAddress(), paymentDenom)), - "removing the bootstrap payment NAV should succeed so the missing-NAV path is exercised") - - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, vault.PrincipalMarkerAddress(), - sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 10))), "funding principal with the payment denom should succeed") - - _, err := s.k.GetTVVInUnderlyingAsset(s.ctx, *vault) - s.Require().Error(err, "an accepted denom with no NAV is a misconfiguration and must still error") - s.Require().Contains(err.Error(), "no internal NAV entry for denom \"usdc\"", "error should propagate from the missing accepted-denom NAV") -} - func (s *TestSuite) TestGetTVVInUnderlyingAsset_InterestAndFeeAccrueOnHeldAssetBase() { underlyingDenom := "ylds" shareDenom := "vshare" @@ -576,13 +480,13 @@ func (s *TestSuite) TestGetTVVInUnderlyingAsset_ExcludesReserves() { func (s *TestSuite) TestGetNAVPerShareInUnderlyingAsset_FloorsToZeroForTinyPerShare() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1000), - sdk.NewInt64Coin(paymentDenom, 10), + sdk.NewInt64Coin(heldDenom, 10), )), "should fund vault marker for NAV calc") totalVaultValueInAsset := math.NewInt(1005) @@ -619,20 +523,21 @@ func (s *TestSuite) TestGetNAVPerShareInUnderlyingAsset_ZeroSupplyAndNormalNAV() s.Require().Equal(math.NewInt(2), navPerShareNormal, "1000 TVV / 500 shares should be 2 NAV per share") } -func (s *TestSuite) TestConvertDepositToSharesInUnderlyingAsset_UsesNAV() { +func (s *TestSuite) TestConvertDepositToSharesInUnderlyingAsset_ValuesHeldAssetsInTVV() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) testKeeper := s.k s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1000), - sdk.NewInt64Coin(paymentDenom, 10), + sdk.NewInt64Coin(heldDenom, 10), )), "should fund vault marker for TVV") tvv, err := testKeeper.GetTVVInUnderlyingAsset(s.ctx, *vault) s.Require().NoError(err, "should compute TVV") + s.Require().Equal(math.NewInt(1005), tvv, "TVV should value the held-asset balance through its NAV") initialShares := sdk.NewCoin(shareDenom, tvv.Mul(utils.ShareScalar)) s.Require().NoError( s.k.MarkerKeeper.MintCoin(s.ctx, vault.GetAddress(), initialShares), @@ -641,47 +546,32 @@ func (s *TestSuite) TestConvertDepositToSharesInUnderlyingAsset_UsesNAV() { vault.TotalShares = initialShares s.k.AuthKeeper.SetAccount(s.ctx, vault) - mintedShares, err := testKeeper.ConvertDepositToSharesInUnderlyingAsset(s.ctx, *vault, sdk.NewInt64Coin(paymentDenom, 4)) + mintedShares, err := testKeeper.ConvertDepositToSharesInUnderlyingAsset(s.ctx, *vault, sdk.NewInt64Coin(underlyingDenom, 4)) s.Require().NoError(err, "deposit conversion should succeed") s.Require().Equal(shareDenom, mintedShares.Denom, "minted shares denom should match vault share denom") - s.Require().Equal(utils.ShareScalar.Mul(math.NewInt(2)), mintedShares.Amount, "4 usdc at 1/2 should mint 2*ShareScalar shares") + s.Require().Equal(utils.ShareScalar.Mul(math.NewInt(4)), mintedShares.Amount, "4 underlying should mint 4*ShareScalar shares at parity against the NAV-valued TVV") } -func (s *TestSuite) TestConvertDepositToSharesInUnderlyingAsset_InitialAndDustDeposits() { +func (s *TestSuite) TestConvertDepositToSharesInUnderlyingAsset_InitialDepositMintsAtParity() { underlyingDenom := "ylds" - paymentDenom := "usdc" shareDenom := "vshare" vault := s.setupBaseVault(underlyingDenom, shareDenom) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 2_000_000), s.adminAddr) - s.setVaultPaymentDenomWithNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 1), 2_000_000_000) - - testKeeper := s.k - initialDepositShares, err := testKeeper.ConvertDepositToSharesInUnderlyingAsset(s.ctx, *vault, sdk.NewInt64Coin(underlyingDenom, 100)) + initialDepositShares, err := s.k.ConvertDepositToSharesInUnderlyingAsset(s.ctx, *vault, sdk.NewInt64Coin(underlyingDenom, 100)) s.Require().NoError(err, "initial deposit should succeed") s.Require().Equal(utils.ShareScalar.Mul(math.NewInt(100)), initialDepositShares.Amount, "initial deposit should mint shares at parity with ShareScalar") - - s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( - sdk.NewInt64Coin(underlyingDenom, 1000), - )), "should fund vault for TVV") - s.Require().NoError(s.k.MarkerKeeper.MintCoin(s.ctx, vault.GetAddress(), sdk.NewCoin(shareDenom, math.NewInt(1))), "should add a single share to circulation") - vault.TotalShares = sdk.NewCoin(shareDenom, math.NewInt(1)) - s.k.AuthKeeper.SetAccount(s.ctx, vault) - dustDepositShares, err := testKeeper.ConvertDepositToSharesInUnderlyingAsset(s.ctx, *vault, sdk.NewInt64Coin(paymentDenom, 1)) - s.Require().NoError(err, "dust deposit should not error") - s.Require().True(dustDepositShares.Amount.IsZero(), "dust deposit should floor to zero shares") } -func (s *TestSuite) TestConvertSharesToRedeemCoin_AssetAndPaymentPaths() { +func (s *TestSuite) TestConvertSharesToRedeemCoin_RedeemsInUnderlying() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1000), - sdk.NewInt64Coin(paymentDenom, 10), - )), "should fund vault with base and payment coins") + sdk.NewInt64Coin(heldDenom, 10), + )), "should fund vault with underlying and held-asset coins") totalVaultValueInAsset := math.NewInt(1005) shareSupply := utils.ShareScalar.Mul(totalVaultValueInAsset) @@ -689,65 +579,54 @@ func (s *TestSuite) TestConvertSharesToRedeemCoin_AssetAndPaymentPaths() { vault.TotalShares = sdk.NewCoin(shareDenom, shareSupply) s.k.AuthKeeper.SetAccount(s.ctx, vault) - testKeeper := s.k - outAssetCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, utils.ShareScalar, underlyingDenom) - s.Require().NoError(err, "shares->asset conversion should succeed") - s.Require().Equal(underlyingDenom, outAssetCoin.Denom, "redeem denom should be asset") - s.Require().Equal(math.NewInt(1), outAssetCoin.Amount, "ShareScalar shares should redeem to 1 asset unit at parity") - - outPaymentCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, utils.ShareScalar, paymentDenom) - s.Require().NoError(err, "shares->payment conversion should succeed") - s.Require().Equal(paymentDenom, outPaymentCoin.Denom, "redeem denom should be payment") - s.Require().Equal(math.NewInt(2), outPaymentCoin.Amount, "1 asset at 1/2 asset per 1 payment should yield 2 payment units") - - _, err = testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, utils.ShareScalar, "unknown") - s.Require().Error(err, "should error when redeem denom has no NAV to underlying") - s.Require().Contains(err.Error(), "no internal NAV entry for denom", "error should indicate missing internal NAV mapping") - s.Require().ErrorIs(err, keeper.ErrInternalNAVNotFound, "missing NAV error should carry the typed ErrInternalNAVNotFound sentinel through the conversion") + outAssetCoin, err := s.k.ConvertSharesToRedeemCoin(s.ctx, *vault, utils.ShareScalar) + s.Require().NoError(err, "shares->underlying conversion should succeed") + s.Require().Equal(underlyingDenom, outAssetCoin.Denom, "redeem coin should be denominated in the underlying asset") + s.Require().Equal(math.NewInt(1), outAssetCoin.Amount, "ShareScalar shares should redeem to 1 underlying unit at parity, with the held-asset balance valued into TVV via its NAV") } func (s *TestSuite) TestConvertAndNav_PriceNetOfOutstandingAumFee() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) testKeeper := s.k s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1000), - sdk.NewInt64Coin(paymentDenom, 10), + sdk.NewInt64Coin(heldDenom, 10), )), "should fund vault marker for gross TVV") grossTVV, err := testKeeper.GetTVVInUnderlyingAsset(s.ctx, *vault) s.Require().NoError(err, "should compute gross TVV") - s.Require().Equal(math.NewInt(1005), grossTVV, "gross TVV = 1000 underlying + 10 payment at 1/2") + s.Require().Equal(math.NewInt(1005), grossTVV, "gross TVV = 1000 underlying + 10 held asset at 1/2") totalShares := sdk.NewCoin(shareDenom, grossTVV.Mul(utils.ShareScalar)) s.Require().NoError(s.k.MarkerKeeper.MintCoin(s.ctx, vault.GetAddress(), totalShares), "should mint share supply") vault.TotalShares = totalShares - vault.OutstandingAumFee = sdk.NewInt64Coin(paymentDenom, 10) + vault.OutstandingAumFee = sdk.NewInt64Coin(underlyingDenom, 5) s.k.AuthKeeper.SetAccount(s.ctx, vault) netTVV, err := testKeeper.GetNetTVVInUnderlyingAsset(s.ctx, *vault) s.Require().NoError(err, "should compute net TVV") - s.Require().Equal(math.NewInt(1000), netTVV, "net TVV = gross 1005 minus outstanding fee (10 payment at 1/2 = 5 underlying)") + s.Require().Equal(math.NewInt(1000), netTVV, "net TVV = gross 1005 minus outstanding fee of 5 underlying") deposit := sdk.NewInt64Coin(underlyingDenom, 1000) mintedShares, err := testKeeper.ConvertDepositToSharesInUnderlyingAsset(s.ctx, *vault, deposit) s.Require().NoError(err, "deposit conversion should succeed") - expectedNetMint, err := utils.CalculateSharesProRataFraction(deposit.Amount, math.NewInt(1), netTVV, totalShares.Amount, shareDenom) + expectedNetMint, err := utils.CalculateSharesProRata(deposit.Amount, netTVV, totalShares.Amount, shareDenom) s.Require().NoError(err, "should compute net-priced deposit shares") - expectedGrossMint, err := utils.CalculateSharesProRataFraction(deposit.Amount, math.NewInt(1), grossTVV, totalShares.Amount, shareDenom) + expectedGrossMint, err := utils.CalculateSharesProRata(deposit.Amount, grossTVV, totalShares.Amount, shareDenom) s.Require().NoError(err, "should compute gross-priced deposit shares") s.Require().Equal(expectedNetMint.Amount, mintedShares.Amount, "deposit must be priced off net TVV") s.Require().True(mintedShares.Amount.GT(expectedGrossMint.Amount), "net pricing mints more shares per deposit than gross pricing would (gross overstates TVV)") redeemShares := grossTVV.Mul(utils.ShareScalar) - redeemed, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, redeemShares, underlyingDenom) + redeemed, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, redeemShares) s.Require().NoError(err, "redeem conversion should succeed") - expectedNetRedeem, err := utils.CalculateRedeemProRataFraction(redeemShares, totalShares.Amount, netTVV, math.NewInt(1), math.NewInt(1), underlyingDenom) + expectedNetRedeem, err := utils.CalculateRedeemProRata(redeemShares, totalShares.Amount, netTVV, underlyingDenom) s.Require().NoError(err, "should compute net-priced redemption") - expectedGrossRedeem, err := utils.CalculateRedeemProRataFraction(redeemShares, totalShares.Amount, grossTVV, math.NewInt(1), math.NewInt(1), underlyingDenom) + expectedGrossRedeem, err := utils.CalculateRedeemProRata(redeemShares, totalShares.Amount, grossTVV, underlyingDenom) s.Require().NoError(err, "should compute gross-priced redemption") s.Require().Equal(expectedNetRedeem.Amount, redeemed.Amount, "redemption must be priced off net TVV") s.Require().True(redeemed.Amount.LT(expectedGrossRedeem.Amount), "net pricing pays out less per share than gross pricing would (gross overstates TVV)") @@ -755,9 +634,9 @@ func (s *TestSuite) TestConvertAndNav_PriceNetOfOutstandingAumFee() { func (s *TestSuite) TestGetNetTVVInUnderlyingAsset_FloorsAtZeroWhenOutstandingExceedsGross() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) testKeeper := s.k s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( @@ -768,12 +647,12 @@ func (s *TestSuite) TestGetNetTVVInUnderlyingAsset_FloorsAtZeroWhenOutstandingEx s.Require().NoError(err, "should compute gross TVV") s.Require().Equal(math.NewInt(100), grossTVV, "gross TVV should equal funded underlying balance") - vault.OutstandingAumFee = sdk.NewInt64Coin(paymentDenom, 1000) + vault.OutstandingAumFee = sdk.NewInt64Coin(underlyingDenom, 1000) s.k.AuthKeeper.SetAccount(s.ctx, vault) netTVV, err := testKeeper.GetNetTVVInUnderlyingAsset(s.ctx, *vault) s.Require().NoError(err, "net TVV should not error when outstanding fee exceeds gross TVV") - s.Require().True(netTVV.IsZero(), "net TVV should floor at zero when outstanding fee (500 underlying) exceeds gross TVV (100)") + s.Require().True(netTVV.IsZero(), "net TVV should floor at zero when outstanding fee (1000 underlying) exceeds gross TVV (100)") } func (s *TestSuite) TestConvertSharesToRedeemCoin_ZeroAndDustRedemption() { @@ -783,11 +662,11 @@ func (s *TestSuite) TestConvertSharesToRedeemCoin_ZeroAndDustRedemption() { testKeeper := s.k - zeroCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, math.ZeroInt(), underlyingDenom) + zeroCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, math.ZeroInt()) s.Require().NoError(err, "redeeming zero shares should not error") s.Require().True(zeroCoin.IsZero(), "redeeming zero shares should result in a zero coin") - negativeCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, math.NewInt(-100), underlyingDenom) + negativeCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, math.NewInt(-100)) s.Require().NoError(err, "redeeming negative shares should not error") s.Require().True(negativeCoin.IsZero(), "redeeming negative shares should result in a zero coin") @@ -799,7 +678,7 @@ func (s *TestSuite) TestConvertSharesToRedeemCoin_ZeroAndDustRedemption() { s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 1000), )), "should fund vault for TVV") - dustCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, math.NewInt(1), underlyingDenom) + dustCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, math.NewInt(1)) s.Require().NoError(err, "dust redemption should not error") s.Require().True(dustCoin.IsZero(), "dust redemption should floor to a zero coin") } @@ -818,7 +697,7 @@ func (s *TestSuite) TestConvertSharesToRedeemCoin_TVVZero_SupplyNonzero() { s.k.AuthKeeper.SetAccount(s.ctx, vault) testKeeper := s.k - redeemCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, utils.ShareScalar, underlyingDenom) + redeemCoin, err := testKeeper.ConvertSharesToRedeemCoin(s.ctx, *vault, utils.ShareScalar) s.Require().NoError(err, "redeeming with TVV=0 and shares>0 should not error") s.Require().Equal(underlyingDenom, redeemCoin.Denom, "redeem denom should be the underlying asset") s.Require().True(redeemCoin.Amount.IsZero(), "redeemed amount should be zero when TVV is zero") @@ -826,14 +705,14 @@ func (s *TestSuite) TestConvertSharesToRedeemCoin_TVVZero_SupplyNonzero() { func (s *TestSuite) TestGetTVVInUnderlyingAsset_PausedUsesPausedBalance() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) principal := vault.PrincipalMarkerAddress() s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, principal, sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 9999), - sdk.NewInt64Coin(paymentDenom, 9999), + sdk.NewInt64Coin(heldDenom, 9999), )), "funding principal balances before pause should succeed") vault.Paused = true @@ -848,14 +727,14 @@ func (s *TestSuite) TestGetTVVInUnderlyingAsset_PausedUsesPausedBalance() { func (s *TestSuite) TestGetNetTVVInUnderlyingAsset_PausedReturnsPausedBalanceWithoutNAV() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) principal := vault.PrincipalMarkerAddress() s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, principal, sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 9999), - sdk.NewInt64Coin(paymentDenom, 9999), + sdk.NewInt64Coin(heldDenom, 9999), )), "funding principal balances before pause should succeed") vault.Paused = true @@ -869,14 +748,14 @@ func (s *TestSuite) TestGetNetTVVInUnderlyingAsset_PausedReturnsPausedBalanceWit s.Require().Equal(math.NewInt(42), netTVV, "when paused, net TVV should equal vault.PausedBalance.Amount without subtracting the outstanding fee") } -func (s *TestSuite) TestGetTVVInUnderlyingAsset_AcceptedDenomFiltering() { +func (s *TestSuite) TestGetTVVInUnderlyingAsset_MixedPricedAndUnpricedHeldBalances() { underlyingDenom := "ylds" - paymentDenom := "usdc" - unacceptedDenom := "paymenow" + heldDenom := "usdc" + unpricedDenom := "paymenow" shareDenom := "vshare" - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000), s.adminAddr) - vault := s.setupBaseVault(underlyingDenom, shareDenom, paymentDenom) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(heldDenom, 1_000_000), s.adminAddr) + vault := s.setupBaseVault(underlyingDenom, shareDenom) initialShareSupply := sdk.NewCoin(shareDenom, utils.ShareScalar) s.Require().NoError( @@ -887,18 +766,18 @@ func (s *TestSuite) TestGetTVVInUnderlyingAsset_AcceptedDenomFiltering() { s.k.AuthKeeper.SetAccount(s.ctx, vault) coinsToSend := sdk.NewCoins( - sdk.NewInt64Coin(paymentDenom, 100), - sdk.NewInt64Coin(unacceptedDenom, 50), + sdk.NewInt64Coin(heldDenom, 100), + sdk.NewInt64Coin(unpricedDenom, 50), sdk.NewInt64Coin(underlyingDenom, 5), ) - s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, paymentDenom, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 100))) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(unacceptedDenom, 1_000_000), s.adminAddr) - s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, unacceptedDenom, sdk.NewCoins(sdk.NewInt64Coin(unacceptedDenom, 50))) + s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, heldDenom, sdk.NewCoins(sdk.NewInt64Coin(heldDenom, 100))) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(unpricedDenom, 1_000_000), s.adminAddr) + s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, unpricedDenom, sdk.NewCoins(sdk.NewInt64Coin(unpricedDenom, 50))) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), coinsToSend), "funding principal should succeed") - s.setVaultNAV(vault, paymentDenom, sdk.NewInt64Coin(underlyingDenom, 2), 1) + s.setVaultNAV(vault, heldDenom, sdk.NewInt64Coin(underlyingDenom, 2), 1) testKeeper := s.k tvv, err := testKeeper.GetTVVInUnderlyingAsset(s.ctx, *vault) @@ -906,9 +785,7 @@ func (s *TestSuite) TestGetTVVInUnderlyingAsset_AcceptedDenomFiltering() { expectedTVV := math.NewInt(205) - s.Require().Equal(expectedTVV, tvv, "TVV should only include accepted and non-share balances") - - s.Require().False(vault.IsAcceptedDenom(unacceptedDenom), "unaccepted denom should NOT be an accepted denom") + s.Require().Equal(expectedTVV, tvv, "TVV should count the underlying and NAV-priced held balances while skipping the unpriced denom") } func (s *TestSuite) TestEstimateTotalVaultValue_Paused() { @@ -1023,11 +900,11 @@ func (s *TestSuite) TestEstimateTotalVaultValue_SingleAsset_WithInterest() { } // TestEstimateTotalVaultValue_MultiAsset_Table exercises EstimateTotalVaultValue -// for vaults that hold a mix of underlying + payment denom in their principal -// balance, with the price of one paymentDenom unit fixed at 1 underlying via +// for vaults that hold a mix of underlying + held denom in their principal +// balance, with the price of one heldDenom unit fixed at 1 underlying via // Internal NAV (the previous uylds.fcc 1:1 peg is no longer special-cased). // -// Each case funds the principal with 100 underlying + 50 payment (= 150 +// Each case funds the principal with 100 underlying + 50 held asset (= 150 // underlying after NAV conversion) and 10 underlying as reserves (excluded). // When interestRate is non-empty, simple APY accrual over secondsToAccrue is // applied on top of the base 150. @@ -1037,47 +914,47 @@ func (s *TestSuite) TestEstimateTotalVaultValue_MultiAsset_Table() { cases := []struct { name string underlyingDenom string - paymentDenom string + heldDenom string shareDenom string interestRate string }{ { name: "underlying is uylds.fcc, no interest, sums at 1:1", underlyingDenom: "uylds.fcc", - paymentDenom: "usdc", + heldDenom: "usdc", shareDenom: "vsharefcc", }, { name: "underlying is uylds.fcc, positive interest accrues", underlyingDenom: "uylds.fcc", - paymentDenom: "usdc", + heldDenom: "usdc", shareDenom: "vsharefcc", interestRate: "0.1", }, { name: "underlying is uylds.fcc, negative interest accrues", underlyingDenom: "uylds.fcc", - paymentDenom: "usdc", + heldDenom: "usdc", shareDenom: "vsharefcc", interestRate: "-0.1", }, { - name: "payment is uylds.fcc, no interest, sums at 1:1", + name: "held denom is uylds.fcc, no interest, sums at 1:1", underlyingDenom: "receipttoken", - paymentDenom: "uylds.fcc", + heldDenom: "uylds.fcc", shareDenom: "vsharercpt", }, { - name: "payment is uylds.fcc, positive interest accrues", + name: "held denom is uylds.fcc, positive interest accrues", underlyingDenom: "receipttoken", - paymentDenom: "uylds.fcc", + heldDenom: "uylds.fcc", shareDenom: "vsharercpt", interestRate: "0.1", }, { - name: "payment is uylds.fcc, negative interest accrues", + name: "held denom is uylds.fcc, negative interest accrues", underlyingDenom: "receipttoken", - paymentDenom: "uylds.fcc", + heldDenom: "uylds.fcc", shareDenom: "vsharercpt", interestRate: "-0.1", }, @@ -1088,7 +965,7 @@ func (s *TestSuite) TestEstimateTotalVaultValue_MultiAsset_Table() { s.SetupTest() s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(tc.underlyingDenom, 1_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(tc.paymentDenom, 1_000_000), s.adminAddr) + s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(tc.heldDenom, 1_000_000), s.adminAddr) s.Require().NoError( s.k.MarkerKeeper.WithdrawCoins( s.ctx, s.adminAddr, s.adminAddr, tc.underlyingDenom, @@ -1098,19 +975,19 @@ func (s *TestSuite) TestEstimateTotalVaultValue_MultiAsset_Table() { ) s.Require().NoError( s.k.MarkerKeeper.WithdrawCoins( - s.ctx, s.adminAddr, s.adminAddr, tc.paymentDenom, - sdk.NewCoins(sdk.NewInt64Coin(tc.paymentDenom, 50)), + s.ctx, s.adminAddr, s.adminAddr, tc.heldDenom, + sdk.NewCoins(sdk.NewInt64Coin(tc.heldDenom, 50)), ), - "withdrawing payment marker funds should succeed for case %q", tc.name, + "withdrawing held-asset marker funds should succeed for case %q", tc.name, ) vault, err := s.k.CreateVault(s.ctx, vaultAttrs{admin: s.adminAddr.String(), share: tc.shareDenom, underlying: tc.underlyingDenom}) s.Require().NoError(err, "vault creation should succeed for case %q", tc.name) - s.setVaultPaymentDenomWithNAV(vault, tc.paymentDenom, sdk.NewInt64Coin(tc.underlyingDenom, 1), 1) + s.setVaultNAV(vault, tc.heldDenom, sdk.NewInt64Coin(tc.underlyingDenom, 1), 1) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( sdk.NewInt64Coin(tc.underlyingDenom, 100), - sdk.NewInt64Coin(tc.paymentDenom, 50), + sdk.NewInt64Coin(tc.heldDenom, 50), )), "funding principal should succeed for case %q", tc.name) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.GetAddress(), sdk.NewCoins( sdk.NewInt64Coin(tc.underlyingDenom, 10), @@ -1143,16 +1020,16 @@ func (s *TestSuite) TestEstimateTotalVaultValue_MultiAsset_Table() { func (s *TestSuite) TestEstimateTotalVaultValue_MultiAsset_WithNAV() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) const interestRate = "0.1" const secondsToAccrue = int64(60 * 60 * 24 * 30) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 100), - sdk.NewInt64Coin(paymentDenom, 50), + sdk.NewInt64Coin(heldDenom, 50), )), "funding principal account should succeed") s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.GetAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 10), @@ -1179,16 +1056,16 @@ func (s *TestSuite) TestEstimateTotalVaultValue_MultiAsset_WithNAV() { func (s *TestSuite) TestEstimateTotalVaultValue_MultiAsset_WithNAV_WithNegativeInterest() { underlyingDenom := "ylds" - paymentDenom := "usdc" + heldDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupHeldAssetVault(underlyingDenom, shareDenom, heldDenom, 1, 2) const interestRate = "-0.1" const secondsToAccrue = int64(60 * 60 * 24 * 30) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 100), - sdk.NewInt64Coin(paymentDenom, 50), + sdk.NewInt64Coin(heldDenom, 50), )), "funding principal account should succeed") s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.GetAddress(), sdk.NewCoins( sdk.NewInt64Coin(underlyingDenom, 10), @@ -1238,25 +1115,3 @@ func (s *TestSuite) TestEstimateTotalVaultValue_FullScenario() { s.Require().NoError(err) s.Require().Equal(sdk.NewInt64Coin(underlyingDenom, 1_054), estimatedTVV) } - -func (s *TestSuite) TestEstimateTotalVaultValue_ErrorPropagation() { - underlyingDenom := "ylds" - paymentDenom := "usdc" - shareDenom := "vshare" - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(paymentDenom, 1_000_000), s.adminAddr) - vault := s.setupBaseVault(underlyingDenom, shareDenom, paymentDenom) - s.Require().NoError(s.k.NAVs.Remove(s.ctx, collections.Join(vault.GetAddress(), paymentDenom)), - "removing bootstrap NAV should succeed so the no-NAV path is exercised") - - s.k.MarkerKeeper.WithdrawCoins(s.ctx, s.adminAddr, s.adminAddr, paymentDenom, sdk.NewCoins(sdk.NewInt64Coin(paymentDenom, 10))) - - s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( - sdk.NewInt64Coin(paymentDenom, 10), - )), "funding principal should succeed") - - testKeeper := s.k - _, err := testKeeper.EstimateTotalVaultValue(s.ctx, vault) - - s.Require().Error(err, "estimation should error if GetTVV errors") - s.Require().Contains(err.Error(), "no internal NAV entry for denom \"usdc\"", "error should propagate from missing internal NAV") -} diff --git a/keeper/vault.go b/keeper/vault.go index 36c9ef4e..79ceab2e 100644 --- a/keeper/vault.go +++ b/keeper/vault.go @@ -26,13 +26,11 @@ type VaultAttributer interface { GetAdmin() string GetShareDenom() string GetUnderlyingAsset() string - GetPaymentDenom() string GetWithdrawalDelaySeconds() uint64 GetMinSwapInValue() string GetMinSwapOutValue() string GetMaxSwapInValue() string GetMaxSwapOutValue() string - GetInitialPaymentNav() *types.InitialVaultNAV } // CreateVault creates a new vault and its corresponding share marker atomically. @@ -41,25 +39,20 @@ type VaultAttributer interface { // 1. Creating and persisting a new VaultAccount and its lookup entries. // 2. Initializing the fee timeout queue for the new vault. // 3. Creating, finalizing, and activating a restricted marker for the vault's shares. -// 4. Performing a pre-flight check against the principal/payment path by calling +// 4. 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 payment denomination. -// 5. Seeding the per-vault Internal NAV entry for the payment denom when it -// differs from the underlying asset, so the valuation engine can convert -// payment-denom balances and fee payouts without an out-of-band setup step. +// 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 (k *Keeper) CreateVault(ctx sdk.Context, attributes VaultAttributer) (*types.VaultAccount, error) { underlying := attributes.GetUnderlyingAsset() - payment := attributes.GetPaymentDenom() withdrawalDelay := attributes.GetWithdrawalDelaySeconds() minSwapIn := attributes.GetMinSwapInValue() minSwapOut := attributes.GetMinSwapOutValue() maxSwapIn := attributes.GetMaxSwapInValue() maxSwapOut := attributes.GetMaxSwapOutValue() - initialNAV := attributes.GetInitialPaymentNav() underlyingAssetAddr, err := markertypes.MarkerAddress(underlying) if err != nil { @@ -71,7 +64,7 @@ func (k *Keeper) CreateVault(ctx sdk.Context, attributes VaultAttributer) (*type cacheCtx, write := ctx.CacheContext() - vault, err := k.createVaultAccount(cacheCtx, attributes.GetAdmin(), attributes.GetShareDenom(), underlying, payment, withdrawalDelay, minSwapIn, minSwapOut, maxSwapIn, maxSwapOut) + vault, err := k.createVaultAccount(cacheCtx, attributes.GetAdmin(), attributes.GetShareDenom(), underlying, withdrawalDelay, minSwapIn, minSwapOut, maxSwapIn, maxSwapOut) if err != nil { return nil, fmt.Errorf("failed to create vault account: %w", err) } @@ -89,15 +82,11 @@ func (k *Keeper) CreateVault(ctx sdk.Context, attributes VaultAttributer) (*type markertypes.WithTransferAgents(cacheCtx, vault.GetAddress()), vault.PrincipalMarkerAddress(), provlabsAddr, - sdk.NewCoins(sdk.NewInt64Coin(vault.PaymentDenom, 1)), + sdk.NewCoins(sdk.NewInt64Coin(vault.UnderlyingAsset, 1)), ); err != nil { - return nil, fmt.Errorf("fee account %s is not permissioned to receive payment denom %s: %w", provlabsAddr.String(), vault.PaymentDenom, err) + return nil, fmt.Errorf("fee account %s is not permissioned to receive underlying asset %s: %w", provlabsAddr.String(), vault.UnderlyingAsset, err) } else if !recipient.Equals(provlabsAddr) { - return nil, fmt.Errorf("effective recipient %s differs from expected fee collector %s for payment denom %s", recipient.String(), provlabsAddr.String(), vault.PaymentDenom) - } - - if err := k.seedInitialPaymentNAV(cacheCtx, vault, initialNAV); err != nil { - return nil, fmt.Errorf("failed to seed initial payment NAV: %w", err) + return nil, fmt.Errorf("effective recipient %s differs from expected fee collector %s for underlying asset %s", recipient.String(), provlabsAddr.String(), vault.UnderlyingAsset) } write() @@ -105,32 +94,6 @@ func (k *Keeper) CreateVault(ctx sdk.Context, attributes VaultAttributer) (*type return vault, nil } -// seedInitialPaymentNAV persists the optional bootstrap NAV for a vault's -// payment denom when payment_denom differs from underlying_asset. The caller -// must have already validated the stateless shape of initial via -// types.ValidateInitialPaymentNAV (typically through MsgCreateVaultRequest.ValidateBasic). -// -// When payment_denom equals underlying_asset, no NAV is required (the -// valuation engine's identity fast-path applies) and initial must be nil; the -// function returns an error rather than silently dropping a stray entry. -// -// The NAV is written via SetVaultNAV so that field-level invariants, marker -// existence, and event emission match every other internal NAV update. -func (k *Keeper) seedInitialPaymentNAV(ctx sdk.Context, vault *types.VaultAccount, initial *types.InitialVaultNAV) error { - if err := types.ValidateInitialPaymentNAV(vault.PaymentDenom, vault.UnderlyingAsset, initial); err != nil { - return fmt.Errorf("invalid initial payment NAV: %w", err) - } - if initial == nil { - return nil - } - - nav := types.NewVaultNAV(vault.PaymentDenom, initial.Price, initial.Volume, initial.Source) - if err := k.SetVaultNAV(ctx, vault, nav, vault.Admin); err != nil { - return fmt.Errorf("failed to set initial payment NAV: %w", err) - } - return nil -} - // GetVault returns the vault account for the given address. // This function will return nil if nothing exists at this address. func (k Keeper) GetVault(ctx sdk.Context, address sdk.AccAddress) (*types.VaultAccount, error) { @@ -159,7 +122,7 @@ func (k Keeper) getVault(ctx sdk.Context, addr sdk.AccAddress) (*types.VaultAcco // createVaultAccount creates and stores a new vault account and initializes its fee tracking. // It verifies that the vault address is available and not already associated with another account. -func (k *Keeper) createVaultAccount(ctx sdk.Context, admin, shareDenom, underlyingAsset, paymentDenom string, withdrawalDelay uint64, minSwapIn, minSwapOut, maxSwapIn, maxSwapOut string) (*types.VaultAccount, error) { +func (k *Keeper) createVaultAccount(ctx sdk.Context, admin, shareDenom, underlyingAsset string, withdrawalDelay uint64, minSwapIn, minSwapOut, maxSwapIn, maxSwapOut string) (*types.VaultAccount, error) { vaultAddr := types.GetVaultAddress(shareDenom) params, err := k.Params.Get(ctx) @@ -172,7 +135,6 @@ func (k *Keeper) createVaultAccount(ctx sdk.Context, admin, shareDenom, underlyi admin, shareDenom, underlyingAsset, - paymentDenom, withdrawalDelay, params.DefaultAumFeeBips, minSwapIn, @@ -350,10 +312,11 @@ func (k *Keeper) checkPayoutRestrictions(ctx sdk.Context, vault *types.VaultAcco return nil } -// SwapOut validates a swap-out request, calculates the resulting assets, escrows the user's shares, -// and enqueues a pending withdrawal request to be processed by the EndBlocker. +// 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. -func (k *Keeper) SwapOut(ctx sdk.Context, vaultAddr, owner sdk.AccAddress, shares sdk.Coin, redeemDenom string) (uint64, error) { +func (k *Keeper) SwapOut(ctx sdk.Context, vaultAddr, owner sdk.AccAddress, shares sdk.Coin) (uint64, error) { vault, err := k.GetVault(ctx, vaultAddr) if err != nil { return 0, fmt.Errorf("failed to get vault: %w", err) @@ -374,15 +337,7 @@ func (k *Keeper) SwapOut(ctx sdk.Context, vaultAddr, owner sdk.AccAddress, share return 0, fmt.Errorf("swap out denom must be share denom %v : %v", shares.Denom, vault.TotalShares.Denom) } - if redeemDenom == "" { - redeemDenom = vault.PaymentDenom - } - - if err = vault.ValidateAcceptedDenom(redeemDenom); err != nil { - return 0, fmt.Errorf("failed to validate redeem denom: %w", err) - } - - assets, err := k.ConvertSharesToRedeemCoin(ctx, *vault, shares.Amount, redeemDenom) + assets, err := k.ConvertSharesToRedeemCoin(ctx, *vault, shares.Amount) if err != nil { return 0, fmt.Errorf("failed to calculate assets from shares: %w", err) } @@ -405,13 +360,13 @@ func (k *Keeper) SwapOut(ctx sdk.Context, vaultAddr, owner sdk.AccAddress, share payoutTime := ctx.BlockTime().Unix() + int64(vault.WithdrawalDelaySeconds) //nolint:gosec // G115: WithdrawalDelaySeconds is validated <= MaxWithdrawalDelay. - pendingReq := types.NewPendingSwapOut(owner, vaultAddr, shares, redeemDenom) + pendingReq := types.NewPendingSwapOut(owner, vaultAddr, shares, vault.UnderlyingAsset) requestID, err := k.PendingSwapOutQueue.Enqueue(ctx, payoutTime, &pendingReq) if err != nil { return 0, fmt.Errorf("failed to enqueue pending swap out request: %w", err) } - k.emitEvent(ctx, types.NewEventSwapOutRequested(vaultAddr.String(), owner.String(), redeemDenom, shares, requestID)) + k.emitEvent(ctx, types.NewEventSwapOutRequested(vaultAddr.String(), owner.String(), vault.UnderlyingAsset, shares, requestID)) return requestID, nil } diff --git a/keeper/vault_test.go b/keeper/vault_test.go index 84da021a..c4168486 100644 --- a/keeper/vault_test.go +++ b/keeper/vault_test.go @@ -101,106 +101,32 @@ func (s *TestSuite) TestCreateVault_InvalidAdminFails() { s.Require().ErrorContains(err, "invalid admin address", "error message should mention invalid admin address") } -// TestCreateVault_DistinctPaymentDenomSeedsNAV verifies that creating a vault -// with payment_denom != underlying_asset persists the bootstrap NAV entry in -// the same atomic operation, so the valuation engine can convert payment-denom -// balances without an out-of-band setup step. -func (s *TestSuite) TestCreateVault_DistinctPaymentDenomSeedsNAV() { - share := "vshare.bootstrap" +func (s *TestSuite) TestCreateVault_DefaultsPaymentDenomToUnderlying() { underlying := "ulying" - payment := "upay" s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 1_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 1_000_000), s.adminAddr) - attrs := vaultAttrs{ + vault, err := s.k.CreateVault(s.ctx, vaultAttrs{ admin: s.adminAddr.String(), - share: share, + share: "vshare.single", underlying: underlying, - payment: payment, - initialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlying, 3), - Volume: math.NewInt(2), - Source: "create-bootstrap", - }, - } - - vault, err := s.k.CreateVault(s.ctx, attrs) - s.Require().NoError(err, "CreateVault should succeed when initial payment NAV is supplied") - - stored, err := s.k.GetVaultNAV(s.ctx, vault.GetAddress(), payment) - s.Require().NoError(err, "bootstrap NAV should be persisted for payment denom %q", payment) - s.Require().Equal(payment, stored.Denom, "stored NAV denom should be payment denom") - s.Require().Equal(sdk.NewInt64Coin(underlying, 3), stored.Price, "stored NAV price should match supplied price") - s.Require().Equal(math.NewInt(2), stored.Volume, "stored NAV volume should match supplied volume") - s.Require().Equal("create-bootstrap", stored.Source, "stored NAV source should match supplied attribution") -} - -// TestCreateVault_MissingInitialPaymentNAVFails verifies that creating a vault -// with payment_denom != underlying_asset fails when the bootstrap NAV is -// omitted. The check is enforced at ValidateBasic so an operator cannot stand -// up a vault that would silently stall fee collection and payment-denom -// swap-outs. -func (s *TestSuite) TestCreateVault_MissingInitialPaymentNAVFails() { - share := "vshare.missing.nav" - underlying := "ulying" - payment := "upay" - - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 1_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 1_000_000), s.adminAddr) - - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: s.adminAddr.String(), - ShareDenom: share, - UnderlyingAsset: underlying, - PaymentDenom: payment, }) - s.Require().Error(err, "CreateVault should reject a vault with mismatched denoms and no initial NAV") - s.Require().ErrorContains(err, "initial_payment_nav is required", "error should call out missing bootstrap NAV") + s.Require().NoError(err, "CreateVault should succeed for a single-denom vault") + s.Require().Equal(underlying, vault.PaymentDenom, "deprecated payment denom state field should default to the underlying asset") + _, navErr := s.k.GetVaultNAV(s.ctx, vault.GetAddress(), underlying) + s.Require().Error(navErr, "no internal NAV entry should be seeded at creation") } -// TestCreateVault_InitialPaymentNAVRolledBackOnFailure verifies that the -// bootstrap NAV is written under the same cache context as the rest of vault -// creation: a downstream failure (here, the share-denom marker already exists) -// rolls back the NAV alongside the vault account. -func (s *TestSuite) TestCreateVault_InitialPaymentNAVRolledBackOnFailure() { - share := "vshare.rollback" - underlying := "ulying" - payment := "upay" - - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(underlying, 1_000_000), s.adminAddr) - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(payment, 1_000_000), s.adminAddr) - // Pre-create a marker at the share denom so createVaultMarker fails. - s.requireAddFinalizeAndActivateMarker(sdk.NewInt64Coin(share, 1), s.adminAddr) - - vaultAddr := types.GetVaultAddress(share) - _, err := s.k.CreateVault(s.ctx, &types.MsgCreateVaultRequest{ - Admin: s.adminAddr.String(), - ShareDenom: share, - UnderlyingAsset: underlying, - PaymentDenom: payment, - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlying, 1), - Volume: math.OneInt(), - }, - }) - s.Require().Error(err, "CreateVault should fail when the share marker already exists") - - _, navErr := s.k.GetVaultNAV(s.ctx, vaultAddr, payment) - s.Require().Error(navErr, "bootstrap NAV must not be persisted when create fails") -} - -func (s *TestSuite) TestSwapIn_MultiAsset() { +func (s *TestSuite) TestSwapIn_SingleDenomEnforcement() { underlyingDenom := "ylds" - paymentDenom := "usdc" - unacceptedDenom := "junk" + unacceptedDenom := "usdc" shareDenom := "vshare" - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupBaseVault(underlyingDenom, shareDenom) vault.SwapInEnabled = true s.k.AuthKeeper.SetAccount(s.ctx, vault) - depositorAddr := s.CreateAndFundAccount(sdk.NewInt64Coin(paymentDenom, 1000)) - s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, depositorAddr, sdk.NewCoins(sdk.NewInt64Coin(unacceptedDenom, 1000))), "should fund depositor with unaccepted denom") + depositorAddr := s.CreateAndFundAccount(sdk.NewInt64Coin(underlyingDenom, 1000)) + s.Require().NoError(FundAccount(s.ctx, s.simApp.BankKeeper, depositorAddr, sdk.NewCoins(sdk.NewInt64Coin(unacceptedDenom, 1000))), "should fund depositor with a non-underlying denom") totalShares := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(1000)) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins(sdk.NewInt64Coin(underlyingDenom, 1000))), "should fund vault principal with initial TVV") @@ -208,18 +134,18 @@ func (s *TestSuite) TestSwapIn_MultiAsset() { vault.TotalShares = totalShares s.k.AuthKeeper.SetAccount(s.ctx, vault) - depositCoin := sdk.NewInt64Coin(paymentDenom, 10) + depositCoin := sdk.NewInt64Coin(underlyingDenom, 10) mintedShares, err := s.k.SwapIn(s.ctx, vault.GetAddress(), depositorAddr, depositCoin) - s.Require().NoError(err, "should successfully swap in an accepted payment denom") + s.Require().NoError(err, "should successfully swap in the underlying asset") - expectedShares := utils.ShareScalar.MulRaw(5) - s.Require().Equal(expectedShares, mintedShares.Amount, "minted shares should be proportional to the payment denom's value in the underlying asset") + expectedShares := utils.ShareScalar.MulRaw(10) + s.Require().Equal(expectedShares, mintedShares.Amount, "minted shares should be proportional to the underlying deposit at the current share price") s.assertBalance(depositorAddr, shareDenom, expectedShares) - s.assertBalance(vault.PrincipalMarkerAddress(), paymentDenom, math.NewInt(10)) + s.assertBalance(vault.PrincipalMarkerAddress(), underlyingDenom, math.NewInt(1_010)) unacceptedCoin := sdk.NewInt64Coin(unacceptedDenom, 50) _, err = s.k.SwapIn(s.ctx, vault.GetAddress(), depositorAddr, unacceptedCoin) - s.Require().Error(err, "should fail to swap in an unaccepted asset") + s.Require().Error(err, "should reject a swap in of a non-underlying denom under single-denom enforcement") s.Require().ErrorContains(err, "denom not supported for vault", "error should indicate the denom is not accepted") } @@ -316,63 +242,48 @@ func (s *TestSuite) TestSwapIn_ZeroShareDeposit() { } } -func (s *TestSuite) TestSwapOut_MultiAsset() { +func (s *TestSuite) TestSwapOut_RedeemsInUnderlying() { underlyingDenom := "ylds" - paymentDenom := "usdc" - unacceptedDenom := "junk" shareDenom := "vshare" blockTime := time.Now().UTC() s.ctx = s.ctx.WithBlockTime(blockTime) initialShares := utils.ShareScalar.MulRaw(100) - vault := s.setupSinglePaymentDenomVault(underlyingDenom, shareDenom, paymentDenom, 1, 2) + vault := s.setupBaseVault(underlyingDenom, shareDenom) vault.SwapOutEnabled = true - vault.WithdrawalDelaySeconds = 0 // Set to zero for instant processing in the same block's endblocker + vault.WithdrawalDelaySeconds = 0 vault.TotalShares = sdk.NewCoin(shareDenom, initialShares) s.k.AuthKeeper.SetAccount(s.ctx, vault) redeemerAddr := s.CreateAndFundAccount(sdk.NewCoin(shareDenom, initialShares)) s.Require().NoError(s.k.BankKeeper.SendCoins(s.ctx, s.adminAddr, vault.PrincipalMarkerAddress(), sdk.NewCoins( - sdk.NewInt64Coin(underlyingDenom, 500), - sdk.NewInt64Coin(paymentDenom, 500), + sdk.NewInt64Coin(underlyingDenom, 600), )), "should fund vault principal with liquidity") vault, err := s.k.GetVault(s.ctx, vault.GetAddress()) s.Require().NoError(err, "should get vault") s.Require().NotNil(vault, "vault should not be nil") - s.Require().NoError(s.k.MarkerKeeper.MintCoin(s.ctx, vault.GetAddress(), sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(500))), "should mint initial share supply") + s.Require().NoError(s.k.MarkerKeeper.MintCoin(s.ctx, vault.GetAddress(), sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(500))), "should mint additional share supply") vault.TotalShares = vault.TotalShares.Add(sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(500))) s.k.AuthKeeper.SetAccount(s.ctx, vault) - sharesToRedeemForPayment := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(10)) - reqID1, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeemForPayment, paymentDenom) - s.Require().NoError(err, "should successfully queue swap out for an accepted payment denom") + sharesToRedeemFirst := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(10)) + reqID1, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeemFirst) + s.Require().NoError(err, "should successfully queue the first swap out") s.Require().Equal(uint64(0), reqID1, "first request id should be 0") - s.assertBalance(redeemerAddr, shareDenom, initialShares.Sub(sharesToRedeemForPayment.Amount)) - s.assertBalance(vault.GetAddress(), shareDenom, sharesToRedeemForPayment.Amount) + s.assertBalance(redeemerAddr, shareDenom, initialShares.Sub(sharesToRedeemFirst.Amount)) + s.assertBalance(vault.GetAddress(), shareDenom, sharesToRedeemFirst.Amount) - sharesToRedeemForDefaultPayment := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(5)) - reqID2, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeemForDefaultPayment, "") - s.Require().NoError(err, "should successfully queue swap out for the default underlying asset") + sharesToRedeemSecond := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(5)) + reqID2, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeemSecond) + s.Require().NoError(err, "should successfully queue the second swap out") s.Require().Equal(uint64(1), reqID2, "second request id should be 1") - sharesToRedeemForUnderlying := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(8)) - reqID3, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeemForUnderlying, underlyingDenom) - s.Require().NoError(err, "should successfully queue swap out for the default underlying asset") - s.Require().Equal(uint64(2), reqID3, "third request id should be 2") - err = s.k.TestAccessor_processPendingSwapOuts(s.T(), s.ctx, keeper.MaxSwapOutBatchSize) s.Require().NoError(err, "processing pending withdrawals should not fail") - // --- Assert Final Balances --- - s.assertBalance(redeemerAddr, paymentDenom, math.NewInt(36)) - s.assertBalance(redeemerAddr, underlyingDenom, math.NewInt(10)) - - // --- Test 3: Unaccepted Denom --- - _, err = s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeemForDefaultPayment, unacceptedDenom) - s.Require().Error(err, "should fail to swap out for an unaccepted asset") - s.Require().ErrorContains(err, "denom not supported for vault", "error should indicate the denom is not accepted") + s.assertBalance(redeemerAddr, underlyingDenom, math.NewInt(15)) } func (s *TestSuite) TestSwapOut_FailsWhenDisabled() { @@ -384,7 +295,7 @@ func (s *TestSuite) TestSwapOut_FailsWhenDisabled() { vault.SwapOutEnabled = false s.k.AuthKeeper.SetAccount(s.ctx, vault) - _, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sdk.NewInt64Coin(shareDenom, 10), "") + _, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sdk.NewInt64Coin(shareDenom, 10)) s.Require().Error(err, "SwapOut should fail when swaps are disabled") s.Require().ErrorContains(err, "swaps are not enabled", "error message should mention swaps are disabled") } @@ -407,7 +318,7 @@ func (s *TestSuite) TestSwapOut_FailsWithInsufficientShares() { s.k.AuthKeeper.SetAccount(s.ctx, vault) sharesToRedeem := utils.ShareScalar.MulRaw(101) - _, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sdk.NewCoin(shareDenom, sharesToRedeem), "") + _, err := s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sdk.NewCoin(shareDenom, sharesToRedeem)) s.Require().Error(err, "swap out should fail with insufficient shares") s.Require().ErrorContains(err, "insufficient funds", "error should mention insufficient funds for shares") } @@ -455,7 +366,7 @@ func (s *TestSuite) TestSwapOut_FailsWithRestrictedUnderlyingAssetNoAttributes() s.Require().NoError(err, "should fetch active marker") activeMarker := marker.(*markertypes.MarkerAccount) - // Now REMOVE the transfer permission from the vault to test the "fail-on-no-attributes" path + // Remove the vault's transfer permission to exercise the fail-on-no-attributes path. activeMarker.AccessControl = []markertypes.AccessGrant{ {Address: s.adminAddr.String(), Permissions: markertypes.AccessList{markertypes.Access_Mint, markertypes.Access_Admin, markertypes.Access_Withdraw, markertypes.Access_Burn, markertypes.Access_Transfer}}, {Address: s.EnsureTechFeeAccount().String(), Permissions: markertypes.AccessList{markertypes.Access_Transfer, markertypes.Access_Deposit}}, @@ -473,7 +384,7 @@ func (s *TestSuite) TestSwapOut_FailsWithRestrictedUnderlyingAssetNoAttributes() s.Require().NoError(s.k.MarkerKeeper.WithdrawCoins(s.ctx, vault.GetAddress(), redeemerAddr, shareDenom, sdk.NewCoins(sdk.NewCoin(shareDenom, sharesForRedeemer))), "should fund redeemer from the vault's existing shares") sharesToRedeem := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(50)) - _, err = s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeem, "") + _, err = s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeem) s.Require().Error(err, "swap-out should fail because the vault lacks transfer permission and the asset is restricted (even with no attributes)") s.Require().ErrorContains(err, "does not have transfer permissions", "error should indicate missing transfer permissions") @@ -521,7 +432,7 @@ func (s *TestSuite) TestSwapOut_FailsWithRestrictedUnderlyingAssetRequiredAttrib redeemerAddr := s.CreateAndFundAccount(sdk.NewCoin(shareDenom, sharesForRedeemer)) sharesToRedeem := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(50)) - _, err = s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeem, "") + _, err = s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeem) s.Require().Error(err, "swap-out should fail because the redeemer is missing a required attribute") s.Require().ErrorContains(err, "required attribute: \"you.dont.have.me\"", "error should indicate a missing attribute failure") @@ -560,7 +471,7 @@ func (s *TestSuite) TestSwapOut_SucceedsWithRestrictedUnderlyingAssetRequiredAtt vault, err := s.k.CreateVault(s.ctx, vaultCfg) s.Require().NoError(err, "vault creation with restricted underlying should succeed") vault.SwapOutEnabled = true - vault.WithdrawalDelaySeconds = 0 // Set to zero for same-block processing + vault.WithdrawalDelaySeconds = 0 s.k.AuthKeeper.SetAccount(s.ctx, vault) initialTVV := int64(500) @@ -584,7 +495,7 @@ func (s *TestSuite) TestSwapOut_SucceedsWithRestrictedUnderlyingAssetRequiredAtt s.Require().NoError(s.simApp.AttributeKeeper.SetAttribute(s.ctx, attribute, s.adminAddr), "should successfully set the required attribute on the redeemer") sharesToRedeem := sdk.NewCoin(shareDenom, utils.ShareScalar.MulRaw(50)) - _, err = s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeem, "") + _, err = s.k.SwapOut(s.ctx, vault.GetAddress(), redeemerAddr, sharesToRedeem) s.Require().NoError(err, "swap-out request should succeed because the redeemer has the required attribute") s.assertBalance(redeemerAddr, shareDenom, sharesForRedeemer.Sub(sharesToRedeem.Amount)) diff --git a/module.go b/module.go index c1160c8b..3e35c558 100644 --- a/module.go +++ b/module.go @@ -190,18 +190,14 @@ func (AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { Use: "create [admin] [share_denom] [underlying_asset]", Alias: []string{"c", "new"}, Short: "Create a new vault", - Long: "Create a new vault with an underlying asset and share denom. Optionally set a default payment denom for redemptions and a withdrawal delay that queues swap-outs until the delay elapses.", - Example: fmt.Sprintf("%s create %s svnhash nhash --payment-denom nhash --withdrawal-delay-seconds 86400", txStart, exampleAdminAddr), + Long: "Create a new vault with an underlying asset and share denom. Optionally set a withdrawal delay that queues swap-outs until the delay elapses.", + Example: fmt.Sprintf("%s create %s svnhash nhash --withdrawal-delay-seconds 86400", txStart, exampleAdminAddr), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: fieldAdmin}, {ProtoField: "share_denom"}, {ProtoField: "underlying_asset"}, }, FlagOptions: map[string]*autocliv1.FlagOptions{ - "payment_denom": { - Name: "payment-denom", - Usage: "Payment denom used for swap-outs and payouts. If omitted, the underlying asset is used.", - }, "withdrawal_delay_seconds": { Name: "withdrawal-delay-seconds", Usage: "Minimum delay (in seconds) before a queued swap-out can complete. Set to 0 for no delay.", @@ -252,16 +248,15 @@ func (AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, { RpcMethod: "SwapOut", - Use: "swap-out [owner] [vault_address] [assets] [redeem_denom]", + Use: "swap-out [owner] [vault_address] [assets]", Alias: []string{"so"}, - Short: "Queue a withdrawal by redeeming shares for assets", - Long: "Redeem shares to receive assets. The request is queued and completed later according to vault policy and any configured withdrawal delay.", - Example: fmt.Sprintf("%s swap-out %s %s 100svnhash nhash", txStart, exampleOwnerAddr, exampleVaultAddr), + Short: "Queue a withdrawal by redeeming shares for the underlying asset", + Long: "Redeem shares to receive the vault's underlying asset. The request is queued and completed later according to vault policy and any configured withdrawal delay.", + Example: fmt.Sprintf("%s swap-out %s %s 100svnhash", txStart, exampleOwnerAddr, exampleVaultAddr), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: "owner"}, {ProtoField: fieldVaultAddress}, {ProtoField: fieldAssets}, - {ProtoField: "redeem_denom", Optional: true}, }, }, { @@ -627,15 +622,14 @@ func (AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, { RpcMethod: "EstimateSwapOut", - Use: "estimate-swap-out [vault_address] [shares] [redeem_denom]", + Use: "estimate-swap-out [vault_address] [shares]", Alias: []string{"eso"}, - Short: "Estimate assets received for redeeming shares", - Long: "Simulate a swap-out to estimate the assets returned for the provided shares. Optionally specify a redeem denom.", - Example: fmt.Sprintf("%s estimate-swap-out %s 1000000svnhash nhash", queryStart, exampleVaultAddr), + Short: "Estimate underlying assets received for redeeming shares", + Long: "Simulate a swap-out to estimate the underlying assets returned for the provided shares.", + Example: fmt.Sprintf("%s estimate-swap-out %s 1000000svnhash", queryStart, exampleVaultAddr), PositionalArgs: []*autocliv1.PositionalArgDescriptor{ {ProtoField: fieldVaultAddress}, {ProtoField: fieldShares}, - {ProtoField: "redeem_denom", Optional: true}, }, }, { diff --git a/proto/provlabs/vault/v1/events.proto b/proto/provlabs/vault/v1/events.proto index e7d6ca7f..13754dd3 100644 --- a/proto/provlabs/vault/v1/events.proto +++ b/proto/provlabs/vault/v1/events.proto @@ -219,7 +219,8 @@ message EventSwapOutRequested { string vault_address = 1; // owner is the bech32 address of the user who initiated the swap out. string owner = 2; - // redeem_denom is the denomination of the asset to be redeemed. + // redeem_denom is the denomination of the asset to be redeemed. Always the + // vault's underlying_asset; retained for event-schema compatibility. string redeem_denom = 3; // shares is the amount of vault shares the user escrowed for this request. string shares = 4; @@ -495,7 +496,7 @@ message EventAssetAccepted { // target_amount is the funds the vault paid the source, rendered as a coins string. string target_amount = 5; // direction indicates whether the asset moved into the vault ("inbound") or - // out of the vault ("outbound") relative to the vault's payment denom. + // out of the vault ("outbound") relative to the vault's underlying asset. string direction = 6; } diff --git a/proto/provlabs/vault/v1/query.proto b/proto/provlabs/vault/v1/query.proto index a509ae1a..a0bf76bb 100644 --- a/proto/provlabs/vault/v1/query.proto +++ b/proto/provlabs/vault/v1/query.proto @@ -156,7 +156,7 @@ message QueryVaultResponse { message QueryEstimateSwapInRequest { // vault_address is the bech32 address of the vault to query. string vault_address = 1; - // assets is the amount of underlying or payment denom to swap in. + // assets is the amount of the underlying asset to swap in. cosmos.base.v1beta1.Coin assets = 2 [(gogoproto.nullable) = false]; } @@ -179,8 +179,11 @@ message QueryEstimateSwapOutRequest { string vault_address = 1; // shares is the amount of shares to swap out. string shares = 2; - // redeem_denom is the payout denom to estimate; if empty, the underlying asset is used. - string redeem_denom = 3; + + // Field 3 held redeem_denom, a never-released choice of payout denom; the + // estimated payout is always the underlying asset. Reserved to prevent reuse. + reserved 3; + reserved "redeem_denom"; } // QueryEstimateSwapOutResponse is the response message for the Query/EstimateSwapOut endpoint. diff --git a/proto/provlabs/vault/v1/tx.proto b/proto/provlabs/vault/v1/tx.proto index 6d913a5d..63e329d4 100644 --- a/proto/provlabs/vault/v1/tx.proto +++ b/proto/provlabs/vault/v1/tx.proto @@ -116,7 +116,7 @@ service Msg { rpc UpdateNAVAuthority(MsgUpdateNAVAuthorityRequest) returns (MsgUpdateNAVAuthorityResponse); // AcceptAsset settles a pending exchange-module payment whose target is the vault, - // exchanging an external asset for the vault's payment denom. + // exchanging an external asset for the vault's underlying asset. // Must be signed by the vault's asset manager; the admin cannot settle. rpc AcceptAsset(MsgAcceptAssetRequest) returns (MsgAcceptAssetResponse); @@ -136,9 +136,6 @@ message MsgCreateVaultRequest { string share_denom = 2; // underlying_asset is the denomination of the asset supported by the vault. string underlying_asset = 3; - // payment_denom is the secondary denomination the vault can accept. - // if not specified, vault payment_denom will be set to underlying_asset. - string payment_denom = 4; // withdrawal_delay_seconds is the time period (in seconds) that a withdrawal // must wait in the pending queue before being processed. uint64 withdrawal_delay_seconds = 5; @@ -158,13 +155,12 @@ message MsgCreateVaultRequest { // - Values must be positive (> 0). // - An empty string "" indicates no maximum limit. string max_swap_out_value = 9 [(cosmos_proto.scalar) = "cosmos.IntString"]; - // initial_payment_nav seeds the per-vault Internal NAV entry for payment_denom - // at creation, ensuring fee accrual and payment-denom swap-outs are operational - // from block one. The entry's denom is implicitly payment_denom; the price - // denom must be underlying_asset. - // - Required when payment_denom is set and payment_denom != underlying_asset. - // - Must be omitted when payment_denom is empty or equal to underlying_asset. - InitialVaultNAV initial_payment_nav = 10; + + // Field 4 held payment_denom and field 10 held initial_payment_nav + // (InitialVaultNAV), never-released mixed-denom creation inputs; reserved to + // prevent reuse. Vaults are single-denom on underlying_asset. + reserved 4, 10; + reserved "payment_denom", "initial_payment_nav"; } // MsgCreateVaultResponse is the response message for the CreateVault endpoint. @@ -220,10 +216,11 @@ message MsgSwapOutRequest { string vault_address = 2; // assets is the amount of underlying assets to withdraw. cosmos.base.v1beta1.Coin assets = 3 [(gogoproto.nullable) = false]; - // redeem_denom selects the payout coin. - // - If empty, defaults to the vault’s payment_denom. - // - Must be either the vault’s underlying_asset or its payment_denom. - string redeem_denom = 4; + + // Field 4 held redeem_denom, a never-released choice of payout denom; the + // payout is always the underlying asset. Reserved to prevent reuse. + reserved 4; + reserved "redeem_denom"; } // MsgSwapOutResponse is the response message for the SwapOut endpoint. @@ -621,11 +618,10 @@ message MsgUpdateVaultNAVRequest { // vault_address is the bech32 address of the vault whose NAV entry is being updated. string vault_address = 2; // denom is the asset denomination being priced. It must not be the vault's - // share denom. The underlying asset is a valid denom (e.g. to record its - // price in payment-denom terms). + // share denom. string denom = 3; // price is the total value of `volume` units of the denom, denominated in - // one of the vault's accepted denoms (underlying asset or payment denom). + // the vault's underlying asset. cosmos.base.v1beta1.Coin price = 4 [(gogoproto.nullable) = false]; // volume is the number of units of the denom that price covers. It must be positive. string volume = 5 [ @@ -658,8 +654,8 @@ message MsgUpdateNAVAuthorityResponse {} // MsgAcceptAssetRequest is the request message for settling a pending exchange-module // payment whose target is the vault. The payment is identified by its source account and -// external_id. The vault settles only payments where one leg is the vault's payment_denom; -// the settlement direction (inbound or outbound) is derived from which leg that is. +// external_id. The vault settles only payments where one leg is the vault's underlying +// asset; the settlement direction (inbound or outbound) is derived from which leg that is. message MsgAcceptAssetRequest { option (cosmos.msg.v1.signer) = "authority"; diff --git a/proto/provlabs/vault/v1/vault.proto b/proto/provlabs/vault/v1/vault.proto index 94812e1e..9f8919b4 100644 --- a/proto/provlabs/vault/v1/vault.proto +++ b/proto/provlabs/vault/v1/vault.proto @@ -23,20 +23,16 @@ message VaultAccount { // underlying_asset is the vault’s single principal collateral AND valuation/base unit. // - Exactly one denom. // - Total Vault Value (TVV) and NAV-per-share are computed and reported in this denom. - // - Interest accrual and internal accounting are measured in this denom. - // - Any other coin accepted for I/O (i.e. a distinct payment_denom) must have a NAV record priced INTO this denom. + // - Interest accrual, fees, and internal accounting are measured in this denom. + // - Held assets acquired via settlement must have an internal NAV record priced INTO this denom. string underlying_asset = 3; - // payment_denom is the external payment coin supported for user I/O alongside the underlying_asset. - // - Always populated. If not specified during creation, it defaults to underlying_asset. - // - If payment_denom equals underlying_asset, the vault operates as a single-denom vault. - // - If payment_denom differs from underlying_asset, swap-in/out accept either denom (one per call). - // - Default Swap-Out: If a user does not specify a redeem_denom during withdrawal, - // the vault defaults to paying out in this payment_denom. - // - NAV Requirement: If payment_denom differs from underlying_asset, it requires an on-chain NAV record - // mapping payment_denom -> underlying_asset to value deposits and redemptions. - // (Note: In current versions, this NAV check is strictly enforced unless payment_denom is 'uylds.fcc'). - string payment_denom = 4; + // payment_denom always equals underlying_asset. Vaults are single-denom; the + // field is inert and retained only for wire compatibility. + // + // Deprecated: The mixed-denom vault concept has been flattened into a single + // underlying denom. Deletion of this field is deferred to a future major release. + string payment_denom = 4 [deprecated = true]; // admin is the address that has administrative privileges over the vault. string admin = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"]; @@ -107,7 +103,7 @@ message VaultAccount { // outstanding_aum_fee is the amount of AUM fee that has been calculated but not yet collected // due to insufficient liquidity in the principal marker. This amount is always denominated - // in the vault's payment_denom, must be preserved, and is carried into valuation computations. + // in the vault's underlying_asset, must be preserved, and is carried into valuation computations. cosmos.base.v1beta1.Coin outstanding_aum_fee = 23 [(gogoproto.nullable) = false]; // aum_fee_bips is the AUM fee rate (in basis points) for this specific vault. @@ -119,7 +115,6 @@ message VaultAccount { // min_swap_in_value is a string representing the minimum value required for a deposit. // - The value is measured in the underlying_asset. - // - Incoming payment_denom deposits are converted to this unit before checking. // - Values must be non-negative (>= 0). // - If empty ("") or "0", there is no minimum limit. string min_swap_in_value = 25 [(cosmos_proto.scalar) = "cosmos.IntString"]; @@ -133,7 +128,6 @@ message VaultAccount { // max_swap_in_value is a string representing the maximum value allowed for a deposit. // - The value is measured in the underlying_asset. - // - Incoming payment_denom deposits are converted to this unit before checking. // - Values must be positive (> 0). // - An empty string "" indicates no maximum limit. string max_swap_in_value = 27 [(cosmos_proto.scalar) = "cosmos.IntString"]; @@ -179,27 +173,6 @@ message VaultNAV { ]; } -// InitialVaultNAV seeds a per-vault Internal NAV entry at vault creation time. -// It is the stateless subset of VaultNAV (no updated_block_height or -// updated_time, which are stamped by the keeper when the entry is persisted) -// and omits the denom, which is implied by the field that carries it on the -// containing message (e.g. payment_denom on MsgCreateVaultRequest). -message InitialVaultNAV { - // price is the total value of `volume` units of the priced denom, denominated - // in one of the vault's accepted denoms (typically the underlying asset). - cosmos.base.v1beta1.Coin price = 1 [(gogoproto.nullable) = false]; - // volume is the number of units of the priced denom that price covers. It - // must be positive; the per-unit value is price divided by volume. - string volume = 2 [ - (cosmos_proto.scalar) = "cosmos.Int", - (gogoproto.customtype) = "cosmossdk.io/math.Int", - (gogoproto.nullable) = false - ]; - // source identifies the origin of this NAV entry (for example an oracle name - // or the settlement path). - string source = 3; -} - // AccountBalance represents the coin balance of a single account. message AccountBalance { option (gogoproto.equal) = false; @@ -226,6 +199,7 @@ message PendingSwapOut { // shares are the shares that were escrowed by the user. cosmos.base.v1beta1.Coin shares = 3 [(gogoproto.nullable) = false]; - // redeem_denom is the denomination of the asset to be redeemed. - string redeem_denom = 4; + // redeem_denom is the denomination of the asset to be redeemed. Always the + // vault's underlying_asset; retained for wire compatibility. + string redeem_denom = 4 [deprecated = true]; } diff --git a/simulation/estimate_accuracy_test.go b/simulation/estimate_accuracy_test.go index 2823f0b4..0b836ee7 100644 --- a/simulation/estimate_accuracy_test.go +++ b/simulation/estimate_accuracy_test.go @@ -11,8 +11,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - - markertypes "github.com/provenance-io/provenance/x/marker/types" ) // newAccuracyVault creates a vault for estimate-accuracy testing. It disables the AUM fee and @@ -20,8 +18,8 @@ import ( // identical vault state at the same block height. AUM fees are disabled because the estimate // reports a net-of-fee value while the settled swap reads gross post-reconcile value; leaving the // default fee enabled would inject a fee-accounting delta that is unrelated to swap math accuracy. -func (s *VaultSimTestSuite) newAccuracyVault(admin simtypes.Account, underlying, payment, share string) *types.VaultAccount { - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, underlying, payment, share, admin, s.accs) +func (s *VaultSimTestSuite) newAccuracyVault(admin simtypes.Account, underlying, share string) *types.VaultAccount { + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, underlying, share, admin, s.accs) s.Require().NoError(err, "CreateVault for share denom %s", share) vault, err := s.app.VaultKeeper.GetVault(s.ctx, types.GetVaultAddress(share)) @@ -50,19 +48,6 @@ func (s *VaultSimTestSuite) accrueInterest(vaultAddr sdk.AccAddress, rate string s.Require().NoError(FundAccount(s.ctx, s.app.BankKeeper, vaultAddr, sdk.NewCoins(reserves)), "fund reserves %s for vault %s", reserves, vaultAddr) } -// setPaymentNav publishes a NAV pricing one unit of paymentDenom at priceInUnderlying units of -// the vault's underlying asset, giving the valuation engine a conversion rate for multi-denom -// vaults. -func (s *VaultSimTestSuite) setPaymentNav(paymentDenom, underlyingDenom string, priceInUnderlying int64) { - marker, err := s.app.MarkerKeeper.GetMarker(s.ctx, markertypes.MustGetMarkerAddress(paymentDenom)) - s.Require().NoError(err, "GetMarker for payment denom %s", paymentDenom) - err = s.app.MarkerKeeper.SetNetAssetValue(s.ctx, marker, markertypes.NetAssetValue{ - Price: sdk.NewInt64Coin(underlyingDenom, priceInUnderlying), - Volume: 1, - }, "test") - s.Require().NoError(err, "SetNetAssetValue for %s priced in %s", paymentDenom, underlyingDenom) -} - // TestEstimateSwapInAccuracy validates that the EstimateSwapIn query reports the same number of // shares a depositor actually receives from SwapIn, across a range of vault states. Both paths run // against the same vault state at the same block height, so an accurate estimate must match the @@ -77,7 +62,7 @@ func (s *VaultSimTestSuite) TestEstimateSwapInAccuracy() { name: "underlying deposit into empty vault", setup: func() (simtypes.Account, sdk.AccAddress, sdk.Coin) { s.SetupTest() - vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "", "accswapinA") + vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "accswapinA") return s.accs[1], vault.GetAddress(), sdk.NewInt64Coin("underlying2vx", 1_000_000) }, }, @@ -85,26 +70,16 @@ func (s *VaultSimTestSuite) TestEstimateSwapInAccuracy() { name: "underlying deposit into seeded vault", setup: func() (simtypes.Account, sdk.AccAddress, sdk.Coin) { s.SetupTest() - vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "", "accswapinB") + vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "accswapinB") s.Require().NoError(simulation.SwapIn(s.ctx, s.app.VaultKeeper, s.accs[1], "accswapinB", sdk.NewInt64Coin("underlying2vx", 2_500_000)), "seed swap-in") return s.accs[2], vault.GetAddress(), sdk.NewInt64Coin("underlying2vx", 1_000_000) }, }, - { - name: "payment-denom deposit uses NAV conversion", - setup: func() (simtypes.Account, sdk.AccAddress, sdk.Coin) { - s.SetupTest() - vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "payment2vx", "accswapinC") - s.setPaymentNav("payment2vx", "underlying2vx", 2) - s.Require().NoError(simulation.SwapIn(s.ctx, s.app.VaultKeeper, s.accs[1], "accswapinC", sdk.NewInt64Coin("underlying2vx", 2_000_000)), "seed swap-in") - return s.accs[2], vault.GetAddress(), sdk.NewInt64Coin("payment2vx", 500_000) - }, - }, { name: "underlying deposit with accrued interest", setup: func() (simtypes.Account, sdk.AccAddress, sdk.Coin) { s.SetupTest() - vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "", "accswapinD") + vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "accswapinD") s.Require().NoError(simulation.SwapIn(s.ctx, s.app.VaultKeeper, s.accs[1], "accswapinD", sdk.NewInt64Coin("underlying2vx", 3_000_000)), "seed swap-in") s.accrueInterest(vault.GetAddress(), "0.10", 30*24*time.Hour, sdk.NewInt64Coin("underlying2vx", 1_000_000)) return s.accs[2], vault.GetAddress(), sdk.NewInt64Coin("underlying2vx", 1_000_000) @@ -150,8 +125,7 @@ func (s *VaultSimTestSuite) TestEstimateSwapInAccuracy() { // owner actually receives once a swap-out settles. SwapOut is asynchronous: the message only // escrows shares, and the payout is realized by the EndBlocker. With a zero withdrawal delay the // payout settles in the same block as the estimate, so an accurate estimate must match the realized -// payout exactly. The redeem denom is always passed explicitly because EstimateSwapOut and SwapOut -// disagree on the default for an empty redeem denom (underlying vs payment respectively). +// payout exactly. The payout is always the vault's underlying asset. func (s *VaultSimTestSuite) TestEstimateSwapOutAccuracy() { tests := []struct { name string @@ -162,7 +136,7 @@ func (s *VaultSimTestSuite) TestEstimateSwapOutAccuracy() { name: "full underlying redeem, no interest", setup: func() (simtypes.Account, sdk.AccAddress, sdk.Coin, string) { s.SetupTest() - vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "", "accswapoutA") + vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "accswapoutA") owner := s.accs[1] s.Require().NoError(simulation.SwapIn(s.ctx, s.app.VaultKeeper, owner, "accswapoutA", sdk.NewInt64Coin("underlying2vx", 2_000_000)), "owner swap-in") shares := s.app.BankKeeper.GetBalance(s.ctx, owner.Address, "accswapoutA") @@ -173,31 +147,18 @@ func (s *VaultSimTestSuite) TestEstimateSwapOutAccuracy() { name: "partial underlying redeem, no interest", setup: func() (simtypes.Account, sdk.AccAddress, sdk.Coin, string) { s.SetupTest() - vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "", "accswapoutB") + vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "accswapoutB") owner := s.accs[1] s.Require().NoError(simulation.SwapIn(s.ctx, s.app.VaultKeeper, owner, "accswapoutB", sdk.NewInt64Coin("underlying2vx", 2_000_000)), "owner swap-in") bal := s.app.BankKeeper.GetBalance(s.ctx, owner.Address, "accswapoutB") return owner, vault.GetAddress(), sdk.NewCoin(bal.Denom, bal.Amount.Quo(math.NewInt(2))), "underlying2vx" }, }, - { - name: "payment-denom redeem uses NAV conversion", - setup: func() (simtypes.Account, sdk.AccAddress, sdk.Coin, string) { - s.SetupTest() - vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "payment2vx", "accswapoutC") - s.setPaymentNav("payment2vx", "underlying2vx", 2) - owner := s.accs[1] - s.Require().NoError(simulation.SwapIn(s.ctx, s.app.VaultKeeper, owner, "accswapoutC", sdk.NewInt64Coin("underlying2vx", 2_000_000)), "owner swap-in") - s.Require().NoError(FundAccount(s.ctx, s.app.BankKeeper, vault.PrincipalMarkerAddress(), sdk.NewCoins(sdk.NewInt64Coin("payment2vx", 2_000_000))), "fund principal payment liquidity") - bal := s.app.BankKeeper.GetBalance(s.ctx, owner.Address, "accswapoutC") - return owner, vault.GetAddress(), sdk.NewCoin(bal.Denom, bal.Amount.Quo(math.NewInt(4))), "payment2vx" - }, - }, { name: "underlying redeem with accrued interest", setup: func() (simtypes.Account, sdk.AccAddress, sdk.Coin, string) { s.SetupTest() - vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "", "accswapoutD") + vault := s.newAccuracyVault(s.accs[0], "underlying2vx", "accswapoutD") owner := s.accs[1] s.Require().NoError(simulation.SwapIn(s.ctx, s.app.VaultKeeper, owner, "accswapoutD", sdk.NewInt64Coin("underlying2vx", 3_000_000)), "owner swap-in") s.accrueInterest(vault.GetAddress(), "0.10", 30*24*time.Hour, sdk.NewInt64Coin("underlying2vx", 1_000_000)) @@ -215,7 +176,6 @@ func (s *VaultSimTestSuite) TestEstimateSwapOutAccuracy() { estResp, err := qs.EstimateSwapOut(s.ctx, &types.QueryEstimateSwapOutRequest{ VaultAddress: vaultAddr.String(), Shares: shares.Amount.String(), - RedeemDenom: redeemDenom, }) s.Require().NoError(err, "EstimateSwapOut for vault %s shares %s redeem %s", vaultAddr, shares, redeemDenom) @@ -226,7 +186,6 @@ func (s *VaultSimTestSuite) TestEstimateSwapOutAccuracy() { Owner: owner.Address.String(), VaultAddress: vaultAddr.String(), Assets: shares, - RedeemDenom: redeemDenom, }) s.Require().NoError(err, "SwapOut for vault %s shares %s redeem %s", vaultAddr, shares, redeemDenom) diff --git a/simulation/operations.go b/simulation/operations.go index f6dae124..bf0c2e61 100644 --- a/simulation/operations.go +++ b/simulation/operations.go @@ -205,19 +205,12 @@ func SimulateMsgCreateVault(k keeper.Keeper) simtypes.Operation { if err != nil { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgCreateVaultRequest{}), "unable to get random denom for underlying"), nil, nil } - payment, err := getRandomDenom(r, k, ctx, admin) - if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgCreateVaultRequest{}), "unable to get random denom for payment"), nil, nil - } - if payment == underlying { - payment = "" - } markerKeeper, ok := k.MarkerKeeper.(markerkeeper.Keeper) if !ok { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgCreateVaultRequest{}), "marker keeper is not of type markerkeeper.Keeper"), nil, fmt.Errorf("marker keeper is not of type markerkeeper.Keeper") } - if err = PrepareVaultMarkers(ctx, k.AuthKeeper, markerKeeper, underlying, payment, denom); err != nil { + if err = PrepareVaultMarkers(ctx, k.AuthKeeper, markerKeeper, underlying, denom); err != nil { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgCreateVaultRequest{}), "failed to prepare vault markers"), nil, err } @@ -225,16 +218,8 @@ func SimulateMsgCreateVault(k keeper.Keeper) simtypes.Operation { Admin: admin.Address.String(), ShareDenom: denom, UnderlyingAsset: underlying, - PaymentDenom: payment, WithdrawalDelaySeconds: interest.SecondsPerDay, } - if payment != "" && payment != underlying { - msg.InitialPaymentNav = &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlying, 1), - Volume: math.OneInt(), - Source: "simulation", - } - } if r.Intn(2) == 0 { msg.MinSwapInValue = math.NewInt(int64(r.Intn(1000))).String() @@ -281,7 +266,7 @@ func SimulateMsgSwapIn(k keeper.Keeper) simtypes.Operation { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSwapInRequest{}), "unable to get random vault"), nil, err } - assetDenom := getRandomVaultAsset(r, vault) + assetDenom := vault.UnderlyingAsset owner, balance, err := getRandomAccountWithDenom(r, k, ctx, accs, assetDenom) if err != nil { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgSwapInRequest{}), "no account has funds for this vault's accepted assets"), nil, nil @@ -345,15 +330,10 @@ func SimulateMsgSwapOut(k keeper.Keeper) simtypes.Operation { } shares := sdk.NewCoin(vault.TotalShares.Denom, amount) - // Pick a random asset to receive it in - redeemDenom := getRandomVaultAsset(r, vault) - - // Create and dispatch the message msg := &types.MsgSwapOutRequest{ Owner: owner.Address.String(), VaultAddress: vault.GetAddress().String(), Assets: shares, - RedeemDenom: redeemDenom, } handler := keeper.NewMsgServer(&k) @@ -669,7 +649,7 @@ func SimulateMsgDepositPrincipalFunds(k keeper.Keeper) simtypes.Operation { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgDepositPrincipalFundsRequest{}), "unable to get random authority"), nil, nil } - asset := getRandomVaultAsset(r, vault) + asset := vault.UnderlyingAsset balance := k.BankKeeper.GetBalance(ctx, authority.Address, asset) if balance.IsZero() { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgDepositPrincipalFundsRequest{}), "authority has no funds to deposit"), nil, nil @@ -724,7 +704,7 @@ func SimulateMsgWithdrawPrincipalFunds(k keeper.Keeper) simtypes.Operation { } principalAddr := vault.PrincipalMarkerAddress() - asset := getRandomVaultAsset(r, vault) + asset := vault.UnderlyingAsset balance := k.BankKeeper.GetBalance(ctx, principalAddr, asset) if balance.IsZero() { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgWithdrawPrincipalFundsRequest{}), "no underlying asset funds"), nil, nil @@ -1316,7 +1296,7 @@ func SimulateMsgUpdateVaultNAV(k keeper.Keeper) simtypes.Operation { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgUpdateVaultNAVRequest{}), "unable to create nav marker"), nil, err } - priceDenom := getRandomVaultAsset(r, vault) + priceDenom := vault.UnderlyingAsset priceAmount := math.NewInt(int64(r.Intn(1_000_000) + 1)) volume := math.NewInt(int64(r.Intn(1_000_000) + 1)) @@ -1387,11 +1367,11 @@ type paymentCreator interface { // multiple of the reduced NAV ratio so the settlement passes the exact-price guardrail // (random amounts would NoOp on every settlement after the first); when no NAV exists yet // (first acquisition, guardrail skipped) the amounts are random. -func settlementAmounts(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, vault *types.VaultAccount, sourceDenom string, portion math.Int) (sourceAmount, targetAmount math.Int, err error) { - nav, err := k.GetVaultNAV(ctx, vault.GetAddress(), vault.UnderlyingAsset) +func settlementAmounts(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, vault *types.VaultAccount, sourceDenom, assetDenom string, portion math.Int) (sourceAmount, targetAmount math.Int, err error) { + nav, err := k.GetVaultNAV(ctx, vault.GetAddress(), assetDenom) if err != nil { if !errors.Is(err, collections.ErrNotFound) { - return math.Int{}, math.Int{}, fmt.Errorf("failed to get internal NAV for denom %q: %w", vault.UnderlyingAsset, err) + return math.Int{}, math.Int{}, fmt.Errorf("failed to get internal NAV for denom %q: %w", assetDenom, err) } sourceAmount, err = simtypes.RandPositiveInt(r, portion) if err != nil { @@ -1405,12 +1385,12 @@ func settlementAmounts(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, vault *ty unitAsset := nav.Volume.Quo(math.NewIntFromBigInt(gcd)) sourceUnit, targetUnit := unitAsset, unitPayment - if sourceDenom == vault.PaymentDenom { + if sourceDenom == vault.UnderlyingAsset { sourceUnit, targetUnit = unitPayment, unitAsset } maxMultiple := portion.Quo(sourceUnit) if maxMultiple.IsZero() { - return math.Int{}, math.Int{}, fmt.Errorf("source balance too low for an exact-NAV settlement of %s per %s%s", nav.Price, nav.Volume, vault.UnderlyingAsset) + return math.Int{}, math.Int{}, fmt.Errorf("source balance too low for an exact-NAV settlement of %s per %s%s", nav.Price, nav.Volume, assetDenom) } multiple, err := simtypes.RandPositiveInt(r, maxMultiple) if err != nil { @@ -1421,27 +1401,26 @@ func settlementAmounts(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, vault *ty // stagePayment creates a pending exchange payment targeting the vault, drawing the source leg // from an account that already holds the chosen denom. The settlement direction is chosen at -// random: one leg always carries the vault's payment denom and the other its underlying asset, -// which is the shape AcceptAsset requires. Leg amounts come from settlementAmounts so repeat -// settlements trade at the vault's internal NAV. Funds are never minted because the vault -// denoms are fixed-supply markers; inflating their circulating supply would trip the marker -// module's BeginBlocker supply reconciliation. The created payment is returned so callers can -// stage the principal marker for the leg the vault must pay out. +// random: one leg always carries the vault's underlying asset and the other an external asset +// denom, which is the shape AcceptAsset requires. Leg amounts come from settlementAmounts so +// repeat settlements trade at the vault's internal NAV. Funds are never minted because the +// sim denoms are fixed-supply markers; inflating their circulating supply would trip the +// marker module's BeginBlocker supply reconciliation. The created payment is returned so +// callers can stage the principal marker for the leg the vault must pay out. func stagePayment(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, vault *types.VaultAccount, accs []simtypes.Account) (*exchange.Payment, error) { creator, ok := k.ExchangeKeeper.(paymentCreator) if !ok { return nil, fmt.Errorf("exchange keeper does not support creating payments") } - paymentDenom := vault.PaymentDenom - assetDenom := vault.UnderlyingAsset - if assetDenom == paymentDenom { - return nil, fmt.Errorf("vault underlying and payment denom are identical") + assetDenom, err := getRandomExternalAssetDenom(r, k, ctx, accs, vault.UnderlyingAsset) + if err != nil { + return nil, err } - sourceDenom, targetDenom := assetDenom, paymentDenom + sourceDenom, targetDenom := assetDenom, vault.UnderlyingAsset if r.Intn(2) == 0 { - sourceDenom, targetDenom = paymentDenom, assetDenom + sourceDenom, targetDenom = targetDenom, sourceDenom } source, sourceBalance, err := getRandomAccountWithDenom(r, k, ctx, accs, sourceDenom) @@ -1452,7 +1431,7 @@ func stagePayment(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, vault *types.V if portion.IsZero() { return nil, fmt.Errorf("source balance too low to stage a payment") } - sourceAmount, targetAmount, err := settlementAmounts(ctx, r, k, vault, sourceDenom, portion) + sourceAmount, targetAmount, err := settlementAmounts(ctx, r, k, vault, sourceDenom, assetDenom, portion) if err != nil { return nil, err } @@ -1520,11 +1499,9 @@ func SimulateMsgAcceptAsset(k keeper.Keeper) simtypes.Operation { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgAcceptAssetRequest{}), "unable to setup initial state"), nil, err } - vault, err := getRandomVaultWithCondition(r, k, ctx, func(vault types.VaultAccount) bool { - return vault.PaymentDenom != "" - }) + vault, err := getRandomVault(r, k, ctx) if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgAcceptAssetRequest{}), "no vault with a payment denom"), nil, nil + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgAcceptAssetRequest{}), "unable to get random vault"), nil, nil } authority, err := ensureSettlementAuthority(ctx, r, k, vault, accs) @@ -1567,11 +1544,9 @@ func SimulateMsgRejectAsset(k keeper.Keeper) simtypes.Operation { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgRejectAssetRequest{}), "unable to setup initial state"), nil, err } - vault, err := getRandomVaultWithCondition(r, k, ctx, func(vault types.VaultAccount) bool { - return vault.PaymentDenom != "" - }) + vault, err := getRandomVault(r, k, ctx) if err != nil { - return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgRejectAssetRequest{}), "no vault with a payment denom"), nil, nil + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(&types.MsgRejectAssetRequest{}), "unable to get random vault"), nil, nil } authority, err := ensureSettlementAuthority(ctx, r, k, vault, accs) diff --git a/simulation/operations_test.go b/simulation/operations_test.go index 8b73d023..03601094 100644 --- a/simulation/operations_test.go +++ b/simulation/operations_test.go @@ -64,8 +64,8 @@ func (s *VaultSimTestSuite) SetupTest() { err = simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("underlying2vx", 100_000_000), s.accs, true, s.provlabsAddr) s.Require().NoError(err, "CreateGlobalMarker underlying") - err = simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("payment2vx", 100_000_000), s.accs, true, s.provlabsAddr) - s.Require().NoError(err, "CreateGlobalMarker payment") + err = simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("external2vx", 100_000_000), s.accs, true, s.provlabsAddr) + s.Require().NoError(err, "CreateGlobalMarker external asset") } func (s *VaultSimTestSuite) setupAccounts() { @@ -100,7 +100,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgCreateVault() { func (s *VaultSimTestSuite) TestSimulateMsgSwapIn() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgSwapIn(*s.app.VaultKeeper) @@ -116,7 +116,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgSwapOut() { s.ctx = s.ctx.WithBlockTime(time.Now()) selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") err = simulation.SwapIn(s.ctx, s.app.VaultKeeper, selected, "underlyingshare", sdk.NewInt64Coin("underlying2vx", 100)) s.Require().NoError(err, "SwapIn") @@ -133,7 +133,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgSwapOut() { func (s *VaultSimTestSuite) TestSimulateMsgToggleSwapIn() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgToggleSwapIn(*s.app.VaultKeeper) @@ -148,7 +148,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgToggleSwapIn() { func (s *VaultSimTestSuite) TestSimulateMsgToggleSwapOut() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgToggleSwapOut(*s.app.VaultKeeper) @@ -163,7 +163,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgToggleSwapOut() { func (s *VaultSimTestSuite) TestSimulateMsgPauseVault() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgPauseVault(*s.app.VaultKeeper) @@ -178,7 +178,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgPauseVault() { func (s *VaultSimTestSuite) TestSimulateMsgUnpauseVault() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") err = simulation.PauseVault(s.ctx, s.app.VaultKeeper, "underlyingshare") s.Require().NoError(err, "PauseVault") @@ -197,12 +197,12 @@ func (s *VaultSimTestSuite) TestSimulateMsgExpeditePendingSwapOut() { user := s.accs[0] admin := s.accs[1] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", admin, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", admin, s.accs) s.Require().NoError(err, "CreateVault") err = simulation.SwapIn(s.ctx, s.app.VaultKeeper, user, "underlyingshare", sdk.NewInt64Coin("underlying2vx", 100)) s.Require().NoError(err, "SwapIn") shares := s.app.BankKeeper.GetBalance(s.ctx, user.Address, "underlyingshare") - err = simulation.SwapOut(s.ctx, s.app.VaultKeeper, user, shares, "underlying2vx") + err = simulation.SwapOut(s.ctx, s.app.VaultKeeper, user, shares) s.Require().NoError(err, "SwapOut") // Now run the simulation for Expedite @@ -218,7 +218,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgExpeditePendingSwapOut() { func (s *VaultSimTestSuite) TestSimulateMsgDepositInterestFunds() { admin := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", admin, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", admin, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgDepositInterestFunds(*s.app.VaultKeeper) @@ -233,7 +233,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgDepositInterestFunds() { func (s *VaultSimTestSuite) TestSimulateMsgDepositPrincipalFunds() { admin := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", admin, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", admin, s.accs) s.Require().NoError(err, "CreateVault") err = simulation.PauseVault(s.ctx, s.app.VaultKeeper, "underlyingshare") s.Require().NoError(err, "PauseVault") @@ -250,7 +250,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgDepositPrincipalFunds() { func (s *VaultSimTestSuite) TestSimulateMsgWithdrawInterestFunds() { admin := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", admin, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", admin, s.accs) s.Require().NoError(err, "CreateVault") _, err = simulation.DepositInterestFunds(s.ctx, s.app.VaultKeeper, "underlyingshare", sdk.NewInt64Coin("underlying2vx", 100)) s.Require().NoError(err, "DepositInterest") @@ -267,7 +267,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgWithdrawInterestFunds() { func (s *VaultSimTestSuite) TestSimulateMsgWithdrawPrincipalFunds() { admin := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", admin, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", admin, s.accs) s.Require().NoError(err, "CreateVault") err = simulation.PauseVault(s.ctx, s.app.VaultKeeper, "underlyingshare") s.Require().NoError(err, "PauseVault") @@ -286,7 +286,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgWithdrawPrincipalFunds() { func (s *VaultSimTestSuite) TestSimulateMsgUpdateInterestRate() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgUpdateInterestRate(*s.app.VaultKeeper) @@ -301,7 +301,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgUpdateInterestRate() { func (s *VaultSimTestSuite) TestSimulateMsgUpdateMinInterestRate() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgUpdateMinInterestRate(*s.app.VaultKeeper) @@ -316,7 +316,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgUpdateMinInterestRate() { func (s *VaultSimTestSuite) TestSimulateMsgUpdateMaxInterestRate() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgUpdateMaxInterestRate(*s.app.VaultKeeper) @@ -331,7 +331,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgUpdateMaxInterestRate() { func (s *VaultSimTestSuite) TestSimulateMsgToggleBridge() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") err = simulation.SetVaultBridge(s.ctx, s.app.VaultKeeper, "underlyingshare", sdk.AccAddress("bridgeaddr"), true) @@ -349,7 +349,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgToggleBridge() { func (s *VaultSimTestSuite) TestSimulateMsgSetBridgeAddress() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgSetBridgeAddress(*s.app.VaultKeeper) @@ -365,7 +365,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgBridgeMintShares() { admin := s.accs[0] bridge := s.accs[1] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", admin, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", admin, s.accs) s.Require().NoError(err, "CreateVault") err = simulation.BridgeAssets(s.ctx, s.app.VaultKeeper, "underlyingshare", sdk.NewInt64Coin("underlyingshare", 1_000), sdk.NewInt64Coin("underlyingshare", 500)) @@ -390,7 +390,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgBridgeBurnShares() { admin := s.accs[0] bridge := s.accs[1] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", admin, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", admin, s.accs) s.Require().NoError(err, "CreateVault") err = simulation.SetVaultBridge(s.ctx, s.app.VaultKeeper, "underlyingshare", bridge.Address, true) @@ -415,7 +415,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgBridgeBurnShares() { func (s *VaultSimTestSuite) TestSimulateMsgUpdateWithdrawalDelay() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgUpdateWithdrawalDelay(*s.app.VaultKeeper) @@ -441,7 +441,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgUpdateParams() { func (s *VaultSimTestSuite) TestSimulateMsgUpdateVaultAUMFeeBips() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgUpdateVaultAUMFeeBips(*s.app.VaultKeeper) @@ -456,7 +456,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgUpdateVaultAUMFeeBips() { func (s *VaultSimTestSuite) TestSimulateMsgUpdateVaultNAV() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgUpdateVaultNAV(*s.app.VaultKeeper) @@ -471,7 +471,7 @@ func (s *VaultSimTestSuite) TestSimulateMsgUpdateVaultNAV() { func (s *VaultSimTestSuite) TestSimulateMsgUpdateNAVAuthority() { selected := s.accs[0] - err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "", "underlyingshare", selected, s.accs) + err := simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "underlying2vx", "underlyingshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgUpdateNAVAuthority(*s.app.VaultKeeper) @@ -488,10 +488,10 @@ func (s *VaultSimTestSuite) TestSimulateMsgAcceptAsset() { err := simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("acceptunder2vx", 100_000_000), s.accs, false, s.provlabsAddr) s.Require().NoError(err, "CreateGlobalMarker underlying") - err = simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("acceptpay2vx", 100_000_000), s.accs, false, s.provlabsAddr) - s.Require().NoError(err, "CreateGlobalMarker payment") + err = simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("acceptexternal2vx", 100_000_000), s.accs, false, s.provlabsAddr) + s.Require().NoError(err, "CreateGlobalMarker external asset") - err = simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "acceptunder2vx", "acceptpay2vx", "acceptshare", selected, s.accs) + err = simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "acceptunder2vx", "acceptshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgAcceptAsset(*s.app.VaultKeeper) @@ -513,10 +513,10 @@ func (s *VaultSimTestSuite) TestSimulateMsgRejectAsset() { err := simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("rejectunder2vx", 100_000_000), s.accs, false, s.provlabsAddr) s.Require().NoError(err, "CreateGlobalMarker underlying") - err = simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("rejectpay2vx", 100_000_000), s.accs, false, s.provlabsAddr) - s.Require().NoError(err, "CreateGlobalMarker payment") + err = simulation.CreateGlobalMarker(s.ctx, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, sdk.NewInt64Coin("rejectexternal2vx", 100_000_000), s.accs, false, s.provlabsAddr) + s.Require().NoError(err, "CreateGlobalMarker external asset") - err = simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "rejectunder2vx", "rejectpay2vx", "rejectshare", selected, s.accs) + err = simulation.CreateVault(s.ctx, s.app.VaultKeeper, s.app.AccountKeeper, s.app.BankKeeper, s.app.MarkerKeeper, "rejectunder2vx", "rejectshare", selected, s.accs) s.Require().NoError(err, "CreateVault") op := simulation.SimulateMsgRejectAsset(*s.app.VaultKeeper) diff --git a/simulation/provenance.go b/simulation/provenance.go index c670b115..4a6d8173 100644 --- a/simulation/provenance.go +++ b/simulation/provenance.go @@ -110,28 +110,6 @@ func GrantAccess(ctx context.Context, keeper markerkeeper.Keeper, denom string, return nil } -// AddNav adds a net asset value to a marker. -func AddNav(ctx context.Context, keeper markerkeeper.Keeper, denom string, admin sdk.AccAddress, price sdk.Coin, volume uint64) error { - sdkCtx := sdk.UnwrapSDKContext(ctx) - nav := []markertypes.NetAssetValue{ - { - Price: price, - Volume: volume, - UpdatedBlockHeight: uint64(sdkCtx.BlockHeight()), - }, - } - - msg := &markertypes.MsgAddNetAssetValuesRequest{ - Denom: denom, - Administrator: admin.String(), - NetAssetValues: nav, - } - - markerMsgServer := markerkeeper.NewMsgServerImpl(keeper) - _, err := markerMsgServer.AddNetAssetValues(ctx, msg) - return err -} - // AddAttribute adds an attribute to an account using the provided owner to authorize the action. func AddAttribute(ctx context.Context, owner sdk.AccAddress, acc sdk.AccAddress, attrName string, _ types.NameKeeper, ak types.AttributeKeeper) error { attr := NewAttribute( diff --git a/simulation/rand.go b/simulation/rand.go index 03c74fd4..827f0ae2 100644 --- a/simulation/rand.go +++ b/simulation/rand.go @@ -87,32 +87,6 @@ func getRandomVault(r *rand.Rand, k keeper.Keeper, ctx sdk.Context) (*types.Vaul return vault, nil } -// getRandomVaultWithCondition gets a random vault that satisfies a given condition. -func getRandomVaultWithCondition(r *rand.Rand, k keeper.Keeper, ctx sdk.Context, condition func(vault types.VaultAccount) bool) (*types.VaultAccount, error) { - allVaultAddrs, err := k.GetVaults(ctx) - if err != nil { - return nil, err - } - - var matchingVaults []*types.VaultAccount - for _, vaultAddr := range allVaultAddrs { - vault, err := k.GetVault(ctx, vaultAddr) - if err != nil || vault == nil { - continue - } - - if condition(*vault) { - matchingVaults = append(matchingVaults, vault) - } - } - - if len(matchingVaults) == 0 { - return nil, fmt.Errorf("no vaults found matching condition") - } - - return matchingVaults[r.Intn(len(matchingVaults))], nil -} - // getRandomBridgedVault finds a random vault that has bridging enabled and the bridge address is a sim account. func getRandomBridgedVault(r *rand.Rand, k keeper.Keeper, ctx sdk.Context, accs []simtypes.Account, checkBalance bool) (types.VaultAccount, error) { addrs, err := k.GetVaults(sdk.UnwrapSDKContext(ctx)) @@ -335,15 +309,23 @@ func getRandomPendingSwapOut(r *rand.Rand, k keeper.Keeper, ctx sdk.Context, vau return randomID, nil } -// getRandomVaultAsset gets a random asset (either underlying or payment) accepted by a vault. -func getRandomVaultAsset(r *rand.Rand, vault *types.VaultAccount) string { - if vault.PaymentDenom == "" { - return vault.UnderlyingAsset - } - if r.Intn(2) == 0 { - return vault.UnderlyingAsset +// getRandomExternalAssetDenom finds a global sim marker denom, held by one of the +// given accounts, that differs from the vault's underlying asset. Settlement +// operations trade an external asset against the vault's underlying, so a +// distinct denom is required. +func getRandomExternalAssetDenom(r *rand.Rand, k keeper.Keeper, ctx sdk.Context, accs []simtypes.Account, underlying string) (string, error) { + shuffled := make([]simtypes.Account, len(accs)) + copy(shuffled, accs) + r.Shuffle(len(shuffled), func(i, j int) { shuffled[i], shuffled[j] = shuffled[j], shuffled[i] }) + + for _, acc := range shuffled { + for _, coin := range k.BankKeeper.GetAllBalances(ctx, acc.Address) { + if strings.HasSuffix(coin.Denom, VaultGlobalDenomSuffix) && coin.Denom != underlying { + return coin.Denom, nil + } + } } - return vault.PaymentDenom + return "", fmt.Errorf("no account holds a global marker denom distinct from underlying %q", underlying) } // getRandomMinSwapValue generates a random valid minimum swap value for a given vault. diff --git a/simulation/setup.go b/simulation/setup.go index da5e217d..26dd7abc 100644 --- a/simulation/setup.go +++ b/simulation/setup.go @@ -68,7 +68,7 @@ func Setup(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, ak types.AccountKeepe write() underlyingDenom := genRandomDenom(r, denomRegex, VaultGlobalDenomSuffix) - paymentDenom := genRandomDenom(r, denomRegex, VaultGlobalDenomSuffix) + externalAssetDenom := genRandomDenom(r, denomRegex, VaultGlobalDenomSuffix) markerKeeper, ok := mk.(markerkeeper.Keeper) if !ok { @@ -78,22 +78,14 @@ func Setup(ctx sdk.Context, r *rand.Rand, k keeper.Keeper, ak types.AccountKeepe if err := CreateGlobalMarker(ctx, ak, bk, markerKeeper, sdk.NewInt64Coin(underlyingDenom, 1_000_000_000), accs, false, feeCollectorAddr); err != nil { return fmt.Errorf("failed to create global marker for underlying %s: %w", underlyingDenom, err) } - if err := CreateGlobalMarker(ctx, ak, bk, markerKeeper, sdk.NewInt64Coin(paymentDenom, 1_000_000_000), accs, false, feeCollectorAddr); err != nil { - return fmt.Errorf("failed to create global marker for payment %s: %w", paymentDenom, err) - } - - volume := uint64(r.Intn(4) + 1) - if err := AddNav(ctx, markerKeeper, paymentDenom, ak.GetModuleAddress("mint"), sdk.NewInt64Coin(underlyingDenom, 1), volume); err != nil { - return fmt.Errorf("failed to add nav for payment %s: %w", paymentDenom, err) + // A second marker distinct from any underlying gives the settlement operations an + // external asset to trade against a vault's underlying via AcceptAsset. + if err := CreateGlobalMarker(ctx, ak, bk, markerKeeper, sdk.NewInt64Coin(externalAssetDenom, 1_000_000_000), accs, false, feeCollectorAddr); err != nil { + return fmt.Errorf("failed to create global marker for external asset %s: %w", externalAssetDenom, err) } admin, _ := simtypes.RandomAcc(r, accs) shareDenom := fmt.Sprintf("vaultshare%d", r.Intn(1_000)) - selectedPayment := "" - if r.Intn(2) == 0 { - selectedPayment = paymentDenom - } - - return CreateVault(ctx, &k, ak, bk, markerKeeper, underlyingDenom, selectedPayment, shareDenom, admin, accs) + return CreateVault(ctx, &k, ak, bk, markerKeeper, underlyingDenom, shareDenom, admin, accs) } diff --git a/simulation/vault.go b/simulation/vault.go index d3fa2380..05b9d468 100644 --- a/simulation/vault.go +++ b/simulation/vault.go @@ -7,8 +7,6 @@ import ( "github.com/provlabs/vault/keeper" "github.com/provlabs/vault/types" - sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -22,15 +20,12 @@ const ( ) // CreateVault creates a new vault with a marker and funds accounts. -func CreateVault(ctx sdk.Context, vk *keeper.Keeper, ak types.AccountKeeper, _ types.BankKeeper, mk markerkeeper.Keeper, underlying, paymentDenom, share string, admin simtypes.Account, _ []simtypes.Account) error { +func CreateVault(ctx sdk.Context, vk *keeper.Keeper, ak types.AccountKeeper, _ types.BankKeeper, mk markerkeeper.Keeper, underlying, share string, admin simtypes.Account, _ []simtypes.Account) error { if !MarkerExists(ctx, mk, underlying) { return fmt.Errorf("underlying marker %s does not exist", underlying) } - if paymentDenom != "" && !MarkerExists(ctx, mk, paymentDenom) { - return fmt.Errorf("payment denom marker %s does not exist", paymentDenom) - } - if err := PrepareVaultMarkers(ctx, ak, mk, underlying, paymentDenom, share); err != nil { + if err := PrepareVaultMarkers(ctx, ak, mk, underlying, share); err != nil { return err } @@ -39,43 +34,30 @@ func CreateVault(ctx sdk.Context, vk *keeper.Keeper, ak types.AccountKeeper, _ t Admin: admin.Address.String(), ShareDenom: share, UnderlyingAsset: underlying, - PaymentDenom: paymentDenom, WithdrawalDelaySeconds: interest.SecondsPerDay, } - if paymentDenom != "" && paymentDenom != underlying { - newVault.InitialPaymentNav = &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin(underlying, 1), - Volume: sdkmath.OneInt(), - Source: "simulation", - } - } msgServer := keeper.NewMsgServer(vk) _, err := msgServer.CreateVault(ctx, newVault) return err } // PrepareVaultMarkers grants the necessary permissions to the predicted vault address -// for its underlying and payment markers. This is required for the vault creation -// pre-flight check and for collecting AUM fees. -func PrepareVaultMarkers(ctx sdk.Context, ak types.AccountKeeper, mk markerkeeper.Keeper, underlying, paymentDenom, share string) error { +// for its underlying marker. This is required for the vault creation pre-flight check +// and for collecting AUM fees. +func PrepareVaultMarkers(ctx sdk.Context, ak types.AccountKeeper, mk markerkeeper.Keeper, underlying, share string) error { vaultAddr := types.GetVaultAddress(share) mintAddr := ak.GetModuleAddress("mint") - for _, denom := range []string{underlying, paymentDenom} { - if denom == "" { - continue - } - m, err := mk.GetMarker(ctx, markertypes.MustGetMarkerAddress(denom)) - if err != nil { - return fmt.Errorf("failed to get marker for %s: %w", denom, err) + m, err := mk.GetMarker(ctx, markertypes.MustGetMarkerAddress(underlying)) + if err != nil { + return fmt.Errorf("failed to get marker for %s: %w", underlying, err) + } + if m.GetMarkerType() == markertypes.MarkerType_RestrictedCoin { + if err := GrantTransferPermission(ctx, mk, underlying, vaultAddr, mintAddr); err != nil { + return fmt.Errorf("failed to grant transfer permission for %s: %w", underlying, err) } - if m.GetMarkerType() == markertypes.MarkerType_RestrictedCoin { - if err := GrantTransferPermission(ctx, mk, denom, vaultAddr, mintAddr); err != nil { - return fmt.Errorf("failed to grant transfer permission for %s: %w", denom, err) - } - } else { - if err := GrantWithdrawPermission(ctx, mk, denom, vaultAddr, mintAddr); err != nil { - return fmt.Errorf("failed to grant withdraw permission for %s: %w", denom, err) - } + } else { + if err := GrantWithdrawPermission(ctx, mk, underlying, vaultAddr, mintAddr); err != nil { + return fmt.Errorf("failed to grant withdraw permission for %s: %w", underlying, err) } } return nil @@ -95,13 +77,12 @@ func SwapIn(ctx sdk.Context, vk *keeper.Keeper, user simtypes.Account, shareDeno } // SwapOut performs a swap out for a user. -func SwapOut(ctx sdk.Context, vk *keeper.Keeper, user simtypes.Account, shares sdk.Coin, redeemDenom string) error { +func SwapOut(ctx sdk.Context, vk *keeper.Keeper, user simtypes.Account, shares sdk.Coin) error { vaultAddress := types.GetVaultAddress(shares.Denom) swapOut := &types.MsgSwapOutRequest{ Owner: user.Address.String(), VaultAddress: vaultAddress.String(), Assets: shares, - RedeemDenom: redeemDenom, } msgServer := keeper.NewMsgServer(vk) _, err := msgServer.SwapOut(ctx, swapOut) diff --git a/spec/01_concepts.md b/spec/01_concepts.md index 444d14fd..3947cb37 100644 --- a/spec/01_concepts.md +++ b/spec/01_concepts.md @@ -2,16 +2,25 @@ The `x/vault` module provides a system for tokenized vaults built on Provenance’s marker and account model. Vaults allow users to deposit underlying assets in exchange for vault shares, redeem those shares later, and participate in configurable interest accrual. -Each vault is configured with both an **underlying asset denom** (the backing collateral) and an optional **payment denom**. -The payment denom provides a secondary unit for payouts and redemptions: users can request to redeem shares into either the underlying asset or the configured payment denom (if supported), with conversions handled via on-chain NAV pricing. -The module manages vault lifecycle, share issuance, redemptions, dual-asset accounting, interest accrual, AUM fee collection, and time-based job queues for automated processing. +Each vault is strictly **single-denom**: it is configured with one **underlying asset denom** (the backing collateral), which is the only accepted denom for deposits, redemptions, interest, and AUM fees. +The module manages vault lifecycle, share issuance, redemptions, interest accrual, AUM fee collection, and time-based job queues for automated processing. Total share supply is tracked on the vault as **total_shares**, the authoritative supply-of-record across chains; local marker supply must never exceed this amount. +> **Deprecation notice:** The mixed-denom vault functionality has been removed. Vaults are strictly +> **single underlying denom**: the `payment_denom` configuration (including receipt tokens as +> payment denoms), the `redeem_denom` payout selection on swap-out, and the `uylds.fcc` NAV-check +> exemption no longer exist. The never-released request fields — `payment_denom` and +> `initial_payment_nav` on `MsgCreateVaultRequest`, and `redeem_denom` on `MsgSwapOutRequest` and +> `QueryEstimateSwapOutRequest` — have been removed outright and their field numbers reserved. The +> **state** fields `VaultAccount.payment_denom` (always equal to `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. Do not build new integrations against this surface. + --- - [Key Definitions](#key-definitions) - [Marker Authority Rules](#marker-authority-rules) - - [Special Case: YLDS Peg Mode](#special-case-ylds-peg-mode) - [Keeper Responsibilities](#keeper-responsibilities) - [Vault Lifecycle](#vault-lifecycle) - [Swap Operations](#swap-operations) @@ -29,15 +38,14 @@ Total share supply is tracked on the vault as **total_shares**, the authoritativ ## Key Definitions -- **Underlying Asset**: the base denom that defines vault value and payouts. TVV is always expressed in this unit. -- **Payment Denom (Secondary)**: an optional denom configured on a vault. It may be a normal swappable token (e.g., `uusdc`) or a restricted **receipt token** used for accounting. Swapability is determined by marker configuration. -- **Receipt Token**: a restricted marker that may be set as the payment denom. The only account with transfer authority is the holder of the receipt itself, which represents deployed capital (e.g., receipts into a fund). User swap-out to a receipt token is not possible unless the marker explicitly grants transfer authority. -- **Principal**: the vault’s total assets held in the **share marker account**, including underlying balances and any payment denom balances (normal or receipt). +- **Underlying Asset**: the base denom that defines vault value and payouts. It is the sole accepted denom for all user I/O, interest, and fees. TVV is always expressed in this unit. +- **Payment Denom (Secondary)** *(removed)*: the former optional secondary denom configured on a vault (a normal swappable token or a restricted **receipt token**). The functionality has been removed; the `VaultAccount.payment_denom` state field remains on the wire for migration decoding and always equals `underlying_asset`. Field deletion is deferred to a future major release. +- **Principal**: the vault’s total assets held in the **share marker account**: the underlying asset balance plus any external assets acquired through P2P settlement. - **Reserves**: the vault account balance used to pay positive interest or receive refunds from negative interest. - **TVV (Total Vault Value)**: the value of all principal assets, computed and reported in the underlying unit. - **Gross TVV**: The literal sum of all assets sitting in the principal marker. Used for interest and fee accruals. - **Net TVV**: Gross TVV minus **Outstanding AUM Fees**. This is the authoritative value used for share pricing (NAV) and user-facing valuation. -- **AUM Technology Fee**: a 15 bps (0.15% annual) fee collected from the vault principal to support protocol maintenance. It is accrued continuously and collected in the vault's configured `payment_denom`. +- **AUM Technology Fee**: a 15 bps (0.15% annual) fee collected from the vault principal to support protocol maintenance. It is accrued continuously and collected in the vault's underlying asset. - **NAV**: conversion rate between denoms, used for valuation and conversions, subject to special-case rules. - **Internal NAV Table**: per-vault price entries (`price` for `volume` units of a denom) that are the **sole source of truth** for the valuation engine's conversions. The module never reads external oracles or marker NAVs at valuation time. - **NAV Authority**: an optional per-vault address authorized to maintain the internal NAV table via `UpdateVaultNAV`. The vault admin acts as NAV authority when unset; the admin rotates it via `UpdateNAVAuthority`. @@ -51,14 +59,8 @@ All user I/O must satisfy **both** layers: 1) **Vault-level gates** — the vault must be unpaused and the relevant toggle (`SwapIn`/`SwapOut`) must be enabled. 2) **Marker permissions** — the marker for the target denom (including the **underlying**) must allow the transfer (attributes, restrictions, transfer authority). -Examples: -- `uylds.fcc` is a restricted marker with required attributes; users must satisfy those attributes to deposit/withdraw even when vault toggles are enabled. -- Receipt tokens typically deny public transfers; therefore user swap-out to a receipt token is not possible regardless of vault toggles. - -### Special Case: YLDS Peg Mode - -If a vault’s underlying is set to `uylds.fcc`, all conversions are treated as **1:1** with YLDS regardless of NAV. -This means any configured payment denom (normal token or receipt token) is valued **1:1** with `uylds.fcc` for TVV and estimates. +Example: +- `uylds.fcc` is a restricted marker with required attributes; users must satisfy those attributes to deposit/withdraw even when vault toggles are enabled. --- @@ -99,7 +101,7 @@ The keeper ties together state management, account operations, marker integratio - **Payout Timeout Queue**: tracks when vaults must be revisited for automatic interest reconciliation. - **Fee Timeout Queue**: tracks when vaults must be revisited for automatic AUM fee collection. - **Payout Verification Set**: temporary holding set for vaults awaiting validation after rate changes or reconciliations. -- **Pending Swap-Out Queue**: time-ordered queue of withdrawal requests, processed in EndBlocker. Jobs include owner, vault, shares, redeem denom, and request ID. +- **Pending Swap-Out Queue**: time-ordered queue of withdrawal requests, processed in EndBlocker. Jobs include owner, vault, shares, and request ID; payouts are always made in the vault's underlying asset. ### Genesis - **InitGenesis**: loads vault accounts, queue entries, and validates stored state. @@ -127,26 +129,25 @@ Bridging lets vault shares move across chains. The on-chain accounting model and ## Internal NAV & Multi-Asset Settlement -Vaults can take in **external assets** beyond the underlying and payment denoms, settling them peer-to-peer against the vault's payment denom. Two pieces make this work: the **internal NAV table** (the module's own price book) and the **p2p settlement workflow** built on `x/exchange` payments. +Vaults can take in **external assets** beyond the underlying asset, settling them peer-to-peer against the vault's underlying asset. Two pieces make this work: the **internal NAV table** (the module's own price book) and the **p2p settlement workflow** built on `x/exchange` payments. ### Internal NAV Table -Each vault carries its own table of price entries, one per asset denom. An entry records `price` (a coin in one of the vault's accepted denoms) for `volume` units of the denom; the per-unit value is `price / volume`, kept as an exact fraction. The valuation engine converts denoms **exclusively** through this table — no oracle or marker-module reads happen at valuation time, so pricing is deterministic and admin-auditable. +Each vault carries its own table of price entries, one per asset denom. An entry records `price` (a coin in the vault's underlying asset) for `volume` units of the denom; the per-unit value is `price / volume`, kept as an exact fraction. The valuation engine converts denoms **exclusively** through this table — no oracle or marker-module reads happen at valuation time, so pricing is deterministic and admin-auditable. -Entries are written by four paths: +Entries are written by three paths: -1. **Creation seed** — an optional `InitialVaultNAV` bootstraps the payment denom's price when the vault is created. -2. **NAV authority updates** — the configured `nav_authority` (the admin when unset) maintains entries via `UpdateVaultNAV`. -3. **Settlements** — each `AcceptAsset` records the realized settlement price as the asset denom's entry (and removes the entry when an outbound settlement drains the denom from the principal). -4. **Migration seeding** — a one-time upgrade migration seeded entries from existing marker-module NAVs. +1. **NAV authority updates** — the configured `nav_authority` (the admin when unset) maintains entries via `UpdateVaultNAV`. +2. **Settlements** — each `AcceptAsset` records the realized settlement price as the asset denom's entry (and removes the entry when an outbound settlement drains the denom from the principal). +3. **Migration seeding** — a one-time upgrade migration seeded entries from existing marker-module NAVs. -NAV upserts from paths 2 and 3 are also **published one-way to the marker module**, attributed to the vault address, so downstream marker-NAV consumers can distinguish vault-originated prices. Removals are internal-only: when a settlement drains a denom and its entry is deleted, the marker NAV is left as-is — publishing simply stops. The vault never reads marker NAVs back — the internal table remains authoritative. +NAV upserts from paths 1 and 2 are also **published one-way to the marker module**, attributed to the vault address, so downstream marker-NAV consumers can distinguish vault-originated prices. Removals are internal-only: when a settlement drains a denom and its entry is deleted, the marker NAV is left as-is — publishing simply stops. The vault never reads marker NAVs back — the internal table remains authoritative. ### P2P Settlement Workflow External counterparties propose trades by creating `x/exchange` **payments** that target the vault, escrowing their side. The vault's **asset manager** then settles (`AcceptAsset`) or declines (`RejectAsset`) each pending payment; rejection refunds the counterparty's escrow. The admin cannot settle or reject — a vault without an asset manager has no settlement capability until one is assigned. -Exactly one payment leg must carry the vault's payment denom, which determines the **direction**: *inbound* (vault receives an external asset, pays payment denom) or *outbound* (vault pays out an asset, receives payment denom). Each leg must be a single coin, and the asset denom must be a registered marker. +Exactly one payment leg must carry the vault's underlying asset, which determines the **direction**: *inbound* (vault receives an external asset, pays underlying) or *outbound* (vault pays out an asset, receives underlying). Each leg must be a single coin, and the asset denom must be a registered marker. Settlement is atomic and layers several protections: @@ -156,7 +157,7 @@ Settlement is atomic and layers several protections: ### Valuation Scope -TVV sums every denom held at the principal marker that has a vault internal NAV, expressed in the underlying unit. The underlying and payment denoms are valued as before; any other held asset acquired through settlement (e.g. an `nft/scope…` coin) is valued at its internal NAV — chained through the payment denom to the underlying when the NAV is priced in the payment denom. A held denom with no internal NAV entry contributes nothing and is skipped (it does not fail valuation), while an accepted denom missing its NAV remains an error (a misconfiguration). Because TVV is the base for interest, the AUM fee, and NAV per share, a vault's value and that fee/interest/share-price base move when the NAV authority updates a held asset's NAV — a deliberate economic/trust surface. +TVV sums every denom held at the principal marker that has a vault internal NAV, expressed in the underlying unit. The underlying asset is counted at its identity price; any other held asset acquired through settlement (e.g. an `nft/scope…` coin) is valued at its internal NAV, which is priced directly in the underlying asset. A held denom with no internal NAV entry contributes nothing and is skipped (it does not fail valuation). Because TVV is the base for interest, the AUM fee, and NAV per share, a vault's value and that fee/interest/share-price base move when the NAV authority updates a held asset's NAV — a deliberate economic/trust surface. --- diff --git a/spec/02_state.md b/spec/02_state.md index 25ccc40c..08824f89 100644 --- a/spec/02_state.md +++ b/spec/02_state.md @@ -2,7 +2,12 @@ The Vault module persists **vault accounts**, **interest scheduling metadata**, and **swap-out jobs** using typed collections. Canonical vault accounts live in `x/auth` (as `VaultAccount`), while this module maintains compact lookups and queues for automated processing. -Vaults may be configured with an optional **payment denom** in addition to the **underlying asset**; accepted I/O denoms are always the underlying asset and, if set, the payment denom. :contentReference[oaicite:0]{index=0} +Vaults are strictly **single-denom**: the **underlying asset** is the only accepted I/O denom. Creation no longer takes a payment denom (the request field has been removed and reserved), and the module's v1→v2 state migration flattened any pre-existing mixed-denom vaults so `payment_denom` always equals `underlying_asset`. + +> **Deprecation notice:** The payment denom functionality has been removed. The +> `VaultAccount.payment_denom` state field remains on the wire so the migration can decode +> pre-flatten state and always equals `underlying_asset`; field deletion is deferred to a future +> major release (see `spec/01_concepts.md`). --- @@ -20,6 +25,7 @@ Vaults may be configured with an optional **payment denom** in addition to the * - [Internal NAV Table (prefix 11)](#internal-nav-table-prefix-11) - [Deterministic Vault Addressing](#deterministic-vault-addressing) - [Genesis Notes](#genesis-notes) + - [State Migration (v1 → v2)](#state-migration-v1--v2) --- @@ -27,17 +33,17 @@ Vaults may be configured with an optional **payment denom** in addition to the * Each vault is an `x/auth` account implementing `VaultAccountI`. The canonical record contains: -- Admin address, share denom, underlying asset, optional **payment denom** (must differ from underlying) +- Admin address, share denom, underlying asset, deprecated **payment denom** (inert; always equal to the underlying asset — enforced at creation, by validation, and by the v1→v2 migration for pre-existing vaults) - Interest configuration: `CurrentInterestRate`, `DesiredInterestRate`, optional `MinInterestRate`/`MaxInterestRate` bounds - Swap toggles, `WithdrawalDelaySeconds`, pause flags/reason and `PausedBalance` snapshot - **Swap Limits:** `min_swap_in_value`, `min_swap_out_value`, `max_swap_in_value`, and `max_swap_out_value` (measured in underlying asset) - **Total supply-of-record:** `total_shares` (authoritative across chains; includes locally and externally held shares) - **Bridging controls:** `bridge_address` (the sole authorized external address) and `bridge_enabled` (feature gate) - **Asset Management:** optional `asset_manager` address with delegated authority; it is also the sole authority for P2P settlement (`AcceptAsset`/`RejectAsset`). -- **AUM Fee State:** `fee_period_start`, `fee_period_timeout`, and `outstanding_aum_fee`. +- **AUM Fee State:** `fee_period_start`, `fee_period_timeout`, and `outstanding_aum_fee` (denominated in the underlying asset). - **NAV Authority:** optional `nav_authority` address authorized to mutate the vault's internal NAV table via `MsgUpdateVaultNAV`; the admin acts as NAV authority when unset. -`VaultAccount` enforces invariants (e.g., payment denom cannot equal underlying, rate bounds, etc.) and provides helpers like `AcceptedDenoms()` and `ValidateAcceptedDenom`. :contentReference[oaicite:1]{index=1} +`VaultAccount` enforces invariants (e.g., valid denoms, `payment_denom` empty or equal to the underlying asset, rate bounds, etc.) and provides helpers like `IsAcceptedDenom` and `ValidateAcceptedDenom`, which accept only the underlying asset. > Note: Because vaults are first-class accounts, the **authoritative storage** for the account itself is `x/auth`. The `x/vault` module adds lookups and queues to operate on those accounts efficiently. @@ -45,7 +51,7 @@ Each vault is an `x/auth` account implementing `VaultAccountI`. The canonical re ## Collections (x/vault) -The module uses typed collections with fixed **prefix IDs** for clarity and upgrade stability. Bridging introduces no new collections; capacity is computed at runtime from local marker/bank supply vs `total_shares`. :contentReference[oaicite:2]{index=2} +The module uses typed collections with fixed **prefix IDs** for clarity and upgrade stability. Bridging introduces no new collections; capacity is computed at runtime from local marker/bank supply vs `total_shares`. ### Vault Lookup (prefix 0) @@ -54,7 +60,7 @@ A compact lookup keyed by vault address. Used to enumerate vaults and cache seri - **Prefix:** `VaultsKeyPrefix` (0) - **Key:** `sdk.AccAddress` (vault address) - **Value:** `[]byte` (serialized `VaultAccount`, including `total_shares`, `bridge_address`, `bridge_enabled`) -:contentReference[oaicite:3]{index=3} + ### Payout Verification Set (prefix 1) @@ -63,7 +69,7 @@ A set of vaults queued for **payout verification** (e.g., after rate changes or - **Prefix:** `VaultPayoutVerificationSetPrefix` (1) - **Key:** `sdk.AccAddress` (vault address) - **Value:** none (keyset) -:contentReference[oaicite:4]{index=4} + ### Payout Timeout Queue (prefix 2) @@ -72,7 +78,7 @@ A time-ordered queue scheduling when a vault should be revisited for **automatic - **Prefix:** `VaultPayoutTimeoutQueuePrefix` (2) - **Key:** typically `(uint64 timeoutSeconds, sdk.AccAddress vault)` (implementation uses typed queue entries) - **Value:** none -:contentReference[oaicite:5]{index=5} + ### Vault Fee Timeout Queue (prefix 7) @@ -88,7 +94,7 @@ Holds **withdrawal jobs** created by `SwapOut`. Jobs are processed after the vau - **Prefix:** `VaultPendingSwapOutQueuePrefix` (3) - **Key:** typically `(int64 dueTime, uint64 id)` to maintain time ordering -- **Value:** `types.PayoutJob` (wraps the `PendingSwapOut` request and metadata) :contentReference[oaicite:6]{index=6} :contentReference[oaicite:7]{index=7} +- **Value:** `types.PayoutJob` (wraps the `PendingSwapOut` request and metadata) ### Pending Swap-Out Sequence (prefix 4) @@ -96,7 +102,7 @@ A monotonic sequence used to assign globally unique **request IDs** for pending - **Prefix:** `VaultPendingSwapOutQueueSeqPrefix` (4) - **Value:** last used `uint64` ID (typed by the sequence collection) -:contentReference[oaicite:8]{index=8} + ### Pending Swap-Out by Vault Index (prefix 5) @@ -105,7 +111,7 @@ Reverse index to list all pending requests for a given vault without scanning th - **Prefix:** `VaultPendingSwapOutByVaultIndexPrefix` (5) - **Key:** `(sdk.AccAddress vault, uint64 id)` - **Value:** none -:contentReference[oaicite:9]{index=9} + ### Pending Swap-Out by ID Index (prefix 6) @@ -114,7 +120,7 @@ Direct lookup by **request ID** (useful to expedite or cancel a single job). - **Prefix:** `VaultPendingSwapOutByIdIndexPrefix` (6) - **Key:** `uint64 id` - **Value:** lightweight pointer to the queued entry (implementation detail) -:contentReference[oaicite:10]{index=10} + ### AUM Fee Address (prefix 8) @@ -130,20 +136,25 @@ Per-vault price entries for asset denoms the vault holds or settles. The vault m - **Prefix:** `NAVsKeyPrefix` (11) - **Key:** `(sdk.AccAddress vault, string denom)` -- **Value:** `types.VaultNAV { denom, price, volume, source, updated_block_height, updated_time }` — `price` is the total value of `volume` units of `denom`; per-unit value is `price / volume` +- **Value:** `types.VaultNAV { denom, price, volume, source, updated_block_height, updated_time }` — `price` is the total value of `volume` units of `denom`; per-unit value is `price / volume`. The `price` denom must be the owning vault's underlying asset. --- ## Deterministic Vault Addressing Given a **share denom**, the corresponding vault account address is derived deterministically: -`addr = AddressHash("vault/")`. This enables “find the vault by share denom” without maintaining a separate index. :contentReference[oaicite:11]{index=11} +`addr = AddressHash("vault/")`. This enables “find the vault by share denom” without maintaining a separate index. --- ## Genesis Notes The module defines a minimal `GenesisState` with validation and relies on import/export logic to include **vault accounts** (from `x/auth`) and active **queue entries** (timeouts and pending swap-outs). There are **no module Params** in the vault genesis. -Genesis must preserve `total_shares`, `bridge_address`, and `bridge_enabled`, and validate that local marker supply does not exceed `total_shares`. :contentReference[oaicite:12]{index=12} :contentReference[oaicite:13]{index=13} +Genesis must preserve `total_shares`, `bridge_address`, and `bridge_enabled`, and validate that local marker supply does not exceed `total_shares`. +Genesis validation also enforces the single-denom model: every NAV entry's `price` denom must equal the owning vault's underlying asset, and `VaultAccount` validation requires `payment_denom` to be empty or equal to the underlying asset. + +### State Migration (v1 → v2) + +The module's consensus version 1→2 migration flattens any pre-existing mixed-denom vaults into the single-denom model. For each vault it sets `payment_denom = underlying_asset`, re-denominates `outstanding_aum_fee` into the underlying asset, and defaults `nav_authority` to the admin when unset; it also rewrites any pending swap-out's redeem denom to the owning vault's underlying asset. No funds move and no accounts are deleted. --- \ No newline at end of file diff --git a/spec/03_messages.md b/spec/03_messages.md index ccdfe269..3dc0572e 100644 --- a/spec/03_messages.md +++ b/spec/03_messages.md @@ -85,18 +85,23 @@ All messages are protobuf-defined (`vault.v1`) and handled by the module’s `Ms ## CreateVault -Creates a new vault account with a configured underlying asset, optional payment denom, withdrawal delay, and minimum/maximum swap values. +Creates a new vault account with a configured underlying asset, withdrawal delay, and minimum/maximum swap values. The creator is recorded as vault admin. +* **Single Denom:** Vaults are strictly single-denom on `underlying_asset`; it is the only denom for deposits, redemptions, interest, and fees. * **Units:** All swap limit values (`min_swap_in_value`, `min_swap_out_value`, `max_swap_in_value`, `max_swap_out_value`) are denominated in the vault's **underlying_asset**. * **Clearing Limits:** * Minimums: An empty string "" or the string "0" clears/disables the minimum limit. * Maximums: An empty string "" clears/disables the maximum limit. * **Constraints:** Any provided maximum swap value must be **positive (> 0)**. A value of "0" is invalid and will be rejected. -* **Request:** `MsgCreateVaultRequest { admin, share_denom, underlying_asset, payment_denom?, withdrawal_delay_seconds, min_swap_in_value?, min_swap_out_value?, max_swap_in_value?, max_swap_out_value? }` +* **Request:** `MsgCreateVaultRequest { admin, share_denom, underlying_asset, withdrawal_delay_seconds, min_swap_in_value?, min_swap_out_value?, max_swap_in_value?, max_swap_out_value? }` * **Response:** `MsgCreateVaultResponse {}` +> **Removed:** the never-released mixed-denom creation inputs `payment_denom` and +> `initial_payment_nav` (`InitialVaultNAV`) have been removed from the request and their field +> numbers reserved. + --- ## SetShareDenomMetadata @@ -110,7 +115,7 @@ Admin-only. Sets Bank module metadata for a vault’s share denom, defining how ## SwapIn -Deposits accepted assets (underlying or payment denom) into a vault in exchange for newly minted shares. +Deposits the vault's underlying asset into a vault in exchange for newly minted shares. The underlying asset is the only accepted deposit denom. * **Request:** `MsgSwapInRequest { owner, vault_address, assets }` * **Response:** `MsgSwapInResponse {}` @@ -119,13 +124,16 @@ Deposits accepted assets (underlying or payment denom) into a vault in exchange ## SwapOut -Redeems shares from a vault in exchange for assets. -The `redeem_denom` field selects whether the user wants underlying or the vault’s optional payment denom. +Redeems shares from a vault in exchange for the vault's underlying asset. +Payouts are always made in the underlying asset. Swap-outs are queued with respect to `withdrawal_delay_seconds`. -* **Request:** `MsgSwapOutRequest { owner, vault_address, assets (shares), redeem_denom }` +* **Request:** `MsgSwapOutRequest { owner, vault_address, assets (shares) }` * **Response:** `MsgSwapOutResponse { request_id }` +> **Removed:** the never-released `redeem_denom` payout choice has been removed from the request +> and its field number reserved; payouts are always the underlying asset. + --- ## UpdateMinInterestRate @@ -345,7 +353,7 @@ Passing an empty `asset_manager` clears the configured value. ## UpdateVaultNAV -NAV authority only (the vault admin when no `nav_authority` is configured). Creates or updates the vault's **internal NAV entry** for a denom: the price of `volume` units of `denom`, denominated in one of the vault's accepted denoms. +NAV authority only (the vault admin when no `nav_authority` is configured). Creates or updates the vault's **internal NAV entry** for a denom: the price of `volume` units of `denom`, denominated in the vault's underlying asset. The handler is **rejected while the vault is paused**: a paused vault freezes its value at `PausedBalance`, so a NAV update would assert a price that the vault deliberately ignores until unpause. When not paused, the handler reconciles the vault first, so accrued interest settles against the TVV that held before the price change. After the upsert, the NAV is published downstream to the **marker module**, attributed to the vault address. @@ -369,14 +377,14 @@ Admin-only. Rotates the address authorized to mutate the vault's internal NAV ta ## AcceptAsset -Asset Manager only — the admin cannot settle, and a vault without an asset manager cannot settle at all. Settles a pending `x/exchange` payment whose target is the vault, exchanging an external asset for the vault's payment denom. The payment is identified by its `source` account and `external_id`. +Asset Manager only — the admin cannot settle, and a vault without an asset manager cannot settle at all. Settles a pending `x/exchange` payment whose target is the vault, exchanging an external asset for the vault's underlying asset. The payment is identified by its `source` account and `external_id`. Settlement is **rejected while the vault is paused**: a paused vault freezes its value at `PausedBalance`, and settling would move principal funds and the vault's value. Reject the payment or unpause first. -Exactly one payment leg must carry the vault's `payment_denom`; the **settlement direction** is derived from which leg that is: +Exactly one payment leg must carry the vault's underlying asset; the **settlement direction** is derived from which leg that is: -* **Inbound** — payment denom on the target leg: the vault receives the asset (`source_amount`) and pays the payment denom (`target_amount`). -* **Outbound** — payment denom on the source leg: the vault pays the asset (`target_amount`) and receives the payment denom (`source_amount`). +* **Inbound** — underlying asset on the target leg: the vault receives the asset (`source_amount`) and pays the underlying asset (`target_amount`). +* **Outbound** — underlying asset on the source leg: the vault pays the asset (`target_amount`) and receives the underlying asset (`source_amount`). Each leg must carry exactly one coin, and the asset denom must be a registered marker. diff --git a/spec/04_events.md b/spec/04_events.md index 9cfaf155..df809985 100644 --- a/spec/04_events.md +++ b/spec/04_events.md @@ -112,7 +112,7 @@ Emitted when assets are swapped into shares. **Fields** * `owner` — depositor -* `amount_in` — assets deposited (underlying denom or payment denom if supported for in-flow) +* `amount_in` — assets deposited (always the vault's underlying asset) * `shares_received` — minted shares * `vault_address` — vault @@ -126,7 +126,7 @@ Emitted when a **SwapOut** request is accepted into the **pending** queue. This * `vault_address` — vault * `owner` — requester (recipient will be the same owner) -* `redeem_denom` — chosen payout denom (`underlying_asset` or optional `payment_denom`) +* `redeem_denom` — payout denom; always the vault's `underlying_asset` * `shares` — escrowed shares amount * `request_id` — **stable handle** for this request @@ -156,7 +156,7 @@ Emitted when a pending swap-out is **successfully paid** in `EndBlocker`. * `vault_address` — vault * `owner` — recipient of funds -* `assets` — payout amount (in `redeem_denom` that was requested) +* `assets` — payout amount (in the vault's underlying asset) * `request_id` — the completed request --- @@ -219,10 +219,10 @@ Emitted when the 15 bps AUM technology fee is collected. **Fields** * `vault_address` — vault -* `collected_amount` — amount actually transferred to ProvLabs (payment denom) -* `requested_amount` — total accrued fee for this period + any previous unpaid amount (payment denom) +* `collected_amount` — amount actually transferred to ProvLabs (underlying denom) +* `requested_amount` — total accrued fee for this period + any previous unpaid amount (underlying denom) * `aum_snapshot` — TVV snapshot used for calculation (underlying denom) -* `outstanding_amount` — remaining unpaid fee after this collection (payment denom) +* `outstanding_amount` — remaining unpaid fee after this collection (underlying denom) * `duration_seconds` — time period covered by this collection --- @@ -418,7 +418,7 @@ Emitted when the vault's asset manager settles a pending `x/exchange` payment ta * `external_id` — payment identifier (unique per source) * `source_amount` — funds the source paid the vault (coins string) * `target_amount` — funds the vault paid the source (coins string) -* `direction` — `"inbound"` (asset moved into the vault) or `"outbound"` (asset moved out), relative to the vault's payment denom +* `direction` — `"inbound"` (asset moved into the vault) or `"outbound"` (asset moved out), relative to the vault's underlying asset **Notes** diff --git a/spec/05_queries.md b/spec/05_queries.md index 78143d41..b87d6b20 100644 --- a/spec/05_queries.md +++ b/spec/05_queries.md @@ -59,7 +59,7 @@ Returns configuration **and live balances** for a specific vault. ## EstimateSwapIn -Estimates how many **shares** would be minted for a given deposit of assets (underlying or the optional payment denom). +Estimates how many **shares** would be minted for a given deposit of the vault's underlying asset. - **gRPC:** `Query/EstimateSwapIn` - **REST:** `GET /vault/v1/vaults/{vault_address}/estimate_swap_in` @@ -67,7 +67,7 @@ Estimates how many **shares** would be minted for a given deposit of assets (und ### Request — `QueryEstimateSwapInRequest` - `vault_address`: bech32 vault address. - `assets`: `Coin` you plan to deposit. - - `denom` must be accepted by the vault: `underlying_asset` or the configured `payment_denom` (if set). + - `denom` must be the vault's `underlying_asset` (the only accepted deposit denom). ### Response — `QueryEstimateSwapInResponse` - `assets`: `Coin` representing the **estimated shares** to be received (denom = vault’s `share_denom`). @@ -75,8 +75,7 @@ Estimates how many **shares** would be minted for a given deposit of assets (und - `time`: UTC block time used for the estimate. **How it works (high level)** -- Validates the deposit denom is accepted. -- Converts deposit → underlying using current NAV (unit price of deposit denom versus underlying). +- Validates the deposit denom is the vault's underlying asset. - Computes a **pro-rata** share amount based on: - total shares outstanding, - total principal in the marker, @@ -84,15 +83,14 @@ Estimates how many **shares** would be minted for a given deposit of assets (und - Floors where necessary to prevent over-mint. **Common errors** -- Unsupported deposit denom. -- NAV unavailable for the provided pair. +- Unsupported deposit denom (not the underlying asset). - Invalid vault address. --- ## EstimateSwapOut -Estimates how many **payout assets** (underlying or payment denom) you would receive for a given amount of **shares**. +Estimates how many **payout assets** (in the vault's underlying asset) you would receive for a given amount of **shares**. - **gRPC:** `Query/EstimateSwapOut` - **REST:** `GET /vault/v1/vaults/{vault_address}/estimate_swap_out` @@ -100,22 +98,21 @@ Estimates how many **payout assets** (underlying or payment denom) you would rec ### Request — `QueryEstimateSwapOutRequest` - `vault_address`: bech32 vault address. - `shares`: amount of shares to redeem (as a string-encoded `Int`). -- `redeem_denom` *(optional)*: payout denom to estimate; if empty, defaults to the vault’s `underlying_asset`. - Must be either `underlying_asset` or the configured `payment_denom` (if set). + +> **Removed:** the never-released `redeem_denom` payout choice has been removed from the request +> and its field number reserved; the estimated payout is always the underlying asset. ### Response — `QueryEstimateSwapOutResponse` -- `assets`: `Coin` in the **redeem denom**, representing the estimated payout. +- `assets`: `Coin` in the vault's **underlying asset**, representing the estimated payout. - `height`: block height used. - `time`: UTC block time used. **How it works (high level)** -- Validates the requested payout denom is accepted (underlying or payment denom). -- Computes a **pro-rata** redemption of the vault’s estimated total assets (principal + accrued interest), then converts underlying → payout denom using current NAV. +- Computes a **pro-rata** redemption of the vault’s estimated total assets (principal + accrued interest), expressed in the underlying asset. - Floors where necessary for safety. **Common errors** -- Unsupported payout denom. -- NAV unavailable for the payout pair. +- Unsupported payout denom (not the underlying asset). - Invalid vault address. **Reminder** @@ -136,7 +133,7 @@ Returns a paginated list of all **queued** swap-out requests, with their `reques ### Response — `QueryPendingSwapOutsResponse` - `pending_swap_outs`: array of `PendingSwapOutWithTimeout`: - `request_id`: unique ID assigned at `MsgSwapOut`. - - `pending_swap_out`: the queued request (includes `vault_address`, `owner`, `shares`, `redeem_denom`, etc.). + - `pending_swap_out`: the queued request (includes `vault_address`, `owner`, `shares`, and the deprecated `redeem_denom`, which is always the vault's underlying asset). - `timeout`: the scheduled block time at/after which the job is eligible for processing. - `pagination`: `PageResponse`. @@ -164,7 +161,7 @@ Returns a paginated list of all **queued** swap-out requests for a **specific va ### Response — `QueryVaultPendingSwapOutsResponse` - `pending_swap_outs`: array of `PendingSwapOutWithTimeout`: - `request_id`: unique ID assigned at `MsgSwapOut`. - - `pending_swap_out`: the queued request (includes `vault_address`, `owner`, `shares`, `redeem_denom`, etc.). + - `pending_swap_out`: the queued request (includes `vault_address`, `owner`, `shares`, and the deprecated `redeem_denom`, which is always the vault's underlying asset). - `timeout`: the scheduled block time at/after which the job is eligible for processing. - `pagination`: `PageResponse`. diff --git a/spec/06_blocker.md b/spec/06_blocker.md index 840cc356..fa7565de 100644 --- a/spec/06_blocker.md +++ b/spec/06_blocker.md @@ -149,9 +149,9 @@ This advances vaults from the **verification set**: * **PerformVaultFeeTransfer** Computes the 15 bps (0.15% annual) technology fee based on **Gross TVV**. - - Collects fee in the configured `payment_denom`. + - Collects fee in the vault's `underlying_asset`. - Transfers from **principal (marker account)** → ProvLabs collection address. - - Caps collection at available `payment_denom` balance. + - Caps collection at available `underlying_asset` balance. - Emits `EventVaultFeeCollected`. * **UpdateInterestRates** @@ -164,7 +164,7 @@ This advances vaults from the **verification set**: * **processSingleWithdrawal** (called from `processPendingSwapOuts`) 1. **ReconcileVault** (reconcile both interest and AUM fees using a single `CacheContext`/atomic transfer). - 2. Convert **shares → payout coin** (`underlying_asset` or optional **payment denom**), using current NAV and pro-rata TVV. + 2. Convert **shares → payout coin** (always the `underlying_asset`), using current NAV and pro-rata TVV. 3. **Payout assets** from **principal (marker)** → **owner** with transfer-agent context. 4. **Burn shares**: move escrowed shares **vault → principal**, then `BurnCoin`. 5. Emit `EventSwapOutCompleted`. @@ -232,7 +232,3 @@ Submit `MsgSwapOut` → capture `request_id` → watch for `Completed` or `Refun * **Auto-pause on critical errors** creates a safe dead-stop until an admin resolves the issue. --- - -``` -::contentReference[oaicite:0]{index=0} -``` diff --git a/types/events.go b/types/events.go index b05a5ca9..ea9d4d5a 100644 --- a/types/events.go +++ b/types/events.go @@ -22,10 +22,10 @@ const ( const ( // AssetDirectionInbound indicates an external asset moved into the vault in - // exchange for the vault's payment denom (payment_denom is the target leg). + // exchange for the vault's underlying asset (the underlying is the target leg). AssetDirectionInbound = "inbound" // AssetDirectionOutbound indicates an asset moved out of the vault in - // exchange for the vault's payment denom (payment_denom is the source leg). + // exchange for the vault's underlying asset (the underlying is the source leg). AssetDirectionOutbound = "outbound" ) diff --git a/types/events.pb.go b/types/events.pb.go index 5b3e1088..e2c525a2 100644 --- a/types/events.pb.go +++ b/types/events.pb.go @@ -1266,7 +1266,8 @@ type EventSwapOutRequested struct { VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // owner is the bech32 address of the user who initiated the swap out. Owner string `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"` - // redeem_denom is the denomination of the asset to be redeemed. + // redeem_denom is the denomination of the asset to be redeemed. Always the + // vault's underlying_asset; retained for event-schema compatibility. RedeemDenom string `protobuf:"bytes,3,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` // shares is the amount of vault shares the user escrowed for this request. Shares string `protobuf:"bytes,4,opt,name=shares,proto3" json:"shares,omitempty"` @@ -1568,7 +1569,10 @@ type EventVaultPaused struct { VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // authority is the address (admin or asset manager) that paused the vault. Authority string `protobuf:"bytes,2,opt,name=authority,proto3" json:"authority,omitempty"` - // reason is the reason for pausing the vault. + // reason is the reason for pausing the vault. For a manual pause (PauseVault + // tx) this is the user-supplied reason. For an automated auto-pause triggered + // in the begin/end blocker, this carries the hard-coded reason describing the + // critical error that forced the pause. Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` // total_vault_value is the total value of the vault's assets at the time of pausing. TotalVaultValue string `protobuf:"bytes,4,opt,name=total_vault_value,json=totalVaultValue,proto3" json:"total_vault_value,omitempty"` @@ -1576,9 +1580,11 @@ type EventVaultPaused struct { // reconcile/valuation gate. False for a normal strict pause; true for a // forced manual pause and for automated auto-pauses. Forced bool `protobuf:"varint,5,opt,name=forced,proto3" json:"forced,omitempty"` - // forced_error records the reconcile and/or valuation error that was - // tolerated when forced is true. Empty when nothing failed. When non-empty, - // total_vault_value may be stale or zero. + // forced_error records the reconcile and/or valuation error tolerated by a + // manual force pause (PauseVault tx). Empty when nothing failed. When + // non-empty, total_vault_value may be stale or zero. Only the tx path sets + // this; automated auto-pauses leave it empty and instead encode their error + // in reason. ForcedError string `protobuf:"bytes,6,opt,name=forced_error,json=forcedError,proto3" json:"forced_error,omitempty"` } @@ -2823,7 +2829,7 @@ type EventAssetAccepted struct { // target_amount is the funds the vault paid the source, rendered as a coins string. TargetAmount string `protobuf:"bytes,5,opt,name=target_amount,json=targetAmount,proto3" json:"target_amount,omitempty"` // direction indicates whether the asset moved into the vault ("inbound") or - // out of the vault ("outbound") relative to the vault's payment denom. + // out of the vault ("outbound") relative to the vault's underlying asset. Direction string `protobuf:"bytes,6,opt,name=direction,proto3" json:"direction,omitempty"` } diff --git a/types/genesis.go b/types/genesis.go index 722e41c5..c450f6db 100644 --- a/types/genesis.go +++ b/types/genesis.go @@ -115,11 +115,8 @@ func (gs GenesisState) Validate() error { if err := entry.Nav.Price.Validate(); err != nil { return fmt.Errorf("invalid nav price at index %d: %w", i, err) } - if v.IsAcceptedDenom(entry.Nav.Denom) && !entry.Nav.Price.Amount.IsPositive() { - return fmt.Errorf("nav price at index %d for accepted denom %q must be positive", i, entry.Nav.Denom) - } - if !v.IsAcceptedDenom(entry.Nav.Price.Denom) { - return fmt.Errorf("nav price denom at index %d %q is not an accepted denom for vault %s", i, entry.Nav.Price.Denom, entry.VaultAddress) + if entry.Nav.Price.Denom != v.UnderlyingAsset { + return fmt.Errorf("nav price denom at index %d %q is not the underlying asset for vault %s", i, entry.Nav.Price.Denom, entry.VaultAddress) } if entry.Nav.Volume.IsNil() || !entry.Nav.Volume.IsPositive() { return fmt.Errorf("nav volume at index %d must be positive", i) diff --git a/types/genesis_test.go b/types/genesis_test.go index 3acc9024..9c275d69 100644 --- a/types/genesis_test.go +++ b/types/genesis_test.go @@ -24,6 +24,7 @@ func TestGenesisState_Validate(t *testing.T) { TotalShares: sdk.NewInt64Coin("share", 0), CurrentInterestRate: types.ZeroInterestRate, DesiredInterestRate: types.ZeroInterestRate, + OutstandingAumFee: sdk.NewInt64Coin("under", 0), } tests := []struct { @@ -314,7 +315,7 @@ func TestGenesisState_Validate(t *testing.T) { }, }, { - name: "nav entry for an accepted denom has zero price amount", + name: "mixed-denom vault is rejected", genState: types.GenesisState{ Params: types.DefaultParams(), Vaults: []types.VaultAccount{func() types.VaultAccount { @@ -322,18 +323,8 @@ func TestGenesisState_Validate(t *testing.T) { v.PaymentDenom = "pay" return v }()}, - Navs: []types.VaultNAVEntry{ - { - VaultAddress: validAddr, - Nav: types.VaultNAV{ - Denom: "pay", - Price: sdk.NewInt64Coin("under", 0), - Volume: sdkmath.NewInt(1), - }, - }, - }, }, - expectedErr: `nav price at index 0 for accepted denom "pay" must be positive`, + expectedErr: `invalid vault at index 0: payment denom "pay" must be empty or equal underlying asset "under"; vaults are single-denom`, }, { name: "nav entry has zero volume", @@ -372,7 +363,7 @@ func TestGenesisState_Validate(t *testing.T) { expectedErr: "nav volume at index 0 must be positive", }, { - name: "nav price denom is not an accepted vault denom", + name: "nav price denom is not the underlying asset", genState: types.GenesisState{ Params: types.DefaultParams(), Vaults: []types.VaultAccount{validVault}, @@ -387,7 +378,7 @@ func TestGenesisState_Validate(t *testing.T) { }, }, }, - expectedErr: `nav price denom at index 0 "wrongdenom" is not an accepted denom`, + expectedErr: `nav price denom at index 0 "wrongdenom" is not the underlying asset for vault`, }, { name: "duplicate nav entry for the same vault and denom", diff --git a/types/msgs.go b/types/msgs.go index 40fc207d..48445b16 100644 --- a/types/msgs.go +++ b/types/msgs.go @@ -75,18 +75,9 @@ func (m MsgCreateVaultRequest) ValidateBasic() error { return fmt.Errorf("invalid underlying asset: %q: %w", m.UnderlyingAsset, err) } - if len(m.PaymentDenom) > 0 { - if err := sdk.ValidateDenom(m.PaymentDenom); err != nil { - return fmt.Errorf("invalid payment denom: %q: %w", m.PaymentDenom, err) - } - } - if m.ShareDenom == m.UnderlyingAsset { return fmt.Errorf("share denom (%q) cannot equal underlying asset denom (%q)", m.ShareDenom, m.UnderlyingAsset) } - if m.ShareDenom == m.PaymentDenom { - return fmt.Errorf("share denom (%q) cannot equal payment denom (%q)", m.ShareDenom, m.PaymentDenom) - } if m.WithdrawalDelaySeconds > MaxWithdrawalDelay { return fmt.Errorf("withdrawal delay cannot exceed %d seconds", MaxWithdrawalDelay) @@ -100,48 +91,6 @@ func (m MsgCreateVaultRequest) ValidateBasic() error { return fmt.Errorf("invalid swap-out limits: %w", err) } - if err := ValidateInitialPaymentNAV(m.PaymentDenom, m.UnderlyingAsset, m.InitialPaymentNav); err != nil { - return fmt.Errorf("invalid initial payment NAV: %w", err) - } - - return nil -} - -// ValidateInitialPaymentNAV performs stateless validation on an initial -// payment-denom NAV supplied at vault creation. The NAV must be present when -// paymentDenom is set and differs from underlyingAsset, and must be absent -// otherwise (the identity 1:1 price applies and storing a NAV for the -// underlying asset is rejected by the keeper anyway). -// -// When present, the NAV's price must be denominated in underlyingAsset with a -// positive amount, volume must be positive, and the source string must not -// exceed MaxNAVSourceLength. -func ValidateInitialPaymentNAV(paymentDenom, underlyingAsset string, nav *InitialVaultNAV) error { - requiresNAV := paymentDenom != "" && paymentDenom != underlyingAsset - if !requiresNAV { - if nav != nil { - return fmt.Errorf("initial_payment_nav must be omitted when payment_denom is empty or equals underlying_asset") - } - return nil - } - if nav == nil { - return fmt.Errorf("initial_payment_nav is required when payment_denom %q differs from underlying_asset %q", paymentDenom, underlyingAsset) - } - if err := nav.Price.Validate(); err != nil { - return fmt.Errorf("invalid price coin %v: %w", nav.Price, err) - } - if nav.Price.Denom != underlyingAsset { - return fmt.Errorf("price denom %q must equal underlying_asset %q", nav.Price.Denom, underlyingAsset) - } - if !nav.Price.Amount.IsPositive() { - return fmt.Errorf("price amount must be positive, got %s", nav.Price.Amount) - } - if nav.Volume.IsNil() || !nav.Volume.IsPositive() { - return fmt.Errorf("volume must be positive") - } - if len(nav.Source) > MaxNAVSourceLength { - return fmt.Errorf("source too long (expected <= %d, actual: %d)", MaxNAVSourceLength, len(nav.Source)) - } return nil } @@ -232,12 +181,6 @@ func (m MsgSwapOutRequest) ValidateBasic() error { return fmt.Errorf("invalid amount: assets %s must be greater than zero", m.Assets.Denom) } - if m.RedeemDenom != "" { - if err := sdk.ValidateDenom(m.RedeemDenom); err != nil { - return fmt.Errorf("invalid redeem_denom: %w", err) - } - } - return nil } diff --git a/types/msgs_test.go b/types/msgs_test.go index 2946dfbc..5e9b04da 100644 --- a/types/msgs_test.go +++ b/types/msgs_test.go @@ -23,7 +23,7 @@ func TestMsgCreateVaultRequest_ValidateBasic(t *testing.T) { expectedErr error }{ { - name: "success without payment denom", + name: "success", msg: types.MsgCreateVaultRequest{ Admin: admin, ShareDenom: "vaultshare", @@ -31,72 +31,6 @@ func TestMsgCreateVaultRequest_ValidateBasic(t *testing.T) { }, expectedErr: nil, }, - { - name: "success with distinct payment denom", - msg: types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: "vaultshare", - UnderlyingAsset: "uusd", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("uusd", 1), - Volume: sdkmath.OneInt(), - Source: "test", - }, - }, - expectedErr: nil, - }, - { - name: "missing initial NAV when payment denom differs", - msg: types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: "vaultshare", - UnderlyingAsset: "uusd", - PaymentDenom: "usdc", - }, - expectedErr: fmt.Errorf("invalid initial payment NAV: initial_payment_nav is required when payment_denom %q differs from underlying_asset %q", "usdc", "uusd"), - }, - { - name: "initial NAV supplied without payment denom", - msg: types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: "vaultshare", - UnderlyingAsset: "uusd", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("uusd", 1), - Volume: sdkmath.OneInt(), - }, - }, - expectedErr: fmt.Errorf("invalid initial payment NAV: initial_payment_nav must be omitted when payment_denom is empty or equals underlying_asset"), - }, - { - name: "initial NAV price denom mismatches underlying", - msg: types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: "vaultshare", - UnderlyingAsset: "uusd", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("other", 1), - Volume: sdkmath.OneInt(), - }, - }, - expectedErr: fmt.Errorf("invalid initial payment NAV: price denom %q must equal underlying_asset %q", "other", "uusd"), - }, - { - name: "initial NAV volume non-positive", - msg: types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: "vaultshare", - UnderlyingAsset: "uusd", - PaymentDenom: "usdc", - InitialPaymentNav: &types.InitialVaultNAV{ - Price: sdk.NewInt64Coin("uusd", 1), - Volume: sdkmath.ZeroInt(), - }, - }, - expectedErr: fmt.Errorf("invalid initial payment NAV: volume must be positive"), - }, { name: "admin empty", msg: types.MsgCreateVaultRequest{ @@ -151,36 +85,15 @@ func TestMsgCreateVaultRequest_ValidateBasic(t *testing.T) { }, expectedErr: fmt.Errorf("invalid underlying asset: %q: %w", "inv@lid$", fmt.Errorf("invalid denom: %s", "inv@lid$")), }, - { - name: "payment denom invalid", - msg: types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: "vaultshare", - UnderlyingAsset: "uusd", - PaymentDenom: "inv@lid$", - }, - expectedErr: fmt.Errorf("invalid payment denom: %q: %w", "inv@lid$", fmt.Errorf("invalid denom: %s", "inv@lid$")), - }, { name: "share denom equals underlying (not allowed)", msg: types.MsgCreateVaultRequest{ Admin: admin, ShareDenom: "uusd", UnderlyingAsset: "uusd", - PaymentDenom: "usdc", }, expectedErr: fmt.Errorf("share denom (%q) cannot equal underlying asset denom (%q)", "uusd", "uusd"), }, - { - name: "share denom equals payment denom (not allowed)", - msg: types.MsgCreateVaultRequest{ - Admin: admin, - ShareDenom: "usdc", - UnderlyingAsset: "uusd", - PaymentDenom: "usdc", - }, - expectedErr: fmt.Errorf("share denom (%q) cannot equal payment denom (%q)", "usdc", "usdc"), - }, { name: "swap out delay over two years (not allowed)", msg: types.MsgCreateVaultRequest{ @@ -487,16 +400,6 @@ func TestMsgSwapOutRequest_ValidateBasic(t *testing.T) { }, expectedErr: nil, }, - { - name: "valid with redeem denom", - msg: types.MsgSwapOutRequest{ - Owner: owner, - VaultAddress: vault, - Assets: sdk.NewInt64Coin("uusd", 100), - RedeemDenom: "usdc", - }, - expectedErr: nil, - }, { name: "invalid vault address", msg: types.MsgSwapOutRequest{ @@ -533,16 +436,6 @@ func TestMsgSwapOutRequest_ValidateBasic(t *testing.T) { }, expectedErr: fmt.Errorf("invalid amount: assets %s must be greater than zero", "uusd"), }, - { - name: "invalid redeem denom", - msg: types.MsgSwapOutRequest{ - Owner: owner, - VaultAddress: vault, - Assets: sdk.NewInt64Coin("uusd", 100), - RedeemDenom: "inv@lid$", - }, - expectedErr: fmt.Errorf("invalid redeem_denom: %w", fmt.Errorf("invalid denom: %s", "inv@lid$")), - }, } for _, tc := range tests { diff --git a/types/query.pb.go b/types/query.pb.go index 837c9416..d6c12725 100644 --- a/types/query.pb.go +++ b/types/query.pb.go @@ -539,7 +539,7 @@ func (m *QueryVaultResponse) GetTotalVaultValue() types.Coin { type QueryEstimateSwapInRequest struct { // vault_address is the bech32 address of the vault to query. VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` - // assets is the amount of underlying or payment denom to swap in. + // assets is the amount of the underlying asset to swap in. Assets types.Coin `protobuf:"bytes,2,opt,name=assets,proto3" json:"assets"` } @@ -660,8 +660,6 @@ type QueryEstimateSwapOutRequest struct { VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // shares is the amount of shares to swap out. Shares string `protobuf:"bytes,2,opt,name=shares,proto3" json:"shares,omitempty"` - // redeem_denom is the payout denom to estimate; if empty, the underlying asset is used. - RedeemDenom string `protobuf:"bytes,3,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` } func (m *QueryEstimateSwapOutRequest) Reset() { *m = QueryEstimateSwapOutRequest{} } @@ -711,13 +709,6 @@ func (m *QueryEstimateSwapOutRequest) GetShares() string { return "" } -func (m *QueryEstimateSwapOutRequest) GetRedeemDenom() string { - if m != nil { - return m.RedeemDenom - } - return "" -} - // QueryEstimateSwapOutResponse is the response message for the Query/EstimateSwapOut endpoint. type QueryEstimateSwapOutResponse struct { // assets is the estimated amount of underlying assets that would be received. @@ -1411,97 +1402,97 @@ func init() { func init() { proto.RegisterFile("provlabs/vault/v1/query.proto", fileDescriptor_a1276ddd190bfbca) } var fileDescriptor_a1276ddd190bfbca = []byte{ - // 1438 bytes of a gzipped FileDescriptorProto + // 1434 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcf, 0x6f, 0x1b, 0xc5, - 0x17, 0xcf, 0x3a, 0x89, 0x9b, 0xbc, 0xa4, 0x3f, 0x32, 0xdf, 0xb4, 0x5f, 0xc7, 0x6d, 0xec, 0x74, - 0x4b, 0x9a, 0xb4, 0x34, 0xbb, 0x4d, 0x52, 0x04, 0x2d, 0x2d, 0x52, 0x52, 0x0a, 0xaa, 0x40, 0x69, + 0x17, 0xcf, 0x3a, 0x8e, 0x9b, 0xbc, 0xa6, 0x3f, 0x32, 0xdf, 0xb4, 0x5f, 0xc7, 0x6d, 0xec, 0x74, + 0x4b, 0x9a, 0xb4, 0x34, 0xbb, 0x4d, 0x52, 0x04, 0x2d, 0x2d, 0x52, 0x52, 0x15, 0x54, 0x40, 0x69, 0xea, 0x56, 0xad, 0x84, 0x10, 0xd6, 0xc4, 0x1e, 0x9c, 0x15, 0xf6, 0xee, 0x66, 0x67, 0xec, 0xd2, 0x56, 0xb9, 0x20, 0x8e, 0x1c, 0x2a, 0x81, 0x04, 0x17, 0x4e, 0x5c, 0xa0, 0x07, 0x0e, 0x88, 0xff, 0x81, 0x1e, 0x40, 0x54, 0x70, 0xe1, 0x44, 0x51, 0xcb, 0x5f, 0xc0, 0x5f, 0x80, 0x76, 0xe6, 0x4d, - 0xec, 0xb5, 0x77, 0x6d, 0x07, 0xa5, 0x12, 0x9c, 0xe2, 0x9d, 0x7d, 0xef, 0x7d, 0x3e, 0x9f, 0x37, - 0xef, 0xcd, 0xbe, 0x09, 0x4c, 0xfb, 0x81, 0xd7, 0xa8, 0xd2, 0x0d, 0x6e, 0x37, 0x68, 0xbd, 0x2a, - 0xec, 0xc6, 0xa2, 0xbd, 0x55, 0x67, 0xc1, 0x5d, 0xcb, 0x0f, 0x3c, 0xe1, 0x91, 0x09, 0xfd, 0xda, - 0x92, 0xaf, 0xad, 0xc6, 0x62, 0xf6, 0x74, 0xc9, 0xe3, 0x35, 0x8f, 0xdb, 0x1b, 0x94, 0x33, 0x65, - 0x6b, 0x37, 0x16, 0x37, 0x98, 0xa0, 0x8b, 0xb6, 0x4f, 0x2b, 0x8e, 0x4b, 0x85, 0xe3, 0xb9, 0xca, - 0x3d, 0x9b, 0x6b, 0xb5, 0xd5, 0x56, 0x25, 0xcf, 0xd1, 0xef, 0xa7, 0xd4, 0xfb, 0xa2, 0x7c, 0xb2, - 0xd5, 0x03, 0xbe, 0x9a, 0xac, 0x78, 0x15, 0x4f, 0xad, 0x87, 0xbf, 0x70, 0xf5, 0x58, 0xc5, 0xf3, - 0x2a, 0x55, 0x66, 0x53, 0xdf, 0xb1, 0xa9, 0xeb, 0x7a, 0x42, 0xa2, 0x69, 0x9f, 0x3c, 0xbe, 0x95, - 0x4f, 0x1b, 0xf5, 0xf7, 0x6d, 0xe1, 0xd4, 0x18, 0x17, 0xb4, 0xe6, 0x6b, 0x3e, 0x9d, 0x6a, 0x7d, - 0x1a, 0xd0, 0x9a, 0x0e, 0x10, 0x93, 0x0d, 0xa5, 0x5b, 0xbe, 0x36, 0xef, 0xc1, 0xcc, 0xf5, 0x50, - 0xf0, 0xad, 0x70, 0x6d, 0x9d, 0xb9, 0x65, 0xc7, 0xad, 0xdc, 0xb8, 0x43, 0xfd, 0x6b, 0x75, 0xc1, - 0x0b, 0x6c, 0xab, 0xce, 0xb8, 0x20, 0x07, 0x20, 0xe5, 0x94, 0x33, 0xc6, 0x8c, 0x31, 0x3f, 0x5a, - 0x48, 0x39, 0x65, 0xf2, 0x06, 0x40, 0x33, 0x2d, 0x99, 0xd4, 0x8c, 0x31, 0x3f, 0xb6, 0x74, 0xd2, - 0x42, 0xa9, 0x61, 0x5e, 0x2c, 0x95, 0x6f, 0xcc, 0x8e, 0xb5, 0x4e, 0x2b, 0x0c, 0x63, 0x15, 0x5a, - 0x3c, 0xcd, 0x1f, 0x0d, 0x38, 0xde, 0x05, 0x9c, 0xfb, 0x9e, 0xcb, 0x19, 0x79, 0x0f, 0x26, 0x7c, - 0xf5, 0xaa, 0xc8, 0xef, 0x50, 0xbf, 0xe8, 0xd5, 0x05, 0xcf, 0x18, 0x33, 0x83, 0xf3, 0x63, 0x4b, - 0x67, 0xac, 0x8e, 0xbd, 0xb4, 0xa2, 0x61, 0x6e, 0x3b, 0x62, 0xf3, 0xa6, 0x53, 0x63, 0x5e, 0x5d, - 0xac, 0x0e, 0x3d, 0xfa, 0x3d, 0x3f, 0x50, 0x38, 0xe8, 0x47, 0x71, 0xc8, 0x9b, 0x31, 0x6a, 0xe6, - 0x7a, 0xaa, 0x51, 0xe4, 0x22, 0x72, 0x18, 0x1c, 0x95, 0x6a, 0x12, 0xb2, 0x18, 0xcd, 0x9a, 0xf1, - 0x8f, 0xb3, 0xf6, 0x83, 0x01, 0xc7, 0xe2, 0x71, 0xfe, 0x6b, 0x09, 0xfb, 0xc9, 0x80, 0xa9, 0x44, - 0x74, 0x32, 0x0d, 0x10, 0x28, 0xf9, 0x45, 0xac, 0xbe, 0xa1, 0xc2, 0x28, 0xae, 0x5c, 0x2d, 0x93, - 0xeb, 0x70, 0xa8, 0x5d, 0x25, 0x72, 0x39, 0xde, 0x53, 0x24, 0x2a, 0x3b, 0x10, 0x55, 0x46, 0x5e, - 0x83, 0x7d, 0x42, 0x81, 0x67, 0x06, 0x65, 0xa4, 0xac, 0xa5, 0xba, 0xcf, 0xd2, 0xdd, 0x67, 0xdd, - 0xd4, 0xdd, 0xb7, 0x3a, 0x12, 0x86, 0x78, 0xf0, 0x24, 0x6f, 0x14, 0xb4, 0x93, 0xf9, 0x2e, 0x90, - 0x66, 0x39, 0xef, 0xf9, 0xbe, 0x7f, 0x69, 0xc0, 0xff, 0x22, 0xe1, 0x71, 0xbb, 0x2f, 0x41, 0x5a, - 0xca, 0xd4, 0x7b, 0x9c, 0x8f, 0x91, 0x2f, 0x5d, 0x56, 0x4a, 0x25, 0xaf, 0xee, 0x6a, 0xf1, 0xe8, - 0xb4, 0x77, 0xbb, 0x79, 0x02, 0x26, 0x9a, 0xf4, 0x12, 0x8e, 0x0e, 0xf3, 0x61, 0xaa, 0x35, 0x47, - 0x3b, 0x1a, 0x5e, 0x85, 0x61, 0x49, 0x07, 0xd3, 0xd3, 0xa7, 0x04, 0xe5, 0x43, 0xae, 0xc0, 0xa8, - 0x1f, 0x38, 0x6e, 0xc9, 0xf1, 0x69, 0xb5, 0x4b, 0x09, 0x68, 0x5f, 0x5a, 0xa5, 0x6e, 0x89, 0x61, - 0x88, 0xa6, 0x27, 0xb9, 0x0c, 0x23, 0x01, 0xe3, 0x2c, 0x68, 0x30, 0x8e, 0xdb, 0xdf, 0x77, 0x94, - 0x1d, 0x47, 0xf2, 0x16, 0x4c, 0x08, 0x4f, 0xd0, 0x6a, 0x51, 0x3a, 0x14, 0x1b, 0xb4, 0x5a, 0x67, - 0x99, 0x21, 0x19, 0x6d, 0x2a, 0x92, 0x54, 0x9d, 0xce, 0xcb, 0x9e, 0xe3, 0xea, 0x46, 0x93, 0x9e, - 0x52, 0xe7, 0xad, 0xd0, 0xcf, 0xbc, 0x07, 0x59, 0x99, 0xab, 0x2b, 0x5c, 0x38, 0x35, 0x2a, 0x58, - 0x58, 0xa7, 0x57, 0x5d, 0x9d, 0xda, 0x13, 0xb0, 0x5f, 0x81, 0xd0, 0x72, 0x39, 0x60, 0x9c, 0x63, - 0x96, 0xc7, 0xe5, 0xe2, 0x8a, 0x5a, 0x23, 0x2f, 0x43, 0x9a, 0x72, 0xce, 0x04, 0xc7, 0xc4, 0xf4, - 0x24, 0x81, 0xe6, 0xe6, 0xd7, 0x06, 0x9e, 0x66, 0xed, 0xe0, 0xb8, 0x63, 0xcd, 0xc0, 0xc6, 0xae, - 0x02, 0x93, 0x23, 0x90, 0xde, 0x64, 0x4e, 0x65, 0x53, 0x75, 0xeb, 0x60, 0x01, 0x9f, 0xc8, 0x2b, - 0x30, 0x14, 0xf6, 0xd1, 0xae, 0x3a, 0x4f, 0x7a, 0x98, 0xdb, 0x31, 0x4c, 0xaf, 0xd5, 0xc5, 0xae, - 0xf2, 0x74, 0x04, 0xd2, 0x7c, 0x93, 0x06, 0x4c, 0xe5, 0x69, 0xb4, 0x80, 0x4f, 0xe4, 0x38, 0x8c, - 0x07, 0xac, 0xcc, 0x58, 0xad, 0x58, 0x66, 0xae, 0x57, 0x93, 0xec, 0x46, 0x0b, 0x63, 0x6a, 0xed, - 0xf5, 0x70, 0xc9, 0xfc, 0x46, 0x9f, 0xc7, 0x1d, 0xf8, 0xff, 0xbe, 0x54, 0x4d, 0x62, 0xf7, 0xad, - 0xcb, 0x09, 0x01, 0x33, 0x64, 0xae, 0xe1, 0xc1, 0xa2, 0x57, 0x9b, 0xbc, 0xd5, 0x24, 0xb1, 0xc3, - 0x3b, 0xe6, 0x5c, 0x95, 0x06, 0x9a, 0xb7, 0x32, 0x37, 0x3d, 0x38, 0xdc, 0xec, 0xf1, 0x35, 0xda, - 0x78, 0xee, 0x83, 0xc4, 0x17, 0x06, 0x1c, 0x69, 0x47, 0x44, 0x11, 0x2f, 0xc1, 0x90, 0x4b, 0x1b, - 0xfa, 0x6c, 0x3c, 0x9a, 0x74, 0xb0, 0xac, 0xad, 0xdc, 0x42, 0x11, 0xd2, 0x7c, 0xef, 0x4e, 0xc5, - 0x8b, 0x30, 0x29, 0x99, 0xad, 0xd1, 0x86, 0x6c, 0xea, 0xa4, 0x54, 0x4c, 0xc2, 0xb0, 0xaa, 0x30, - 0x55, 0x7f, 0xea, 0xc1, 0x7c, 0x1b, 0x33, 0xd9, 0xf4, 0x46, 0x59, 0xcb, 0x30, 0xe8, 0xd2, 0x06, - 0x6e, 0x4c, 0x1f, 0xaa, 0x42, 0x6b, 0xf3, 0xaf, 0x14, 0xec, 0x5b, 0xa7, 0x77, 0x6b, 0xcc, 0x15, - 0xe4, 0x2c, 0xa4, 0xb9, 0x57, 0x0f, 0x4a, 0x4c, 0x71, 0x58, 0xcd, 0xfc, 0xf2, 0xfd, 0xc2, 0x24, - 0xea, 0xc3, 0xa6, 0xb8, 0x21, 0x02, 0xc7, 0xad, 0x14, 0xd0, 0x8e, 0xf8, 0xb0, 0x5f, 0xfd, 0x2a, - 0xd2, 0x5a, 0x78, 0x04, 0x66, 0x52, 0x32, 0xa5, 0x5d, 0xaa, 0xf9, 0x6c, 0x08, 0xfd, 0xf0, 0x49, - 0x7e, 0xbe, 0xe2, 0x88, 0xcd, 0xfa, 0x86, 0x55, 0xf2, 0x6a, 0x38, 0x10, 0xe3, 0x9f, 0x05, 0x5e, - 0xfe, 0xc0, 0x16, 0x77, 0x7d, 0xc6, 0xa5, 0x03, 0x2f, 0x8c, 0x2b, 0x84, 0x15, 0x09, 0x10, 0x72, - 0x14, 0x34, 0xa8, 0x30, 0xf5, 0x39, 0xee, 0xca, 0x51, 0xd9, 0x85, 0x1c, 0xd5, 0x2f, 0xcd, 0x71, - 0xe8, 0x39, 0x70, 0x54, 0x08, 0xc8, 0x31, 0x0f, 0x63, 0xec, 0x43, 0xc1, 0x02, 0x97, 0x56, 0xc3, - 0x31, 0x65, 0x58, 0xee, 0x1e, 0xe8, 0xa5, 0xab, 0x65, 0x73, 0x1b, 0x32, 0x2d, 0x33, 0xae, 0xca, - 0x7e, 0x52, 0x11, 0x34, 0x37, 0x25, 0xd5, 0xe7, 0xa6, 0xb4, 0xc1, 0x0f, 0x76, 0xc0, 0xdf, 0x86, - 0xa9, 0x18, 0x78, 0xac, 0xa2, 0x0b, 0xb0, 0xcf, 0x57, 0x4b, 0x58, 0x49, 0xd9, 0xd8, 0x16, 0x97, - 0x16, 0x58, 0x48, 0xda, 0xc1, 0xe4, 0x31, 0x81, 0x9f, 0x7b, 0xa3, 0x7f, 0x65, 0xe0, 0x27, 0xb1, - 0x0d, 0x15, 0xf5, 0x5c, 0x84, 0x11, 0xa4, 0xa7, 0x1b, 0xbe, 0xb7, 0xa0, 0x1d, 0x8f, 0x3d, 0xeb, - 0xf9, 0xa5, 0x9f, 0xc7, 0x61, 0x58, 0xb2, 0x24, 0x5b, 0x90, 0x56, 0xd3, 0x1a, 0x99, 0x8d, 0x21, - 0xd2, 0x39, 0x2c, 0x66, 0x4f, 0xf6, 0x32, 0x53, 0x70, 0x66, 0xe6, 0xa3, 0x5f, 0xff, 0xfc, 0x34, - 0x45, 0xc8, 0xa1, 0xb6, 0x5b, 0x1d, 0x27, 0x1c, 0x86, 0xa5, 0x2d, 0x79, 0xa1, 0x6b, 0x28, 0x0d, - 0x38, 0xdb, 0xc3, 0x0a, 0xf1, 0xa6, 0x25, 0xde, 0xff, 0xc9, 0xe1, 0x76, 0x3c, 0xfb, 0xbe, 0x53, - 0xde, 0x26, 0x0f, 0x0d, 0x38, 0x10, 0x1d, 0x14, 0xc8, 0x42, 0x52, 0xe0, 0xd8, 0x69, 0x26, 0x6b, - 0xf5, 0x6b, 0x8e, 0x84, 0xce, 0x4b, 0x42, 0xcb, 0x64, 0xb1, 0x93, 0x50, 0xe4, 0x6b, 0xbf, 0x6d, - 0x33, 0x0c, 0xa0, 0xae, 0x09, 0x8e, 0x4b, 0xbe, 0x35, 0xe0, 0x60, 0xdb, 0xb7, 0x9a, 0xf4, 0x05, - 0xdf, 0x1c, 0x2a, 0xb2, 0x76, 0xdf, 0xf6, 0xc8, 0xf7, 0x82, 0xe4, 0x7b, 0x8e, 0x2c, 0xed, 0x92, - 0x6f, 0x78, 0x13, 0xfa, 0xdc, 0x80, 0x83, 0x6d, 0x97, 0xbd, 0x64, 0xc2, 0xf1, 0xb7, 0xcf, 0x64, - 0xc2, 0x09, 0xb7, 0x48, 0xf3, 0x84, 0x24, 0x3c, 0x4d, 0x8e, 0xb6, 0xfc, 0x5f, 0xa1, 0xfd, 0x56, - 0x49, 0xbe, 0x33, 0x60, 0x32, 0xee, 0xf2, 0x4e, 0x96, 0xbb, 0x96, 0x55, 0x02, 0xc7, 0x73, 0xbb, - 0x73, 0x42, 0xa2, 0xb6, 0x24, 0x7a, 0x8a, 0xcc, 0xc5, 0x96, 0x66, 0x0c, 0xe9, 0x2d, 0x48, 0xab, - 0xb1, 0x25, 0xb9, 0x29, 0x23, 0xf3, 0x51, 0x72, 0x53, 0x46, 0x07, 0xa6, 0xb8, 0xa6, 0x54, 0x13, - 0x11, 0xf9, 0xd8, 0x80, 0xd1, 0x9d, 0xd9, 0x84, 0xcc, 0x77, 0xd5, 0xd9, 0x32, 0x30, 0x65, 0x4f, - 0xf5, 0x61, 0x89, 0xe0, 0xa6, 0x04, 0x3f, 0x46, 0xb2, 0xf1, 0x69, 0x90, 0x53, 0xcd, 0x27, 0x06, - 0x8c, 0xe8, 0x51, 0x82, 0xcc, 0x25, 0xc5, 0x6e, 0x1b, 0x55, 0xb2, 0xf3, 0xbd, 0x0d, 0x91, 0xc3, - 0x82, 0xe4, 0x30, 0x47, 0x66, 0x93, 0x39, 0xd8, 0xf7, 0xe5, 0x64, 0x73, 0xe9, 0xf4, 0xe9, 0x6d, - 0xf2, 0xc0, 0x80, 0xf1, 0xd6, 0x83, 0x9c, 0xbc, 0xd8, 0xbd, 0x00, 0x22, 0x1f, 0xcf, 0xec, 0x99, - 0xfe, 0x8c, 0x91, 0xda, 0xac, 0xa4, 0x96, 0x27, 0xd3, 0x09, 0x55, 0x82, 0x0c, 0x3e, 0x33, 0x60, - 0x7f, 0xe4, 0xdb, 0x42, 0xfa, 0x82, 0xd9, 0xd9, 0xb0, 0x85, 0x3e, 0xad, 0x91, 0xd5, 0x49, 0xc9, - 0x6a, 0x86, 0xe4, 0xba, 0xb2, 0xe2, 0xab, 0xe7, 0x1f, 0x3d, 0xcd, 0x19, 0x8f, 0x9f, 0xe6, 0x8c, - 0x3f, 0x9e, 0xe6, 0x8c, 0x07, 0xcf, 0x72, 0x03, 0x8f, 0x9f, 0xe5, 0x06, 0x7e, 0x7b, 0x96, 0x1b, - 0x78, 0x27, 0xdf, 0x32, 0xb7, 0xb4, 0xfd, 0xa7, 0x4f, 0x0e, 0x2d, 0x1b, 0x69, 0x79, 0x2d, 0x58, - 0xfe, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x93, 0x91, 0x86, 0x3e, 0x16, 0x15, 0x00, 0x00, + 0xec, 0x75, 0x76, 0x6d, 0x07, 0x25, 0x12, 0x9c, 0xe2, 0x9d, 0x7d, 0xef, 0x7d, 0x3e, 0x9f, 0x37, + 0xef, 0xcd, 0xbe, 0x09, 0x4c, 0xfa, 0x81, 0xd7, 0xac, 0xd1, 0x35, 0x6e, 0x37, 0x69, 0xa3, 0x26, + 0xec, 0xe6, 0xbc, 0xbd, 0xd1, 0x60, 0xc1, 0x3d, 0xcb, 0x0f, 0x3c, 0xe1, 0x91, 0x31, 0xfd, 0xda, + 0x92, 0xaf, 0xad, 0xe6, 0x7c, 0xee, 0x4c, 0xd9, 0xe3, 0x75, 0x8f, 0xdb, 0x6b, 0x94, 0x33, 0x65, + 0x6b, 0x37, 0xe7, 0xd7, 0x98, 0xa0, 0xf3, 0xb6, 0x4f, 0xab, 0x8e, 0x4b, 0x85, 0xe3, 0xb9, 0xca, + 0x3d, 0x97, 0x6f, 0xb7, 0xd5, 0x56, 0x65, 0xcf, 0xd1, 0xef, 0x27, 0xd4, 0xfb, 0x92, 0x7c, 0xb2, + 0xd5, 0x03, 0xbe, 0x1a, 0xaf, 0x7a, 0x55, 0x4f, 0xad, 0x87, 0xbf, 0x70, 0xf5, 0x78, 0xd5, 0xf3, + 0xaa, 0x35, 0x66, 0x53, 0xdf, 0xb1, 0xa9, 0xeb, 0x7a, 0x42, 0xa2, 0x69, 0x9f, 0x02, 0xbe, 0x95, + 0x4f, 0x6b, 0x8d, 0xf7, 0x6d, 0xe1, 0xd4, 0x19, 0x17, 0xb4, 0xee, 0x6b, 0x3e, 0xdb, 0xd5, 0xfa, + 0x34, 0xa0, 0x75, 0x1d, 0x20, 0x26, 0x1b, 0x4a, 0xb7, 0x7c, 0x6d, 0xde, 0x87, 0xa9, 0x1b, 0xa1, + 0xe0, 0xdb, 0xe1, 0xda, 0x2a, 0x73, 0x2b, 0x8e, 0x5b, 0xbd, 0x79, 0x97, 0xfa, 0xd7, 0x1b, 0x82, + 0x17, 0xd9, 0x46, 0x83, 0x71, 0x41, 0x0e, 0x42, 0xca, 0xa9, 0x64, 0x8d, 0x29, 0x63, 0x76, 0xa4, + 0x98, 0x72, 0x2a, 0xe4, 0x75, 0x80, 0x56, 0x5a, 0xb2, 0xa9, 0x29, 0x63, 0x76, 0xff, 0xc2, 0x29, + 0x0b, 0xa5, 0x86, 0x79, 0xb1, 0x54, 0xbe, 0x31, 0x3b, 0xd6, 0x2a, 0xad, 0x32, 0x8c, 0x55, 0x6c, + 0xf3, 0x34, 0x7f, 0x34, 0xe0, 0x44, 0x17, 0x70, 0xee, 0x7b, 0x2e, 0x67, 0xe4, 0x3d, 0x18, 0xf3, + 0xd5, 0xab, 0x12, 0xbf, 0x4b, 0xfd, 0x92, 0xd7, 0x10, 0x3c, 0x6b, 0x4c, 0x0d, 0xce, 0xee, 0x5f, + 0x38, 0x6b, 0x6d, 0xdb, 0x4b, 0x2b, 0x1a, 0xe6, 0x8e, 0x23, 0xd6, 0x6f, 0x39, 0x75, 0xe6, 0x35, + 0xc4, 0x72, 0xfa, 0xf1, 0xef, 0x85, 0x81, 0xe2, 0x21, 0x3f, 0x8a, 0x43, 0xde, 0x88, 0x51, 0x33, + 0xd3, 0x53, 0x8d, 0x22, 0x17, 0x91, 0xc3, 0xe0, 0x98, 0x54, 0x93, 0x90, 0xc5, 0x68, 0xd6, 0x8c, + 0x7f, 0x9c, 0xb5, 0x1f, 0x0c, 0x38, 0x1e, 0x8f, 0xf3, 0x5f, 0x4b, 0xd8, 0x4f, 0x06, 0x4c, 0x24, + 0xa2, 0x93, 0x49, 0x80, 0x40, 0xc9, 0x2f, 0x61, 0xf5, 0xa5, 0x8b, 0x23, 0xb8, 0x72, 0xad, 0x42, + 0x6e, 0xc0, 0xe1, 0x4e, 0x95, 0xc8, 0xe5, 0x44, 0x4f, 0x91, 0xa8, 0xec, 0x60, 0x54, 0x19, 0x79, + 0x0d, 0xf6, 0x09, 0x05, 0x9e, 0x1d, 0x94, 0x91, 0x72, 0x96, 0xea, 0x3e, 0x4b, 0x77, 0x9f, 0x75, + 0x4b, 0x77, 0xdf, 0xf2, 0x70, 0x18, 0xe2, 0xe1, 0xd3, 0x82, 0x51, 0xd4, 0x4e, 0xe6, 0xbb, 0x40, + 0x5a, 0xe5, 0xbc, 0xeb, 0xfb, 0xfe, 0xa5, 0x01, 0xff, 0x8b, 0x84, 0xc7, 0xed, 0xbe, 0x0c, 0x19, + 0x29, 0x53, 0xef, 0x71, 0x21, 0x46, 0xbe, 0x74, 0x59, 0x2a, 0x97, 0xbd, 0x86, 0xab, 0xc5, 0xa3, + 0xd3, 0xee, 0xed, 0xe6, 0x49, 0x18, 0x6b, 0xd1, 0x4b, 0x38, 0x3a, 0xcc, 0x47, 0xa9, 0xf6, 0x1c, + 0x6d, 0x69, 0x78, 0x15, 0x86, 0x24, 0x1d, 0x4c, 0x4f, 0x9f, 0x12, 0x94, 0x0f, 0xb9, 0x0a, 0x23, + 0x7e, 0xe0, 0xb8, 0x65, 0xc7, 0xa7, 0xb5, 0x2e, 0x25, 0xa0, 0x7d, 0x69, 0x8d, 0xba, 0x65, 0x86, + 0x21, 0x5a, 0x9e, 0xe4, 0x0a, 0x0c, 0x07, 0x8c, 0xb3, 0xa0, 0xc9, 0x38, 0x6e, 0x7f, 0xdf, 0x51, + 0xb6, 0x1c, 0xc9, 0x5b, 0x30, 0x26, 0x3c, 0x41, 0x6b, 0x25, 0xe9, 0x50, 0x6a, 0xd2, 0x5a, 0x83, + 0x65, 0xd3, 0x32, 0xda, 0x44, 0x24, 0xa9, 0x3a, 0x9d, 0x57, 0x3c, 0xc7, 0xd5, 0x8d, 0x26, 0x3d, + 0xa5, 0xce, 0xdb, 0xa1, 0x9f, 0x79, 0x1f, 0x72, 0x32, 0x57, 0x57, 0xb9, 0x70, 0xea, 0x54, 0xb0, + 0xb0, 0x4e, 0xaf, 0xb9, 0x3a, 0xb5, 0x27, 0xe1, 0x80, 0x02, 0xa1, 0x95, 0x4a, 0xc0, 0x38, 0xc7, + 0x2c, 0x8f, 0xca, 0xc5, 0x25, 0xb5, 0x46, 0x5e, 0x86, 0x0c, 0xe5, 0x9c, 0x09, 0x8e, 0x89, 0xe9, + 0x49, 0x02, 0xcd, 0xcd, 0xaf, 0x0d, 0x3c, 0xcd, 0x3a, 0xc1, 0x71, 0xc7, 0x5a, 0x81, 0x8d, 0x1d, + 0x05, 0x26, 0x47, 0x21, 0xb3, 0xce, 0x9c, 0xea, 0xba, 0xea, 0xd6, 0xc1, 0x22, 0x3e, 0x91, 0x57, + 0x20, 0x1d, 0xf6, 0xd1, 0x8e, 0x3a, 0x4f, 0x7a, 0x98, 0x6e, 0x0c, 0xd3, 0xeb, 0x0d, 0xb1, 0xa3, + 0x3c, 0x1d, 0x85, 0x0c, 0x5f, 0xa7, 0x01, 0x53, 0x79, 0x1a, 0x29, 0xe2, 0xd3, 0x9b, 0xe9, 0xe1, + 0xc1, 0xc3, 0xe9, 0xe2, 0x68, 0xc0, 0x2a, 0x8c, 0xd5, 0x4b, 0x15, 0xe6, 0x7a, 0x75, 0xf3, 0x1b, + 0x7d, 0x00, 0x6f, 0x03, 0xfc, 0xf7, 0xe5, 0x66, 0x1c, 0xdb, 0x6d, 0x55, 0x8e, 0x04, 0x98, 0x12, + 0x73, 0x05, 0x4f, 0x12, 0xbd, 0xda, 0xe2, 0xad, 0x46, 0x87, 0x2d, 0xde, 0x31, 0x07, 0xa9, 0x34, + 0xd0, 0xbc, 0x95, 0xb9, 0xe9, 0xc1, 0x91, 0x56, 0x53, 0xaf, 0xd0, 0xe6, 0x9e, 0x4f, 0x0e, 0x5f, + 0x18, 0x70, 0xb4, 0x13, 0x11, 0x45, 0xbc, 0x04, 0x69, 0x97, 0x36, 0xf5, 0x61, 0x78, 0x2c, 0xe9, + 0x24, 0x59, 0x59, 0xba, 0x8d, 0x22, 0xa4, 0xf9, 0xee, 0x1d, 0x83, 0x97, 0x60, 0x5c, 0x32, 0x5b, + 0xa1, 0x4d, 0xd9, 0xc5, 0x49, 0xa9, 0x18, 0x87, 0x21, 0x59, 0x4e, 0x58, 0x70, 0xea, 0xc1, 0x7c, + 0x1b, 0x33, 0xd9, 0xf2, 0x46, 0x59, 0x8b, 0x30, 0xe8, 0xd2, 0x26, 0x6e, 0x4c, 0x1f, 0xaa, 0x42, + 0x6b, 0xf3, 0xaf, 0x14, 0xec, 0x5b, 0xa5, 0xf7, 0xea, 0xcc, 0x15, 0xe4, 0x1c, 0x64, 0xb8, 0xd7, + 0x08, 0xca, 0x4c, 0x71, 0x58, 0xce, 0xfe, 0xf2, 0xfd, 0xdc, 0x38, 0xea, 0xc3, 0x2e, 0xb8, 0x29, + 0x02, 0xc7, 0xad, 0x16, 0xd1, 0x8e, 0xf8, 0x70, 0x40, 0xfd, 0x2a, 0xd1, 0x7a, 0x78, 0xe6, 0x65, + 0x53, 0x32, 0xa5, 0x5d, 0xaa, 0xf9, 0x5c, 0x08, 0xfd, 0xe8, 0x69, 0x61, 0xb6, 0xea, 0x88, 0xf5, + 0xc6, 0x9a, 0x55, 0xf6, 0xea, 0x38, 0x01, 0xe3, 0x9f, 0x39, 0x5e, 0xf9, 0xc0, 0x16, 0xf7, 0x7c, + 0xc6, 0xa5, 0x03, 0x2f, 0x8e, 0x2a, 0x84, 0x25, 0x09, 0x10, 0x72, 0x14, 0x34, 0xa8, 0x32, 0xf5, + 0xfd, 0xed, 0xca, 0x51, 0xd9, 0x85, 0x1c, 0xd5, 0x2f, 0xcd, 0x31, 0xbd, 0x07, 0x1c, 0x15, 0x02, + 0x72, 0x2c, 0xc0, 0x7e, 0xf6, 0xa1, 0x60, 0x81, 0x4b, 0x6b, 0xe1, 0x5c, 0x32, 0x24, 0x77, 0x0f, + 0xf4, 0xd2, 0xb5, 0x8a, 0xb9, 0x09, 0xd9, 0xb6, 0xa1, 0x56, 0x65, 0x3f, 0xa9, 0x08, 0x5a, 0x9b, + 0x92, 0xea, 0x73, 0x53, 0x3a, 0xe0, 0x07, 0xb7, 0xc1, 0xdf, 0x81, 0x89, 0x18, 0x78, 0xac, 0xa2, + 0x8b, 0xb0, 0xcf, 0x57, 0x4b, 0x58, 0x49, 0xb9, 0xd8, 0x16, 0x97, 0x16, 0x58, 0x48, 0xda, 0xc1, + 0xe4, 0x31, 0x81, 0xf7, 0xbc, 0xd1, 0xbf, 0x32, 0xf0, 0x1b, 0xd8, 0x81, 0x8a, 0x7a, 0x2e, 0xc1, + 0x30, 0xd2, 0xd3, 0x0d, 0xdf, 0x5b, 0xd0, 0x96, 0xc7, 0xae, 0xf5, 0xfc, 0xc2, 0xcf, 0xa3, 0x30, + 0x24, 0x59, 0x92, 0x0d, 0xc8, 0xa8, 0xf1, 0x8c, 0x4c, 0xc7, 0x10, 0xd9, 0x3e, 0x1d, 0xe6, 0x4e, + 0xf5, 0x32, 0x53, 0x70, 0x66, 0xf6, 0xa3, 0x5f, 0xff, 0xfc, 0x34, 0x45, 0xc8, 0xe1, 0x8e, 0x6b, + 0x1c, 0x27, 0x1c, 0x86, 0xa4, 0x2d, 0x79, 0xa1, 0x6b, 0x28, 0x0d, 0x38, 0xdd, 0xc3, 0x0a, 0xf1, + 0x26, 0x25, 0xde, 0xff, 0xc9, 0x91, 0x4e, 0x3c, 0xfb, 0x81, 0x53, 0xd9, 0x24, 0x8f, 0x0c, 0x38, + 0x18, 0x9d, 0x0c, 0xc8, 0x5c, 0x52, 0xe0, 0xd8, 0xf1, 0x25, 0x67, 0xf5, 0x6b, 0x8e, 0x84, 0x2e, + 0x48, 0x42, 0x8b, 0x64, 0x7e, 0x3b, 0xa1, 0xc8, 0xe7, 0x7d, 0xd3, 0x66, 0x18, 0x40, 0xdd, 0x0b, + 0x1c, 0x97, 0x7c, 0x6b, 0xc0, 0xa1, 0x8e, 0x6f, 0x35, 0xe9, 0x0b, 0xbe, 0x35, 0x45, 0xe4, 0xec, + 0xbe, 0xed, 0x91, 0xef, 0x45, 0xc9, 0xf7, 0x3c, 0x59, 0xd8, 0x21, 0xdf, 0xf0, 0xea, 0xf3, 0xb9, + 0x01, 0x87, 0x3a, 0x6e, 0x77, 0xc9, 0x84, 0xe3, 0xaf, 0x9b, 0xc9, 0x84, 0x13, 0xae, 0x8d, 0xe6, + 0x49, 0x49, 0x78, 0x92, 0x1c, 0x6b, 0xfb, 0x47, 0x42, 0xe7, 0x35, 0x92, 0x7c, 0x67, 0xc0, 0x78, + 0xdc, 0x6d, 0x9d, 0x2c, 0x76, 0x2d, 0xab, 0x04, 0x8e, 0xe7, 0x77, 0xe6, 0x84, 0x44, 0x6d, 0x49, + 0xf4, 0x34, 0x99, 0x89, 0x2d, 0xcd, 0x18, 0xd2, 0x1b, 0x90, 0x51, 0x63, 0x4b, 0x72, 0x53, 0x46, + 0xe6, 0xa3, 0xe4, 0xa6, 0x8c, 0x0e, 0x4c, 0x71, 0x4d, 0xa9, 0x26, 0x22, 0xf2, 0xb1, 0x01, 0x23, + 0x5b, 0xb3, 0x09, 0x99, 0xed, 0xaa, 0xb3, 0x6d, 0x60, 0xca, 0x9d, 0xee, 0xc3, 0x12, 0xc1, 0x4d, + 0x09, 0x7e, 0x9c, 0xe4, 0xe2, 0xd3, 0x20, 0xa7, 0x9a, 0x4f, 0x0c, 0x18, 0xd6, 0xa3, 0x04, 0x99, + 0x49, 0x8a, 0xdd, 0x31, 0xaa, 0xe4, 0x66, 0x7b, 0x1b, 0x22, 0x87, 0x39, 0xc9, 0x61, 0x86, 0x4c, + 0x27, 0x73, 0xb0, 0x1f, 0xc8, 0xc9, 0xe6, 0xf2, 0x99, 0x33, 0x9b, 0xe4, 0xa1, 0x01, 0xa3, 0xed, + 0x07, 0x39, 0x79, 0xb1, 0x7b, 0x01, 0x44, 0x3e, 0x9e, 0xb9, 0xb3, 0xfd, 0x19, 0x23, 0xb5, 0x69, + 0x49, 0xad, 0x40, 0x26, 0x13, 0xaa, 0x04, 0x19, 0x7c, 0x66, 0xc0, 0x81, 0xc8, 0xb7, 0x85, 0xf4, + 0x05, 0xb3, 0xb5, 0x61, 0x73, 0x7d, 0x5a, 0x23, 0xab, 0x53, 0x92, 0xd5, 0x14, 0xc9, 0x77, 0x65, + 0xc5, 0x97, 0x2f, 0x3c, 0x7e, 0x96, 0x37, 0x9e, 0x3c, 0xcb, 0x1b, 0x7f, 0x3c, 0xcb, 0x1b, 0x0f, + 0x9f, 0xe7, 0x07, 0x9e, 0x3c, 0xcf, 0x0f, 0xfc, 0xf6, 0x3c, 0x3f, 0xf0, 0x4e, 0xa1, 0x6d, 0x6e, + 0xe9, 0xf8, 0xd7, 0x9e, 0x1c, 0x5a, 0xd6, 0x32, 0xf2, 0x5a, 0xb0, 0xf8, 0x77, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xdb, 0xf2, 0x88, 0xa2, 0x07, 0x15, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2475,13 +2466,6 @@ func (m *QueryEstimateSwapOutRequest) MarshalToSizedBuffer(dAtA []byte) (int, er _ = i var l int _ = l - if len(m.RedeemDenom) > 0 { - i -= len(m.RedeemDenom) - copy(dAtA[i:], m.RedeemDenom) - i = encodeVarintQuery(dAtA, i, uint64(len(m.RedeemDenom))) - i-- - dAtA[i] = 0x1a - } if len(m.Shares) > 0 { i -= len(m.Shares) copy(dAtA[i:], m.Shares) @@ -3204,10 +3188,6 @@ func (m *QueryEstimateSwapOutRequest) Size() (n int) { if l > 0 { n += 1 + l + sovQuery(uint64(l)) } - l = len(m.RedeemDenom) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } return n } @@ -4810,38 +4790,6 @@ func (m *QueryEstimateSwapOutRequest) Unmarshal(dAtA []byte) error { } m.Shares = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RedeemDenom", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.RedeemDenom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/types/tx.pb.go b/types/tx.pb.go index 98773bc4..172ff86b 100644 --- a/types/tx.pb.go +++ b/types/tx.pb.go @@ -42,9 +42,6 @@ type MsgCreateVaultRequest struct { ShareDenom string `protobuf:"bytes,2,opt,name=share_denom,json=shareDenom,proto3" json:"share_denom,omitempty"` // underlying_asset is the denomination of the asset supported by the vault. UnderlyingAsset string `protobuf:"bytes,3,opt,name=underlying_asset,json=underlyingAsset,proto3" json:"underlying_asset,omitempty"` - // payment_denom is the secondary denomination the vault can accept. - // if not specified, vault payment_denom will be set to underlying_asset. - PaymentDenom string `protobuf:"bytes,4,opt,name=payment_denom,json=paymentDenom,proto3" json:"payment_denom,omitempty"` // withdrawal_delay_seconds is the time period (in seconds) that a withdrawal // must wait in the pending queue before being processed. WithdrawalDelaySeconds uint64 `protobuf:"varint,5,opt,name=withdrawal_delay_seconds,json=withdrawalDelaySeconds,proto3" json:"withdrawal_delay_seconds,omitempty"` @@ -64,13 +61,6 @@ type MsgCreateVaultRequest struct { // - Values must be positive (> 0). // - An empty string "" indicates no maximum limit. MaxSwapOutValue string `protobuf:"bytes,9,opt,name=max_swap_out_value,json=maxSwapOutValue,proto3" json:"max_swap_out_value,omitempty"` - // initial_payment_nav seeds the per-vault Internal NAV entry for payment_denom - // at creation, ensuring fee accrual and payment-denom swap-outs are operational - // from block one. The entry's denom is implicitly payment_denom; the price - // denom must be underlying_asset. - // - Required when payment_denom is set and payment_denom != underlying_asset. - // - Must be omitted when payment_denom is empty or equal to underlying_asset. - InitialPaymentNav *InitialVaultNAV `protobuf:"bytes,10,opt,name=initial_payment_nav,json=initialPaymentNav,proto3" json:"initial_payment_nav,omitempty"` } func (m *MsgCreateVaultRequest) Reset() { *m = MsgCreateVaultRequest{} } @@ -127,13 +117,6 @@ func (m *MsgCreateVaultRequest) GetUnderlyingAsset() string { return "" } -func (m *MsgCreateVaultRequest) GetPaymentDenom() string { - if m != nil { - return m.PaymentDenom - } - return "" -} - func (m *MsgCreateVaultRequest) GetWithdrawalDelaySeconds() uint64 { if m != nil { return m.WithdrawalDelaySeconds @@ -169,13 +152,6 @@ func (m *MsgCreateVaultRequest) GetMaxSwapOutValue() string { return "" } -func (m *MsgCreateVaultRequest) GetInitialPaymentNav() *InitialVaultNAV { - if m != nil { - return m.InitialPaymentNav - } - return nil -} - // MsgCreateVaultResponse is the response message for the CreateVault endpoint. type MsgCreateVaultResponse struct { // vault_address is the bech32 address of the newly created vault. @@ -435,10 +411,6 @@ type MsgSwapOutRequest struct { VaultAddress string `protobuf:"bytes,2,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // assets is the amount of underlying assets to withdraw. Assets types1.Coin `protobuf:"bytes,3,opt,name=assets,proto3" json:"assets"` - // redeem_denom selects the payout coin. - // - If empty, defaults to the vault’s payment_denom. - // - Must be either the vault’s underlying_asset or its payment_denom. - RedeemDenom string `protobuf:"bytes,4,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` } func (m *MsgSwapOutRequest) Reset() { *m = MsgSwapOutRequest{} } @@ -495,13 +467,6 @@ func (m *MsgSwapOutRequest) GetAssets() types1.Coin { return types1.Coin{} } -func (m *MsgSwapOutRequest) GetRedeemDenom() string { - if m != nil { - return m.RedeemDenom - } - return "" -} - // MsgSwapOutResponse is the response message for the SwapOut endpoint. type MsgSwapOutResponse struct { // request_id is the unique identifier for the newly queued swap out request. @@ -2984,11 +2949,10 @@ type MsgUpdateVaultNAVRequest struct { // vault_address is the bech32 address of the vault whose NAV entry is being updated. VaultAddress string `protobuf:"bytes,2,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // denom is the asset denomination being priced. It must not be the vault's - // share denom. The underlying asset is a valid denom (e.g. to record its - // price in payment-denom terms). + // share denom. Denom string `protobuf:"bytes,3,opt,name=denom,proto3" json:"denom,omitempty"` // price is the total value of `volume` units of the denom, denominated in - // one of the vault's accepted denoms (underlying asset or payment denom). + // the vault's underlying asset. Price types1.Coin `protobuf:"bytes,4,opt,name=price,proto3" json:"price"` // volume is the number of units of the denom that price covers. It must be positive. Volume cosmossdk_io_math.Int `protobuf:"bytes,5,opt,name=volume,proto3,customtype=cosmossdk.io/math.Int" json:"volume"` @@ -3205,8 +3169,8 @@ var xxx_messageInfo_MsgUpdateNAVAuthorityResponse proto.InternalMessageInfo // MsgAcceptAssetRequest is the request message for settling a pending exchange-module // payment whose target is the vault. The payment is identified by its source account and -// external_id. The vault settles only payments where one leg is the vault's payment_denom; -// the settlement direction (inbound or outbound) is derived from which leg that is. +// external_id. The vault settles only payments where one leg is the vault's underlying +// asset; the settlement direction (inbound or outbound) is derived from which leg that is. type MsgAcceptAssetRequest struct { // authority is the address of the vault's asset manager authorizing the settlement. Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` @@ -3498,146 +3462,145 @@ func init() { func init() { proto.RegisterFile("provlabs/vault/v1/tx.proto", fileDescriptor_1bb9c8306211b32d) } var fileDescriptor_1bb9c8306211b32d = []byte{ - // 2222 bytes of a gzipped FileDescriptorProto + // 2198 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x5a, 0xcd, 0x6f, 0x1c, 0x49, - 0x15, 0x4f, 0x7b, 0xec, 0x89, 0x5d, 0xfe, 0x48, 0x52, 0x38, 0xc9, 0x78, 0x76, 0xfd, 0x91, 0x09, - 0x08, 0x6f, 0xb2, 0x9e, 0x89, 0x1d, 0x60, 0x21, 0x52, 0xb4, 0x1a, 0x27, 0xac, 0xf0, 0x61, 0xb2, - 0xd6, 0x98, 0x18, 0x09, 0x09, 0x8d, 0x6a, 0xa6, 0x6b, 0xc7, 0x4d, 0xa6, 0xab, 0x67, 0xfb, 0x63, - 0x66, 0x7c, 0x40, 0x5a, 0x81, 0x38, 0x70, 0x43, 0x82, 0x03, 0x1c, 0xb8, 0x22, 0x0e, 0x1c, 0x82, - 0x94, 0x0b, 0x42, 0x42, 0xe2, 0x02, 0x39, 0xa1, 0x90, 0x0b, 0x68, 0x0f, 0x2b, 0x94, 0x1c, 0xf6, - 0x6f, 0xe0, 0x86, 0xba, 0xaa, 0x66, 0xba, 0xab, 0xbb, 0xaa, 0xba, 0xbd, 0x90, 0x61, 0xc3, 0xc9, - 0xee, 0xaa, 0x57, 0x55, 0xbf, 0x5f, 0xbd, 0x57, 0x55, 0xaf, 0x7e, 0x35, 0xa0, 0xdc, 0x77, 0x9d, - 0x41, 0x0f, 0xb5, 0xbd, 0xda, 0x00, 0x05, 0x3d, 0xbf, 0x36, 0xd8, 0xad, 0xf9, 0xa3, 0x6a, 0xdf, - 0x75, 0x7c, 0x07, 0x5e, 0x1a, 0xd7, 0x55, 0x69, 0x5d, 0x75, 0xb0, 0x5b, 0xde, 0xe8, 0x38, 0x9e, - 0xed, 0x78, 0xb5, 0x36, 0x22, 0x8f, 0x6a, 0x83, 0xdd, 0x36, 0xf6, 0xd1, 0x2e, 0xfd, 0x60, 0x4d, - 0x62, 0xf5, 0x1e, 0x9e, 0xd4, 0x77, 0x1c, 0x8b, 0xf0, 0xfa, 0xab, 0xbc, 0xde, 0xf6, 0xba, 0xe1, - 0x50, 0xb6, 0xd7, 0xe5, 0x15, 0x6b, 0xac, 0xa2, 0x45, 0xbf, 0x6a, 0xec, 0x83, 0x57, 0xad, 0x76, - 0x9d, 0xae, 0xc3, 0xca, 0xc3, 0xff, 0xc6, 0x23, 0xa5, 0x81, 0xf7, 0x91, 0x8b, 0xec, 0x71, 0xab, - 0xf5, 0x74, 0x3d, 0x63, 0x41, 0xab, 0x2b, 0x1f, 0xcf, 0x82, 0xcb, 0x0d, 0xaf, 0x7b, 0xcf, 0xc5, - 0xc8, 0xc7, 0xc7, 0x61, 0x45, 0x13, 0x7f, 0x18, 0x60, 0xcf, 0x87, 0x55, 0x30, 0x87, 0x4c, 0xdb, - 0x22, 0x25, 0x63, 0xcb, 0xd8, 0x5e, 0xd8, 0x2f, 0x3d, 0x7f, 0xb2, 0xb3, 0xca, 0xf1, 0xd4, 0x4d, - 0xd3, 0xc5, 0x9e, 0x77, 0xe4, 0xbb, 0x16, 0xe9, 0x36, 0x99, 0x19, 0xdc, 0x04, 0x8b, 0xde, 0x09, - 0x72, 0x71, 0xcb, 0xc4, 0xc4, 0xb1, 0x4b, 0x33, 0x61, 0xab, 0x26, 0xa0, 0x45, 0xf7, 0xc3, 0x12, - 0xf8, 0x16, 0xb8, 0x18, 0x10, 0x13, 0xbb, 0xbd, 0x53, 0x8b, 0x74, 0x5b, 0xc8, 0xf3, 0xb0, 0x5f, - 0x2a, 0x50, 0xab, 0x0b, 0x51, 0x79, 0x3d, 0x2c, 0x86, 0xd7, 0xc1, 0x72, 0x1f, 0x9d, 0xda, 0x98, - 0xf8, 0xbc, 0xb7, 0x59, 0x6a, 0xb7, 0xc4, 0x0b, 0x59, 0x7f, 0x5f, 0x07, 0xa5, 0xa1, 0xe5, 0x9f, - 0x98, 0x2e, 0x1a, 0xa2, 0x5e, 0xcb, 0xc4, 0x3d, 0x74, 0xda, 0xf2, 0x70, 0xc7, 0x21, 0xa6, 0x57, - 0x9a, 0xdb, 0x32, 0xb6, 0x67, 0x9b, 0x57, 0xa2, 0xfa, 0xfb, 0x61, 0xf5, 0x11, 0xab, 0x85, 0xef, - 0x82, 0x4b, 0xb6, 0x45, 0x5a, 0xde, 0x10, 0xf5, 0x5b, 0x16, 0x69, 0x0d, 0x50, 0x2f, 0xc0, 0xa5, - 0x22, 0xa5, 0xb9, 0xfa, 0xfc, 0xc9, 0xce, 0x45, 0x4e, 0xf3, 0x80, 0xf8, 0x9c, 0xe2, 0x8a, 0x6d, - 0x91, 0xa3, 0x21, 0xea, 0x1f, 0x90, 0xe3, 0xd0, 0x16, 0xd6, 0x01, 0x9c, 0x74, 0xe0, 0x04, 0x3e, - 0xef, 0xe1, 0xbc, 0xa6, 0x87, 0x0b, 0xbc, 0x87, 0xf7, 0x03, 0x9f, 0x75, 0x11, 0x62, 0x40, 0xa3, - 0x04, 0x86, 0x79, 0x2d, 0x06, 0x34, 0x4a, 0x62, 0x18, 0x77, 0x10, 0x61, 0x58, 0xd0, 0x62, 0x60, - 0x3d, 0x4c, 0x30, 0x34, 0xc1, 0x17, 0x2c, 0x62, 0xf9, 0x16, 0xea, 0xb5, 0xc6, 0xd3, 0x4d, 0xd0, - 0xa0, 0x04, 0xb6, 0x8c, 0xed, 0xc5, 0xbd, 0x4a, 0x35, 0x15, 0xf6, 0xd5, 0x03, 0x66, 0x4d, 0xe3, - 0xe4, 0x41, 0xfd, 0xb8, 0x79, 0x89, 0x37, 0x3f, 0x64, 0xad, 0x1f, 0xa0, 0xc1, 0x1d, 0xf0, 0xc3, - 0x4f, 0x1f, 0xdf, 0x60, 0x21, 0x51, 0xb9, 0x0b, 0xae, 0x24, 0x63, 0xcb, 0xeb, 0x3b, 0xc4, 0xc3, - 0xa1, 0x83, 0x69, 0xa7, 0x2d, 0xc4, 0x42, 0x89, 0x05, 0x59, 0x73, 0x89, 0x16, 0xf2, 0xf0, 0xaa, - 0xfc, 0xcb, 0x00, 0x9b, 0x0d, 0xaf, 0x7b, 0x84, 0xfd, 0xa3, 0x49, 0x14, 0x35, 0xb0, 0x8f, 0x4c, - 0xe4, 0xa3, 0x71, 0x94, 0x06, 0x60, 0xde, 0xe6, 0x45, 0xb4, 0x8f, 0xc5, 0xbd, 0xf5, 0x2a, 0x27, - 0x4e, 0x97, 0x23, 0x5f, 0x7b, 0xd5, 0x71, 0xbb, 0xfd, 0x3b, 0x4f, 0x3f, 0xd9, 0x3c, 0xf7, 0xf1, - 0x27, 0x9b, 0x7b, 0x5d, 0xcb, 0x3f, 0x09, 0xda, 0xd5, 0x8e, 0x63, 0xf3, 0x65, 0xc6, 0xff, 0xec, - 0x78, 0xe6, 0xa3, 0xda, 0x88, 0xad, 0x6c, 0xff, 0xb4, 0x8f, 0xbd, 0x49, 0xdb, 0xe6, 0x64, 0xa8, - 0x68, 0x71, 0xcc, 0xe4, 0x5b, 0x1c, 0x29, 0xbe, 0x85, 0x34, 0x5f, 0x61, 0xea, 0x2a, 0x60, 0x4b, - 0x4d, 0x9d, 0x4d, 0x62, 0xe5, 0xb7, 0x06, 0xb8, 0x18, 0x1a, 0xd1, 0xa0, 0x88, 0x2d, 0x5b, 0x67, - 0x48, 0xb0, 0x9b, 0xbd, 0x6c, 0xa9, 0x59, 0x1a, 0xd9, 0x4c, 0x1a, 0x19, 0x7c, 0x07, 0x14, 0xe9, - 0x7a, 0x65, 0xb8, 0x17, 0xf7, 0xd6, 0xa2, 0x39, 0xf6, 0xf0, 0x64, 0x8e, 0xef, 0x39, 0x16, 0xd9, - 0x9f, 0x0d, 0xe7, 0xb7, 0xc9, 0xcd, 0x39, 0x25, 0x3a, 0x52, 0xe5, 0x7b, 0xe0, 0x52, 0x0c, 0x2d, - 0x0f, 0x84, 0x6f, 0x81, 0x0b, 0x74, 0x8b, 0xf0, 0x5a, 0x2e, 0xee, 0x60, 0x6b, 0x80, 0x4d, 0xee, - 0xc6, 0xcc, 0x21, 0x56, 0x58, 0xbb, 0x26, 0x6f, 0x56, 0x79, 0x66, 0x4c, 0xfa, 0x7f, 0x3f, 0xf0, - 0x3f, 0x97, 0xd3, 0x01, 0xaf, 0x81, 0x25, 0x17, 0x9b, 0x18, 0xdb, 0xc2, 0xb6, 0xb6, 0xc8, 0xca, - 0xa8, 0x93, 0x85, 0x19, 0xbb, 0x0d, 0x60, 0x9c, 0x11, 0x9f, 0xb2, 0x75, 0x00, 0x5c, 0xc6, 0xae, - 0x65, 0xb1, 0xd9, 0x9a, 0x6d, 0x2e, 0xf0, 0x92, 0x03, 0xb3, 0xf2, 0x2b, 0xb6, 0x6a, 0x1e, 0xf6, - 0x4d, 0xe4, 0xe3, 0x86, 0x45, 0x0e, 0x88, 0x8f, 0x5d, 0xec, 0xf9, 0x4d, 0xe4, 0xe3, 0xcf, 0xba, - 0xb7, 0xe7, 0x9a, 0x95, 0x35, 0x30, 0x1f, 0x6e, 0x8a, 0x2e, 0xf2, 0x31, 0x0f, 0xef, 0xf3, 0xb6, - 0x45, 0xc2, 0x61, 0x25, 0x91, 0xad, 0x80, 0xc7, 0x23, 0x5b, 0xe4, 0x80, 0x46, 0x53, 0xe5, 0x80, - 0x46, 0x22, 0x07, 0x34, 0xd2, 0x73, 0x48, 0xc2, 0xe3, 0x1c, 0x7e, 0x6d, 0x80, 0x37, 0x27, 0x46, - 0x32, 0x02, 0x5f, 0x03, 0x0b, 0x28, 0xf0, 0x4f, 0x1c, 0xd7, 0xf2, 0x4f, 0x33, 0x49, 0x44, 0xa6, - 0xb9, 0x89, 0x10, 0x3c, 0x14, 0x88, 0x10, 0x3c, 0xa4, 0x44, 0x56, 0x42, 0x22, 0x51, 0x7f, 0x95, - 0x4d, 0xb0, 0xae, 0xc0, 0xc9, 0x99, 0x3c, 0x8d, 0x7b, 0xe3, 0x3b, 0xe2, 0x91, 0x3a, 0x15, 0x32, - 0xba, 0x93, 0xbe, 0xa0, 0x3b, 0xe9, 0x53, 0x5c, 0xe3, 0x8e, 0x4b, 0x31, 0xe1, 0x74, 0xff, 0x6a, - 0x80, 0x8d, 0x78, 0x84, 0xc6, 0x0e, 0xdd, 0xa9, 0xb0, 0x95, 0x66, 0x27, 0x85, 0xfc, 0xd9, 0x49, - 0x8a, 0xf4, 0x35, 0x71, 0x43, 0x10, 0xf8, 0x70, 0xce, 0x7f, 0x33, 0xd2, 0x36, 0xe3, 0x34, 0x61, - 0x2a, 0xa4, 0xe5, 0x19, 0x55, 0xe1, 0x0c, 0x19, 0x95, 0xd6, 0xd7, 0x29, 0x4a, 0x52, 0x5f, 0x0b, - 0x09, 0xd6, 0xd4, 0x7c, 0x9d, 0xca, 0x02, 0x0b, 0xf9, 0xb3, 0x40, 0xbd, 0xaf, 0x13, 0x7c, 0xa4, - 0xbe, 0x16, 0x53, 0xc2, 0xa9, 0xf9, 0x3a, 0x9d, 0xb9, 0x16, 0xce, 0x90, 0xb9, 0xea, 0x7d, 0x9d, - 0xa4, 0xc4, 0x79, 0xff, 0xcc, 0xa0, 0xe9, 0xe8, 0xb7, 0x9d, 0x6e, 0xb7, 0x87, 0x53, 0x49, 0xd3, - 0x7f, 0xff, 0x2c, 0x29, 0x81, 0xf3, 0x98, 0xa0, 0x76, 0x0f, 0x9b, 0x94, 0xdb, 0x7c, 0x73, 0xfc, - 0x29, 0x1c, 0x25, 0x6b, 0xe0, 0x6a, 0x0a, 0x14, 0x07, 0xfc, 0x73, 0x23, 0x51, 0x27, 0xe6, 0x35, - 0xff, 0x2b, 0xc4, 0x65, 0x50, 0x4a, 0xa3, 0xe2, 0x90, 0xff, 0xcc, 0xd6, 0xd3, 0x7d, 0xdc, 0x77, - 0x3c, 0xcb, 0x1f, 0x9f, 0x26, 0xef, 0x05, 0xc4, 0xf4, 0xa6, 0x12, 0x5a, 0x61, 0x66, 0x66, 0x3b, - 0x01, 0xf1, 0xf3, 0x67, 0x66, 0xd4, 0x5c, 0xb1, 0x8e, 0xe4, 0x3c, 0x38, 0xd7, 0xbf, 0xb0, 0x75, - 0x34, 0x3e, 0x46, 0x5e, 0x63, 0xb2, 0x6c, 0xf5, 0x28, 0x88, 0x88, 0x6c, 0xf9, 0x8c, 0x1c, 0xba, - 0x16, 0xe9, 0x58, 0x7d, 0xd4, 0x7b, 0x6d, 0xd9, 0x2a, 0x88, 0x44, 0x29, 0x4f, 0x7c, 0x4a, 0x5e, - 0x67, 0xba, 0xd7, 0xc1, 0x35, 0x0d, 0x13, 0xce, 0xf7, 0x27, 0x8c, 0xef, 0x37, 0x47, 0x7d, 0x6c, - 0x5a, 0x3e, 0x3e, 0xc4, 0xc4, 0xb4, 0x48, 0xf2, 0x2e, 0xf5, 0x59, 0xf9, 0x8a, 0x17, 0x96, 0x99, - 0xc4, 0x85, 0x45, 0x01, 0x58, 0x05, 0x85, 0x03, 0xfe, 0x9d, 0x01, 0x56, 0x1b, 0x5e, 0xf7, 0x10, - 0x05, 0x9e, 0x28, 0x5b, 0xbd, 0x52, 0xa7, 0x5c, 0x01, 0x45, 0x17, 0x23, 0xcf, 0x21, 0x3c, 0xa7, - 0xe6, 0x5f, 0x70, 0x15, 0xcc, 0x7d, 0xe0, 0xb8, 0x1d, 0x4c, 0x2f, 0x74, 0xf3, 0x4d, 0xf6, 0x91, - 0x22, 0x76, 0x95, 0x4a, 0x6d, 0x71, 0xc8, 0x9c, 0xcc, 0x8f, 0xd9, 0xc9, 0xf4, 0x90, 0xf4, 0xa7, - 0x4a, 0x27, 0x05, 0x90, 0x9d, 0x45, 0x22, 0x0c, 0x0e, 0xf1, 0x8f, 0x06, 0x28, 0x33, 0x41, 0x62, - 0xdf, 0xb5, 0xcc, 0x2e, 0xe6, 0x5d, 0xbc, 0xd2, 0xe3, 0xe8, 0x5d, 0xb0, 0xd2, 0xa6, 0x83, 0x89, - 0xaa, 0x89, 0xa6, 0xf7, 0xe5, 0x76, 0x1c, 0x9c, 0x70, 0x6a, 0xad, 0x83, 0x37, 0xa4, 0xf8, 0x65, - 0xc9, 0x01, 0x33, 0xf9, 0x9c, 0x25, 0x07, 0x63, 0x50, 0x1c, 0xf0, 0xef, 0x99, 0x43, 0x58, 0x69, - 0xc3, 0x22, 0x4c, 0x28, 0x9a, 0x38, 0xe4, 0x16, 0x28, 0xb2, 0xb9, 0xc8, 0x44, 0xcd, 0xed, 0x72, - 0xef, 0x4a, 0x4c, 0x76, 0xc9, 0xbd, 0x2b, 0x31, 0xf3, 0x3b, 0x8b, 0x21, 0x2b, 0x3e, 0x14, 0xf7, - 0x45, 0x1a, 0xba, 0x8c, 0xda, 0x7e, 0xe0, 0x92, 0xd7, 0x94, 0x5a, 0x1c, 0x3a, 0xa7, 0xf6, 0x07, - 0x03, 0xac, 0xb1, 0x30, 0xa4, 0x42, 0x77, 0x03, 0x11, 0xd4, 0xc5, 0xee, 0x2b, 0x8d, 0xb4, 0xbb, - 0x60, 0x99, 0xaa, 0x4f, 0x2d, 0x9b, 0x0d, 0x96, 0xb9, 0x88, 0x96, 0x50, 0x0c, 0x9a, 0x10, 0x8e, - 0x6f, 0x8e, 0xf7, 0x00, 0x11, 0x3c, 0xe7, 0xf6, 0x4b, 0xbe, 0x8b, 0xd1, 0x24, 0xfc, 0x90, 0xbe, - 0x41, 0xfc, 0xa7, 0xbb, 0xd8, 0x3b, 0xa0, 0xc8, 0x1e, 0x33, 0x28, 0xb3, 0xd0, 0x27, 0x69, 0x4d, - 0x9a, 0x8d, 0x34, 0xf6, 0x09, 0x33, 0x57, 0xed, 0x6c, 0x02, 0x34, 0x0e, 0xfb, 0x71, 0xfc, 0x3a, - 0x44, 0x37, 0xbd, 0xfa, 0xc3, 0xc6, 0x7b, 0x18, 0xef, 0x5b, 0xfd, 0xe9, 0x9c, 0xf4, 0x5b, 0x60, - 0x09, 0x05, 0x76, 0xeb, 0x03, 0x8c, 0x5b, 0x6d, 0xab, 0xcf, 0xc2, 0x6f, 0xb9, 0x09, 0x50, 0x60, - 0x73, 0x14, 0xda, 0xdb, 0x4e, 0x0a, 0x31, 0xa7, 0xf5, 0x9b, 0x19, 0x9a, 0xa6, 0xc7, 0x8c, 0x1e, - 0xd4, 0x8f, 0x63, 0x4b, 0xc8, 0xb3, 0xba, 0x79, 0x64, 0x51, 0x6e, 0x97, 0x8f, 0xc9, 0x2a, 0x98, - 0x63, 0xba, 0x26, 0x3b, 0x1d, 0xd9, 0x07, 0xfc, 0x2a, 0x98, 0xeb, 0xbb, 0x16, 0x3f, 0x1c, 0x73, - 0xac, 0x2b, 0x66, 0x0d, 0xef, 0x81, 0xe2, 0xc0, 0xe9, 0x05, 0x36, 0xa6, 0x8f, 0x39, 0x0b, 0xfb, - 0x37, 0xb9, 0x70, 0x7f, 0x99, 0x35, 0xf7, 0xcc, 0x47, 0x55, 0xcb, 0xa9, 0xd9, 0xc8, 0x3f, 0x09, - 0x2f, 0x8a, 0xcf, 0x9f, 0xec, 0x80, 0xe8, 0xda, 0xd8, 0xe4, 0x4d, 0xc3, 0x03, 0xdb, 0x73, 0x82, - 0xf0, 0x64, 0x2e, 0xb2, 0x03, 0x9b, 0x7d, 0xf1, 0x35, 0xcb, 0xb8, 0x55, 0xde, 0xa0, 0x6b, 0x32, - 0x39, 0x53, 0x7c, 0x1e, 0xff, 0x14, 0x97, 0xf1, 0x1e, 0xd4, 0x8f, 0xeb, 0x63, 0x2f, 0xbc, 0xe2, - 0xb9, 0xbc, 0x0b, 0x96, 0x09, 0x1e, 0xb6, 0xa2, 0xb0, 0xcb, 0x5c, 0xb6, 0x04, 0x0f, 0x27, 0xe0, - 0x44, 0x82, 0x71, 0x85, 0x4f, 0xa4, 0xc0, 0x49, 0xfe, 0xdd, 0xa0, 0xa9, 0x49, 0xbd, 0xd3, 0xc1, - 0x7d, 0xb6, 0xb8, 0xa7, 0x12, 0xf9, 0xb7, 0x26, 0xde, 0x29, 0x64, 0x4e, 0x1d, 0xb5, 0x83, 0x9b, - 0x60, 0x11, 0x8f, 0x7c, 0xec, 0x12, 0xd4, 0x0b, 0x73, 0x49, 0xa6, 0x9f, 0x83, 0x71, 0x91, 0x24, - 0x99, 0x2c, 0xd1, 0x3d, 0x49, 0x20, 0x26, 0x72, 0x6e, 0xe2, 0xef, 0xe3, 0xce, 0xff, 0x23, 0x67, - 0x81, 0x18, 0xe3, 0xbc, 0xf7, 0x8b, 0x75, 0x50, 0x68, 0x78, 0x5d, 0xd8, 0x06, 0x8b, 0xb1, 0x57, - 0x39, 0xb8, 0x2d, 0xd9, 0x56, 0xa5, 0x8f, 0xc2, 0xe5, 0xb7, 0x72, 0x58, 0xf2, 0x67, 0x8a, 0x8f, - 0x0c, 0x70, 0x59, 0xfa, 0x7e, 0x05, 0xf7, 0xe4, 0x9d, 0xe8, 0xde, 0xf9, 0xca, 0xb7, 0xcf, 0xd4, - 0x86, 0x43, 0x38, 0x02, 0x45, 0x26, 0xa9, 0xc0, 0xeb, 0x8a, 0xe6, 0x71, 0x15, 0xa8, 0xfc, 0x45, - 0xbd, 0x11, 0xef, 0xf4, 0x18, 0x9c, 0xe7, 0x97, 0x11, 0xa8, 0x69, 0x10, 0x5d, 0x9b, 0xca, 0x5f, - 0xca, 0xb0, 0x8a, 0xcd, 0x97, 0xf4, 0x55, 0x44, 0x35, 0x5f, 0xba, 0x17, 0x1e, 0xd5, 0x7c, 0x69, - 0x9f, 0x5d, 0xe2, 0x10, 0xc4, 0x47, 0x8d, 0x0c, 0x08, 0xd2, 0x07, 0x9a, 0x0c, 0x08, 0xf2, 0x57, - 0x13, 0x38, 0x04, 0x30, 0xfd, 0x12, 0x01, 0x6b, 0xba, 0xae, 0x64, 0x63, 0xdf, 0xca, 0xdf, 0x20, - 0xc5, 0x3d, 0xf1, 0x2e, 0xa0, 0xe7, 0x2e, 0x7f, 0x0e, 0xd1, 0x73, 0x57, 0x3c, 0x3c, 0xc0, 0x1f, - 0x80, 0x55, 0x99, 0x48, 0x0f, 0x77, 0x33, 0x7c, 0x99, 0x16, 0xad, 0xcb, 0x7b, 0x67, 0x69, 0x22, - 0x0b, 0x40, 0xe1, 0x77, 0x02, 0x79, 0x7a, 0x4b, 0x28, 0xc8, 0x99, 0x01, 0x28, 0x93, 0x68, 0x63, - 0x33, 0x20, 0xfe, 0xd6, 0x61, 0x37, 0x23, 0x94, 0xce, 0x3c, 0x03, 0x52, 0x65, 0x5c, 0x8c, 0xff, - 0x33, 0xcc, 0x80, 0x54, 0x43, 0xcf, 0x8c, 0x7f, 0xe9, 0x0c, 0x60, 0xb0, 0x14, 0xd7, 0x82, 0xa1, - 0x62, 0xc3, 0x95, 0x88, 0xd8, 0xe5, 0x1b, 0x79, 0x4c, 0xf9, 0x30, 0x27, 0x60, 0x59, 0x10, 0x70, - 0x61, 0x66, 0xe3, 0xd8, 0x86, 0x76, 0x33, 0x97, 0x6d, 0xe4, 0x52, 0x99, 0x8a, 0xaa, 0x72, 0xa9, - 0x46, 0x39, 0x56, 0xb9, 0x54, 0x27, 0xd2, 0x52, 0x97, 0x4a, 0x85, 0x4d, 0x95, 0x4b, 0x75, 0x72, - 0xae, 0xca, 0xa5, 0x5a, 0xe5, 0x94, 0x42, 0x90, 0xaa, 0x8d, 0x50, 0x4f, 0x48, 0x2a, 0x3a, 0xaa, - 0x20, 0x68, 0xe5, 0x4c, 0xf8, 0x23, 0x03, 0x5c, 0x91, 0x2b, 0x80, 0x30, 0x83, 0x92, 0x1c, 0xc4, - 0x57, 0xce, 0xd6, 0x28, 0x86, 0x42, 0x2e, 0xeb, 0xa9, 0x50, 0x68, 0xf5, 0x48, 0x15, 0x0a, 0xbd, - 0x72, 0x08, 0x5b, 0x00, 0x44, 0x12, 0x1c, 0xfc, 0xb2, 0xbc, 0x8f, 0x94, 0xae, 0x58, 0xde, 0xce, - 0x36, 0x8c, 0x96, 0x70, 0x5c, 0x42, 0x53, 0x2d, 0x61, 0x89, 0xda, 0xa7, 0x5a, 0xc2, 0x32, 0x45, - 0x0e, 0x7e, 0x08, 0x2e, 0x26, 0xd5, 0x2c, 0xb8, 0xa3, 0xcc, 0x92, 0x64, 0xaa, 0x5d, 0xb9, 0x9a, - 0xd7, 0x3c, 0xb9, 0x39, 0xb1, 0x6a, 0xfd, 0xe6, 0x24, 0x88, 0x68, 0xfa, 0xcd, 0x49, 0x94, 0xb6, - 0x42, 0x66, 0x49, 0x6d, 0x48, 0xc5, 0x4c, 0x21, 0x7f, 0xa9, 0x98, 0xa9, 0x24, 0xa7, 0x68, 0xc8, - 0x48, 0xb3, 0xd1, 0x0f, 0x99, 0x92, 0xa5, 0xf4, 0x43, 0xa6, 0xa5, 0x20, 0x48, 0xc0, 0x85, 0x84, - 0x92, 0x02, 0xdf, 0x56, 0xfa, 0x43, 0xa2, 0x16, 0x95, 0x77, 0x72, 0x5a, 0xc7, 0xc2, 0x32, 0xa6, - 0x7f, 0x28, 0xc3, 0x32, 0x2d, 0xdf, 0x28, 0xc3, 0x52, 0x22, 0xa7, 0xc4, 0xce, 0xd0, 0x84, 0x32, - 0xa1, 0x3f, 0x43, 0xe5, 0xc2, 0x8b, 0xfe, 0x0c, 0x55, 0x48, 0x1f, 0xf0, 0x11, 0x58, 0x11, 0x2f, - 0xf3, 0xf0, 0x66, 0x66, 0x37, 0x91, 0x38, 0x52, 0x7e, 0x3b, 0x9f, 0x71, 0x32, 0x61, 0x8d, 0x5f, - 0xac, 0xf5, 0x09, 0xab, 0x44, 0x45, 0xd0, 0x27, 0xac, 0xb2, 0x3b, 0x7b, 0x78, 0x87, 0x8b, 0x5d, - 0x6b, 0x55, 0x77, 0xb8, 0xf4, 0x95, 0x5e, 0x75, 0x87, 0x93, 0xdc, 0x91, 0xc3, 0x31, 0x62, 0xd7, - 0x48, 0xd5, 0x18, 0xe9, 0x2b, 0xb4, 0x6a, 0x0c, 0xc9, 0x9d, 0xb4, 0x3c, 0xf7, 0xd1, 0xa7, 0x8f, - 0x6f, 0x18, 0xfb, 0xdf, 0x78, 0xfa, 0x62, 0xc3, 0x78, 0xf6, 0x62, 0xc3, 0xf8, 0xe7, 0x8b, 0x0d, - 0xe3, 0xa7, 0x2f, 0x37, 0xce, 0x3d, 0x7b, 0xb9, 0x71, 0xee, 0x1f, 0x2f, 0x37, 0xce, 0x7d, 0x77, - 0x33, 0xf6, 0x4b, 0xcd, 0xc4, 0x8f, 0x99, 0xe9, 0xef, 0x33, 0xdb, 0x45, 0xfa, 0x53, 0xe6, 0xdb, - 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x9c, 0xfd, 0xc0, 0xc4, 0x2d, 0x00, 0x00, + 0xf9, 0x4e, 0x7b, 0xc6, 0x13, 0xbb, 0xfc, 0x11, 0xa7, 0x7e, 0x4e, 0x32, 0x9e, 0x5d, 0xdb, 0xd9, + 0xc9, 0x0f, 0x91, 0x4d, 0xd6, 0x33, 0xb1, 0x03, 0x2c, 0x44, 0x8a, 0x56, 0x76, 0xc2, 0x8a, 0xac, + 0x34, 0xbb, 0xd1, 0x98, 0x18, 0x09, 0x09, 0x8d, 0x6a, 0xa6, 0x6b, 0xc7, 0x4d, 0xa6, 0xab, 0x67, + 0xfb, 0x63, 0x66, 0x7c, 0x40, 0x5a, 0x81, 0x38, 0x70, 0x03, 0xc1, 0x01, 0x0e, 0x5c, 0x11, 0x07, + 0x0e, 0x41, 0xca, 0x05, 0x21, 0x21, 0xed, 0x05, 0x72, 0x42, 0x4b, 0x2e, 0x20, 0x0e, 0x2b, 0x94, + 0x1c, 0xf6, 0x6f, 0xe0, 0x86, 0xba, 0xaa, 0x7a, 0xba, 0xba, 0xbb, 0xaa, 0xba, 0xbd, 0x90, 0x61, + 0xc3, 0xc9, 0xee, 0xaa, 0xb7, 0xaa, 0x9e, 0xa7, 0xde, 0xb7, 0xaa, 0xde, 0x7a, 0x6a, 0x40, 0x6d, + 0xe8, 0x3a, 0xa3, 0x01, 0xea, 0x7a, 0xcd, 0x11, 0x0a, 0x06, 0x7e, 0x73, 0xb4, 0xdb, 0xf4, 0x27, + 0x8d, 0xa1, 0xeb, 0xf8, 0x0e, 0x3c, 0x1f, 0xd5, 0x35, 0x68, 0x5d, 0x63, 0xb4, 0x5b, 0xdb, 0xea, + 0x39, 0x9e, 0xed, 0x78, 0xcd, 0x2e, 0x22, 0x0f, 0x9b, 0xa3, 0xdd, 0x2e, 0xf6, 0xd1, 0x2e, 0xfd, + 0x60, 0x4d, 0x84, 0x7a, 0x0f, 0x4f, 0xeb, 0x7b, 0x8e, 0x45, 0x78, 0xfd, 0x25, 0x5e, 0x6f, 0x7b, + 0xfd, 0x70, 0x28, 0xdb, 0xeb, 0xf3, 0x8a, 0x0d, 0x56, 0xd1, 0xa1, 0x5f, 0x4d, 0xf6, 0xc1, 0xab, + 0xd6, 0xfb, 0x4e, 0xdf, 0x61, 0xe5, 0xe1, 0x7f, 0xd1, 0x48, 0x59, 0xe0, 0x43, 0xe4, 0x22, 0x3b, + 0x6a, 0xb5, 0x99, 0xad, 0x67, 0x2c, 0x68, 0x75, 0xfd, 0x27, 0x65, 0x70, 0xa1, 0xe5, 0xf5, 0xef, + 0xb8, 0x18, 0xf9, 0xf8, 0x28, 0xac, 0x68, 0xe3, 0x0f, 0x02, 0xec, 0xf9, 0xb0, 0x01, 0xe6, 0x91, + 0x69, 0x5b, 0xa4, 0x6a, 0x5c, 0x36, 0xae, 0x2e, 0x1e, 0x54, 0x9f, 0x3e, 0xde, 0x59, 0xe7, 0x78, + 0xf6, 0x4d, 0xd3, 0xc5, 0x9e, 0x77, 0xe8, 0xbb, 0x16, 0xe9, 0xb7, 0x99, 0x19, 0xdc, 0x06, 0x4b, + 0xde, 0x31, 0x72, 0x71, 0xc7, 0xc4, 0xc4, 0xb1, 0xab, 0x73, 0x61, 0xab, 0x36, 0xa0, 0x45, 0x77, + 0xc3, 0x12, 0xf8, 0x3a, 0x58, 0x0b, 0x88, 0x89, 0xdd, 0xc1, 0x89, 0x45, 0xfa, 0x1d, 0xe4, 0x79, + 0xd8, 0xaf, 0x96, 0xa8, 0xd5, 0xb9, 0xb8, 0x7c, 0x3f, 0x2c, 0x86, 0x5f, 0x05, 0xd5, 0xb1, 0xe5, + 0x1f, 0x9b, 0x2e, 0x1a, 0xa3, 0x41, 0xc7, 0xc4, 0x03, 0x74, 0xd2, 0xf1, 0x70, 0xcf, 0x21, 0xa6, + 0x57, 0x9d, 0xbf, 0x6c, 0x5c, 0x2d, 0xb7, 0x2f, 0xc6, 0xf5, 0x77, 0xc3, 0xea, 0x43, 0x56, 0x0b, + 0xdf, 0x02, 0xe7, 0x6d, 0x8b, 0x74, 0xbc, 0x31, 0x1a, 0x76, 0x2c, 0xd2, 0x19, 0xa1, 0x41, 0x80, + 0xab, 0x15, 0xca, 0x60, 0xfd, 0xe9, 0xe3, 0x9d, 0x35, 0xce, 0xe0, 0x1e, 0xf1, 0x39, 0xfa, 0x55, + 0xdb, 0x22, 0x87, 0x63, 0x34, 0xbc, 0x47, 0x8e, 0x42, 0x5b, 0xb8, 0x0f, 0xe0, 0xb4, 0x03, 0x27, + 0xf0, 0x79, 0x0f, 0x67, 0x35, 0x3d, 0x9c, 0xe3, 0x3d, 0xbc, 0x17, 0xf8, 0xac, 0x8b, 0x10, 0x03, + 0x9a, 0xa4, 0x30, 0x2c, 0x68, 0x31, 0xa0, 0x49, 0x1a, 0x43, 0xd4, 0x41, 0x8c, 0x61, 0x51, 0x8b, + 0x81, 0xf5, 0x10, 0x61, 0xb8, 0x05, 0xbe, 0xff, 0xe9, 0xa3, 0x6b, 0xcc, 0x33, 0xef, 0x94, 0x17, + 0xca, 0x6b, 0xf3, 0xef, 0x94, 0x17, 0xc0, 0xda, 0x52, 0x7b, 0x65, 0x88, 0x4e, 0x6c, 0x4c, 0x7c, + 0xe6, 0xa5, 0xf6, 0xff, 0x59, 0xc4, 0xf2, 0x2d, 0x34, 0xe8, 0x44, 0xc5, 0x04, 0x8d, 0xea, 0xb7, + 0xc1, 0xc5, 0x74, 0x48, 0x78, 0x43, 0x87, 0x78, 0x18, 0x5e, 0x01, 0x2b, 0x34, 0x78, 0x3a, 0x88, + 0x45, 0x00, 0x8b, 0x8d, 0xf6, 0x32, 0x2d, 0xe4, 0x51, 0x51, 0xff, 0xa7, 0x01, 0xb6, 0x5b, 0x5e, + 0xff, 0x10, 0xfb, 0x87, 0x53, 0xe7, 0xb7, 0xb0, 0x8f, 0x4c, 0xe4, 0xa3, 0x28, 0xb8, 0x02, 0xb0, + 0x60, 0xf3, 0x22, 0xda, 0xc7, 0xd2, 0xde, 0x66, 0x83, 0x93, 0xa2, 0xab, 0x88, 0x2f, 0x99, 0x46, + 0xd4, 0xee, 0xe0, 0xd6, 0x93, 0x4f, 0xb6, 0xcf, 0xfc, 0xfd, 0x93, 0xed, 0xbd, 0xbe, 0xe5, 0x1f, + 0x07, 0xdd, 0x46, 0xcf, 0xb1, 0xf9, 0xea, 0xe0, 0x7f, 0x76, 0x3c, 0xf3, 0x61, 0x73, 0xc2, 0x16, + 0xa4, 0x7f, 0x32, 0xc4, 0xde, 0xb4, 0x6d, 0x7b, 0x3a, 0x54, 0x1c, 0xd3, 0x73, 0xc5, 0x62, 0x3a, + 0xc3, 0xb7, 0x94, 0xe5, 0x2b, 0x4e, 0x75, 0xbd, 0x0e, 0x2e, 0xab, 0xa9, 0xb3, 0x49, 0xac, 0xff, + 0xc6, 0x00, 0x6b, 0xa1, 0x11, 0x75, 0xb8, 0xb0, 0xda, 0x9c, 0x31, 0xc1, 0x6e, 0xfe, 0x6a, 0xa3, + 0x66, 0x59, 0x64, 0x73, 0x59, 0x64, 0xf0, 0x4d, 0x50, 0xa1, 0xcb, 0x8c, 0xe1, 0x5e, 0xda, 0xdb, + 0x88, 0xe7, 0xd8, 0xc3, 0xd3, 0x39, 0xbe, 0xe3, 0x58, 0xe4, 0xa0, 0x1c, 0xce, 0x6f, 0x9b, 0x9b, + 0x73, 0x4a, 0x74, 0xa4, 0xfa, 0x77, 0xc0, 0x79, 0x01, 0x2d, 0x0f, 0x84, 0x6f, 0x80, 0x73, 0x74, + 0x65, 0x7b, 0x1d, 0x17, 0xf7, 0xb0, 0x35, 0xc2, 0x26, 0x77, 0x63, 0xee, 0x10, 0xab, 0xac, 0x5d, + 0x9b, 0x37, 0xab, 0x7f, 0x64, 0x4c, 0xfb, 0x7f, 0x2f, 0xf0, 0x3f, 0xf7, 0xd3, 0xc1, 0x16, 0x53, + 0x7b, 0xd9, 0xc5, 0x26, 0xc6, 0x36, 0x5b, 0x45, 0xf5, 0x9b, 0x00, 0x8a, 0x14, 0xf8, 0x1c, 0x6d, + 0x02, 0xe0, 0x32, 0x3a, 0x1d, 0x8b, 0x4d, 0x4f, 0xb9, 0xbd, 0xc8, 0x4b, 0xee, 0x99, 0xf5, 0x5f, + 0xb2, 0x65, 0xf2, 0x60, 0x68, 0x22, 0x1f, 0xb7, 0x2c, 0x72, 0x8f, 0xf8, 0xd8, 0xc5, 0x9e, 0xdf, + 0x46, 0x3e, 0xfe, 0xac, 0x7b, 0x70, 0xa1, 0x69, 0xd8, 0x00, 0x0b, 0xe1, 0x0e, 0xe7, 0x22, 0x1f, + 0xf3, 0x78, 0x3e, 0x6b, 0x5b, 0x24, 0x1c, 0x56, 0x12, 0xca, 0x0a, 0x78, 0x3c, 0x94, 0x93, 0x1c, + 0xd0, 0x64, 0xa6, 0x1c, 0xd0, 0x24, 0xc9, 0x01, 0x4d, 0xf4, 0x1c, 0xd2, 0xf0, 0x38, 0x87, 0x5f, + 0x19, 0xe0, 0xd5, 0xa9, 0x91, 0x8c, 0xc0, 0x57, 0xc0, 0x22, 0x0a, 0xfc, 0x63, 0xc7, 0xb5, 0xfc, + 0x93, 0x5c, 0x12, 0xb1, 0x69, 0x61, 0x22, 0x04, 0x8f, 0x13, 0x44, 0x08, 0x1e, 0x53, 0x22, 0xab, + 0x21, 0x91, 0xb8, 0xbf, 0xfa, 0x36, 0xd8, 0x54, 0xe0, 0xe4, 0x4c, 0x9e, 0x88, 0xde, 0xf8, 0x56, + 0xf2, 0x7c, 0x9c, 0x09, 0x19, 0xdd, 0xb1, 0x5d, 0xd2, 0x1d, 0xdb, 0x19, 0xae, 0xa2, 0xe3, 0x32, + 0x4c, 0x38, 0xdd, 0x3f, 0x1b, 0x60, 0x4b, 0x8c, 0x50, 0xe1, 0x04, 0x9d, 0x09, 0x5b, 0x69, 0xaa, + 0x51, 0x2a, 0x9e, 0x6a, 0x64, 0x48, 0xbf, 0x96, 0xdc, 0x10, 0x12, 0x7c, 0x38, 0xe7, 0xbf, 0x18, + 0x59, 0x9b, 0xe8, 0xcc, 0x9f, 0x09, 0x69, 0x79, 0x7a, 0x54, 0x3a, 0x45, 0x7a, 0xa4, 0xf5, 0x75, + 0x86, 0x92, 0xd4, 0xd7, 0x89, 0x6c, 0x69, 0x66, 0xbe, 0xce, 0xa4, 0x74, 0xa5, 0xe2, 0x29, 0x9d, + 0xde, 0xd7, 0x29, 0x3e, 0x52, 0x5f, 0x27, 0xf3, 0xbb, 0x99, 0xf9, 0x3a, 0x9b, 0x86, 0x96, 0x4e, + 0x93, 0x86, 0x6a, 0x7d, 0x9d, 0xa6, 0xc4, 0x79, 0xff, 0xd4, 0xa0, 0xf9, 0xe7, 0x37, 0x9d, 0x7e, + 0x7f, 0x80, 0x33, 0x59, 0xd2, 0x7f, 0xfe, 0x2c, 0xa9, 0x82, 0xb3, 0x98, 0xa0, 0xee, 0x00, 0x9b, + 0x94, 0xdb, 0x42, 0x3b, 0xfa, 0x4c, 0x1c, 0x25, 0x1b, 0xe0, 0x52, 0x06, 0x14, 0x07, 0xfc, 0x33, + 0x23, 0x55, 0x97, 0x4c, 0x64, 0xfe, 0x5b, 0x88, 0x6b, 0xa0, 0x9a, 0x45, 0xc5, 0x21, 0xff, 0x91, + 0xad, 0xa7, 0xbb, 0x78, 0xe8, 0x78, 0x96, 0x1f, 0x9d, 0x26, 0x6f, 0x07, 0xc4, 0xf4, 0x66, 0x12, + 0x5a, 0x61, 0x2a, 0x66, 0x3b, 0x01, 0xf1, 0x8b, 0xa7, 0x62, 0xd4, 0x5c, 0xb1, 0x8e, 0xe4, 0x3c, + 0x38, 0xd7, 0x3f, 0xb1, 0x75, 0x14, 0x1d, 0x23, 0x2f, 0x31, 0x59, 0xb6, 0x7a, 0x14, 0x44, 0x92, + 0x6c, 0xf9, 0x8c, 0xdc, 0x77, 0x2d, 0xd2, 0xb3, 0x86, 0x68, 0xf0, 0xd2, 0xb2, 0x55, 0x10, 0x89, + 0x53, 0x1e, 0x71, 0x4a, 0x5e, 0x66, 0xba, 0x57, 0xc0, 0x6b, 0x1a, 0x26, 0x9c, 0xef, 0x8f, 0x18, + 0xdf, 0xaf, 0x4f, 0x86, 0xd8, 0xb4, 0x7c, 0x7c, 0x1f, 0x13, 0xd3, 0x22, 0xe9, 0xcb, 0xd3, 0x67, + 0xe5, 0x9b, 0xbc, 0xb0, 0xcc, 0xa5, 0x2e, 0x2c, 0x0a, 0xc0, 0x2a, 0x28, 0x1c, 0xf0, 0x6f, 0x0d, + 0xb0, 0xde, 0xf2, 0xfa, 0xf7, 0x51, 0xe0, 0x25, 0xe5, 0xa5, 0x17, 0xea, 0x94, 0x8b, 0xa0, 0xe2, + 0x62, 0xe4, 0x39, 0x84, 0xe7, 0xd4, 0xfc, 0x0b, 0xae, 0x83, 0xf9, 0xf7, 0x1d, 0xb7, 0x87, 0xab, + 0x65, 0xba, 0x6d, 0xb2, 0x8f, 0x0c, 0xb1, 0x4b, 0x54, 0x12, 0x13, 0x21, 0x73, 0x32, 0x3f, 0x64, + 0x27, 0xd3, 0x03, 0x32, 0x9c, 0x29, 0x9d, 0x0c, 0x40, 0x76, 0x16, 0x25, 0x61, 0x70, 0x88, 0x7f, + 0x30, 0x40, 0x8d, 0x29, 0x10, 0x07, 0xae, 0x65, 0xf6, 0x31, 0xef, 0xe2, 0x85, 0x1e, 0x47, 0x6f, + 0x81, 0xd5, 0x2e, 0x1d, 0x2c, 0x29, 0x93, 0x68, 0x7a, 0x5f, 0xe9, 0x8a, 0xe0, 0x12, 0xa7, 0xd6, + 0x26, 0x78, 0x45, 0x8a, 0x5f, 0x96, 0x1c, 0x30, 0x93, 0xcf, 0x59, 0x72, 0x10, 0x81, 0xe2, 0x80, + 0x7f, 0xc7, 0x1c, 0xc2, 0x4a, 0x5b, 0x16, 0x61, 0xca, 0xd0, 0xd4, 0x21, 0x37, 0x40, 0x85, 0xcd, + 0x45, 0x2e, 0x6a, 0x6e, 0x57, 0x78, 0x57, 0x62, 0x3a, 0x4b, 0xe1, 0x5d, 0x89, 0x99, 0xdf, 0x5a, + 0x0a, 0x59, 0xf1, 0xa1, 0xb8, 0x2f, 0xb2, 0xd0, 0x65, 0xd4, 0x0e, 0x02, 0x97, 0xbc, 0xa4, 0xd4, + 0x44, 0xe8, 0x9c, 0xda, 0xef, 0x0d, 0xb0, 0xc1, 0xc2, 0x90, 0x0a, 0xd2, 0x2d, 0x44, 0x50, 0x1f, + 0xbb, 0x2f, 0x34, 0xd2, 0x6e, 0x83, 0x15, 0x2a, 0x37, 0x75, 0x6c, 0x36, 0x58, 0xee, 0x22, 0x5a, + 0x46, 0x02, 0xb4, 0x44, 0x38, 0xbe, 0x1a, 0xed, 0x01, 0x49, 0xf0, 0x9c, 0xdb, 0x2f, 0xf8, 0x2e, + 0x46, 0x93, 0xf0, 0xfb, 0xf4, 0xad, 0xe0, 0xdf, 0xdd, 0xc5, 0xde, 0x04, 0x15, 0xf6, 0xe8, 0x40, + 0x99, 0x85, 0x3e, 0xc9, 0x3c, 0x99, 0x34, 0xd8, 0x48, 0x91, 0x4f, 0x98, 0xb9, 0x6a, 0x67, 0x4b, + 0x40, 0xe3, 0xb0, 0x1f, 0x89, 0xd7, 0x21, 0xba, 0xe9, 0xed, 0x3f, 0x68, 0xbd, 0x8d, 0xf1, 0x81, + 0x35, 0x9c, 0xcd, 0x49, 0x7f, 0x19, 0x2c, 0xa3, 0xc0, 0xee, 0xbc, 0x8f, 0x71, 0xa7, 0x6b, 0x0d, + 0x59, 0xf8, 0xad, 0xb4, 0x01, 0x0a, 0x6c, 0x8e, 0x42, 0x7b, 0xdb, 0xc9, 0x20, 0xe6, 0xb4, 0x7e, + 0x3d, 0x47, 0xd3, 0x74, 0xc1, 0xe8, 0xdd, 0xfd, 0x23, 0x61, 0x09, 0x79, 0x56, 0xbf, 0x88, 0x0e, + 0xca, 0xed, 0x8a, 0x31, 0x59, 0x07, 0xf3, 0xec, 0x91, 0x86, 0x9d, 0x8e, 0xec, 0x03, 0x7e, 0x19, + 0xcc, 0x0f, 0x5d, 0x8b, 0x1f, 0x8e, 0x05, 0xd6, 0x15, 0xb3, 0x86, 0x77, 0x40, 0x65, 0xe4, 0x0c, + 0x02, 0x1b, 0xd3, 0x97, 0x99, 0xc5, 0x83, 0xeb, 0x5c, 0xa9, 0xbf, 0xc0, 0x9a, 0x7b, 0xe6, 0xc3, + 0x86, 0xe5, 0x34, 0x6d, 0xe4, 0x1f, 0x87, 0x17, 0xc5, 0xa7, 0x8f, 0x77, 0x40, 0x7c, 0x6d, 0x6c, + 0xf3, 0xa6, 0xe1, 0x81, 0xed, 0x39, 0x41, 0x78, 0x32, 0x57, 0xd8, 0x81, 0xcd, 0xbe, 0xf8, 0x9a, + 0x65, 0xdc, 0xea, 0xaf, 0xd0, 0x35, 0x99, 0x9e, 0x29, 0x3e, 0x8f, 0x1f, 0x89, 0x32, 0xde, 0xbb, + 0xfb, 0x47, 0xfb, 0x91, 0x17, 0x5e, 0xf0, 0x5c, 0xde, 0x06, 0x2b, 0x04, 0x8f, 0x3b, 0x71, 0xd8, + 0xe5, 0x2e, 0x5b, 0x82, 0xc7, 0x53, 0x70, 0x49, 0x82, 0xa2, 0xc2, 0x97, 0xa4, 0xc0, 0x49, 0xfe, + 0xd5, 0xa0, 0xa9, 0xc9, 0x7e, 0xaf, 0x87, 0x87, 0x6c, 0x71, 0xcf, 0x24, 0xf2, 0x6f, 0x4c, 0xbd, + 0x53, 0xca, 0x9d, 0x3a, 0x6a, 0x07, 0xb7, 0xc1, 0x12, 0x9e, 0xf8, 0xd8, 0x25, 0x68, 0x10, 0xe6, + 0x92, 0x65, 0xf6, 0x18, 0x18, 0x15, 0x49, 0x92, 0xc9, 0x2a, 0xdd, 0x93, 0x12, 0xc4, 0x92, 0x9c, + 0xdb, 0xf8, 0xbb, 0xb8, 0xf7, 0xbf, 0xc8, 0x39, 0x41, 0x8c, 0x71, 0xde, 0xfb, 0xf9, 0x26, 0x28, + 0xb5, 0xbc, 0x3e, 0xec, 0x82, 0x25, 0xe1, 0x19, 0x0e, 0x5e, 0x95, 0x6c, 0xab, 0xd2, 0xc7, 0xdb, + 0xda, 0xeb, 0x05, 0x2c, 0xf9, 0x33, 0xc5, 0x87, 0x06, 0xb8, 0x20, 0x7d, 0xb0, 0x82, 0x7b, 0xf2, + 0x4e, 0x74, 0x0f, 0x7b, 0xb5, 0x9b, 0xa7, 0x6a, 0xc3, 0x21, 0x1c, 0x82, 0x0a, 0x93, 0x54, 0xe0, + 0x15, 0x45, 0x73, 0x51, 0x05, 0xaa, 0xfd, 0xbf, 0xde, 0x88, 0x77, 0x7a, 0x04, 0xce, 0xf2, 0xcb, + 0x08, 0xd4, 0x34, 0x88, 0xaf, 0x4d, 0xb5, 0x2f, 0xe4, 0x58, 0x09, 0xf3, 0x25, 0x7d, 0x15, 0x51, + 0xcd, 0x97, 0xee, 0x85, 0x47, 0x35, 0x5f, 0xda, 0x67, 0x17, 0x11, 0x42, 0xf2, 0x51, 0x23, 0x07, + 0x82, 0xf4, 0x81, 0x26, 0x07, 0x82, 0xfc, 0xd5, 0x04, 0x8e, 0x01, 0xcc, 0xbe, 0x44, 0xc0, 0xa6, + 0xae, 0x2b, 0xd9, 0xd8, 0x37, 0x8a, 0x37, 0xc8, 0x70, 0x4f, 0xbd, 0x0b, 0xe8, 0xb9, 0xcb, 0x9f, + 0x43, 0xf4, 0xdc, 0x15, 0x0f, 0x0f, 0xf0, 0x7b, 0x60, 0x5d, 0x26, 0xd2, 0xc3, 0xdd, 0x1c, 0x5f, + 0x66, 0x45, 0xeb, 0xda, 0xde, 0x69, 0x9a, 0xc8, 0x02, 0x30, 0xf1, 0xc3, 0x83, 0x22, 0xbd, 0xa5, + 0x14, 0xe4, 0xdc, 0x00, 0x94, 0x49, 0xb4, 0xc2, 0x0c, 0x24, 0x7f, 0xb8, 0xb0, 0x9b, 0x13, 0x4a, + 0xa7, 0x9e, 0x01, 0xa9, 0x32, 0x9e, 0x8c, 0xff, 0x53, 0xcc, 0x80, 0x54, 0x43, 0xcf, 0x8d, 0x7f, + 0xe9, 0x0c, 0x60, 0xb0, 0x2c, 0x6a, 0xc1, 0x50, 0xb1, 0xe1, 0x4a, 0x44, 0xec, 0xda, 0xb5, 0x22, + 0xa6, 0x7c, 0x98, 0x63, 0xb0, 0x92, 0x10, 0x70, 0x61, 0x6e, 0x63, 0x61, 0x43, 0xbb, 0x5e, 0xc8, + 0x36, 0x76, 0xa9, 0x4c, 0x45, 0x55, 0xb9, 0x54, 0xa3, 0x1c, 0xab, 0x5c, 0xaa, 0x13, 0x69, 0xa9, + 0x4b, 0xa5, 0xc2, 0xa6, 0xca, 0xa5, 0x3a, 0x39, 0x57, 0xe5, 0x52, 0xad, 0x72, 0x4a, 0x21, 0x48, + 0xd5, 0x46, 0xa8, 0x27, 0x24, 0x15, 0x1d, 0x55, 0x10, 0xb4, 0x72, 0x26, 0xfc, 0x81, 0x01, 0x2e, + 0xca, 0x15, 0x40, 0x98, 0x43, 0x49, 0x0e, 0xe2, 0x4b, 0xa7, 0x6b, 0x24, 0xa0, 0x90, 0xcb, 0x7a, + 0x2a, 0x14, 0x5a, 0x3d, 0x52, 0x85, 0x42, 0xaf, 0x1c, 0xc2, 0x0e, 0x00, 0xb1, 0x04, 0x07, 0xbf, + 0x28, 0xef, 0x23, 0xa3, 0x2b, 0xd6, 0xae, 0xe6, 0x1b, 0xc6, 0x4b, 0x58, 0x94, 0xd0, 0x54, 0x4b, + 0x58, 0xa2, 0xf6, 0xa9, 0x96, 0xb0, 0x4c, 0x91, 0x83, 0x1f, 0x80, 0xb5, 0xb4, 0x9a, 0x05, 0x77, + 0x94, 0x59, 0x92, 0x4c, 0xb5, 0xab, 0x35, 0x8a, 0x9a, 0xa7, 0x37, 0x27, 0x56, 0xad, 0xdf, 0x9c, + 0x12, 0x22, 0x9a, 0x7e, 0x73, 0x4a, 0x4a, 0x5b, 0x21, 0xb3, 0xb4, 0x36, 0xa4, 0x62, 0xa6, 0x90, + 0xbf, 0x54, 0xcc, 0x54, 0x92, 0x53, 0x3c, 0x64, 0xac, 0xd9, 0xe8, 0x87, 0xcc, 0xc8, 0x52, 0xfa, + 0x21, 0xb3, 0x52, 0x10, 0x24, 0xe0, 0x5c, 0x4a, 0x49, 0x81, 0x6f, 0x28, 0xfd, 0x21, 0x51, 0x8b, + 0x6a, 0x3b, 0x05, 0xad, 0x85, 0xb0, 0x14, 0xf4, 0x0f, 0x65, 0x58, 0x66, 0xe5, 0x1b, 0x65, 0x58, + 0x4a, 0xe4, 0x14, 0xe1, 0x0c, 0x4d, 0x29, 0x13, 0xfa, 0x33, 0x54, 0x2e, 0xbc, 0xe8, 0xcf, 0x50, + 0x85, 0xf4, 0x01, 0x1f, 0x82, 0xd5, 0xe4, 0x65, 0x1e, 0x5e, 0xcf, 0xed, 0x26, 0x16, 0x47, 0x6a, + 0x6f, 0x14, 0x33, 0x4e, 0x27, 0xac, 0xe2, 0xc5, 0x5a, 0x9f, 0xb0, 0x4a, 0x54, 0x04, 0x7d, 0xc2, + 0x2a, 0xbb, 0xb3, 0x87, 0x77, 0x38, 0xe1, 0x5a, 0xab, 0xba, 0xc3, 0x65, 0xaf, 0xf4, 0xaa, 0x3b, + 0x9c, 0xe4, 0x8e, 0x1c, 0x8e, 0x21, 0x5c, 0x23, 0x55, 0x63, 0x64, 0xaf, 0xd0, 0xaa, 0x31, 0x24, + 0x77, 0xd2, 0xda, 0xfc, 0x87, 0x9f, 0x3e, 0xba, 0x66, 0x1c, 0x7c, 0xed, 0xc9, 0xb3, 0x2d, 0xe3, + 0xe3, 0x67, 0x5b, 0xc6, 0x3f, 0x9e, 0x6d, 0x19, 0x3f, 0x7e, 0xbe, 0x75, 0xe6, 0xe3, 0xe7, 0x5b, + 0x67, 0xfe, 0xf6, 0x7c, 0xeb, 0xcc, 0xb7, 0xb7, 0x85, 0x9f, 0x66, 0xa6, 0x7e, 0x74, 0x4c, 0x7f, + 0x90, 0xd9, 0xad, 0xd0, 0x9f, 0x1c, 0xdf, 0xfc, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4d, 0xc5, + 0x31, 0x9d, 0x6c, 0x2d, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3723,7 +3686,7 @@ type MsgClient interface { // Must be signed by the vault admin. UpdateNAVAuthority(ctx context.Context, in *MsgUpdateNAVAuthorityRequest, opts ...grpc.CallOption) (*MsgUpdateNAVAuthorityResponse, error) // AcceptAsset settles a pending exchange-module payment whose target is the vault, - // exchanging an external asset for the vault's payment denom. + // exchanging an external asset for the vault's underlying asset. // Must be signed by the vault's asset manager; the admin cannot settle. AcceptAsset(ctx context.Context, in *MsgAcceptAssetRequest, opts ...grpc.CallOption) (*MsgAcceptAssetResponse, error) // RejectAsset declines a pending exchange-module payment whose target is the vault, @@ -4101,7 +4064,7 @@ type MsgServer interface { // Must be signed by the vault admin. UpdateNAVAuthority(context.Context, *MsgUpdateNAVAuthorityRequest) (*MsgUpdateNAVAuthorityResponse, error) // AcceptAsset settles a pending exchange-module payment whose target is the vault, - // exchanging an external asset for the vault's payment denom. + // exchanging an external asset for the vault's underlying asset. // Must be signed by the vault's asset manager; the admin cannot settle. AcceptAsset(context.Context, *MsgAcceptAssetRequest) (*MsgAcceptAssetResponse, error) // RejectAsset declines a pending exchange-module payment whose target is the vault, @@ -4949,18 +4912,6 @@ func (m *MsgCreateVaultRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.InitialPaymentNav != nil { - { - size, err := m.InitialPaymentNav.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x52 - } if len(m.MaxSwapOutValue) > 0 { i -= len(m.MaxSwapOutValue) copy(dAtA[i:], m.MaxSwapOutValue) @@ -4994,13 +4945,6 @@ func (m *MsgCreateVaultRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x28 } - if len(m.PaymentDenom) > 0 { - i -= len(m.PaymentDenom) - copy(dAtA[i:], m.PaymentDenom) - i = encodeVarintTx(dAtA, i, uint64(len(m.PaymentDenom))) - i-- - dAtA[i] = 0x22 - } if len(m.UnderlyingAsset) > 0 { i -= len(m.UnderlyingAsset) copy(dAtA[i:], m.UnderlyingAsset) @@ -5225,13 +5169,6 @@ func (m *MsgSwapOutRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.RedeemDenom) > 0 { - i -= len(m.RedeemDenom) - copy(dAtA[i:], m.RedeemDenom) - i = encodeVarintTx(dAtA, i, uint64(len(m.RedeemDenom))) - i-- - dAtA[i] = 0x22 - } { size, err := m.Assets.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -7246,10 +7183,6 @@ func (m *MsgCreateVaultRequest) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - l = len(m.PaymentDenom) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } if m.WithdrawalDelaySeconds != 0 { n += 1 + sovTx(uint64(m.WithdrawalDelaySeconds)) } @@ -7269,10 +7202,6 @@ func (m *MsgCreateVaultRequest) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if m.InitialPaymentNav != nil { - l = m.InitialPaymentNav.Size() - n += 1 + l + sovTx(uint64(l)) - } return n } @@ -7363,10 +7292,6 @@ func (m *MsgSwapOutRequest) Size() (n int) { } l = m.Assets.Size() n += 1 + l + sovTx(uint64(l)) - l = len(m.RedeemDenom) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } return n } @@ -8340,38 +8265,6 @@ func (m *MsgCreateVaultRequest) Unmarshal(dAtA []byte) error { } m.UnderlyingAsset = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PaymentDenom", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.PaymentDenom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex case 5: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field WithdrawalDelaySeconds", wireType) @@ -8519,42 +8412,6 @@ func (m *MsgCreateVaultRequest) Unmarshal(dAtA []byte) error { } m.MaxSwapOutValue = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 10: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field InitialPaymentNav", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.InitialPaymentNav == nil { - m.InitialPaymentNav = &InitialVaultNAV{} - } - if err := m.InitialPaymentNav.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) @@ -9211,38 +9068,6 @@ func (m *MsgSwapOutRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RedeemDenom", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.RedeemDenom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/types/vault.go b/types/vault.go index 9e82a410..7d8030f5 100644 --- a/types/vault.go +++ b/types/vault.go @@ -70,9 +70,6 @@ type VaultAccountI interface { // GetUnderlyingAsset returns the denom of the asset the vault actually holds. GetUnderlyingAsset() string - // GetPaymentDenom returns the denom used for fees/interest payments, if any. - GetPaymentDenom() string - // GetWithdrawalDelaySeconds returns the number of seconds that // withdrawals from this vault are delayed after a swap-out request. // A value of 0 means withdrawals are processed immediately in the end blocker. @@ -88,7 +85,10 @@ type VaultAccountI interface { GetPausedBalance() sdk.Coin } -// NewVaultAccount creates a new vault with an optional payment denom allowed for I/O alongside the underlying asset. +// NewVaultAccount creates a new single-denom vault: the underlying asset is the only +// denom accepted for deposits, redemptions, fees, and interest. The deprecated +// payment_denom field is populated with the underlying asset purely for wire +// compatibility; it carries no independent meaning. // // The vault's operational limits are configured via: // - withdrawalDelay: minimum seconds a swap-out must wait in queue. @@ -100,17 +100,14 @@ type VaultAccountI interface { // by validation (administrators should use Toggle messages to disable operations instead). // // All swap limit values are represented as integer strings (cosmos.IntString). -func NewVaultAccount(baseAcc *authtypes.BaseAccount, admin, shareDenom, underlyingAsset, paymentDenom string, withdrawalDelay uint64, aumFeeBips uint32, minSwapInValue, minSwapOutValue, maxSwapInValue, maxSwapOutValue string) *VaultAccount { - if paymentDenom == "" { - paymentDenom = underlyingAsset - } +func NewVaultAccount(baseAcc *authtypes.BaseAccount, admin, shareDenom, underlyingAsset string, withdrawalDelay uint64, aumFeeBips uint32, minSwapInValue, minSwapOutValue, maxSwapInValue, maxSwapOutValue string) *VaultAccount { return &VaultAccount{ BaseAccount: baseAcc, Admin: admin, NavAuthority: admin, TotalShares: sdk.Coin{Denom: shareDenom, Amount: sdkmath.ZeroInt()}, UnderlyingAsset: underlyingAsset, - PaymentDenom: paymentDenom, + PaymentDenom: underlyingAsset, CurrentInterestRate: ZeroInterestRate, DesiredInterestRate: ZeroInterestRate, SwapInEnabled: true, @@ -120,7 +117,7 @@ func NewVaultAccount(baseAcc *authtypes.BaseAccount, admin, shareDenom, underlyi PausedBalance: sdk.Coin{}, BridgeEnabled: false, BridgeAddress: "", - OutstandingAumFee: sdk.NewCoin(paymentDenom, sdkmath.ZeroInt()), + OutstandingAumFee: sdk.NewCoin(underlyingAsset, sdkmath.ZeroInt()), AumFeeBips: aumFeeBips, MinSwapInValue: minSwapInValue, MinSwapOutValue: minSwapOutValue, @@ -195,8 +192,8 @@ func (v VaultAccount) Validate() error { return fmt.Errorf("invalid underlying asset denom: %s", v.UnderlyingAsset) } - if err := sdk.ValidateDenom(v.PaymentDenom); err != nil { - return fmt.Errorf("invalid payment denom: %q: %w", v.PaymentDenom, err) + if v.PaymentDenom != "" && v.PaymentDenom != v.UnderlyingAsset { + return fmt.Errorf("payment denom %q must be empty or equal underlying asset %q; vaults are single-denom", v.PaymentDenom, v.UnderlyingAsset) } if v.AssetManager != "" { @@ -288,11 +285,14 @@ func (v VaultAccount) Validate() error { return fmt.Errorf("AUM fee bips cannot exceed 10,000: %d", v.AumFeeBips) } - if !v.OutstandingAumFee.Amount.IsNil() && v.OutstandingAumFee.IsNegative() { + if v.OutstandingAumFee.Amount.IsNil() { + return fmt.Errorf("outstanding AUM fee amount cannot be nil; use a zero coin of the underlying asset %q", v.UnderlyingAsset) + } + if v.OutstandingAumFee.IsNegative() { return fmt.Errorf("outstanding AUM fee cannot be negative: %s", v.OutstandingAumFee) } - if (v.OutstandingAumFee.Denom != "" || (!v.OutstandingAumFee.Amount.IsNil() && !v.OutstandingAumFee.Amount.IsZero())) && v.OutstandingAumFee.Denom != v.PaymentDenom { - return fmt.Errorf("outstanding AUM fee denom %s does not match payment denom %s", v.OutstandingAumFee.Denom, v.PaymentDenom) + if (v.OutstandingAumFee.Denom != "" || !v.OutstandingAumFee.Amount.IsZero()) && v.OutstandingAumFee.Denom != v.UnderlyingAsset { + return fmt.Errorf("outstanding AUM fee denom %s does not match underlying asset %s", v.OutstandingAumFee.Denom, v.UnderlyingAsset) } if err := ValidateSwapLimits(v.MinSwapInValue, v.MaxSwapInValue); err != nil { @@ -364,37 +364,18 @@ func (v *VaultAccount) ValidateNAVAuthority(signer string) error { return nil } -func (v *VaultAccount) ValuationDenom() string { - return v.UnderlyingAsset -} - -// AcceptedDenoms returns the list of coin denoms accepted for I/O. -// Always includes the underlying asset; includes payment_denom only if set and distinct. -func (v *VaultAccount) AcceptedDenoms() []string { - if v.PaymentDenom != "" && v.PaymentDenom != v.UnderlyingAsset { - return []string{v.UnderlyingAsset, v.PaymentDenom} - } - return []string{v.UnderlyingAsset} -} - -// IsAcceptedDenom reports whether denom is allowed by the vault configuration. +// IsAcceptedDenom reports whether denom is allowed for vault I/O. Vaults are +// single-denom: only the underlying asset is accepted. func (v *VaultAccount) IsAcceptedDenom(denom string) bool { - if denom == v.UnderlyingAsset { - return true - } - return v.PaymentDenom != "" && denom == v.PaymentDenom + return denom == v.UnderlyingAsset } -// ValidateAcceptedDenom returns an error if denom is not supported by the vault. +// ValidateAcceptedDenom returns an error if denom is not the vault's underlying asset. func (v *VaultAccount) ValidateAcceptedDenom(denom string) error { if v.IsAcceptedDenom(denom) { return nil } - allowed := v.AcceptedDenoms() - if len(allowed) == 1 { - return fmt.Errorf(`denom not supported for vault; must be "%s": got "%s"`, allowed[0], denom) - } - return fmt.Errorf(`denom not supported for vault; must be one of "%s" or "%s": got "%s"`, allowed[0], allowed[1], denom) + return fmt.Errorf(`denom not supported for vault; must be "%s": got "%s"`, v.UnderlyingAsset, denom) } // ValidateAcceptedCoin returns an error if the coin amount is zero or its denom is not supported. diff --git a/types/vault.pb.go b/types/vault.pb.go index a0432719..6964a425 100644 --- a/types/vault.pb.go +++ b/types/vault.pb.go @@ -44,19 +44,15 @@ type VaultAccount struct { // underlying_asset is the vault’s single principal collateral AND valuation/base unit. // - Exactly one denom. // - Total Vault Value (TVV) and NAV-per-share are computed and reported in this denom. - // - Interest accrual and internal accounting are measured in this denom. - // - Any other coin accepted for I/O (i.e. a distinct payment_denom) must have a NAV record priced INTO this denom. + // - Interest accrual, fees, and internal accounting are measured in this denom. + // - Held assets acquired via settlement must have an internal NAV record priced INTO this denom. UnderlyingAsset string `protobuf:"bytes,3,opt,name=underlying_asset,json=underlyingAsset,proto3" json:"underlying_asset,omitempty"` - // payment_denom is the external payment coin supported for user I/O alongside the underlying_asset. - // - Always populated. If not specified during creation, it defaults to underlying_asset. - // - If payment_denom equals underlying_asset, the vault operates as a single-denom vault. - // - If payment_denom differs from underlying_asset, swap-in/out accept either denom (one per call). - // - Default Swap-Out: If a user does not specify a redeem_denom during withdrawal, - // the vault defaults to paying out in this payment_denom. - // - NAV Requirement: If payment_denom differs from underlying_asset, it requires an on-chain NAV record - // mapping payment_denom -> underlying_asset to value deposits and redemptions. - // (Note: In current versions, this NAV check is strictly enforced unless payment_denom is 'uylds.fcc'). - PaymentDenom string `protobuf:"bytes,4,opt,name=payment_denom,json=paymentDenom,proto3" json:"payment_denom,omitempty"` + // payment_denom always equals underlying_asset. Vaults are single-denom; the + // field is inert and retained only for wire compatibility. + // + // Deprecated: The mixed-denom vault concept has been flattened into a single + // underlying denom. Deletion of this field is deferred to a future major release. + PaymentDenom string `protobuf:"bytes,4,opt,name=payment_denom,json=paymentDenom,proto3" json:"payment_denom,omitempty"` // Deprecated: Do not use. // admin is the address that has administrative privileges over the vault. Admin string `protobuf:"bytes,5,opt,name=admin,proto3" json:"admin,omitempty"` // current_interest_rate is a decimal string (e.g., "0.9" for 90% and "0.9001353" for 90.01353%) representing the actual annual interest rate currently being applied. @@ -108,7 +104,7 @@ type VaultAccount struct { FeePeriodTimeout int64 `protobuf:"varint,22,opt,name=fee_period_timeout,json=feePeriodTimeout,proto3" json:"fee_period_timeout,omitempty"` // outstanding_aum_fee is the amount of AUM fee that has been calculated but not yet collected // due to insufficient liquidity in the principal marker. This amount is always denominated - // in the vault's payment_denom, must be preserved, and is carried into valuation computations. + // in the vault's underlying_asset, must be preserved, and is carried into valuation computations. OutstandingAumFee types1.Coin `protobuf:"bytes,23,opt,name=outstanding_aum_fee,json=outstandingAumFee,proto3" json:"outstanding_aum_fee"` // aum_fee_bips is the AUM fee rate (in basis points) for this specific vault. // Units: Basis Points (1 bps = 0.01%). @@ -118,7 +114,6 @@ type VaultAccount struct { AumFeeBips uint32 `protobuf:"varint,24,opt,name=aum_fee_bips,json=aumFeeBips,proto3" json:"aum_fee_bips,omitempty"` // min_swap_in_value is a string representing the minimum value required for a deposit. // - The value is measured in the underlying_asset. - // - Incoming payment_denom deposits are converted to this unit before checking. // - Values must be non-negative (>= 0). // - If empty ("") or "0", there is no minimum limit. MinSwapInValue string `protobuf:"bytes,25,opt,name=min_swap_in_value,json=minSwapInValue,proto3" json:"min_swap_in_value,omitempty"` @@ -130,7 +125,6 @@ type VaultAccount struct { MinSwapOutValue string `protobuf:"bytes,26,opt,name=min_swap_out_value,json=minSwapOutValue,proto3" json:"min_swap_out_value,omitempty"` // max_swap_in_value is a string representing the maximum value allowed for a deposit. // - The value is measured in the underlying_asset. - // - Incoming payment_denom deposits are converted to this unit before checking. // - Values must be positive (> 0). // - An empty string "" indicates no maximum limit. MaxSwapInValue string `protobuf:"bytes,27,opt,name=max_swap_in_value,json=maxSwapInValue,proto3" json:"max_swap_in_value,omitempty"` @@ -193,6 +187,7 @@ func (m *VaultAccount) GetUnderlyingAsset() string { return "" } +// Deprecated: Do not use. func (m *VaultAccount) GetPaymentDenom() string { if m != nil { return m.PaymentDenom @@ -464,70 +459,6 @@ func (m *VaultNAV) GetUpdatedTime() time.Time { return time.Time{} } -// InitialVaultNAV seeds a per-vault Internal NAV entry at vault creation time. -// It is the stateless subset of VaultNAV (no updated_block_height or -// updated_time, which are stamped by the keeper when the entry is persisted) -// and omits the denom, which is implied by the field that carries it on the -// containing message (e.g. payment_denom on MsgCreateVaultRequest). -type InitialVaultNAV struct { - // price is the total value of `volume` units of the priced denom, denominated - // in one of the vault's accepted denoms (typically the underlying asset). - Price types1.Coin `protobuf:"bytes,1,opt,name=price,proto3" json:"price"` - // volume is the number of units of the priced denom that price covers. It - // must be positive; the per-unit value is price divided by volume. - Volume cosmossdk_io_math.Int `protobuf:"bytes,2,opt,name=volume,proto3,customtype=cosmossdk.io/math.Int" json:"volume"` - // source identifies the origin of this NAV entry (for example an oracle name - // or the settlement path). - Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` -} - -func (m *InitialVaultNAV) Reset() { *m = InitialVaultNAV{} } -func (m *InitialVaultNAV) String() string { return proto.CompactTextString(m) } -func (*InitialVaultNAV) ProtoMessage() {} -func (*InitialVaultNAV) Descriptor() ([]byte, []int) { - return fileDescriptor_2e0d78aae3177bea, []int{2} -} -func (m *InitialVaultNAV) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *InitialVaultNAV) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_InitialVaultNAV.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *InitialVaultNAV) XXX_Merge(src proto.Message) { - xxx_messageInfo_InitialVaultNAV.Merge(m, src) -} -func (m *InitialVaultNAV) XXX_Size() int { - return m.Size() -} -func (m *InitialVaultNAV) XXX_DiscardUnknown() { - xxx_messageInfo_InitialVaultNAV.DiscardUnknown(m) -} - -var xxx_messageInfo_InitialVaultNAV proto.InternalMessageInfo - -func (m *InitialVaultNAV) GetPrice() types1.Coin { - if m != nil { - return m.Price - } - return types1.Coin{} -} - -func (m *InitialVaultNAV) GetSource() string { - if m != nil { - return m.Source - } - return "" -} - // AccountBalance represents the coin balance of a single account. type AccountBalance struct { // address is the account address. @@ -540,7 +471,7 @@ func (m *AccountBalance) Reset() { *m = AccountBalance{} } func (m *AccountBalance) String() string { return proto.CompactTextString(m) } func (*AccountBalance) ProtoMessage() {} func (*AccountBalance) Descriptor() ([]byte, []int) { - return fileDescriptor_2e0d78aae3177bea, []int{3} + return fileDescriptor_2e0d78aae3177bea, []int{2} } func (m *AccountBalance) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -577,15 +508,16 @@ type PendingSwapOut struct { VaultAddress string `protobuf:"bytes,2,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` // shares are the shares that were escrowed by the user. Shares types1.Coin `protobuf:"bytes,3,opt,name=shares,proto3" json:"shares"` - // redeem_denom is the denomination of the asset to be redeemed. - RedeemDenom string `protobuf:"bytes,4,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` + // redeem_denom is the denomination of the asset to be redeemed. Always the + // vault's underlying_asset; retained for wire compatibility. + RedeemDenom string `protobuf:"bytes,4,opt,name=redeem_denom,json=redeemDenom,proto3" json:"redeem_denom,omitempty"` // Deprecated: Do not use. } func (m *PendingSwapOut) Reset() { *m = PendingSwapOut{} } func (m *PendingSwapOut) String() string { return proto.CompactTextString(m) } func (*PendingSwapOut) ProtoMessage() {} func (*PendingSwapOut) Descriptor() ([]byte, []int) { - return fileDescriptor_2e0d78aae3177bea, []int{4} + return fileDescriptor_2e0d78aae3177bea, []int{3} } func (m *PendingSwapOut) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -635,6 +567,7 @@ func (m *PendingSwapOut) GetShares() types1.Coin { return types1.Coin{} } +// Deprecated: Do not use. func (m *PendingSwapOut) GetRedeemDenom() string { if m != nil { return m.RedeemDenom @@ -645,7 +578,6 @@ func (m *PendingSwapOut) GetRedeemDenom() string { func init() { proto.RegisterType((*VaultAccount)(nil), "provlabs.vault.v1.VaultAccount") proto.RegisterType((*VaultNAV)(nil), "provlabs.vault.v1.VaultNAV") - proto.RegisterType((*InitialVaultNAV)(nil), "provlabs.vault.v1.InitialVaultNAV") proto.RegisterType((*AccountBalance)(nil), "provlabs.vault.v1.AccountBalance") proto.RegisterType((*PendingSwapOut)(nil), "provlabs.vault.v1.PendingSwapOut") } @@ -653,81 +585,79 @@ func init() { func init() { proto.RegisterFile("provlabs/vault/v1/vault.proto", fileDescriptor_2e0d78aae3177bea) } var fileDescriptor_2e0d78aae3177bea = []byte{ - // 1169 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4d, 0x6f, 0x1b, 0x45, - 0x18, 0xf6, 0xc6, 0x49, 0x9a, 0x8e, 0xbf, 0x92, 0xa9, 0x5b, 0xb6, 0x85, 0xda, 0x26, 0x08, 0x64, - 0x04, 0xb1, 0x9b, 0x22, 0xc4, 0x87, 0x54, 0x15, 0xbb, 0xa1, 0x34, 0x07, 0x48, 0xb5, 0xa9, 0x72, - 0xe0, 0xb2, 0x1a, 0xef, 0xbe, 0xb1, 0x47, 0xd9, 0x9d, 0x59, 0xed, 0xcc, 0x3a, 0xc9, 0x3f, 0xe0, - 0xd8, 0x1b, 0xd7, 0x5e, 0xb8, 0x70, 0xe1, 0x92, 0x1f, 0x51, 0x6e, 0x51, 0x4e, 0x08, 0xa4, 0x14, - 0x25, 0x17, 0x7e, 0x06, 0x9a, 0x8f, 0x75, 0x3e, 0x2a, 0x39, 0x11, 0xe2, 0x64, 0xcf, 0xf3, 0x3e, - 0xef, 0xb3, 0xef, 0xbe, 0xfb, 0xcc, 0xbc, 0x83, 0xee, 0x27, 0x29, 0x1f, 0x47, 0x64, 0x20, 0xba, - 0x63, 0x92, 0x45, 0xb2, 0x3b, 0x5e, 0x35, 0x7f, 0x3a, 0x49, 0xca, 0x25, 0xc7, 0x4b, 0x79, 0xb8, - 0x63, 0xd0, 0xf1, 0xea, 0xbd, 0x46, 0xc0, 0x45, 0xcc, 0x45, 0x97, 0x64, 0x72, 0xd4, 0x1d, 0xaf, - 0x0e, 0x40, 0x92, 0x55, 0xbd, 0x30, 0x29, 0x93, 0xf8, 0x80, 0x08, 0x98, 0xc4, 0x03, 0x4e, 0x99, - 0x8d, 0xdf, 0x35, 0x71, 0x5f, 0xaf, 0xba, 0x66, 0x61, 0x43, 0xf5, 0x21, 0x1f, 0x72, 0x83, 0xab, - 0x7f, 0x16, 0x6d, 0x0e, 0x39, 0x1f, 0x46, 0xd0, 0xd5, 0xab, 0x41, 0xb6, 0xdd, 0x95, 0x34, 0x06, - 0x21, 0x49, 0x9c, 0x18, 0xc2, 0xf2, 0xef, 0x65, 0x54, 0xde, 0x52, 0xe5, 0xf5, 0x82, 0x80, 0x67, - 0x4c, 0xe2, 0x75, 0x54, 0x56, 0x4f, 0xf7, 0x89, 0x59, 0xbb, 0x4e, 0xcb, 0x69, 0x97, 0x1e, 0xb6, - 0x3a, 0xf6, 0x61, 0xba, 0x58, 0x5b, 0x59, 0xa7, 0x4f, 0x04, 0xd8, 0xbc, 0xfe, 0xec, 0xe1, 0x71, - 0xd3, 0xf1, 0x4a, 0x83, 0x33, 0x08, 0xf7, 0x51, 0x59, 0x72, 0x49, 0x22, 0x5f, 0x8c, 0x48, 0x0a, - 0xc2, 0x9d, 0xd1, 0x52, 0x77, 0x73, 0x29, 0x45, 0x9d, 0x48, 0x3d, 0xe1, 0x94, 0xf5, 0x67, 0x5f, - 0x1f, 0x37, 0x0b, 0x5e, 0x49, 0x27, 0x6d, 0xea, 0x1c, 0xfc, 0x31, 0x5a, 0xcc, 0x58, 0x08, 0x69, - 0xb4, 0x4f, 0xd9, 0xd0, 0x27, 0x42, 0x80, 0x74, 0x8b, 0x2d, 0xa7, 0x7d, 0xd3, 0xab, 0x9d, 0xe1, - 0x3d, 0x05, 0xe3, 0x0f, 0x50, 0x25, 0x21, 0xfb, 0x31, 0x30, 0xe9, 0x87, 0xc0, 0x78, 0xec, 0xce, - 0x6a, 0x5e, 0xd9, 0x82, 0x6b, 0x0a, 0xc3, 0x1d, 0x34, 0x47, 0xc2, 0x98, 0x32, 0x77, 0x4e, 0x05, - 0xfb, 0xee, 0xd1, 0xc1, 0x4a, 0xdd, 0xd6, 0xd3, 0x0b, 0xc3, 0x14, 0x84, 0xd8, 0x94, 0x29, 0x65, - 0x43, 0xcf, 0xd0, 0xf0, 0x33, 0x74, 0x3b, 0xc8, 0xd2, 0x54, 0x89, 0x52, 0x26, 0x21, 0x05, 0x21, - 0xfd, 0x94, 0x48, 0x70, 0xe7, 0x75, 0x7e, 0xfd, 0xe8, 0x60, 0x65, 0xd1, 0xe6, 0xaf, 0x41, 0x60, - 0x73, 0x6f, 0xd9, 0x94, 0x75, 0x9b, 0xe1, 0x11, 0x09, 0x4a, 0x29, 0x04, 0x41, 0x53, 0x08, 0x2f, - 0x29, 0xdd, 0x98, 0xa6, 0x64, 0x53, 0x2e, 0x28, 0x7d, 0x83, 0x96, 0x62, 0xca, 0x2e, 0xa9, 0x2c, - 0x4c, 0x51, 0xa9, 0xc5, 0x94, 0xbd, 0xa5, 0x40, 0xf6, 0x2e, 0x29, 0xdc, 0x9c, 0xaa, 0x40, 0xf6, - 0x2e, 0x28, 0xbc, 0x8f, 0xca, 0x09, 0xa4, 0x94, 0x87, 0xbe, 0x90, 0x24, 0x95, 0x2e, 0x6a, 0x39, - 0xed, 0xa2, 0x57, 0x32, 0xd8, 0xa6, 0x82, 0xf0, 0x87, 0xa8, 0x6a, 0x29, 0xca, 0x74, 0x3c, 0x93, - 0x6e, 0x49, 0x93, 0x2a, 0x06, 0x7d, 0x61, 0x40, 0xfc, 0x11, 0xaa, 0x89, 0x5d, 0x92, 0xf8, 0x94, - 0xf9, 0xc0, 0xc8, 0x20, 0x82, 0xd0, 0x2d, 0xb7, 0x9c, 0xf6, 0x82, 0x57, 0x51, 0xf0, 0x3a, 0xfb, - 0xd6, 0x80, 0xb8, 0x8d, 0x16, 0x35, 0x8f, 0x67, 0x72, 0x42, 0xac, 0x68, 0x62, 0x55, 0xe1, 0x1b, - 0x99, 0xcc, 0x99, 0x5f, 0x22, 0x77, 0x97, 0xca, 0x51, 0x98, 0x92, 0x5d, 0x12, 0xf9, 0x21, 0x44, - 0x64, 0xdf, 0x17, 0x10, 0x70, 0x16, 0x0a, 0xb7, 0xda, 0x72, 0xda, 0xb3, 0xde, 0x9d, 0xb3, 0xf8, - 0x9a, 0x0a, 0x6f, 0x9a, 0x28, 0xbe, 0x83, 0xe6, 0x13, 0x92, 0x09, 0x08, 0xdd, 0x9a, 0x56, 0xb6, - 0x2b, 0xfc, 0x14, 0x55, 0xcd, 0x3f, 0x7f, 0x40, 0x22, 0xc2, 0x02, 0x70, 0x17, 0xaf, 0xe7, 0xe5, - 0x8a, 0x49, 0xeb, 0x9b, 0x2c, 0x63, 0x51, 0xad, 0x93, 0x02, 0x11, 0x9c, 0xb9, 0x4b, 0xb9, 0x45, - 0x15, 0xe8, 0x69, 0x0c, 0x3f, 0x46, 0xd5, 0x41, 0x4a, 0xc3, 0x21, 0xf8, 0xc4, 0x38, 0xd2, 0xc5, - 0x57, 0x78, 0xb5, 0x62, 0xf8, 0x16, 0x54, 0x8d, 0xb7, 0x02, 0x79, 0x9f, 0x6e, 0x99, 0x86, 0x1a, - 0x34, 0x6f, 0xd3, 0x23, 0x54, 0xd1, 0xfb, 0xc9, 0x8f, 0x09, 0x23, 0x43, 0x48, 0xdd, 0xfa, 0x15, - 0x8f, 0x29, 0x6b, 0xfa, 0xf7, 0x86, 0xad, 0xbe, 0xc7, 0x36, 0x80, 0x7f, 0xc1, 0x05, 0xb7, 0xf5, - 0x07, 0xae, 0x6e, 0x03, 0x3c, 0x3f, 0x67, 0x84, 0x4f, 0x11, 0x3e, 0xc7, 0xcc, 0xcd, 0x70, 0x47, - 0x73, 0x17, 0x27, 0xdc, 0xdc, 0x0f, 0x1b, 0xe8, 0x16, 0xcf, 0xa4, 0x90, 0x84, 0x85, 0x7a, 0xcb, - 0x67, 0xb1, 0xbf, 0x0d, 0xe0, 0xbe, 0x73, 0xbd, 0x86, 0x2f, 0x9d, 0xcb, 0xed, 0x65, 0xf1, 0x53, - 0x00, 0xdc, 0x42, 0x65, 0x2b, 0xe2, 0x0f, 0x68, 0x22, 0x5c, 0xb7, 0xe5, 0xb4, 0x2b, 0x1e, 0x22, - 0x3a, 0xda, 0xa7, 0x89, 0xc0, 0x8f, 0xcd, 0x86, 0xca, 0x6d, 0x38, 0x26, 0x51, 0x06, 0xee, 0xdd, - 0xb7, 0xb6, 0xc3, 0x3a, 0x93, 0xb6, 0x13, 0xd5, 0x98, 0xb2, 0x4d, 0xed, 0xce, 0x2d, 0xc5, 0xc5, - 0x3d, 0x84, 0x27, 0x02, 0xca, 0x9f, 0x46, 0xe1, 0xde, 0x14, 0x85, 0x9a, 0x55, 0xd8, 0xc8, 0xa4, - 0x91, 0x78, 0x6c, 0xb6, 0xe4, 0xc5, 0x1a, 0xde, 0x9d, 0x5a, 0x03, 0xd9, 0xbb, 0x5c, 0x43, 0x2e, - 0x70, 0x56, 0xc3, 0x7b, 0x53, 0x6b, 0x30, 0x0a, 0x93, 0x1a, 0x1e, 0xa1, 0x0a, 0x23, 0x63, 0x5f, - 0x9d, 0xf1, 0x3c, 0xa5, 0x72, 0xdf, 0xbd, 0x7f, 0x95, 0x23, 0x18, 0x19, 0xf7, 0x72, 0xf6, 0xf2, - 0x6f, 0x33, 0x68, 0x41, 0xcf, 0x92, 0x1f, 0x7a, 0x5b, 0xb8, 0x8e, 0xe6, 0xcc, 0x29, 0xec, 0x68, - 0x8b, 0x9b, 0x05, 0xfe, 0x1c, 0xcd, 0x25, 0x29, 0x0d, 0xe0, 0xba, 0xb3, 0xc0, 0xb0, 0xf1, 0x13, - 0x34, 0x3f, 0xe6, 0x51, 0x16, 0x83, 0x39, 0xfb, 0xfb, 0x9f, 0xa8, 0xe0, 0x9f, 0xc7, 0xcd, 0xdb, - 0x26, 0x5d, 0x84, 0x3b, 0x1d, 0xca, 0xbb, 0x31, 0x91, 0x23, 0xf5, 0x7a, 0x47, 0x07, 0x2b, 0xe8, - 0xec, 0x65, 0x3d, 0x9b, 0xaa, 0x36, 0xb7, 0xe0, 0x59, 0x1a, 0x80, 0x1d, 0x0c, 0x76, 0x85, 0x1f, - 0xa0, 0x7a, 0x96, 0x84, 0x44, 0xaa, 0xdd, 0x1d, 0xf1, 0x60, 0xc7, 0x1f, 0x01, 0x1d, 0x8e, 0xa4, - 0x9e, 0x10, 0x45, 0x0f, 0xdb, 0x58, 0x5f, 0x85, 0x9e, 0xe9, 0x08, 0xfe, 0x0e, 0x95, 0xf3, 0x0c, - 0xe5, 0x66, 0x3d, 0x0b, 0x4a, 0x0f, 0xef, 0x75, 0xcc, 0xb0, 0xed, 0xe4, 0xc3, 0xb6, 0xf3, 0x22, - 0x1f, 0xb6, 0xfd, 0x05, 0x55, 0xf0, 0xcb, 0x37, 0x6a, 0x42, 0xda, 0x4c, 0x15, 0x5b, 0xfe, 0xc5, - 0x41, 0xb5, 0x75, 0x46, 0x25, 0x25, 0xd1, 0xa4, 0x71, 0x93, 0x16, 0x39, 0xff, 0xb1, 0x45, 0x33, - 0xff, 0x47, 0x8b, 0x8a, 0xe7, 0x5b, 0xb4, 0xfc, 0xb3, 0x83, 0xaa, 0xf9, 0xa0, 0xb7, 0x47, 0x99, - 0x8b, 0x6e, 0xe4, 0xc7, 0x93, 0xf9, 0xc2, 0xf9, 0x12, 0x13, 0x34, 0xa7, 0xae, 0x2c, 0x6a, 0xde, - 0x17, 0xa7, 0xbf, 0xc0, 0x03, 0x55, 0xe3, 0xaf, 0x6f, 0x9a, 0xed, 0x21, 0x95, 0xa3, 0x6c, 0xd0, - 0x09, 0x78, 0x6c, 0x2f, 0x35, 0xf6, 0x67, 0x45, 0x84, 0x3b, 0x5d, 0xb9, 0x9f, 0x80, 0xd0, 0x09, - 0xc2, 0x33, 0xca, 0x5f, 0x2f, 0xfc, 0xf4, 0xaa, 0x59, 0xf8, 0xe7, 0x55, 0xb3, 0xb0, 0xfc, 0x97, - 0x83, 0xaa, 0xcf, 0x41, 0x6f, 0x77, 0x6b, 0x65, 0x35, 0xe2, 0xf9, 0x2e, 0x83, 0xd4, 0xd4, 0x35, - 0x6d, 0xc4, 0x6b, 0x9a, 0x72, 0xbd, 0xbe, 0xa0, 0x4d, 0x8e, 0xdb, 0x99, 0xab, 0x5c, 0xaf, 0xe9, - 0xf9, 0x69, 0xfb, 0x05, 0x9a, 0xb7, 0xf7, 0x9b, 0xe2, 0xf5, 0x3e, 0x98, 0xa5, 0xab, 0x11, 0x9a, - 0x42, 0x08, 0x10, 0x5f, 0xb8, 0xae, 0x94, 0x0c, 0xa6, 0x6f, 0x2b, 0xfd, 0xaf, 0x5e, 0x9f, 0x34, - 0x9c, 0xc3, 0x93, 0x86, 0xf3, 0xf7, 0x49, 0xc3, 0x79, 0x79, 0xda, 0x28, 0x1c, 0x9e, 0x36, 0x0a, - 0x7f, 0x9c, 0x36, 0x0a, 0x3f, 0x36, 0xcf, 0xb5, 0xec, 0xd2, 0x35, 0x54, 0xf7, 0x6b, 0x30, 0xaf, - 0x5d, 0xf8, 0xd9, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x04, 0x49, 0xa7, 0x78, 0xa5, 0x0a, 0x00, - 0x00, + // 1147 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x56, 0xcb, 0x6e, 0xdb, 0x46, + 0x14, 0x15, 0xfd, 0x8a, 0x33, 0xa2, 0x64, 0x7b, 0xa2, 0xa4, 0x93, 0xb4, 0x91, 0x54, 0x17, 0x69, + 0x55, 0xb4, 0x96, 0xe2, 0x14, 0x45, 0x1f, 0x40, 0x90, 0x4a, 0x49, 0xd3, 0x78, 0xd1, 0x3a, 0xa0, + 0x03, 0x2f, 0xba, 0x21, 0x46, 0xe4, 0xb5, 0x44, 0x98, 0x9c, 0x21, 0x38, 0x43, 0xd9, 0xfe, 0x83, + 0x2e, 0xb3, 0xeb, 0x36, 0xeb, 0x6e, 0xba, 0xf1, 0x47, 0x64, 0x53, 0xc0, 0xf0, 0xaa, 0xe8, 0xc2, + 0x2e, 0xec, 0x4d, 0x3f, 0xa3, 0x98, 0x07, 0xe5, 0x17, 0x20, 0x7b, 0x25, 0xce, 0xb9, 0xe7, 0x1e, + 0x5e, 0x5d, 0x9e, 0x99, 0x3b, 0xe8, 0x61, 0x9a, 0xf1, 0x51, 0x4c, 0xfb, 0xa2, 0x33, 0xa2, 0x79, + 0x2c, 0x3b, 0xa3, 0x55, 0xf3, 0xd0, 0x4e, 0x33, 0x2e, 0x39, 0x5e, 0x2a, 0xc2, 0x6d, 0x83, 0x8e, + 0x56, 0x1f, 0xd4, 0x03, 0x2e, 0x12, 0x2e, 0x3a, 0x34, 0x97, 0xc3, 0xce, 0x68, 0xb5, 0x0f, 0x92, + 0xae, 0xea, 0x85, 0x49, 0x19, 0xc7, 0xfb, 0x54, 0xc0, 0x38, 0x1e, 0xf0, 0x88, 0xd9, 0xf8, 0x7d, + 0x13, 0xf7, 0xf5, 0xaa, 0x63, 0x16, 0x36, 0x54, 0x1b, 0xf0, 0x01, 0x37, 0xb8, 0x7a, 0xb2, 0x68, + 0x63, 0xc0, 0xf9, 0x20, 0x86, 0x8e, 0x5e, 0xf5, 0xf3, 0xad, 0x8e, 0x8c, 0x12, 0x10, 0x92, 0x26, + 0xa9, 0x21, 0x2c, 0xff, 0xe5, 0x22, 0x77, 0x53, 0x95, 0xd7, 0x0d, 0x02, 0x9e, 0x33, 0x89, 0xd7, + 0x90, 0xab, 0xde, 0xee, 0x53, 0xb3, 0x26, 0x4e, 0xd3, 0x69, 0x95, 0x9f, 0x34, 0xdb, 0xf6, 0x65, + 0xba, 0x58, 0x5b, 0x59, 0xbb, 0x47, 0x05, 0xd8, 0xbc, 0xde, 0xcc, 0xc1, 0x51, 0xc3, 0xf1, 0xca, + 0xfd, 0x33, 0x08, 0xf7, 0x90, 0x2b, 0xb9, 0xa4, 0xb1, 0x2f, 0x86, 0x34, 0x03, 0x41, 0xa6, 0xb4, + 0xd4, 0xfd, 0x42, 0x4a, 0x51, 0xc7, 0x52, 0xcf, 0x79, 0xc4, 0x7a, 0x33, 0xef, 0x8f, 0x1a, 0x25, + 0xaf, 0xac, 0x93, 0x36, 0x74, 0x0e, 0xfe, 0x1c, 0x2d, 0xe6, 0x2c, 0x84, 0x2c, 0xde, 0x8b, 0xd8, + 0xc0, 0xa7, 0x42, 0x80, 0x24, 0xd3, 0x4d, 0xa7, 0x75, 0xdb, 0x5b, 0x38, 0xc3, 0xbb, 0x0a, 0xc6, + 0x9f, 0xa1, 0x4a, 0x4a, 0xf7, 0x12, 0x60, 0xd2, 0x0f, 0x81, 0xf1, 0x84, 0xcc, 0x28, 0x5e, 0x6f, + 0x8a, 0x38, 0x9e, 0x6b, 0x03, 0x2f, 0x14, 0x8e, 0xdb, 0x68, 0x96, 0x86, 0x49, 0xc4, 0xc8, 0xac, + 0x26, 0x90, 0xc3, 0xfd, 0x95, 0x9a, 0xad, 0xa9, 0x1b, 0x86, 0x19, 0x08, 0xb1, 0x21, 0xb3, 0x88, + 0x0d, 0x3c, 0x43, 0xc3, 0xaf, 0xd0, 0xdd, 0x20, 0xcf, 0x32, 0x25, 0x1c, 0x31, 0x09, 0x19, 0x08, + 0xe9, 0x67, 0x54, 0x02, 0x99, 0xd3, 0xf9, 0xb5, 0xc3, 0xfd, 0x95, 0x45, 0x9b, 0xff, 0x02, 0x02, + 0x9b, 0x7b, 0xc7, 0xa6, 0xac, 0xd9, 0x0c, 0x8f, 0x4a, 0x50, 0x4a, 0x21, 0x88, 0x28, 0x83, 0xf0, + 0x92, 0xd2, 0xad, 0x49, 0x4a, 0x36, 0xe5, 0x82, 0xd2, 0x0f, 0x68, 0x29, 0x89, 0xd8, 0x25, 0x95, + 0xf9, 0x09, 0x2a, 0x0b, 0x49, 0xc4, 0xae, 0x28, 0xd0, 0xdd, 0x4b, 0x0a, 0xb7, 0x27, 0x2a, 0xd0, + 0xdd, 0x0b, 0x0a, 0x1f, 0x23, 0x37, 0x85, 0x2c, 0xe2, 0xa1, 0x2f, 0x24, 0xcd, 0x24, 0x41, 0x4d, + 0xa7, 0x35, 0xed, 0x95, 0x0d, 0xb6, 0xa1, 0x20, 0xfc, 0x08, 0x55, 0x2d, 0x45, 0x19, 0x8f, 0xe7, + 0x92, 0x94, 0x35, 0xa9, 0x62, 0xd0, 0x37, 0x06, 0xc4, 0x9f, 0xa2, 0x05, 0xb1, 0x43, 0x53, 0x3f, + 0x62, 0x3e, 0x30, 0xda, 0x8f, 0x21, 0x24, 0x6e, 0xd3, 0x69, 0xcd, 0x7b, 0x15, 0x05, 0xaf, 0xb1, + 0x1f, 0x0d, 0x88, 0x5b, 0x68, 0x51, 0xf3, 0x78, 0x2e, 0xc7, 0xc4, 0x8a, 0x26, 0x56, 0x15, 0xbe, + 0x9e, 0xcb, 0x82, 0xf9, 0x2d, 0x22, 0x3b, 0x91, 0x1c, 0x86, 0x19, 0xdd, 0xa1, 0xb1, 0x1f, 0x42, + 0x4c, 0xf7, 0x7c, 0x01, 0x01, 0x67, 0xa1, 0x20, 0xd5, 0xa6, 0xd3, 0x9a, 0xf1, 0xee, 0x9d, 0xc5, + 0x5f, 0xa8, 0xf0, 0x86, 0x89, 0xe2, 0x7b, 0x68, 0x2e, 0xa5, 0xb9, 0x80, 0x90, 0x2c, 0x68, 0x65, + 0xbb, 0xc2, 0x2f, 0x51, 0xd5, 0x3c, 0xf9, 0x7d, 0x1a, 0x53, 0x16, 0x00, 0x59, 0xbc, 0x99, 0x9f, + 0x2b, 0x26, 0xad, 0x67, 0xb2, 0xf0, 0x27, 0xc8, 0x02, 0x7e, 0x06, 0x54, 0x70, 0x46, 0x96, 0xb4, + 0x9d, 0x5d, 0x03, 0x7a, 0x1a, 0xc3, 0xcf, 0x50, 0xb5, 0x9f, 0x45, 0xe1, 0x00, 0x7c, 0x6a, 0x1c, + 0x49, 0xf0, 0x35, 0x5e, 0xad, 0x18, 0xbe, 0x05, 0x55, 0xe3, 0xad, 0x40, 0xd1, 0xa7, 0x3b, 0xa6, + 0xa1, 0x06, 0x2d, 0xda, 0xf4, 0x14, 0x55, 0xf4, 0x9e, 0xf2, 0x13, 0xca, 0xe8, 0x00, 0x32, 0x52, + 0xbb, 0xe6, 0x35, 0xae, 0xa6, 0xff, 0x6c, 0xd8, 0xea, 0x7b, 0x6c, 0x01, 0xf8, 0x17, 0x5c, 0x70, + 0x57, 0x7f, 0xe0, 0xea, 0x16, 0xc0, 0xeb, 0x73, 0x46, 0xf8, 0x12, 0xe1, 0x73, 0xcc, 0xc2, 0x0c, + 0xf7, 0x34, 0x77, 0x71, 0xcc, 0x2d, 0xfc, 0xb0, 0x8e, 0xee, 0xf0, 0x5c, 0x0a, 0x49, 0x59, 0xa8, + 0xb7, 0x7d, 0x9e, 0xf8, 0x5b, 0x00, 0xe4, 0x83, 0x9b, 0x35, 0x7c, 0xe9, 0x5c, 0x6e, 0x37, 0x4f, + 0x5e, 0x02, 0xe0, 0x26, 0x72, 0xad, 0x88, 0xdf, 0x8f, 0x52, 0x41, 0x48, 0xd3, 0x69, 0x55, 0x3c, + 0x44, 0x75, 0xb4, 0x17, 0xa5, 0x02, 0x3f, 0x33, 0x1b, 0xaa, 0xb0, 0xe1, 0x88, 0xc6, 0x39, 0x90, + 0xfb, 0x57, 0xb6, 0xc3, 0x1a, 0x93, 0xb6, 0x13, 0xd5, 0x24, 0x62, 0x1b, 0xda, 0x9d, 0x9b, 0x8a, + 0x8b, 0xbb, 0x08, 0x8f, 0x05, 0x94, 0x3f, 0x8d, 0xc2, 0x83, 0x09, 0x0a, 0x0b, 0x56, 0x61, 0x3d, + 0x97, 0x46, 0xe2, 0x99, 0xd9, 0x92, 0x17, 0x6b, 0xf8, 0x70, 0x62, 0x0d, 0x74, 0xf7, 0x72, 0x0d, + 0x85, 0xc0, 0x59, 0x0d, 0x1f, 0x4d, 0xac, 0xc1, 0x28, 0x8c, 0x6b, 0x78, 0x8a, 0x2a, 0x8c, 0x8e, + 0x7c, 0x75, 0xce, 0xf3, 0x2c, 0x92, 0x7b, 0xe4, 0xe1, 0x75, 0x8e, 0x60, 0x74, 0xd4, 0x2d, 0xd8, + 0xcb, 0x7f, 0x4e, 0xa1, 0x79, 0x3d, 0x4f, 0x7e, 0xe9, 0x6e, 0xe2, 0x1a, 0x9a, 0x35, 0x27, 0xb1, + 0xa3, 0x2d, 0x6e, 0x16, 0xf8, 0x6b, 0x34, 0x9b, 0x66, 0x51, 0x00, 0x37, 0x9d, 0x07, 0x86, 0x8d, + 0x9f, 0xa3, 0xb9, 0x11, 0x8f, 0xf3, 0x04, 0xcc, 0xf9, 0xdf, 0xfb, 0x42, 0x05, 0xff, 0x39, 0x6a, + 0xdc, 0x35, 0xe9, 0x22, 0xdc, 0x6e, 0x47, 0xbc, 0x93, 0x50, 0x39, 0x54, 0x7f, 0xef, 0x70, 0x7f, + 0x05, 0x9d, 0xfd, 0x59, 0xcf, 0xa6, 0xaa, 0xcd, 0x2d, 0x78, 0x9e, 0x05, 0x60, 0x86, 0x83, 0x67, + 0x57, 0xf8, 0x31, 0xaa, 0xe5, 0x69, 0x48, 0xa5, 0xda, 0xdd, 0x31, 0x0f, 0xb6, 0xfd, 0x21, 0x44, + 0x83, 0xa1, 0xd4, 0x13, 0x62, 0xda, 0xc3, 0x36, 0xd6, 0x53, 0xa1, 0x57, 0x3a, 0x82, 0x7f, 0x42, + 0x6e, 0x91, 0xa1, 0xdc, 0xac, 0x67, 0x41, 0xf9, 0xc9, 0x83, 0xb6, 0x19, 0xb8, 0xed, 0x62, 0xe0, + 0xb6, 0xdf, 0x14, 0x03, 0xb7, 0x37, 0xaf, 0x0a, 0x7e, 0x7b, 0xac, 0xa6, 0xa4, 0xcd, 0x54, 0xb1, + 0xe5, 0xdf, 0x1d, 0x54, 0x2d, 0x86, 0xa8, 0x3d, 0x22, 0x08, 0xba, 0x55, 0x6c, 0x7b, 0xd3, 0xb9, + 0x62, 0x89, 0x29, 0x9a, 0x55, 0xd7, 0x01, 0x35, 0x4b, 0xa7, 0x27, 0xf7, 0xee, 0xb1, 0x7a, 0xdb, + 0x1f, 0xc7, 0x8d, 0xd6, 0x20, 0x92, 0xc3, 0xbc, 0xdf, 0x0e, 0x78, 0x62, 0x2f, 0x0c, 0xf6, 0x67, + 0x45, 0x84, 0xdb, 0x1d, 0xb9, 0x97, 0x82, 0xd0, 0x09, 0xc2, 0x33, 0xca, 0xdf, 0xcf, 0xff, 0xf6, + 0xae, 0x51, 0xfa, 0xef, 0x5d, 0xa3, 0xb4, 0x7c, 0xec, 0xa0, 0xea, 0x6b, 0xd0, 0xdb, 0xc8, 0x5a, + 0x44, 0x8d, 0x4e, 0xbe, 0xc3, 0x20, 0x33, 0x75, 0x4d, 0x1a, 0x9d, 0x9a, 0xa6, 0xdc, 0xa4, 0x2f, + 0x3f, 0xe3, 0x63, 0x6c, 0xea, 0x3a, 0x37, 0x69, 0x7a, 0x71, 0x8a, 0x7d, 0x83, 0xe6, 0xec, 0xdd, + 0x61, 0xfa, 0x66, 0x5e, 0xb1, 0x74, 0xfc, 0x08, 0xb9, 0x19, 0x84, 0x00, 0xc9, 0x95, 0xab, 0x40, + 0xd9, 0xe0, 0xfa, 0x26, 0xd0, 0xfb, 0xee, 0xfd, 0x49, 0xdd, 0x39, 0x38, 0xa9, 0x3b, 0xff, 0x9e, + 0xd4, 0x9d, 0xb7, 0xa7, 0xf5, 0xd2, 0xc1, 0x69, 0xbd, 0xf4, 0xf7, 0x69, 0xbd, 0xf4, 0x6b, 0xe3, + 0x5c, 0xdb, 0x2e, 0x5d, 0xf3, 0x74, 0xcf, 0xfa, 0x73, 0xfa, 0x0b, 0x7f, 0xf5, 0x7f, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x18, 0x12, 0x9f, 0x2d, 0x05, 0x0a, 0x00, 0x00, } func (m *VaultAccount) Marshal() (dAtA []byte, err error) { @@ -1068,56 +998,6 @@ func (m *VaultNAV) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *InitialVaultNAV) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *InitialVaultNAV) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *InitialVaultNAV) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Source) > 0 { - i -= len(m.Source) - copy(dAtA[i:], m.Source) - i = encodeVarintVault(dAtA, i, uint64(len(m.Source))) - i-- - dAtA[i] = 0x1a - } - { - size := m.Volume.Size() - i -= size - if _, err := m.Volume.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintVault(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - { - size, err := m.Price.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintVault(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil -} - func (m *AccountBalance) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1362,23 +1242,6 @@ func (m *VaultNAV) Size() (n int) { return n } -func (m *InitialVaultNAV) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Price.Size() - n += 1 + l + sovVault(uint64(l)) - l = m.Volume.Size() - n += 1 + l + sovVault(uint64(l)) - l = len(m.Source) - if l > 0 { - n += 1 + l + sovVault(uint64(l)) - } - return n -} - func (m *AccountBalance) Size() (n int) { if m == nil { return 0 @@ -2519,155 +2382,6 @@ func (m *VaultNAV) Unmarshal(dAtA []byte) error { } return nil } -func (m *InitialVaultNAV) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowVault - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: InitialVaultNAV: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: InitialVaultNAV: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowVault - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthVault - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthVault - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Price.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Volume", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowVault - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthVault - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthVault - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Volume.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Source", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowVault - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthVault - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthVault - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Source = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipVault(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthVault - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *AccountBalance) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/types/vault_test.go b/types/vault_test.go index 8fca2805..5bcb5bb9 100644 --- a/types/vault_test.go +++ b/types/vault_test.go @@ -143,7 +143,7 @@ func TestVaultAccount_Validate(t *testing.T) { expectedErr: fmt.Sprintf("invalid underlying asset denom: %s", invalidDenom), }, { - name: "payment denom omitted => fails validation", + name: "empty payment denom is valid under single-denom semantics", vaultAccount: types.VaultAccount{ BaseAccount: baseAcc, Admin: validAdmin, @@ -154,10 +154,10 @@ func TestVaultAccount_Validate(t *testing.T) { DesiredInterestRate: validInterest, OutstandingAumFee: sdk.Coin{Denom: "", Amount: math.NewInt(0)}, }, - expectedErr: "invalid payment denom: \"\": invalid denom: ", + expectedErr: "", }, { - name: "payment denom valid and distinct => ok", + name: "payment denom distinct from underlying is rejected as mixed-denom", vaultAccount: types.VaultAccount{ BaseAccount: baseAcc, Admin: validAdmin, @@ -166,12 +166,12 @@ func TestVaultAccount_Validate(t *testing.T) { PaymentDenom: "usdc", CurrentInterestRate: validInterest, DesiredInterestRate: validInterest, - OutstandingAumFee: sdk.NewInt64Coin("usdc", 0), + OutstandingAumFee: sdk.NewInt64Coin("uusd", 0), }, - expectedErr: "", + expectedErr: `payment denom "usdc" must be empty or equal underlying asset "uusd"; vaults are single-denom`, }, { - name: "payment denom invalid format => error", + name: "payment denom with invalid format is rejected as mixed-denom", vaultAccount: types.VaultAccount{ BaseAccount: baseAcc, Admin: validAdmin, @@ -180,9 +180,9 @@ func TestVaultAccount_Validate(t *testing.T) { PaymentDenom: "inv@lid$", CurrentInterestRate: validInterest, DesiredInterestRate: validInterest, - OutstandingAumFee: sdk.Coin{Denom: "inv@lid$", Amount: math.NewInt(0)}, + OutstandingAumFee: sdk.NewInt64Coin("uusd", 0), }, - expectedErr: "invalid payment denom", + expectedErr: `payment denom "inv@lid$" must be empty or equal underlying asset "uusd"; vaults are single-denom`, }, { name: "invalid current interest rate", @@ -607,7 +607,7 @@ func TestVaultAccount_Validate(t *testing.T) { DesiredInterestRate: "0.0", OutstandingAumFee: sdk.NewInt64Coin("wrong", 100), }, - expectedErr: "outstanding AUM fee denom wrong does not match payment denom uusd", + expectedErr: "outstanding AUM fee denom wrong does not match underlying asset uusd", }, { name: "negative outstanding AUM fee", @@ -623,6 +623,20 @@ func TestVaultAccount_Validate(t *testing.T) { }, expectedErr: "outstanding AUM fee cannot be negative", }, + { + name: "outstanding AUM fee with nil amount is rejected before it can panic consensus math", + vaultAccount: types.VaultAccount{ + BaseAccount: baseAcc, + Admin: validAdmin, + TotalShares: sdk.NewInt64Coin(validDenom, 0), + UnderlyingAsset: "uusd", + PaymentDenom: "uusd", + CurrentInterestRate: "0.0", + DesiredInterestRate: "0.0", + OutstandingAumFee: sdk.Coin{}, + }, + expectedErr: "outstanding AUM fee amount cannot be nil; use a zero coin of the underlying asset \"uusd\"", + }, { name: "non-zero outstanding AUM fee with empty denom", vaultAccount: types.VaultAccount{ @@ -635,7 +649,7 @@ func TestVaultAccount_Validate(t *testing.T) { DesiredInterestRate: "0.0", OutstandingAumFee: sdk.Coin{Denom: "", Amount: math.NewInt(100)}, }, - expectedErr: "outstanding AUM fee denom does not match payment denom uusd", + expectedErr: "outstanding AUM fee denom does not match underlying asset uusd", }, { name: "invalid swap-in limits", @@ -647,6 +661,7 @@ func TestVaultAccount_Validate(t *testing.T) { PaymentDenom: "uusd", CurrentInterestRate: "0.0", DesiredInterestRate: "0.0", + OutstandingAumFee: sdk.NewInt64Coin("uusd", 0), MinSwapInValue: "abc", }, expectedErr: "failed to validate swap-in limits: invalid min value: abc", @@ -661,6 +676,7 @@ func TestVaultAccount_Validate(t *testing.T) { PaymentDenom: "uusd", CurrentInterestRate: "0.0", DesiredInterestRate: "0.0", + OutstandingAumFee: sdk.NewInt64Coin("uusd", 0), MinSwapOutValue: "1000", MaxSwapOutValue: "500", }, @@ -726,30 +742,37 @@ func TestVaultAccount_Validate(t *testing.T) { } } -func TestNewVaultAccount_DefaultsNavAuthorityToAdmin(t *testing.T) { +func TestNewVaultAccount(t *testing.T) { admin, _, _, baseAcc := makeNAVAuthorityFixtures() tests := []struct { - name string - admin string - paymentDenom string + name string + admin string + shareDenom string + underlyingAsset string }{ { - name: "nav authority equals admin when payment denom is set", - admin: admin, - paymentDenom: "usdc", + name: "seeds single-denom defaults for a standard vault", + admin: admin, + shareDenom: "vshare", + underlyingAsset: "uusd", }, { - name: "nav authority equals admin when payment denom is empty", - admin: admin, - paymentDenom: "", + name: "seeds single-denom defaults for a distinct underlying asset", + admin: admin, + shareDenom: "bondshare", + underlyingAsset: "under", }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - vault := types.NewVaultAccount(baseAcc, tc.admin, "vshare", "uusd", tc.paymentDenom, 0, 0, "", "", "", "") - require.Equal(t, tc.admin, vault.NavAuthority, "NewVaultAccount should set NavAuthority to admin for case: %s", tc.name) + vault := types.NewVaultAccount(baseAcc, tc.admin, tc.shareDenom, tc.underlyingAsset, 0, 0, "", "", "", "") + require.Equal(t, tc.admin, vault.NavAuthority, "NewVaultAccount should default NavAuthority to admin for case: %s", tc.name) + require.Equal(t, tc.underlyingAsset, vault.PaymentDenom, "NewVaultAccount should set PaymentDenom to the underlying asset for case: %s", tc.name) + require.Equal(t, tc.underlyingAsset, vault.UnderlyingAsset, "NewVaultAccount should set UnderlyingAsset for case: %s", tc.name) + require.Equal(t, sdk.NewInt64Coin(tc.underlyingAsset, 0), vault.OutstandingAumFee, "NewVaultAccount should seed OutstandingAumFee as a zero coin of the underlying asset for case: %s", tc.name) + require.NoError(t, vault.Validate(), "NewVaultAccount should produce a valid single-denom vault for case: %s", tc.name) }) } } @@ -954,103 +977,131 @@ func TestNewVaultNAV(t *testing.T) { } } -func TestVaultAccount_AcceptedDenoms(t *testing.T) { +func TestVaultAccount_IsAcceptedDenom(t *testing.T) { tests := []struct { name string underlyingAsset string paymentDenom string - expectedDenoms []string + denom string + expected bool }{ { - name: "only underlying when payment empty", + name: "underlying asset is accepted", underlyingAsset: "uusd", - paymentDenom: "", - expectedDenoms: []string{"uusd"}, + denom: "uusd", + expected: true, }, { - name: "only underlying when payment equals underlying", + name: "non-underlying denom is not accepted", underlyingAsset: "uusd", - paymentDenom: "uusd", - expectedDenoms: []string{"uusd"}, + denom: "usdc", + expected: false, }, { - name: "underlying and payment when distinct", + name: "stale payment denom does not widen acceptance", underlyingAsset: "uusd", paymentDenom: "usdc", - expectedDenoms: []string{"uusd", "usdc"}, + denom: "usdc", + expected: false, + }, + { + name: "underlying still accepted when payment denom mirrors it", + underlyingAsset: "uusd", + paymentDenom: "uusd", + denom: "uusd", + expected: true, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { v := types.VaultAccount{UnderlyingAsset: tc.underlyingAsset, PaymentDenom: tc.paymentDenom} - got := v.AcceptedDenoms() - assert.ElementsMatch(t, tc.expectedDenoms, got, "accepted denoms should match expected") + got := v.IsAcceptedDenom(tc.denom) + assert.Equal(t, tc.expected, got, "IsAcceptedDenom(%q) mismatch for case: %s", tc.denom, tc.name) }) } } -func TestVaultAccount_IsAcceptedDenom(t *testing.T) { - vaWithMulti := types.VaultAccount{UnderlyingAsset: "uusd", PaymentDenom: "usdc"} - assert.True(t, vaWithMulti.IsAcceptedDenom("uusd"), "underlying should be accepted") - assert.True(t, vaWithMulti.IsAcceptedDenom("usdc"), "payment denom should be accepted") - assert.False(t, vaWithMulti.IsAcceptedDenom("uatom"), "unlisted denom should not be accepted") - - vaUnderlyingOnly := types.VaultAccount{UnderlyingAsset: "uusd", PaymentDenom: ""} - assert.True(t, vaUnderlyingOnly.IsAcceptedDenom("uusd"), "underlying should be accepted when payment empty") - assert.False(t, vaUnderlyingOnly.IsAcceptedDenom("usdc"), "payment should not be accepted when not configured") - - vaMultiSameDenom := types.VaultAccount{UnderlyingAsset: "uusd", PaymentDenom: "uusd"} - assert.True(t, vaMultiSameDenom.IsAcceptedDenom("uusd"), "underlying should be accepted when payment equals underlying") - assert.False(t, vaMultiSameDenom.IsAcceptedDenom("usdc"), "unlisted denom should not be accepted when payment equals underlying") -} - func TestVaultAccount_ValidateAcceptedDenom(t *testing.T) { - vaUnderlyingOnly := types.VaultAccount{UnderlyingAsset: "uusd"} - err := vaUnderlyingOnly.ValidateAcceptedDenom("uusd") - assert.NoError(t, err, "valid underlying should pass") - - err = vaUnderlyingOnly.ValidateAcceptedDenom("usdc") - assert.Error(t, err, "unlisted denom should error") - assert.Contains(t, err.Error(), `denom not supported for vault`, "error should indicate unsupported denom") - assert.Contains(t, err.Error(), `"uusd"`, "error should list allowed denom") - assert.Contains(t, err.Error(), `"usdc"`, "error should include the provided denom") - - vaWithMulti := types.VaultAccount{UnderlyingAsset: "uusd", PaymentDenom: "usdc"} - err = vaWithMulti.ValidateAcceptedDenom("uusd") - assert.NoError(t, err, "underlying should pass when dual") - - err = vaWithMulti.ValidateAcceptedDenom("usdc") - assert.NoError(t, err, "payment denom should pass when dual") + tests := []struct { + name string + underlyingAsset string + denom string + expectedErr string + }{ + { + name: "underlying asset passes", + underlyingAsset: "uusd", + denom: "uusd", + expectedErr: "", + }, + { + name: "non-underlying denom is rejected", + underlyingAsset: "uusd", + denom: "usdc", + expectedErr: `denom not supported for vault; must be "uusd": got "usdc"`, + }, + { + name: "empty denom is rejected", + underlyingAsset: "uusd", + denom: "", + expectedErr: `denom not supported for vault; must be "uusd": got ""`, + }, + } - err = vaWithMulti.ValidateAcceptedDenom("uatom") - assert.Error(t, err, "unlisted denom should error when dual") - assert.Contains(t, err.Error(), `"uusd"`, "error should include first allowed denom") - assert.Contains(t, err.Error(), `"usdc"`, "error should include second allowed denom") - assert.Contains(t, err.Error(), `"uatom"`, "error should include provided denom") + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + v := types.VaultAccount{UnderlyingAsset: tc.underlyingAsset} + err := v.ValidateAcceptedDenom(tc.denom) + if tc.expectedErr == "" { + assert.NoError(t, err, "expected no error for case: %s", tc.name) + } else { + assert.Error(t, err, "expected an error for case: %s", tc.name) + assert.Equal(t, tc.expectedErr, err.Error(), "error message mismatch for case: %s", tc.name) + } + }) + } } func TestVaultAccount_ValidateAcceptedCoin(t *testing.T) { - vaWithMulti := types.VaultAccount{UnderlyingAsset: "uusd", PaymentDenom: "usdc"} - - err := vaWithMulti.ValidateAcceptedCoin(sdk.NewInt64Coin("uusd", 1)) - assert.NoError(t, err, "non-zero underlying coin should be accepted") - - err = vaWithMulti.ValidateAcceptedCoin(sdk.NewInt64Coin("usdc", 5)) - assert.NoError(t, err, "non-zero payment coin should be accepted") - - err = vaWithMulti.ValidateAcceptedCoin(sdk.NewInt64Coin("uatom", 7)) - assert.Error(t, err, "unlisted denom should error") - assert.Contains(t, err.Error(), "denom not supported for vault", "error should indicate unsupported denom") - - err = vaWithMulti.ValidateAcceptedCoin(sdk.NewInt64Coin("uusd", 0)) - assert.Error(t, err, "zero amount should error") - assert.Equal(t, "amount must be greater than zero", err.Error(), "error should match expected message") + tests := []struct { + name string + underlyingAsset string + coin sdk.Coin + expectedErr string + }{ + { + name: "non-zero underlying coin is accepted", + underlyingAsset: "uusd", + coin: sdk.NewInt64Coin("uusd", 1), + expectedErr: "", + }, + { + name: "non-underlying denom is rejected", + underlyingAsset: "uusd", + coin: sdk.NewInt64Coin("usdc", 5), + expectedErr: `denom not supported for vault; must be "uusd": got "usdc"`, + }, + { + name: "zero amount is rejected before denom check", + underlyingAsset: "uusd", + coin: sdk.NewInt64Coin("uusd", 0), + expectedErr: "amount must be greater than zero", + }, + } - vaUnderlyingOnly := types.VaultAccount{UnderlyingAsset: "uusd"} - err = vaUnderlyingOnly.ValidateAcceptedCoin(sdk.NewInt64Coin("usdc", 3)) - assert.Error(t, err, "payment denom should not be accepted when not configured") - assert.Contains(t, err.Error(), "denom not supported for vault", "error should indicate unsupported denom") + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + v := types.VaultAccount{UnderlyingAsset: tc.underlyingAsset} + err := v.ValidateAcceptedCoin(tc.coin) + if tc.expectedErr == "" { + assert.NoError(t, err, "expected no error for case: %s", tc.name) + } else { + assert.Error(t, err, "expected an error for case: %s", tc.name) + assert.Equal(t, tc.expectedErr, err.Error(), "error message mismatch for case: %s", tc.name) + } + }) + } } func TestPendingSwapOut_Validate(t *testing.T) { diff --git a/utils/shares.go b/utils/shares.go index ea2b48d0..6551bbe7 100644 --- a/utils/shares.go +++ b/utils/shares.go @@ -24,103 +24,78 @@ var ( VirtualShares = ShareScalar ) -// CalculateSharesProRataFraction computes minted shares for a deposit using a -// single-floor, pro-rata formula with virtual offsets and an explicit price fraction. +// CalculateSharesProRata computes minted shares for a deposit of the vault's +// underlying asset using a single-floor, pro-rata formula with virtual offsets. +// Vaults are single-denom, so the deposit amount is already in underlying units +// and no price conversion applies. // // Arguments: -// - amountNumerator / amountDenominator represent the deposit value expressed -// in underlying units as a rational (e.g., amount * priceNum / priceDen). -// For underlying deposits, pass (amount, 1). +// - amount is the deposit amount in underlying units. // - totalAssets / totalShares are the vault-wide totals prior to the deposit. // - shareDenom is the vault share denom for the resulting coin. // // Behavior: // - Applies virtual offsets: ta' = totalAssets + VirtualAssets, ts' = totalShares + VirtualShares. -// - First deposit mints amount * ShareScalar / amountDenominator. -// - Otherwise: shares = floor( amountNumerator * ts' / (amountDenominator * ta') ). +// - First deposit mints amount * ShareScalar. +// - Otherwise: shares = floor( amount * ts' / ta' ). // -// Errors if any input is negative or if amountDenominator == 0. -func CalculateSharesProRataFraction( - amountNumerator math.Int, - amountDenominator math.Int, +// Errors if any input is negative. +func CalculateSharesProRata( + amount math.Int, totalAssets math.Int, totalShares math.Int, shareDenom string, ) (sdk.Coin, error) { - if amountNumerator.IsNegative() || amountDenominator.IsNegative() || totalAssets.IsNegative() || totalShares.IsNegative() { + if amount.IsNegative() || totalAssets.IsNegative() || totalShares.IsNegative() { return sdk.Coin{}, fmt.Errorf("invalid input: negative values not allowed") } - if amountNumerator.IsZero() { + if amount.IsZero() { return sdk.NewCoin(shareDenom, math.ZeroInt()), nil } - if amountDenominator.IsZero() { - return sdk.Coin{}, fmt.Errorf("invalid input: zero denominator") - } if totalAssets.IsZero() && totalShares.IsZero() { - scaled, err := amountNumerator.SafeMul(ShareScalar) + scaled, err := amount.SafeMul(ShareScalar) if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to multiply amount numerator %s by share scalar %s: %w", amountNumerator, ShareScalar, err) + return sdk.Coin{}, fmt.Errorf("failed to multiply amount %s by share scalar %s: %w", amount, ShareScalar, err) } - return sdk.NewCoin(shareDenom, scaled.Quo(amountDenominator)), nil + return sdk.NewCoin(shareDenom, scaled), nil } ta := totalAssets.Add(VirtualAssets) ts := totalShares.Add(VirtualShares) - den, err := amountDenominator.SafeMul(ta) - if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to multiply amount denominator %s by total assets %s: %w", amountDenominator, ta, err) - } - numerator, err := amountNumerator.SafeMul(ts) + numerator, err := amount.SafeMul(ts) if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to multiply amount numerator %s by total shares %s: %w", amountNumerator, ts, err) + return sdk.Coin{}, fmt.Errorf("failed to multiply amount %s by total shares %s: %w", amount, ts, err) } - return sdk.NewCoin(shareDenom, numerator.Quo(den)), nil + return sdk.NewCoin(shareDenom, numerator.Quo(ta)), nil } -// CalculateRedeemProRataFraction computes the payout amount for redeeming shares -// into an arbitrary payout denom using a single-floor, pro-rata formula with -// virtual offsets and an explicit price fraction. +// CalculateRedeemProRata computes the payout amount for redeeming shares into +// the vault's underlying asset using a single-floor, pro-rata formula with +// virtual offsets. Vaults are single-denom, so the payout is always in +// underlying units and no price conversion applies. // // Arguments: // - shares is the number of vault shares being redeemed. // - totalShares / totalAssets are the vault-wide totals prior to redemption. -// - priceNumerator / priceDenominator encode the payout denom’s price in -// underlying units (1 payout = priceNum / priceDen underlying). For -// underlying payouts, pass (1, 1). -// - payoutDenom is the target payout denom for the resulting coin. +// - payoutDenom is the underlying asset denom for the resulting coin. // // Behavior: // - Applies virtual offsets: ta' = totalAssets + VirtualAssets, ts' = totalShares + VirtualShares. -// - Computes: payout = floor( shares * ta' * priceDen / (ts' * priceNum) ). +// - Computes: payout = floor( shares * ta' / ts' ). // - Returns sdk.Coin(payoutDenom, payout). // -// Errors if any input is negative or if priceNumerator == 0. -func CalculateRedeemProRataFraction(shares math.Int, totalShares math.Int, totalAssets math.Int, priceNumerator math.Int, priceDenominator math.Int, payoutDenom string) (sdk.Coin, error) { - if shares.IsNegative() || totalShares.IsNegative() || totalAssets.IsNegative() || priceNumerator.IsNegative() || priceDenominator.IsNegative() { +// Errors if any input is negative. +func CalculateRedeemProRata(shares math.Int, totalShares math.Int, totalAssets math.Int, payoutDenom string) (sdk.Coin, error) { + if shares.IsNegative() || totalShares.IsNegative() || totalAssets.IsNegative() { return sdk.Coin{}, fmt.Errorf("invalid input: negative values not allowed") } if shares.IsZero() { return sdk.NewCoin(payoutDenom, math.ZeroInt()), nil } ts := totalShares.Add(VirtualShares) - if ts.IsZero() { - return sdk.NewCoin(payoutDenom, math.ZeroInt()), nil - } - if priceNumerator.IsZero() { - return sdk.Coin{}, fmt.Errorf("invalid input: zero price numerator") - } ta := totalAssets.Add(VirtualAssets) sharesTa, err := shares.SafeMul(ta) if err != nil { return sdk.Coin{}, fmt.Errorf("failed to multiply shares %s by total assets %s: %w", shares, ta, err) } - num, err := sharesTa.SafeMul(priceDenominator) - if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to multiply shares-assets product %s by price denominator %s: %w", sharesTa, priceDenominator, err) - } - den, err := ts.SafeMul(priceNumerator) - if err != nil { - return sdk.Coin{}, fmt.Errorf("failed to multiply total shares %s by price numerator %s: %w", ts, priceNumerator, err) - } - out := num.Quo(den) - return sdk.NewCoin(payoutDenom, out), nil + return sdk.NewCoin(payoutDenom, sharesTa.Quo(ts)), nil } diff --git a/utils/shares_test.go b/utils/shares_test.go index 92dcae7c..fcaeb710 100644 --- a/utils/shares_test.go +++ b/utils/shares_test.go @@ -22,8 +22,8 @@ func TestCalculateAssetsFromShares(t *testing.T) { assetDenom := "asset" // This test name is retained for continuity. Internally it now routes to the - // single-floor redeem path (CalculateRedeemProRataFraction) with price 1:1. The intent - // remains identical: “given shares and totals, how many assets do I get back?” + // single-floor redeem path (CalculateRedeemProRata). The intent remains + // identical: “given shares and totals, how many assets do I get back?” tests := []struct { name string shares sdkmath.Int @@ -91,12 +91,10 @@ func TestCalculateAssetsFromShares(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - result, err := utils.CalculateRedeemProRataFraction( + result, err := utils.CalculateRedeemProRata( tc.shares, tc.totalShares, tc.totalAssets, - sdkmath.NewInt(1), // price numerator (underlying->underlying) - sdkmath.NewInt(1), // price denominator assetDenom, ) if tc.expectErr { @@ -114,13 +112,12 @@ func TestCalculateAssetsFromShares(t *testing.T) { } } -func TestCalculateSharesProRataFraction(t *testing.T) { +func TestCalculateSharesProRata(t *testing.T) { shareDenom := "vaultshare" tests := []struct { name string - amountNum sdkmath.Int - amountDen sdkmath.Int + amount sdkmath.Int totalAssets sdkmath.Int totalShares sdkmath.Int expected sdk.Coin @@ -129,76 +126,44 @@ func TestCalculateSharesProRataFraction(t *testing.T) { errContains string }{ { - name: "first deposit mints amount * ShareScalar (price 1:1)", - amountNum: sdkmath.NewInt(100), - amountDen: sdkmath.NewInt(1), + name: "first deposit mints amount * ShareScalar", + amount: sdkmath.NewInt(100), totalAssets: sdkmath.NewInt(0), totalShares: sdkmath.NewInt(0), expected: sdk.NewCoin(shareDenom, sdkmath.NewInt(100_000_000)), }, { name: "assets zero but shares non-zero uses pro-rata path", - amountNum: sdkmath.NewInt(1), - amountDen: sdkmath.NewInt(1), + amount: sdkmath.NewInt(1), totalAssets: sdkmath.NewInt(0), totalShares: sdkmath.NewInt(1), expected: sdk.NewCoin(shareDenom, sdkmath.NewInt(1_000_001)), }, { - name: "proportional mint with virtual offsets (price 1:1)", - amountNum: sdkmath.NewInt(50), - amountDen: sdkmath.NewInt(1), + name: "proportional mint with virtual offsets", + amount: sdkmath.NewInt(50), totalAssets: sdkmath.NewInt(100), totalShares: sdkmath.NewInt(200), expected: sdk.NewCoin(shareDenom, sdkmath.NewInt(495_148)), }, { - name: "small deposit precision and offsets (price 1:1)", - amountNum: sdkmath.NewInt(1), - amountDen: sdkmath.NewInt(1), + name: "small deposit precision and offsets", + amount: sdkmath.NewInt(1), totalAssets: sdkmath.NewInt(3), totalShares: sdkmath.NewInt(10), expected: sdk.NewCoin(shareDenom, sdkmath.NewInt(250_002)), }, { - name: "priced deposit 3/2 into non-empty vault", - amountNum: sdkmath.NewInt(6), - amountDen: sdkmath.NewInt(2), - totalAssets: sdkmath.NewInt(100), - totalShares: sdkmath.NewInt(200), - expected: sdk.NewCoin(shareDenom, sdkmath.NewInt(29_708)), - }, - { - name: "reject negative amount numerator", - amountNum: sdkmath.NewInt(-1), - amountDen: sdkmath.NewInt(1), + name: "reject negative amount", + amount: sdkmath.NewInt(-1), totalAssets: sdkmath.NewInt(0), totalShares: sdkmath.NewInt(0), expectErr: true, expectedErrText: "invalid input: negative values not allowed", }, - { - name: "reject negative denominator", - amountNum: sdkmath.NewInt(1), - amountDen: sdkmath.NewInt(-1), - totalAssets: sdkmath.NewInt(0), - totalShares: sdkmath.NewInt(0), - expectErr: true, - expectedErrText: "invalid input: negative values not allowed", - }, - { - name: "reject zero denominator", - amountNum: sdkmath.NewInt(1), - amountDen: sdkmath.NewInt(0), - totalAssets: sdkmath.NewInt(0), - totalShares: sdkmath.NewInt(0), - expectErr: true, - expectedErrText: "invalid input: zero denominator", - }, { name: "reject negative totals", - amountNum: sdkmath.NewInt(1), - amountDen: sdkmath.NewInt(1), + amount: sdkmath.NewInt(1), totalAssets: sdkmath.NewInt(-1), totalShares: sdkmath.NewInt(0), expectErr: true, @@ -206,17 +171,15 @@ func TestCalculateSharesProRataFraction(t *testing.T) { }, { name: "oversized first deposit overflows share scalar and returns error", - amountNum: nearMaxInt(), - amountDen: sdkmath.NewInt(1), + amount: nearMaxInt(), totalAssets: sdkmath.NewInt(0), totalShares: sdkmath.NewInt(0), expectErr: true, errContains: "integer overflow", }, { - name: "oversized priced deposit overflows pro-rata path and returns error", - amountNum: nearMaxInt(), - amountDen: sdkmath.NewInt(1), + name: "oversized deposit overflows pro-rata path and returns error", + amount: nearMaxInt(), totalAssets: sdkmath.NewInt(100), totalShares: nearMaxInt(), expectErr: true, @@ -226,7 +189,7 @@ func TestCalculateSharesProRataFraction(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - got, err := utils.CalculateSharesProRataFraction(tc.amountNum, tc.amountDen, tc.totalAssets, tc.totalShares, shareDenom) + got, err := utils.CalculateSharesProRata(tc.amount, tc.totalAssets, tc.totalShares, shareDenom) if tc.expectErr { require.Error(t, err, "expected error for case: %s", tc.name) @@ -239,7 +202,7 @@ func TestCalculateSharesProRataFraction(t *testing.T) { } require.NoError(t, err, "unexpected error for case: %s", tc.name) - require.Equal(t, tc.expected, got, fmt.Sprintf("unexpected shares for amount=%s/%s totalAssets=%s totalShares=%s", tc.amountNum, tc.amountDen, tc.totalAssets, tc.totalShares)) + require.Equal(t, tc.expected, got, fmt.Sprintf("unexpected shares for amount=%s totalAssets=%s totalShares=%s", tc.amount, tc.totalAssets, tc.totalShares)) }) } } @@ -260,7 +223,7 @@ func TestSmallFirstSwapInThenHugeSwapInThenSwapOut(t *testing.T) { totalShares := sdkmath.ZeroInt() shareDenom := "shares" - firstShares, err := utils.CalculateSharesProRataFraction(firstIn, sdkmath.NewInt(1), totalAssets, totalShares, shareDenom) + firstShares, err := utils.CalculateSharesProRata(firstIn, totalAssets, totalShares, shareDenom) require.NoErrorf(t, err, "first swap-in conversion should not error") require.Equalf(t, firstIn.Mul(utils.ShareScalar), firstShares.Amount, "first swap-in should mint amount * ShareScalar") @@ -272,7 +235,7 @@ func TestSmallFirstSwapInThenHugeSwapInThenSwapOut(t *testing.T) { totalAssets = totalAssets.Add(hugeIn) assetDenom := "underlying" - outAll, err := utils.CalculateRedeemProRataFraction(firstShares.Amount, totalShares, totalAssets, sdkmath.NewInt(1), sdkmath.NewInt(1), assetDenom) + outAll, err := utils.CalculateRedeemProRata(firstShares.Amount, totalShares, totalAssets, assetDenom) require.NoErrorf(t, err, "swap-out conversion should not error") require.Truef(t, @@ -303,7 +266,7 @@ func TestVeryLargeInitialSwapInRoundTrip(t *testing.T) { totalShares := sdkmath.ZeroInt() shareDenom := "shares" - minted, err := utils.CalculateSharesProRataFraction(largeIn, sdkmath.NewInt(1), totalAssets, totalShares, shareDenom) + minted, err := utils.CalculateSharesProRata(largeIn, totalAssets, totalShares, shareDenom) require.NoErrorf(t, err, "large swap-in conversion should not error") require.Equalf(t, largeIn.Mul(utils.ShareScalar), minted.Amount, "minted shares should equal swap-in * ShareScalar") @@ -311,7 +274,7 @@ func TestVeryLargeInitialSwapInRoundTrip(t *testing.T) { totalShares = totalShares.Add(minted.Amount) assetDenom := "underlying" - out, err := utils.CalculateRedeemProRataFraction(minted.Amount, totalShares, totalAssets, sdkmath.NewInt(1), sdkmath.NewInt(1), assetDenom) + out, err := utils.CalculateRedeemProRata(minted.Amount, totalShares, totalAssets, assetDenom) require.NoErrorf(t, err, "swap-out conversion should not error") price := totalAssets.Mul(utils.ShareScalar).Quo(totalShares)