Skip to content

Minimum amounts for swap in and swap out#156

Merged
nullpointer0x00 merged 18 commits intomainfrom
nullpointer0x00/39-minimums-for-swap-in-out-amounts
Apr 21, 2026
Merged

Minimum amounts for swap in and swap out#156
nullpointer0x00 merged 18 commits intomainfrom
nullpointer0x00/39-minimums-for-swap-in-out-amounts

Conversation

@nullpointer0x00
Copy link
Copy Markdown
Collaborator

@nullpointer0x00 nullpointer0x00 commented Dec 12, 2025

closes: #39

Summary by CodeRabbit

  • New Features

    • Per-vault configurable minimum and maximum limits for swap-in and swap-out, set at creation or via new update transactions/CLI commands
    • Swap operations now enforce configured bounds and will reject amounts outside limits
    • Events emitted when vault swap limits are updated
  • Documentation

    • Spec updated to document swap limit fields and validation/clear semantics
  • Tests

    • Expanded test coverage for creation, validation, updates, and swap-limit enforcement

@nullpointer0x00 nullpointer0x00 self-assigned this Dec 12, 2025
@nullpointer0x00 nullpointer0x00 added the enhancement New feature or request label Dec 12, 2025
@nullpointer0x00 nullpointer0x00 added this to the v1.0.14 milestone Dec 12, 2025
@nullpointer0x00 nullpointer0x00 marked this pull request as ready for review April 20, 2026 17:26
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
keeper/query_server_test.go (1)

23-36: ⚠️ Potential issue | 🟡 Minor

Assert the new min-swap fields in query responses.

The expected VaultAccounts now include MinSwapInValue / MinSwapOutValue, but both manual comparators omit those fields, so Vault and Vaults could stop returning them without failing these tests.

Proposed test assertion update
 		ManualEquality: func(s querytest.TestSuiter, expected, actual *types.QueryVaultResponse) {
 			s.Require().NotNil(actual, "actual response should not be nil")
 			s.Require().NotNil(expected, "expected response should not be nil")
 			s.Assert().Equal(expected.Vault.Address, actual.Vault.Address, "vault address")
 			s.Assert().Equal(expected.Vault.Admin, actual.Vault.Admin, "vault admin")
 			s.Assert().Equal(expected.Vault.TotalShares, actual.Vault.TotalShares, "vault total shares")
 			s.Assert().Equal(expected.Vault.UnderlyingAsset, actual.Vault.UnderlyingAsset, "vault underlying asset")
 			s.Assert().Equal(expected.Vault.AumFeeBips, actual.Vault.AumFeeBips, "vault AUM fee bips")
+			s.Assert().Equal(expected.Vault.MinSwapInValue, actual.Vault.MinSwapInValue, "vault min swap in value")
+			s.Assert().Equal(expected.Vault.MinSwapOutValue, actual.Vault.MinSwapOutValue, "vault min swap out value")
 			s.Assert().Equal(expected.Principal.Address, actual.Principal.Address, "principal address")
 			s.Assert().Equal(expected.Principal.Coins, actual.Principal.Coins, "principal coins")
 			s.Assert().Equal(expected.Reserves.Address, actual.Reserves.Address, "reserves address")
 			s.Assert().Equal(expected.Reserves.Coins, actual.Reserves.Coins, "reserves coins")
 			s.Assert().Equal(expected.TotalVaultValue, actual.TotalVaultValue, "total vault value")
@@
 			type vaultView struct {
 				Address         string
 				Admin           string
 				ShareDenom      string
 				UnderlyingAsset string
 				PaymentDenom    string
 				AumFeeBips      uint32
 				IsPaused        bool
+				MinSwapInValue  string
+				MinSwapOutValue string
 			}
@@
 					PaymentDenom:    v.GetPaymentDenom(),
 					AumFeeBips:      v.AumFeeBips,
 					IsPaused:        v.GetPaused(),
+					MinSwapInValue:  v.MinSwapInValue,
+					MinSwapOutValue: v.MinSwapOutValue,
 				})

