-
Notifications
You must be signed in to change notification settings - Fork 237
fix: distribute only INIT token #409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughWalkthroughThe changes refactor how internal keepers and components are accessed in the application by moving getter methods into a dedicated file and introducing a new interface for upgrade handling. Upgrade handler registration is now delegated to a versioned package, and the distribution module is updated to interact with custom keeper interfaces and focus fee allocation on a single base denomination. The Move bank keeper is enhanced to fetch balances via Move VM view functions with pagination support and improved type consistency. Changes
Sequence Diagram(s)sequenceDiagram
participant App as InitiaApp
participant Upgrades as upgrades/v1_1_1
participant MoveKeeper as MoveKeeper
App->>Upgrades: RegisterUpgradeHandlers(app)
Upgrades->>App: GetUpgradeKeeper()
Upgrades->>App: GetMoveKeeper()
Upgrades->>App: GetConfigurator()
Upgrades->>App: GetModuleManager()
Upgrades->MoveKeeper: Publish module bundle (decoded from base64)
MoveKeeper-->>Upgrades: Result (success or error)
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
⏰ Context from checks skipped due to timeout of 90000ms (3)
🔇 Additional comments (8)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
app/app.go
(2 hunks)app/getters.go
(1 hunks)app/upgrade.go
(0 hunks)app/upgrades/expected_app.go
(1 hunks)app/upgrades/v1_1_1/modules.go
(1 hunks)app/upgrades/v1_1_1/upgrade.go
(1 hunks)x/distribution/keeper/allocation.go
(1 hunks)x/distribution/keeper/common_test.go
(1 hunks)x/distribution/keeper/keeper.go
(2 hunks)x/distribution/module.go
(1 hunks)x/distribution/types/expected_keepers.go
(2 hunks)
💤 Files with no reviewable changes (1)
- app/upgrade.go
🧰 Additional context used
🧬 Code Graph Analysis (4)
x/distribution/keeper/keeper.go (1)
x/distribution/types/expected_keepers.go (2)
BankKeeper
(40-43)StakingKeeper
(15-32)
x/distribution/module.go (1)
x/distribution/types/expected_keepers.go (1)
BankKeeper
(40-43)
app/upgrades/v1_1_1/upgrade.go (2)
app/upgrades/expected_app.go (1)
InitiaApp
(11-18)api/initia/move/v1/types.pulsar.go (1)
UpgradePolicy_COMPATIBLE
(5917-5917)
app/app.go (1)
app/upgrades/v1_1_1/upgrade.go (1)
RegisterUpgradeHandlers
(19-48)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Run test and upload codecov
- GitHub Check: golangci-lint
- GitHub Check: Analyze (go)
🔇 Additional comments (17)
app/upgrades/v1_1_1/modules.go (1)
5-12
: LGTM: Well-structured module definition.The variable structure is clean and the comments clearly identify each Move module. The approach of storing base64-encoded modules as strings is appropriate for embedding binary data.
x/distribution/keeper/common_test.go (1)
581-583
: LGTM: Proper test implementation.The
BaseDenom
method correctly delegates to the embeddedmoveKeeper
, maintaining consistency with the test keeper's delegation pattern. This supports testing of the new base denomination functionality introduced in the distribution keeper.x/distribution/module.go (1)
180-180
: LGTM: Consistent interface upgrade.The change from
types.BankKeeper
tocustomtypes.BankKeeper
aligns with the custom interface extension that adds theGetBalance
method. This is necessary to support the new base denomination functionality while maintaining backward compatibility.x/distribution/keeper/keeper.go (2)
26-26
: LGTM: Keeper field type update.The change from
types.BankKeeper
tocustomtypes.BankKeeper
is consistent with the interface extension that adds balance querying capabilities for the base denomination functionality.
52-52
: LGTM: Constructor parameter consistency.The
NewKeeper
constructor parameter type update matches the struct field change, maintaining consistency across the keeper implementation. This enables the distribution keeper to utilize the enhanced bank keeper interface.x/distribution/keeper/allocation.go (2)
43-50
: LGTM: Correctly implements base denomination restriction.The changes successfully implement the PR objective by restricting fee collection to only the base denomination (INIT token). The logic properly:
- Retrieves the base denomination via the dex keeper
- Gets only the balance for that specific denomination
- Includes proper error handling for the base denomination retrieval
This prevents malicious dispatchable assets from disrupting the distribution process.
53-53
:✅ Verification successful
Verify transfer logic consistency.
The transfer now uses
sdk.NewCoins(feesCollectedInt)
to explicitly wrap the single base denomination coin. This is correct, but ensure that this change doesn't introduce any edge cases where the fee collector module might have a non-zero balance in other denominations after thebeforeAllocateTokens
swap operation.
🏁 Script executed:
#!/bin/bash # Search for other usages of SendCoinsFromModuleToModule in distribution to verify consistency rg -A 3 -B 3 "SendCoinsFromModuleToModule.*distribution" --type goLength of output: 68
🏁 Script executed:
#!/bin/bash set -eo pipefail # 1. Search all usages of SendCoinsFromModuleToModule across the repo rg "SendCoinsFromModuleToModule" -A3 -B3 --type go # 2. Locate the beforeAllocateTokens function to inspect its logic rg "beforeAllocateTokens" -n --type go # 3. Find the declaration of feesCollectedInt to confirm its type rg "feesCollectedInt" -n --type goLength of output: 11451
🏁 Script executed:
#!/bin/bash set -eo pipefail # Display the beforeAllocateTokens function to verify swap logic rg -A30 -B0 "func (k Keeper) beforeAllocateTokens" x/distribution/keeper/allocation.goLength of output: 107
🏁 Script executed:
#!/bin/bash set -eo pipefail # Dump the beforeAllocateTokens function with surrounding context rg -n -C50 "beforeAllocateTokens" x/distribution/keeper/allocation.goLength of output: 3618
All fee denominations are swapped before transfer—no leftover coins
The
beforeAllocateTokens
method (lines 18–27) iterates overGetAllBalances
and callsdexKeeper.SwapToBase
for every coin, ensuring that only the base denomination remains in the fee‐collector account. Immediately after, we read the base‐denom balance and wrap it insdk.NewCoins
forSendCoinsFromModuleToModule
. This guarantees no non‐base coins are ever transferred.No changes required.
app/upgrades/v1_1_1/upgrade.go (1)
23-24
: Excellent context documentation.The comment clearly links this upgrade to the movevm PR that introduced dispatchable fungible assets, providing valuable context for why this upgrade is needed alongside the distribution changes.
x/distribution/types/expected_keepers.go (2)
37-38
: Well-designed interface extension.The addition of
BaseDenom
method to theDexKeeper
interface is clean and necessary for the security fix. The method signature appropriately returns both the denomination string and an error for proper error handling.
40-43
: Excellent use of interface embedding.The new
BankKeeper
interface cleanly extends the existing distribution bank keeper interface by embedding it and adding the requiredGetBalance
method. This maintains compatibility while providing the specific functionality needed for the base denomination restriction.app/upgrades/expected_app.go (1)
11-18
: Clean interface design for upgrade system.The
InitiaApp
interface properly defines the contract for upgrade handlers, providing access to essential keepers (Account, Move, Upgrade) and module management components. The interface follows good design principles by exposing only what's needed for upgrade operations.app/app.go (2)
58-58
: Import addition looks good.The import for the new upgrade package is correctly added to support the new upgrade handler registration approach.
251-251
:✅ Verification successful
Verify the upgrade handler architecture change.
The change from
app.RegisterUpgradeHandlers(app.configurator)
toupgrades_v1_1_1.RegisterUpgradeHandlers(app)
represents a significant architectural shift. The new approach passes the entire app instance instead of just the configurator, which allows the upgrade handler to access multiple keepers (AccountKeeper, MoveKeeper, UpgradeKeeper) as seen in the upgrade function.This change appears correct based on the relevant code snippets, but ensure that:
- The old
RegisterUpgradeHandlers
method has been properly removed from theInitiaApp
struct- All necessary getters are available in the new
app/getters.go
file to support the upgrade handler's requirements
🏁 Script executed:
#!/bin/bash # Description: Verify that the old RegisterUpgradeHandlers method is removed and the new upgrade interface is properly implemented # Test 1: Check if old RegisterUpgradeHandlers method still exists in the app echo "=== Checking for old RegisterUpgradeHandlers method ===" rg -A 5 "func.*RegisterUpgradeHandlers" --type go # Test 2: Verify the upgrade interface implementation echo "=== Checking upgrade interface usage ===" rg -A 10 "upgrades_v1_1_1\.RegisterUpgradeHandlers" --type go # Test 3: Check if the expected app interface is properly defined echo "=== Checking expected app interface ===" fd "expected_app.go" --type f --exec cat {}Length of output: 1974
Upgrade handler architecture change verified
All checks pass:
- The legacy
RegisterUpgradeHandlers
method on the app type is gone (only the free function inapp/upgrades/v1_1_1/upgrade.go
remains).- The new call
upgrades_v1_1_1.RegisterUpgradeHandlers(app)
is correctly invoked inapp/app.go
.- The
InitiaApp
interface in the upgrades package definesGetAccountKeeper
,GetMoveKeeper
,GetUpgradeKeeper
,GetConfigurator
, andGetModuleManager
, satisfying all handler requirements.No further changes required.
app/getters.go (4)
1-18
: Good code organization and import structure.The extraction of getter methods into a dedicated file improves code organization and separates concerns nicely. The import statements are well-organized and include all necessary dependencies for the getter methods.
20-78
: Getter methods implementation looks correct.All getter methods follow a consistent pattern and correctly return the corresponding fields from the
InitiaApp
struct. The methods provide proper access to:
- Core components (BaseApp, AccountKeeper, StakingKeeper)
- Specialized keepers (MoveKeeper, UpgradeKeeper, IBC-related keepers)
- Configuration components (TxConfig, Configurator, ModuleManager)
The implementation aligns with the interface requirements mentioned in the AI summary for upgrade handling.
1-85
: Flag inconsistency with PR objectives.The code changes in both files focus on refactoring getter methods and upgrade handlers, but the PR objectives specifically mention "fix: distribute only INIT token" and preventing malicious assets from disrupting staking reward distribution.
These files don't contain any distribution logic or token restriction code. The actual distribution fixes might be in other files not included in this review, or there might be a mismatch between the PR description and the actual changes being reviewed.
Likely an incorrect or invalid review comment.
80-85
:❓ Verification inconclusive
Review CheckStateContextGetter implementation.
The
CheckStateContextGetter
method returns a function that callsapp.GetContextForCheckTx(nil)
. While this follows the expected pattern, passingnil
as the argument might need verification to ensure it's the intended behavior for state checking contexts.
🏁 Script executed:
#!/bin/bash # Description: Verify the usage pattern of GetContextForCheckTx with nil argument # Check how GetContextForCheckTx is used elsewhere in the codebase echo "=== Checking GetContextForCheckTx usage patterns ===" rg -A 3 -B 3 "GetContextForCheckTx" --type go # Check if there are any tests or documentation about the nil parameter echo "=== Checking for related tests or docs ===" rg -A 5 -B 5 "CheckStateContextGetter\|GetContextForCheckTx.*nil" --type goLength of output: 658
🏁 Script executed:
#!/bin/bash # Locate the GetContextForCheckTx method declaration to inspect its parameter type echo "=== Declaration of GetContextForCheckTx with surrounding context ===" rg -n -C3 "func (.*InitiaApp) GetContextForCheckTx" --type goLength of output: 210
Verify GetContextForCheckTx signature and nil parameter
Please double-check that passing
nil
intoapp.GetContextForCheckTx(nil)
is the intended pattern for creating a “check state” context:• Locate the declaration of
GetContextForCheckTx
on*InitiaApp
and confirm its first parameter’s type allows anil
value.
• Ensure that any documentation or tests forGetContextForCheckTx
cover thenil
case and that it produces a validsdk.Context
for state checks.
• Ifnil
is not officially supported, consider initializing with an explicit default or overloading the method to avoid ambiguity.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #409 +/- ##
==========================================
+ Coverage 40.15% 40.33% +0.18%
==========================================
Files 295 296 +1
Lines 27726 27882 +156
==========================================
+ Hits 11132 11246 +114
- Misses 14883 14898 +15
- Partials 1711 1738 +27
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (1)
x/move/keeper/bank_test.go (1)
86-92
:⚠️ Potential issueSame compilation issue in second test
Apply the identical correction here:
-for i := range tokenNum { +for i := 0; i < tokenNum; i++ {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
x/move/keeper/bank.go
(6 hunks)x/move/keeper/bank_test.go
(2 hunks)x/move/keeper/fungible_asset.go
(1 hunks)x/move/types/connector.go
(2 hunks)x/move/types/errors.go
(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- x/move/types/errors.go
- x/move/keeper/fungible_asset.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
x/move/types/connector.go (1)
x/move/types/keys.go (1)
AddressBytesLength
(31-31)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Run test and upload codecov
- GitHub Check: golangci-lint
- GitHub Check: Analyze (go)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 6
♻️ Duplicate comments (1)
x/move/keeper/bank_test.go (1)
86-92
:⚠️ Potential issueSame compilation issue in second test
Apply the identical correction here:
-for i := range tokenNum { +for i := 0; i < tokenNum; i++ {
🛑 Comments failed to post (6)
x/move/types/connector.go (2)
257-271: 🛠️ Refactor suggestion
Bounds-check before reading length field
ReadTableLengthFromTable
also assumes the raw slice isAddressBytesLength + 8
bytes long. A bad slice will panic here:length, err := DeserializeUint64(bz[cursor : cursor+8])Add the same defensive guard:
func ReadTableLengthFromTable(bz []byte) (math.Int, error) { cursor := 0 // read table handle address cursor += AddressBytesLength + if len(bz) < cursor+8 { + return math.ZeroInt(), errors.Wrap(types.ErrInvalidResponse, "table bytes too short for length") + } // read table length u64 length, err := DeserializeUint64(bz[cursor : cursor+8])🤖 Prompt for AI Agents
In x/move/types/connector.go around lines 257 to 271, the function ReadTableLengthFromTable slices the input byte array without checking if it has enough length, which can cause a panic. Add a bounds check before slicing to ensure the input slice length is at least AddressBytesLength plus 8 bytes. If the slice is too short, return an appropriate error instead of proceeding.
252-256:
⚠️ Potential issueAdd defensive length-check before slicing
bz
ReadTableHandleFromTable
slicesbz[:AddressBytesLength]
without first ensuring thatbz
is at least that long.
If a malformed or truncated byte-array is passed in, the program will panic with an out-of-range slice instead of returning an error.func ReadTableHandleFromTable(bz []byte) (vmtypes.AccountAddress, error) { - return vmtypes.NewAccountAddressFromBytes(bz[:AddressBytesLength]) + if len(bz) < AddressBytesLength { + return vmtypes.AccountAddress{}, errors.Wrap(types.ErrInvalidResponse, "table bytes too short for handle") + } + return vmtypes.NewAccountAddressFromBytes(bz[:AddressBytesLength]) }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.// ReadTableHandleFromTable util function to read table handle from the table raw bytes func ReadTableHandleFromTable(bz []byte) (vmtypes.AccountAddress, error) { if len(bz) < AddressBytesLength { return vmtypes.AccountAddress{}, errors.Wrap(types.ErrInvalidResponse, "table bytes too short for handle") } return vmtypes.NewAccountAddressFromBytes(bz[:AddressBytesLength]) }
🤖 Prompt for AI Agents
In x/move/types/connector.go around lines 252 to 256, the function ReadTableHandleFromTable slices the input byte array bz without checking its length, which can cause a panic if bz is shorter than AddressBytesLength. Add a defensive check at the start of the function to verify that len(bz) is at least AddressBytesLength, and if not, return an appropriate error instead of proceeding with the slice operation.
x/move/keeper/bank.go (3)
161-165:
⚠️ Potential issueUndefined helper
min
causes compilation failure
min(pageReq.Limit, tableLength.Uint64())
will not compile – there is nomin
function in scope andmath.Min
operates on floats.- limit := uint64(100) - if pageReq != nil && pageReq.Limit > 0 { - limit = min(pageReq.Limit, tableLength.Uint64()) - } + limit := uint64(100) + if pageReq != nil && pageReq.Limit > 0 { + limit = pageReq.Limit + if limit > tableLength.Uint64() { + limit = tableLength.Uint64() + } + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.limit := uint64(100) if pageReq != nil && pageReq.Limit > 0 { limit = pageReq.Limit if limit > tableLength.Uint64() { limit = tableLength.Uint64() } }
🤖 Prompt for AI Agents
In x/move/keeper/bank.go around lines 161 to 165, the code uses an undefined min function to limit the page size, causing a compilation error. Replace the call to min with a custom inline comparison that returns the smaller of pageReq.Limit and tableLength.Uint64(), ensuring both values are of the same uint64 type to avoid type mismatches.
107-129:
⚠️ Potential issueCallback early-exit does not stop outer pagination loop
IterateAccountBalances
breaks only the innerfor _, coin
loop when the callback returnstrue
, but the surroundingfor { … }
continues to fetch the next page, defeating the “halt iteration” contract.- for _, coin := range coins { + outerStop := false + for _, coin := range coins { … - if stop, err := cb(coin); err != nil { + if stop, err := cb(coin); err != nil { return err } else if stop { - break + outerStop = true + break } } + + if outerStop { + break + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const fetchLimit = 100 startAfter := "null" for { coins, nextKey, err := k.balances(ctx, userAddr, startAfter, fetchLimit, true) if err != nil { return err } else if len(coins) == 0 { break } outerStop := false for _, coin := range coins { if coin.Amount.IsZero() { continue } if stop, err := cb(coin); err != nil { return err } else if stop { outerStop = true break } } if outerStop { break } // …presumably continue pagination, e.g.: startAfter = nextKey }
🤖 Prompt for AI Agents
In x/move/keeper/bank.go around lines 107 to 129, the callback's early-exit signal only breaks the inner coin iteration loop but does not stop the outer pagination loop, causing unwanted continued fetching. Modify the code so that when the callback returns true, both the inner loop and the outer pagination loop are exited immediately to fully halt iteration as intended.
255-260:
⚠️ Potential issue
for i := range resLength
is invalid – results in build error
range
expects an array/slice/map/string/channel; passing anint
will not compile.- for i := range resLength { + for i := 0; i < resLength; i++ {Apply the same change to any similar loop elsewhere in this file.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.coins := make([]sdk.Coin, 0, resLength) for i := 0; i < resLength; i++ { amount, ok := sdkmath.NewIntFromString(amountArray[i]) if !ok { return nil, nil, moderrors.Wrapf(types.ErrInvalidResponse, "invalid balance amount: %s", amountArray[i]) }
🤖 Prompt for AI Agents
In x/move/keeper/bank.go around lines 255 to 260, the loop uses 'for i := range resLength' where resLength is an int, causing a build error because range requires a collection. Change the loop to 'for i := 0; i < resLength; i++' to iterate correctly over the intended range. Also, search the file for similar loops using 'range' on an int and fix them the same way.
x/move/keeper/bank_test.go (1)
53-59:
⚠️ Potential issueLoop construction invalid – use classic
for
instead ofrange int
for i := range tokenNum { … }
is illegal becauserange
can’t iterate over anint
.-for i := range tokenNum { +for i := 0; i < tokenNum; i++ {Repeat the fix for the identical loop in
Test_GetPaginatedBalances
.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.// create 200 tokens tokenNum := 200 for i := 0; i < tokenNum; i++ { denom := fmt.Sprintf("test%d", i) err = moveBankKeeper.MintCoins(ctx, twoAddr, sdk.NewCoins(sdk.NewInt64Coin(denom, int64(i)))) require.NoError(t, err) }
🤖 Prompt for AI Agents
In x/move/keeper/bank_test.go around lines 53 to 59, the loop uses `for i := range tokenNum` which is invalid because `range` cannot iterate over an integer. Replace this with a classic for loop: `for i := 0; i < tokenNum; i++` to correctly iterate from 0 to tokenNum-1. Apply the same fix to the identical loop in the Test_GetPaginatedBalances function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 6
♻️ Duplicate comments (1)
x/move/keeper/bank_test.go (1)
86-92
:⚠️ Potential issueSame compilation issue in second test
Apply the identical correction here:
-for i := range tokenNum { +for i := 0; i < tokenNum; i++ {
🛑 Comments failed to post (6)
x/move/types/connector.go (2)
257-271: 🛠️ Refactor suggestion
Bounds-check before reading length field
ReadTableLengthFromTable
also assumes the raw slice isAddressBytesLength + 8
bytes long. A bad slice will panic here:length, err := DeserializeUint64(bz[cursor : cursor+8])Add the same defensive guard:
func ReadTableLengthFromTable(bz []byte) (math.Int, error) { cursor := 0 // read table handle address cursor += AddressBytesLength + if len(bz) < cursor+8 { + return math.ZeroInt(), errors.Wrap(types.ErrInvalidResponse, "table bytes too short for length") + } // read table length u64 length, err := DeserializeUint64(bz[cursor : cursor+8])🤖 Prompt for AI Agents
In x/move/types/connector.go around lines 257 to 271, the function ReadTableLengthFromTable slices the input byte array without checking if it has enough length, which can cause a panic. Add a bounds check before slicing to ensure the input slice length is at least AddressBytesLength plus 8 bytes. If the slice is too short, return an appropriate error instead of proceeding.
252-256:
⚠️ Potential issueAdd defensive length-check before slicing
bz
ReadTableHandleFromTable
slicesbz[:AddressBytesLength]
without first ensuring thatbz
is at least that long.
If a malformed or truncated byte-array is passed in, the program will panic with an out-of-range slice instead of returning an error.func ReadTableHandleFromTable(bz []byte) (vmtypes.AccountAddress, error) { - return vmtypes.NewAccountAddressFromBytes(bz[:AddressBytesLength]) + if len(bz) < AddressBytesLength { + return vmtypes.AccountAddress{}, errors.Wrap(types.ErrInvalidResponse, "table bytes too short for handle") + } + return vmtypes.NewAccountAddressFromBytes(bz[:AddressBytesLength]) }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.// ReadTableHandleFromTable util function to read table handle from the table raw bytes func ReadTableHandleFromTable(bz []byte) (vmtypes.AccountAddress, error) { if len(bz) < AddressBytesLength { return vmtypes.AccountAddress{}, errors.Wrap(types.ErrInvalidResponse, "table bytes too short for handle") } return vmtypes.NewAccountAddressFromBytes(bz[:AddressBytesLength]) }
🤖 Prompt for AI Agents
In x/move/types/connector.go around lines 252 to 256, the function ReadTableHandleFromTable slices the input byte array bz without checking its length, which can cause a panic if bz is shorter than AddressBytesLength. Add a defensive check at the start of the function to verify that len(bz) is at least AddressBytesLength, and if not, return an appropriate error instead of proceeding with the slice operation.
x/move/keeper/bank.go (3)
161-165:
⚠️ Potential issueUndefined helper
min
causes compilation failure
min(pageReq.Limit, tableLength.Uint64())
will not compile – there is nomin
function in scope andmath.Min
operates on floats.- limit := uint64(100) - if pageReq != nil && pageReq.Limit > 0 { - limit = min(pageReq.Limit, tableLength.Uint64()) - } + limit := uint64(100) + if pageReq != nil && pageReq.Limit > 0 { + limit = pageReq.Limit + if limit > tableLength.Uint64() { + limit = tableLength.Uint64() + } + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.limit := uint64(100) if pageReq != nil && pageReq.Limit > 0 { limit = pageReq.Limit if limit > tableLength.Uint64() { limit = tableLength.Uint64() } }
🤖 Prompt for AI Agents
In x/move/keeper/bank.go around lines 161 to 165, the code uses an undefined min function to limit the page size, causing a compilation error. Replace the call to min with a custom inline comparison that returns the smaller of pageReq.Limit and tableLength.Uint64(), ensuring both values are of the same uint64 type to avoid type mismatches.
107-129:
⚠️ Potential issueCallback early-exit does not stop outer pagination loop
IterateAccountBalances
breaks only the innerfor _, coin
loop when the callback returnstrue
, but the surroundingfor { … }
continues to fetch the next page, defeating the “halt iteration” contract.- for _, coin := range coins { + outerStop := false + for _, coin := range coins { … - if stop, err := cb(coin); err != nil { + if stop, err := cb(coin); err != nil { return err } else if stop { - break + outerStop = true + break } } + + if outerStop { + break + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const fetchLimit = 100 startAfter := "null" for { coins, nextKey, err := k.balances(ctx, userAddr, startAfter, fetchLimit, true) if err != nil { return err } else if len(coins) == 0 { break } outerStop := false for _, coin := range coins { if coin.Amount.IsZero() { continue } if stop, err := cb(coin); err != nil { return err } else if stop { outerStop = true break } } if outerStop { break } // …presumably continue pagination, e.g.: startAfter = nextKey }
🤖 Prompt for AI Agents
In x/move/keeper/bank.go around lines 107 to 129, the callback's early-exit signal only breaks the inner coin iteration loop but does not stop the outer pagination loop, causing unwanted continued fetching. Modify the code so that when the callback returns true, both the inner loop and the outer pagination loop are exited immediately to fully halt iteration as intended.
255-260:
⚠️ Potential issue
for i := range resLength
is invalid – results in build error
range
expects an array/slice/map/string/channel; passing anint
will not compile.- for i := range resLength { + for i := 0; i < resLength; i++ {Apply the same change to any similar loop elsewhere in this file.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.coins := make([]sdk.Coin, 0, resLength) for i := 0; i < resLength; i++ { amount, ok := sdkmath.NewIntFromString(amountArray[i]) if !ok { return nil, nil, moderrors.Wrapf(types.ErrInvalidResponse, "invalid balance amount: %s", amountArray[i]) }
🤖 Prompt for AI Agents
In x/move/keeper/bank.go around lines 255 to 260, the loop uses 'for i := range resLength' where resLength is an int, causing a build error because range requires a collection. Change the loop to 'for i := 0; i < resLength; i++' to iterate correctly over the intended range. Also, search the file for similar loops using 'range' on an int and fix them the same way.
x/move/keeper/bank_test.go (1)
53-59:
⚠️ Potential issueLoop construction invalid – use classic
for
instead ofrange int
for i := range tokenNum { … }
is illegal becauserange
can’t iterate over anint
.-for i := range tokenNum { +for i := 0; i < tokenNum; i++ {Repeat the fix for the identical loop in
Test_GetPaginatedBalances
.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.// create 200 tokens tokenNum := 200 for i := 0; i < tokenNum; i++ { denom := fmt.Sprintf("test%d", i) err = moveBankKeeper.MintCoins(ctx, twoAddr, sdk.NewCoins(sdk.NewInt64Coin(denom, int64(i)))) require.NoError(t, err) }
🤖 Prompt for AI Agents
In x/move/keeper/bank_test.go around lines 53 to 59, the loop uses `for i := range tokenNum` which is invalid because `range` cannot iterate over an integer. Replace this with a classic for loop: `for i := 0; i < tokenNum; i++` to correctly iterate from 0 to tokenNum-1. Apply the same fix to the identical loop in the Test_GetPaginatedBalances function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Description
In the current distribution module, any token can be distributed as staking rewards. However, following the changes introduced in this PR, which allows fees to be paid with dispatchable fungible assets, we need to restrict the distribution to a specific asset.
The risk arises because anyone can create a dispatchable asset and use it to pay fees. When the distribution module later attempts to distribute that asset as staking rewards, the asset creator could design it in a way that causes the distribution action to fail—potentially leading to a chain halt.
To prevent this, we are updating the logic to restrict staking reward distributions to the INIT token only.
Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
!
in the type prefix if API or client breaking changeReviewers Checklist
All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.
I have...