Also applies to: 139-165

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@keeper/query_server_test.go` around lines 23 - 36, The ManualEquality
comparator for types.QueryVaultResponse is missing assertions for the new
VaultAccount fields MinSwapInValue and MinSwapOutValue; update the
ManualEquality function (used with querytest.TestSuiter) to Assert().Equal
expected.Vault.MinSwapInValue vs actual.Vault.MinSwapInValue and
expected.Vault.MinSwapOutValue vs actual.Vault.MinSwapOutValue (and do the same
for any other ManualEquality comparator that compares Vault/Vaults responses) so
tests will fail if those fields are omitted or change.
keeper/vault.go (1)

111-132: ⚠️ Potential issue | 🟠 Major

Validate minimum swap values to prevent negative or malformed values from disabling swap gates.

createVaultAccount persists minSwapIn/minSwapOut without validation, and SetMinSwapInValue/SetMinSwapOutValue only check parseability, not whether values are negative. Additionally, AllowSwapInAmount and AllowSwapOutAmount return true on parse failures, silently allowing swaps when configured minimums are malformed. This requires:

  • Validating both parseability and non-negative values in all write paths (createVaultAccount and the setters)
  • Returning errors (not true) on invalid persisted state in AllowSwapInAmount and AllowSwapOutAmount
  • Adding a Godoc comment to the exported AllowSwapInAmount function
  • Fixing the parameter typo swapInAssestswapInAsset on line 549
Suggested validation hardening
+func validateMinSwapValue(name, value string) error {
+	if value == "" {
+		return nil
+	}
+	minLimit, ok := sdkmath.NewIntFromString(value)
+	if !ok {
+		return fmt.Errorf("invalid %s: %s", name, value)
+	}
+	if minLimit.IsNegative() {
+		return fmt.Errorf("%s cannot be negative: %s", name, value)
+	}
+	return nil
+}
+
 func (k *Keeper) createVaultAccount(ctx sdk.Context, admin, shareDenom, underlyingAsset, paymentDenom string, withdrawalDelay uint64, minSwapIn, minSwapOut string) (*types.VaultAccount, error) {
 	vaultAddr := types.GetVaultAddress(shareDenom)
+
+	if err := validateMinSwapValue("min swap in value", minSwapIn); err != nil {
+		return nil, fmt.Errorf("failed to validate min swap in value: %w", err)
+	}
+	if err := validateMinSwapValue("min swap out value", minSwapOut); err != nil {
+		return nil, fmt.Errorf("failed to validate min swap out value: %w", err)
+	}
 
 	params, err := k.Params.Get(ctx)
 func (k *Keeper) SetMinSwapInValue(ctx sdk.Context, vault *types.VaultAccount, minSwapIn string) error {
-	if minSwapIn != "" {
-		if _, ok := sdkmath.NewIntFromString(minSwapIn); !ok {
-			return fmt.Errorf("invalid min swap in value: %s", minSwapIn)
-		}
+	if err := validateMinSwapValue("min swap in value", minSwapIn); err != nil {
+		return fmt.Errorf("failed to validate min swap in value: %w", err)
 	}
 	if vault.MinSwapInValue == minSwapIn {
 		return nil
 	}
@@
 func (k *Keeper) SetMinSwapOutValue(ctx sdk.Context, vault *types.VaultAccount, minSwapOut string) error {
-	if minSwapOut != "" {
-		if _, ok := sdkmath.NewIntFromString(minSwapOut); !ok {
-			return fmt.Errorf("invalid min swap out value: %s", minSwapOut)
-		}
+	if err := validateMinSwapValue("min swap out value", minSwapOut); err != nil {
+		return fmt.Errorf("failed to validate min swap out value: %w", err)
 	}
 	if vault.MinSwapOutValue == minSwapOut {
 		return nil
 	}
 	minLimit, ok := sdkmath.NewIntFromString(vault.MinSwapInValue)
 	if !ok {
-		return true, nil
+		return false, fmt.Errorf("invalid configured min swap in value: %s", vault.MinSwapInValue)
+	}
+	if minLimit.IsNegative() {
+		return false, fmt.Errorf("configured min swap in value cannot be negative: %s", vault.MinSwapInValue)
 	}
 	minLimit, ok := sdkmath.NewIntFromString(vault.MinSwapOutValue)
 	if !ok {
-		return true, nil
+		return false, fmt.Errorf("invalid configured min swap out value: %s", vault.MinSwapOutValue)
+	}
+	if minLimit.IsNegative() {
+		return false, fmt.Errorf("configured min swap out value cannot be negative: %s", vault.MinSwapOutValue)
 	}

Also applies to: 514–547, 559–568, 572–591

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@keeper/vault.go` around lines 111 - 132, The persisted minSwapIn/minSwapOut
values must be validated for parseability and non-negativity: update
createVaultAccount to parse minSwapIn/minSwapOut as sdk.Int (or the project’s
numeric type) and return an error if parsing fails or the value is negative
before constructing the VaultAccount; likewise harden SetMinSwapInValue and
SetMinSwapOutValue to validate parseability and non-negative values and reject
invalid inputs. Modify AllowSwapInAmount and AllowSwapOutAmount to return an
error (not silently true) when the stored min values cannot be parsed, and add a
Godoc comment to the exported AllowSwapInAmount explaining its behavior and
error return. Finally, fix the parameter name typo swapInAssest → swapInAsset in
the referenced function signature to match callers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.changelog/unreleased/features/39-minimums-for-swap-in-out-amounts.md:
- Line 1: The changelog entry incorrectly states both minimum and maximum
limits; update the entry text in
.changelog/unreleased/features/39-minimums-for-swap-in-out-amounts.md to remove
any mention of "maximum" (e.g., change "minimum and maximum limits" to "minimum
limits" or similar), since only min_swap_in_value and min_swap_out_value were
added and no configurable maximum swap amount fields exist (MaxSwapOutBatchSize
is a batch-size constant, not a swap-value limit).

In `@keeper/msg_server_test.go`:
- Around line 968-1202: Extract the repeated vault creation/setup used by
TestMsgServer_UpdateMinSwapInValue, TestMsgServer_UpdateMinSwapInValue_Failures,
TestMsgServer_UpdateMinSwapOutValue, and
TestMsgServer_UpdateMinSwapOutValue_Failures into a helper in suite_test.go
(e.g., CreateAndActivateVault(admin sdk.AccAddress, share string, underlying
string) that calls requireAddFinalizeAndActivateMarker and k.CreateVault and
returns the vault address), then replace the inline setup closures with calls to
that helper; also update the assertions inside the test postCheck and setup code
(the s.Require().NoError(err) and s.Require().Equal(...) calls in the postCheck
closures and setup) to include descriptive failure messages (e.g., "unexpected
error creating vault", "vault MinSwapInValue mismatch: expected %s got %s",
"vault MinSwapOutValue mismatch: expected %s got %s") so every Require has
contextual text. Ensure you reference
keeper.NewMsgServer(...).UpdateMinSwapInValue, UpdateMinSwapOutValue,
requireAddFinalizeAndActivateMarker, and k.CreateVault when making the changes.

In `@keeper/vault.go`:
- Around line 549-552: Add a proper Godoc comment for the exported method
AllowSwapInAmount on Keeper and rename the misspelled parameter swapInAssest to
swapInAsset in its signature and all usages (including calls to
ToUnderlyingAssetAmount and any interfaces/tests) so the public API no longer
exposes the typo; update the function comment to describe purpose, parameters
(ctx, swapInAsset, vault types.VaultAccount) and return values, and run/adjust
any callers or generated docs that reference the old name.

In `@proto/provlabs/vault/v1/events.proto`:
- Around line 381-399: Update the proto docs for EventMinSwapInValueUpdated and
EventMinSwapOutValueUpdated to explicitly state the "clear-minimum" semantics
for the min_swap_in and min_swap_out fields: document that an empty string ("")
or "0" indicates the minimum was cleared / no configured minimum, and align the
wording with the tx/state scalar metadata conventions; update the comment blocks
on the min_swap_in and min_swap_out fields in those message definitions
(EventMinSwapInValueUpdated, EventMinSwapOutValueUpdated) to include this
behavior so event consumers and generated API docs unambiguously understand the
cleared-minimum semantics.

In `@proto/provlabs/vault/v1/tx.proto`:
- Around line 120-123: Update the CreateVault message documentation for the
fields min_swap_in_value and min_swap_out_value to state the no-minimum
semantics consistently with the update messages: clearly document that setting
the field to "" (empty string) or "0" disables the minimum, indicate the unit
(underlying_asset) and that values are encoded as cosmos.IntString, and include
examples or allowed formats if helpful; modify the comments above string
min_swap_in_value and string min_swap_out_value to reflect this behavior so the
public API docs match the update messages.
- Around line 42-46: The proto currently only exposes UpdateMinSwapInValue and
UpdateMinSwapOutValue RPCs; add symmetric maximum-value endpoints and messages
by introducing rpc MsgUpdateMaxSwapInValue(MsgUpdateMaxSwapInValueRequest)
returns (MsgUpdateMaxSwapInValueResponse) and rpc
MsgUpdateMaxSwapOutValue(MsgUpdateMaxSwapOutValueRequest) returns
(MsgUpdateMaxSwapOutValueResponse) in proto/provlabs/vault/v1/tx.proto, define
the corresponding request/response message types (including validator/owner, max
value field, and standard Msg fields), and implement the server-side handlers
(e.g., MsgServer methods named UpdateMaxSwapInValue and UpdateMaxSwapOutValue
and their keeper/handler logic) to persist and validate the configured maximums
consistent with existing UpdateMin* implementations.

In `@proto/provlabs/vault/v1/vault.proto`:
- Around line 119-129: The comments for the proto fields min_swap_in_value and
min_swap_out_value lack an explicit non-negative invariant; update the
documentation in vault.proto to state that these fields are integer strings
(cosmos.IntString) and must be non-negative (>= 0), e.g., clarify that values
are measured in underlying_asset, inputs are converted before checking, and that
the empty string or "0" disables the minimum; ensure both min_swap_in_value and
min_swap_out_value documentation include the non-negative requirement so clients
cannot assume signed values are allowed.

In `@spec/03_messages.md`:
- Around line 74-77: Update the spec text for MsgCreateVaultRequest (and the
analogous update message around the second range) to state that
min_swap_in_value and min_swap_out_value are denominated in the vault's
underlying_asset and that sending an empty string ("") or the string "0"
indicates clearing/disabling the minimum; reference the exact fields by name
(MsgCreateVaultRequest.admin, MsgCreateVaultRequest.share_denom,
MsgCreateVaultRequest.underlying_asset, MsgCreateVaultRequest.payment_denom,
MsgCreateVaultRequest.withdrawal_delay_seconds,
MsgCreateVaultRequest.min_swap_in_value,
MsgCreateVaultRequest.min_swap_out_value) and mirror the proto semantics so
clients know to express amounts in underlying_asset units and to use "" or "0"
to clear the minimums.

In `@types/msgs.go`:
- Around line 78-88: The current validation for m.MinSwapInValue and
m.MinSwapOutValue uses sdkmath.NewIntFromString but permits negative integers;
update the validators (e.g., in the message ValidateBasic function handling
m.MinSwapInValue and m.MinSwapOutValue) to parse the string with
sdkmath.NewIntFromString and then check the resulting Int is >= 0 (treat "" and
"0" as valid), returning an error like "invalid min swap in value: must be
non-negative: %q" (or similar) if the value is negative; apply the same
non-negative check to the other similar fields noted (the block around lines
481-499) so all min-swap thresholds reject negative values.

In `@types/vault.go`:
- Around line 209-219: The current validation uses sdkmath.NewIntFromString for
v.MinSwapInValue and v.MinSwapOutValue but doesn't reject negative values;
update the validation in the same blocks that call sdkmath.NewIntFromString (for
v.MinSwapInValue and v.MinSwapOutValue) to parse the value and then check that
the resulting Int is >= 0, returning an error like "min swap in/out value must
be non-negative" if it's negative so that AllowSwapInAmount and
AllowSwapOutAmount comparisons cannot be bypassed by negative minima.

---

Outside diff comments:
In `@keeper/query_server_test.go`:
- Around line 23-36: The ManualEquality comparator for types.QueryVaultResponse
is missing assertions for the new VaultAccount fields MinSwapInValue and
MinSwapOutValue; update the ManualEquality function (used with
querytest.TestSuiter) to Assert().Equal expected.Vault.MinSwapInValue vs
actual.Vault.MinSwapInValue and expected.Vault.MinSwapOutValue vs
actual.Vault.MinSwapOutValue (and do the same for any other ManualEquality
comparator that compares Vault/Vaults responses) so tests will fail if those
fields are omitted or change.

In `@keeper/vault.go`:
- Around line 111-132: The persisted minSwapIn/minSwapOut values must be
validated for parseability and non-negativity: update createVaultAccount to
parse minSwapIn/minSwapOut as sdk.Int (or the project’s numeric type) and return
an error if parsing fails or the value is negative before constructing the
VaultAccount; likewise harden SetMinSwapInValue and SetMinSwapOutValue to
validate parseability and non-negative values and reject invalid inputs. Modify
AllowSwapInAmount and AllowSwapOutAmount to return an error (not silently true)
when the stored min values cannot be parsed, and add a Godoc comment to the
exported AllowSwapInAmount explaining its behavior and error return. Finally,
fix the parameter name typo swapInAssest → swapInAsset in the referenced
function signature to match callers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 704aa915-d0a5-4829-9783-b80dbac7c8d6

📥 Commits

Reviewing files that changed from the base of the PR and between 76c4d99 and 5d98d4a.

⛔ Files ignored due to path filters (4)
  • api/provlabs/vault/v1/tx_grpc.pb.go is excluded by !**/*.pb.go
  • types/events.pb.go is excluded by !**/*.pb.go
  • types/tx.pb.go is excluded by !**/*.pb.go
  • types/vault.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (17)
  • .changelog/unreleased/features/39-minimums-for-swap-in-out-amounts.md
  • api/provlabs/vault/v1/events.pulsar.go
  • api/provlabs/vault/v1/tx.pulsar.go
  • api/provlabs/vault/v1/vault.pulsar.go
  • keeper/msg_server.go
  • keeper/msg_server_test.go
  • keeper/query_server_test.go
  • keeper/suite_test.go
  • keeper/vault.go
  • proto/provlabs/vault/v1/events.proto
  • proto/provlabs/vault/v1/tx.proto
  • proto/provlabs/vault/v1/vault.proto
  • spec/02_state.md
  • spec/03_messages.md
  • types/events.go
  • types/msgs.go
  • types/vault.go

Comment thread keeper/msg_server_test.go
Comment thread keeper/vault.go Outdated
Comment thread proto/provlabs/vault/v1/events.proto
Comment thread proto/provlabs/vault/v1/tx.proto
Comment thread proto/provlabs/vault/v1/tx.proto
Comment thread proto/provlabs/vault/v1/vault.proto
Comment thread spec/03_messages.md Outdated
Comment thread types/msgs.go Outdated
Comment thread types/vault.go Outdated
Comment thread keeper/msg_server.go Outdated
Comment thread keeper/msg_server.go Outdated
@nullpointer0x00
Copy link
Copy Markdown
Collaborator Author

@coderabbitai resolve

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

✅ Actions performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

@ProvLabs ProvLabs deleted a comment from coderabbitai Bot Apr 20, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
simulation/operations.go (2)

640-657: ⚠️ Potential issue | 🟡 Minor

Use the selected accepted asset when constructing principal deposits.

Line 640 may select payment_denom, but Line 657 always creates an underlying_asset coin. That can base the amount on one balance and attempt to send another denom.

Proposed fix
-		amount := sdk.NewCoin(vault.UnderlyingAsset, amountInt)
+		amount := sdk.NewCoin(asset, amountInt)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@simulation/operations.go` around lines 640 - 657, The code builds the deposit
coin with vault.UnderlyingAsset even though you previously selected and used a
random asset (asset) for balance checks; update the creation of the deposit coin
to use the selected asset's denom so the coin's denom matches the balance you
sampled. Specifically, in the block around getRandomVaultAsset, balance, portion
and amountInt, replace the sdk.NewCoin(vault.UnderlyingAsset, amountInt)
construction with sdk.NewCoin(asset.Denom, amountInt) (or the appropriate field
name on the selected asset) so the deposit uses the same denom as the sampled
balance.

694-700: ⚠️ Potential issue | 🟡 Minor

Use the selected accepted asset when constructing principal withdrawals.

Line 695 may choose payment_denom, but Line 700 always withdraws underlying_asset; this can make the simulation no-op even when the selected accepted asset has funds.

Proposed fix
-		amount := sdk.NewInt64Coin(vault.UnderlyingAsset, r.Int63n(balance.Amount.Int64()))
+		amount := sdk.NewInt64Coin(asset, r.Int63n(balance.Amount.Int64()))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@simulation/operations.go` around lines 694 - 700, The simulation is picking a
random accepted asset via getRandomVaultAsset but then always builds the
withdrawal coin using vault.UnderlyingAsset, which can cause a no-op; change the
coin construction to use the selected asset denomination (the variable asset)
and its balance when creating amount in the principal withdrawal flow (around
principalAddr, getRandomVaultAsset, balance, amount and
MsgWithdrawPrincipalFundsRequest) so the sdk.NewCoin/ NewInt64Coin uses asset as
the denom and the random amount is based on balance.Amount.
keeper/msg_server_test.go (2)

722-782: ⚠️ Potential issue | 🟡 Minor

Mint enough shares for the swap-out max-limit case.

The “above maximum” case burns 150_000_000 shares, but setup mints only 100_000_000. Increase the setup deposit or top up that case so the expected failure is only the max-limit violation, not insufficient shares.

Proposed test isolation fix
-	initialAssets := sdk.NewInt64Coin(underlyingDenom, 100)
+	initialAssets := sdk.NewInt64Coin(underlyingDenom, 150)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@keeper/msg_server_test.go` around lines 722 - 782, The "above maximum" test
currently burns 150_000_000 shares but the setup only mints 100_000_000 via
initialAssets; adjust the setup so the vault mints at least 150_000_000 shares
(e.g., increase initialAssets or add a top-up FundAccount + SwapIn for the
specific test case) so the failure is due solely to the MaxSwapOutValue check;
update the test case that calls setup(true, false, "", "100") or add a per-test
FundAccount/SwapIn using vaultAddr and owner to ensure sufficient mintedShares
before invoking MsgSwapOutRequest.

491-541: ⚠️ Potential issue | 🟡 Minor

Isolate the swap-in max-limit assertion from balance failures.

The “above maximum” case sends 150 underlying, but setup funds the owner with only assets (100). This makes the test depend on max-limit validation running before balance validation.

Proposed test isolation fix
-	assets := sdk.NewInt64Coin(underlyingDenom, 100)
+	assets := sdk.NewInt64Coin(underlyingDenom, 150)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@keeper/msg_server_test.go` around lines 491 - 541, The "above maximum" test
relies on owner having only `assets` (100) which causes a balance failure before
the vault max-limit check; update the test setup so the owner is funded with
more than the attempted swap amount for that case (e.g., fund with >=150) or
override the `assets` used in FundAccount for the specific "swap in above
maximum value" case so the MsgSwapInRequest (types.MsgSwapInRequest) with 150
triggers the vault max validation rather than a balance error; locate the
closure `setup(swapInEnabled, vaultPaused bool, minSwapIn, maxSwapIn string)`
and the test entry in `tests := []msgServerTestCase[...]` to apply this change.
♻️ Duplicate comments (1)
proto/provlabs/vault/v1/tx.proto (1)

126-133: ⚠️ Potential issue | 🟡 Minor

Document create-time clear/block semantics for all swap limits.

These CreateVault fields should mirror the update-message docs: non-negative values, ""/"0" clears minimums, "" clears maximums, and "0" blocks swap-in/out for maximums.

Suggested proto doc update
-  // min_swap_in_value is the minimum value required for a deposit, measured in the underlying_asset.
+  // min_swap_in_value is the minimum value required for a deposit, measured in the underlying_asset.
+  // - Values must be non-negative (>= 0).
+  // - An empty string "" or "0" represents no minimum.
   string min_swap_in_value = 6 [(cosmos_proto.scalar) = "cosmos.IntString"];
-  // min_swap_out_value is the minimum value required for a withdrawal, measured in the underlying_asset.
+  // min_swap_out_value is the minimum value required for a withdrawal, measured in the underlying_asset.
+  // - Values must be non-negative (>= 0).
+  // - An empty string "" or "0" represents no minimum.
   string min_swap_out_value = 7 [(cosmos_proto.scalar) = "cosmos.IntString"];
-  // max_swap_in_value is the maximum value allowed for a deposit, measured in the underlying_asset.
+  // max_swap_in_value is the maximum value allowed for a deposit, measured in the underlying_asset.
+  // - Values must be non-negative (>= 0).
+  // - An empty string "" represents no maximum.
+  // - A value of "0" blocks all deposits.
   string max_swap_in_value = 8 [(cosmos_proto.scalar) = "cosmos.IntString"];
-  // max_swap_out_value is the maximum value allowed for a withdrawal, measured in the underlying_asset.
+  // max_swap_out_value is the maximum value allowed for a withdrawal, measured in the underlying_asset.
+  // - Values must be non-negative (>= 0).
+  // - An empty string "" represents no maximum.
+  // - A value of "0" blocks all withdrawals.
   string max_swap_out_value = 9 [(cosmos_proto.scalar) = "cosmos.IntString"];

As per coding guidelines, proto/**/*.proto: “All fields and messages in .proto files must be thoroughly documented, as these propagate to generated code and public API specs”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@proto/provlabs/vault/v1/tx.proto` around lines 126 - 133, Create-time
semantics for the CreateVault swap limit fields (min_swap_in_value,
min_swap_out_value, max_swap_in_value, max_swap_out_value) are undocumented;
update the proto comments for these fields in the CreateVault message to mirror
the update-message docs: state that values must be non-negative, that an empty
string "" or "0" clears minimums as specified, that "" clears maximums and "0"
blocks swap-in/out for maximums, and include explicit examples for clearing vs
blocking; reference the exact field names (min_swap_in_value,
min_swap_out_value, max_swap_in_value, max_swap_out_value) and mention
CreateVault so readers can find the fields.
🧹 Nitpick comments (2)
simulation/rand.go (1)

416-436: Drop the unused keeper parameter from the helper.

k keeper.Keeper is not used in getRandomManagementAuthority; removing it will simplify every call site.

Small cleanup
-func getRandomManagementAuthority(r *rand.Rand, k keeper.Keeper, ctx sdk.Context, vault *types.VaultAccount, accs []simtypes.Account) (simtypes.Account, error) {
+func getRandomManagementAuthority(r *rand.Rand, ctx sdk.Context, vault *types.VaultAccount, accs []simtypes.Account) (simtypes.Account, error) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@simulation/rand.go` around lines 416 - 436, The function
getRandomManagementAuthority currently accepts an unused parameter k of type
keeper.Keeper; remove this parameter from the function signature
(getRandomManagementAuthority(r *rand.Rand, ctx sdk.Context, vault
*types.VaultAccount, accs []simtypes.Account) ...) and update every call site to
stop passing the keeper; also update any tests or helper callers and imports if
necessary so builds pass after deleting the unused k argument.
keeper/msg_server_test.go (1)

1118-1148: Add negative-value rows for the new limit update endpoints.

The failure tables cover non-numeric values, but "-1" is a separate edge case: it can parse while still being an invalid limit. Please add negative cases for min/max swap-in/out updates to lock in the “no negative limits” behavior.

As per coding guidelines, "**/*_test.go: Table-driven tests are mandatory for unit and integration tests to ensure exhaustive coverage of edge cases."

Also applies to: 1257-1287, 1396-1426, 1535-1565

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@keeper/msg_server_test.go` around lines 1118 - 1148, Add table rows that
assert negative numeric inputs are rejected: for the tests slice of
msgServerTestCase for MsgUpdateMinSwapInValueRequest, add a case with
MinSwapInValue set to "-1" (Authority admin, VaultAddress
types.GetVaultAddress(share).String()) and an expectedErrSubstrs entry
indicating the "negative" or "no negative limits" rejection (e.g., "negative" or
"invalid min swap in value" depending on existing error messages). Repeat the
same pattern for the other limit-update test tables referenced (the Min/Max
swap-in/out update tables around the other noted blocks) so each has an explicit
negative-value test row verifying the “no negative limits” behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@keeper/vault.go`:
- Around line 530-616: The setters (SetMinSwapInValue, SetMinSwapOutValue,
SetMaxSwapInValue, SetMaxSwapOutValue) only validate their single argument,
allowing admins to create invalid ranges (min > max); update each setter to
check the new value against the opposite bound stored on vault before calling
SetVaultAccount—e.g., in SetMinSwapInValue ensure new min <= existing
MaxSwapInValue (unless MaxSwapInValue == "0" which should remain a valid “block
all” sentinel), and similarly validate SetMinSwapOutValue against
MaxSwapOutValue, SetMaxSwapInValue against MinSwapInValue, and
SetMaxSwapOutValue against MinSwapOutValue; if the pair is invalid return an
error and do not persist, mirroring the interest-rate validation pattern already
used elsewhere.
- Around line 625-637: Parsing of stored limits (MinSwapInValue/MaxSwapInValue)
currently ignores NewIntFromString failures and treats "0" max as allowing a
zero swap; change both AllowSwapInAmount and AllowSwapOutAmount to fail-closed:
attempt NewIntFromString for MinSwapInValue/MaxSwapInValue and if parsing
returns !ok return false with a parse error message; after successful parse, for
min check the existing LT(minLimit) behavior, and for max treat a parsed
maxLimit that .IsZero() as blocking all swaps (return false) rather than
allowing equality — i.e., return false immediately if maxLimit.IsZero(),
otherwise keep the GT(maxLimit) check; apply identical parsing+fail-closed logic
for both min and max in the referenced functions.

---

Outside diff comments:
In `@keeper/msg_server_test.go`:
- Around line 722-782: The "above maximum" test currently burns 150_000_000
shares but the setup only mints 100_000_000 via initialAssets; adjust the setup
so the vault mints at least 150_000_000 shares (e.g., increase initialAssets or
add a top-up FundAccount + SwapIn for the specific test case) so the failure is
due solely to the MaxSwapOutValue check; update the test case that calls
setup(true, false, "", "100") or add a per-test FundAccount/SwapIn using
vaultAddr and owner to ensure sufficient mintedShares before invoking
MsgSwapOutRequest.
- Around line 491-541: The "above maximum" test relies on owner having only
`assets` (100) which causes a balance failure before the vault max-limit check;
update the test setup so the owner is funded with more than the attempted swap
amount for that case (e.g., fund with >=150) or override the `assets` used in
FundAccount for the specific "swap in above maximum value" case so the
MsgSwapInRequest (types.MsgSwapInRequest) with 150 triggers the vault max
validation rather than a balance error; locate the closure `setup(swapInEnabled,
vaultPaused bool, minSwapIn, maxSwapIn string)` and the test entry in `tests :=
[]msgServerTestCase[...]` to apply this change.

In `@simulation/operations.go`:
- Around line 640-657: The code builds the deposit coin with
vault.UnderlyingAsset even though you previously selected and used a random
asset (asset) for balance checks; update the creation of the deposit coin to use
the selected asset's denom so the coin's denom matches the balance you sampled.
Specifically, in the block around getRandomVaultAsset, balance, portion and
amountInt, replace the sdk.NewCoin(vault.UnderlyingAsset, amountInt)
construction with sdk.NewCoin(asset.Denom, amountInt) (or the appropriate field
name on the selected asset) so the deposit uses the same denom as the sampled
balance.
- Around line 694-700: The simulation is picking a random accepted asset via
getRandomVaultAsset but then always builds the withdrawal coin using
vault.UnderlyingAsset, which can cause a no-op; change the coin construction to
use the selected asset denomination (the variable asset) and its balance when
creating amount in the principal withdrawal flow (around principalAddr,
getRandomVaultAsset, balance, amount and MsgWithdrawPrincipalFundsRequest) so
the sdk.NewCoin/ NewInt64Coin uses asset as the denom and the random amount is
based on balance.Amount.

---

Duplicate comments:
In `@proto/provlabs/vault/v1/tx.proto`:
- Around line 126-133: Create-time semantics for the CreateVault swap limit
fields (min_swap_in_value, min_swap_out_value, max_swap_in_value,
max_swap_out_value) are undocumented; update the proto comments for these fields
in the CreateVault message to mirror the update-message docs: state that values
must be non-negative, that an empty string "" or "0" clears minimums as
specified, that "" clears maximums and "0" blocks swap-in/out for maximums, and
include explicit examples for clearing vs blocking; reference the exact field
names (min_swap_in_value, min_swap_out_value, max_swap_in_value,
max_swap_out_value) and mention CreateVault so readers can find the fields.

---

Nitpick comments:
In `@keeper/msg_server_test.go`:
- Around line 1118-1148: Add table rows that assert negative numeric inputs are
rejected: for the tests slice of msgServerTestCase for
MsgUpdateMinSwapInValueRequest, add a case with MinSwapInValue set to "-1"
(Authority admin, VaultAddress types.GetVaultAddress(share).String()) and an
expectedErrSubstrs entry indicating the "negative" or "no negative limits"
rejection (e.g., "negative" or "invalid min swap in value" depending on existing
error messages). Repeat the same pattern for the other limit-update test tables
referenced (the Min/Max swap-in/out update tables around the other noted blocks)
so each has an explicit negative-value test row verifying the “no negative
limits” behavior.

In `@simulation/rand.go`:
- Around line 416-436: The function getRandomManagementAuthority currently
accepts an unused parameter k of type keeper.Keeper; remove this parameter from
the function signature (getRandomManagementAuthority(r *rand.Rand, ctx
sdk.Context, vault *types.VaultAccount, accs []simtypes.Account) ...) and update
every call site to stop passing the keeper; also update any tests or helper
callers and imports if necessary so builds pass after deleting the unused k
argument.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aacaf6c6-cb79-4ee2-8d79-a3e50ebc1ad0

📥 Commits

Reviewing files that changed from the base of the PR and between 5d98d4a and cb2f2a1.

⛔ Files ignored due to path filters (4)
  • api/provlabs/vault/v1/tx_grpc.pb.go is excluded by !**/*.pb.go
  • types/events.pb.go is excluded by !**/*.pb.go
  • types/tx.pb.go is excluded by !**/*.pb.go
  • types/vault.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (19)
  • api/provlabs/vault/v1/events.pulsar.go
  • api/provlabs/vault/v1/tx.pulsar.go
  • api/provlabs/vault/v1/vault.pulsar.go
  • keeper/msg_server.go
  • keeper/msg_server_test.go
  • keeper/query_server_test.go
  • keeper/suite_test.go
  • keeper/vault.go
  • module.go
  • proto/provlabs/vault/v1/events.proto
  • proto/provlabs/vault/v1/tx.proto
  • proto/provlabs/vault/v1/vault.proto
  • simulation/operations.go
  • simulation/rand.go
  • spec/02_state.md
  • spec/03_messages.md
  • types/events.go
  • types/msgs.go
  • types/vault.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • spec/02_state.md
  • keeper/query_server_test.go
  • proto/provlabs/vault/v1/vault.proto
  • types/vault.go
  • proto/provlabs/vault/v1/events.proto
  • spec/03_messages.md
  • types/msgs.go
  • keeper/suite_test.go

Comment thread keeper/vault.go
Comment thread keeper/vault.go Outdated
@nullpointer0x00
Copy link
Copy Markdown
Collaborator Author

@coderabbitai resolve

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

✅ Actions performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

@ProvLabs ProvLabs deleted a comment from coderabbitai Bot Apr 20, 2026
Comment thread proto/provlabs/vault/v1/tx.proto Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
spec/03_messages.md (1)

78-81: ⚠️ Potential issue | 🟡 Minor

Mirror the proto swap-limit semantics in the spec.

Line 78 and the new update sections don’t tell clients that all swap-limit values are measured in the vault’s underlying_asset; the CreateVault section also omits the min/max clearing rules and max positivity constraint.

Suggested docs update
-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, optional payment denom, withdrawal delay, and optional minimum/maximum swap values measured in the vault’s `underlying_asset`.
+For `min_swap_in_value` and `min_swap_out_value`, an empty string (`""`) or `"0"` means no minimum.
+For `max_swap_in_value` and `max_swap_out_value`, an empty string (`""`) means no maximum; set values must be positive (`> 0`).
@@
-Admin or Asset Manager. Updates the minimum allowed value for a swap-in operation.
+Admin or Asset Manager. Updates the minimum allowed value for a swap-in operation, measured in the vault’s `underlying_asset`.
@@
-Admin or Asset Manager. Updates the minimum allowed value for a swap-out operation.
+Admin or Asset Manager. Updates the minimum allowed value for a swap-out operation, measured in the vault’s `underlying_asset`.
@@
-Admin or Asset Manager. Updates the maximum allowed value for a swap-in operation.
+Admin or Asset Manager. Updates the maximum allowed value for a swap-in operation, measured in the vault’s `underlying_asset`.
@@
-Admin or Asset Manager. Updates the maximum allowed value for a swap-out operation.
+Admin or Asset Manager. Updates the maximum allowed value for a swap-out operation, measured in the vault’s `underlying_asset`.

Also applies to: 153-190

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec/03_messages.md` around lines 78 - 81, The spec's MsgCreateVaultRequest
and related update sections must explicitly state that all swap-limit fields
(min_swap_in_value, min_swap_out_value, max_swap_in_value, max_swap_out_value)
are denominated in the vault's underlying_asset, and must document the same
min/max clearing rules and the "max must be positive" constraint used in the
proto: update the CreateVault description for MsgCreateVaultRequest and the
corresponding update sections to (1) state units = underlying_asset, (2) explain
that unspecified min values clear to zero and unspecified max values
clear/unset, and (3) assert that any provided max_swap_* value must be > 0;
reference MsgCreateVaultRequest and the swap-limit field names so clients can
locate and apply the same semantics across the spec.
🧹 Nitpick comments (1)
keeper/vault.go (1)

532-533: Wrap swap-limit validation errors with setter context.

The new setters return types.ValidateSwapLimits errors directly, unlike the surrounding setters that add operation context before returning.

Proposed cleanup
 	if err := types.ValidateSwapLimits(minSwapIn, vault.MaxSwapInValue, true); err != nil {
-		return err
+		return fmt.Errorf("failed to validate swap-in value limits: %w", err)
 	}
@@
 	if err := types.ValidateSwapLimits(minSwapOut, vault.MaxSwapOutValue, false); err != nil {
-		return err
+		return fmt.Errorf("failed to validate swap-out value limits: %w", err)
 	}
@@
 	if err := types.ValidateSwapLimits(vault.MinSwapInValue, maxSwapIn, true); err != nil {
-		return err
+		return fmt.Errorf("failed to validate swap-in value limits: %w", err)
 	}
@@
 	if err := types.ValidateSwapLimits(vault.MinSwapOutValue, maxSwapOut, false); err != nil {
-		return err
+		return fmt.Errorf("failed to validate swap-out value limits: %w", err)
 	}

As per coding guidelines, "**/*.go: Always wrap errors with context using fmt.Errorf(\"failed to [action]: %w\", err) pattern."

Also applies to: 548-549, 564-565, 580-581

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@keeper/vault.go` around lines 532 - 533, The calls to
types.ValidateSwapLimits (e.g., the invocation using minSwapIn and
vault.MaxSwapInValue) return errors directly; wrap each returned error with
contextual setter information using fmt.Errorf("failed to set [field]: %w", err)
before returning so the caller knows which setter failed. Update the specific
ValidateSwapLimits call shown and the other occurrences referenced (the calls at
the other three sites) to return a wrapped error that names the setter operation
(for example "failed to set MinSwapIn" or the appropriate field name) while
preserving the original error via %w.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@types/msgs_test.go`:
- Around line 1615-1805: The test tables for MsgUpdate* swap-limit validations
are asymmetric and missing invalid VaultAddress, invalid authority and
non-integer cases across MsgUpdateMinSwapOutValueRequest,
MsgUpdateMaxSwapInValueRequest, and MsgUpdateMaxSwapOutValueRequest, and the
assertion blocks lack descriptive messages; update each of the four table-driven
tests (tables for MsgUpdateMinSwapInValueRequest,
MsgUpdateMinSwapOutValueRequest, MsgUpdateMaxSwapInValueRequest,
MsgUpdateMaxSwapOutValueRequest) to include the same edge cases: invalid
VaultAddress, invalid authority, non-integer value, negative value and
zero-if-blocked as applicable, and then replace the repeated assertion block
that calls ValidateBasic() with a single shared assertion that includes a
descriptive failure message (e.g., include tt.name and expectedErr in the
assert.NoError/assert.Error/assert.Contains messages) so failures self-diagnose;
ensure you reference and update the ValidateBasic() checks for those message
structs accordingly.

In `@types/msgs.go`:
- Around line 42-43: AllRequestMsgs is missing the new max-swap update message
types, causing asymmetry with the min-swap entries; add
(*MsgUpdateMaxSwapInValueRequest)(nil) and
(*MsgUpdateMaxSwapOutValueRequest)(nil) to the AllRequestMsgs slice/registry so
the max update messages are registered alongside
(*MsgUpdateMinSwapInValueRequest)(nil) and
(*MsgUpdateMinSwapOutValueRequest)(nil), ensuring downstream message/interface
registration sees the new types.

In `@types/vault_test.go`:
- Around line 884-889: The assertions around tt.expectedErr and err lack
descriptive failure messages; update the assert calls (assert.NoError,
assert.Error, assert.Contains) to include a clear message that references the
test case (e.g., tt.name or similar), the expected error (tt.expectedErr) and
the actual error (err) so failures show context and expected vs actual; locate
the assertion block using symbols tt.expectedErr, err,
assert.NoError/assert.Error/assert.Contains and add formatted messages via t or
fmt.Sprintf to each assertion call.

In `@types/vault.go`:
- Around line 71-72: Update the Godoc for NewVaultAccount to reflect current
swap-limit semantics and to document the new swap-limit parameters: explain that
maxSwapInValue/maxSwapOutValue of "0" are rejected by validation (callers should
toggle messages instead), and describe the purpose and units/format of
minSwapInValue, minSwapOutValue, maxSwapInValue, and maxSwapOutValue; reference
the NewVaultAccount signature and mention withdrawalDelay and aumFeeBips briefly
to keep context about related parameters.

---

Duplicate comments:
In `@spec/03_messages.md`:
- Around line 78-81: The spec's MsgCreateVaultRequest and related update
sections must explicitly state that all swap-limit fields (min_swap_in_value,
min_swap_out_value, max_swap_in_value, max_swap_out_value) are denominated in
the vault's underlying_asset, and must document the same min/max clearing rules
and the "max must be positive" constraint used in the proto: update the
CreateVault description for MsgCreateVaultRequest and the corresponding update
sections to (1) state units = underlying_asset, (2) explain that unspecified min
values clear to zero and unspecified max values clear/unset, and (3) assert that
any provided max_swap_* value must be > 0; reference MsgCreateVaultRequest and
the swap-limit field names so clients can locate and apply the same semantics
across the spec.

---

Nitpick comments:
In `@keeper/vault.go`:
- Around line 532-533: The calls to types.ValidateSwapLimits (e.g., the
invocation using minSwapIn and vault.MaxSwapInValue) return errors directly;
wrap each returned error with contextual setter information using
fmt.Errorf("failed to set [field]: %w", err) before returning so the caller
knows which setter failed. Update the specific ValidateSwapLimits call shown and
the other occurrences referenced (the calls at the other three sites) to return
a wrapped error that names the setter operation (for example "failed to set
MinSwapIn" or the appropriate field name) while preserving the original error
via %w.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 14c0c2c4-40e9-41a9-a4c1-c084bf39d1cf

📥 Commits

Reviewing files that changed from the base of the PR and between cb2f2a1 and 426089f.

⛔ Files ignored due to path filters (3)
  • types/events.pb.go is excluded by !**/*.pb.go
  • types/tx.pb.go is excluded by !**/*.pb.go
  • types/vault.pb.go is excluded by !**/*.pb.go
📒 Files selected for processing (15)
  • api/provlabs/vault/v1/events.pulsar.go
  • api/provlabs/vault/v1/tx.pulsar.go
  • api/provlabs/vault/v1/vault.pulsar.go
  • keeper/msg_server_test.go
  • keeper/vault.go
  • proto/provlabs/vault/v1/events.proto
  • proto/provlabs/vault/v1/tx.proto
  • proto/provlabs/vault/v1/vault.proto
  • simulation/operations.go
  • simulation/rand.go
  • spec/03_messages.md
  • types/msgs.go
  • types/msgs_test.go
  • types/vault.go
  • types/vault_test.go
✅ Files skipped from review due to trivial changes (2)
  • proto/provlabs/vault/v1/events.proto
  • api/provlabs/vault/v1/vault.pulsar.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • proto/provlabs/vault/v1/vault.proto

Comment thread types/msgs_test.go
Comment thread types/msgs.go
Comment thread types/vault_test.go
Comment thread types/vault.go
@ProvLabs ProvLabs deleted a comment from coderabbitai Bot Apr 20, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Warning

Rate limit exceeded

@nullpointer0x00 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 27 minutes and 28 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 27 minutes and 28 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c6d15e6a-9e2b-4b3a-9db2-a7be2a895746

📥 Commits

Reviewing files that changed from the base of the PR and between 0f650c8 and 245f962.

📒 Files selected for processing (6)
  • keeper/msg_server_test.go
  • keeper/vault.go
  • types/msgs.go
  • types/msgs_test.go
  • types/vault.go
  • types/vault_test.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nullpointer0x00/39-minimums-for-swap-in-out-amounts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nullpointer0x00 nullpointer0x00 merged commit 510b966 into main Apr 21, 2026
13 checks passed
@nullpointer0x00 nullpointer0x00 deleted the nullpointer0x00/39-minimums-for-swap-in-out-amounts branch April 21, 2026 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Minimums for Deposit and Withdraw

2 participants