Skip to content
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

refactor: many-to-one logic #746

Merged
merged 2 commits into from
Oct 17, 2024
Merged

refactor: many-to-one logic #746

merged 2 commits into from
Oct 17, 2024

Conversation

zakir-code
Copy link
Contributor

@zakir-code zakir-code commented Oct 16, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new message types for ERC20 tokens, including ERC20Token, BridgeToken, and IBCToken.
    • Enhanced error handling in genesis initialization and export processes.
    • Added caching functionality for improved performance in the Keeper structure.
  • Bug Fixes

    • Simplified configuration by removing deprecated parameters from the genesis file.
    • Updated error messages for better clarity.
  • Documentation

    • Updated API documentation to reflect the removal of several endpoints and changes in response schemas.
  • Chores

    • Adjusted linting rules to allow fewer 'nolint' comments.
    • Updated dependencies in the project management file.
  • Tests

    • Overhauled test functions for improved structure and clarity.
    • Removed outdated tests related to ERC20 token functionality.

Copy link

coderabbitai bot commented Oct 16, 2024

Walkthrough

This pull request encompasses a series of changes across multiple files, focusing primarily on the ERC20 token handling within the application. Key modifications include the replacement of the TokenPair type with ERC20Token, adjustments to various structures and methods, simplification of configuration parameters, and the introduction of new message types. Additionally, several files related to deprecated functionalities have been removed, and the Makefile has been updated to reflect changes in linting rules. Overall, the changes aim to streamline the ERC20 module and improve its integration within the broader application framework.

Changes

File Path Change Summary
Makefile Updated check-no-lint target to reduce allowed nolint comments from 29 to 26.
api/fx/erc20/v1/genesis.pulsar.go Replaced TokenPair with ERC20Token, updated GenesisState and Params structs, removing certain fields.
api/fx/erc20/v1/types.pulsar.go Introduced new message types: ERC20Token, BridgeToken, IBCToken, and an enum Owner.
app/app_test.go Added new message types to the deprecated map in Test_MsgServiceRouter.
app/encoding_test.go Adjusted assertion in TestRegisterInterfaces from 298 to 293.
app/genesis.go Updated NewDefAppGenesisByDenom function for DenomMetadata population.
app/genesis.json Removed enable_evm_hook and ibc_timeout parameters from erc20 section.
app/interface_registry.json Removed several entries related to fx.erc20 module from TypeURLMap.
app/keepers/keepers.go Refactored NewAppKeeper function and updated initialization of keeper instances.
docs/swagger-ui/swagger.yaml Removed several API endpoints and restructured response schemas for ERC20-related queries.
go.mod Updated dependencies, reintroducing golang.org/x/exp and replacing some dependencies with forked versions.
proto/fx/erc20/v1/erc20.proto Deleted file defining Protocol Buffers schema for ERC20 functionality.
proto/fx/erc20/v1/genesis.proto Updated import statement and changed GenesisState message to use ERC20Token.
proto/fx/erc20/v1/legacy.proto Introduced new message definitions for ERC20 conversions, marked as deprecated.
proto/fx/erc20/v1/query.proto Updated import statement, marked several RPC methods as deprecated, and changed return types.
proto/fx/erc20/v1/types.proto Introduced new Protocol Buffers file defining message types related to ERC20 tokens.
tests/crosschain_suite.go Removed SelectTokenMetadata method.
tests/crosschain_test.go Overhauled CrossChainTest function for structured testing of cross-chain interactions.
tests/erc20_suite.go Removed several methods related to ERC20 token handling.
x/crosschain/keeper/bridge_call_in.go Renamed variables for clarity and altered logic for handling bridge tokens.
x/crosschain/keeper/bridge_call_out.go Updated handling of outgoing bridge calls with new parameters.
x/erc20/keeper/keeper.go Significant restructuring of Keeper struct, including new fields and methods related to ERC20 token management.
x/erc20/keeper/msg_server.go Transitioned from Keeper method receiver to a new msgServer type, altering method signatures and logic.
x/erc20/module.go Removed command methods from AppModuleBasic, updated service registration, and added error handling in InitGenesis and ExportGenesis.
x/erc20/types/errors.go Updated error messages for ErrUndefinedOwner and ErrERC20TokenPairDisabled.
x/erc20/types/events.go Removed several constants related to ERC20 events and attributes.

Possibly related PRs

🐇 In the meadow, we hop with glee,
ERC20 tokens, as bright as can be!
With bridges and tokens, we dance and play,
Simplified paths light up our way.
Hopping through changes, we cheer and sing,
A world of tokens, oh what joy they bring! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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.

Caution

Inline review comments failed to post

🛑 Comments failed to post (81)
x/erc20/keeper/chache.go (1)

1-19: ⚠️ Potential issue

Overall structure is good, but file name contains a typo.

The overall structure of the file is clean and follows Go best practices. The three cache-related methods (HasCache, SetCache, and DeleteCache) are well-organized and consistent in their implementation.

However, there's a typo in the file name:

  • Current: chache.go
  • Correct: cache.go

Please rename the file to correct this typo.

app/app_test.go (1)

28-32: 💡 Codebase verification

Action Required: Deprecated ERC20 message types are still in use.

The verification script found usages of the newly deprecated ERC20 message types in various parts of the codebase:

  • MsgConvertDenom is used in x/erc20/types/... and api/fx/erc20/v1/legacy.pulsar.go.
  • MsgConvertERC20 is used in x/erc20/types/... and api/fx/erc20/v1/legacy.pulsar.go.
  • MsgUpdateDenomAlias is used in x/gov/types/... and api/fx/erc20/v1/legacy.pulsar.go.
  • MsgRegisterERC20 is used in x/gov/types/... and api/fx/erc20/v1/legacy.pulsar.go.
  • MsgRegisterCoin is used in x/gov/types/... and api/fx/erc20/v1/legacy.pulsar.go.

These usages indicate that the deprecated message types are still being referenced elsewhere and may require removal or replacement to fully deprecate them.

🔗 Analysis chain

LGTM: New ERC20 message types added to deprecated map.

The addition of these ERC20-related message types to the deprecated map is consistent with the pull request objectives. This change correctly expands the set of deprecated message types in the context of the message service router test.

To ensure that these newly deprecated message types are not still in use elsewhere in the codebase, please run the following verification script:

This script will search for any remaining usage of these deprecated message types in the Go files of the project, excluding the app/app_test.go file where we expect them to be listed as deprecated.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of newly deprecated ERC20 message types

# Define the deprecated message types
deprecated_types=(
  "MsgConvertDenom"
  "MsgConvertERC20"
  "MsgUpdateDenomAlias"
  "MsgRegisterERC20"
  "MsgRegisterCoin"
)

echo "Checking for usage of deprecated ERC20 message types:"

for type in "${deprecated_types[@]}"; do
  echo "Searching for $type..."
  rg --type go -i "$type" --glob '!app/app_test.go'
done

echo "Verification complete. If no results were found, the deprecated types are not in use elsewhere."

Length of output: 88115

x/crosschain/keeper/bridge_call_in_test.go (1)

12-12: 💡 Codebase verification

⚠️ Potential issue

Multiple Skipped Tests Detected

Several tests have been skipped without sufficient context or tracking:

  • x/crosschain/keeper/bridge_call_in_test.go: suite.T().SkipNow() // todo: re-enable this test
  • testutil/helpers/tools.go: t.Skip(append(msg, "#Please set env LOCAL_TEST=true#")...)
  • tests/integration_test.go: t.Skip("skip integration test")

Please ensure that all skipped tests include clear reasons and are properly tracked, either through descriptive TODO comments or by linking to relevant GitHub issues.

🔗 Analysis chain

Provide more context for skipped test

Skipping tests without a clear reason or timeline can lead to overlooked issues. Please provide more context about why this test is being skipped and when it will be re-enabled. Consider using a more descriptive TODO comment or creating a GitHub issue to track this.

To check if there are other skipped tests, run:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other skipped tests in the codebase

# Test: Search for skipped tests. Expect: No other occurrences of T().SkipNow() or t.Skip().
rg --type go 'T\(\)\.SkipNow\(\)|t\.Skip\('

Length of output: 285

x/crosschain/precompile/contract.go (1)

27-28: 💡 Codebase verification

Issues Found: Remaining erc20Keeper References

The removal of erc20Keeper from the NewPrecompiledContract function has left several residual references in the codebase, which may lead to potential issues:

  • Files with erc20Keeper references:

    • x/crosschain/keeper/outgoing_tx.go
    • x/crosschain/keeper/send_to_fx.go
    • x/crosschain/keeper/grpc_query.go
    • x/crosschain/keeper/bridge_token.go
    • x/crosschain/keeper/many_to_one.go
    • x/crosschain/keeper/bridge_call_in.go
    • x/crosschain/keeper/bridge_call_out.go
    • x/crosschain/keeper/keeper.go
    • x/crosschain/keeper/keeper_test.go
  • TODO/FIXME Comments:

    • x/erc20/types/token.go: Replace with crosschaintypes.NewBridgeToken
    • x/crosschain/keeper/many_to_one.go: Handle error in DeleteCache
    • tests/erc20_suite.go: Implement missing functionality

Next Steps:

  • Refactor Remaining References: Ensure that all instances of erc20Keeper are appropriately refactored or removed to maintain codebase integrity.
  • Address TODOs: Complete the pending tasks indicated by TODO comments to finalize the refactoring process.
  • Update Tests: Modify or add tests in keeper_test.go and erc20_suite.go to reflect the changes and ensure comprehensive coverage.
🔗 Analysis chain

LGTM. Verify impact and update documentation.

The removal of erc20Keeper from the NewPrecompiledContract function and the Keeper struct initialization aligns with the PR objective of refactoring the many-to-one logic. This change simplifies the contract's dependencies.

To ensure this change doesn't introduce any regressions:

  1. Verify that all calls to NewPrecompiledContract have been updated to remove the erc20Keeper argument.
  2. Check if any methods previously using erc20Keeper have been appropriately refactored or removed.

Please update any relevant documentation (e.g., README, API docs) to reflect this change in the contract's initialization.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of NewPrecompiledContract and potential references to erc20Keeper

# Test 1: Check for any remaining calls to NewPrecompiledContract with 4 arguments
echo "Checking for calls to NewPrecompiledContract with 4 arguments:"
rg --type go 'NewPrecompiledContract\([^)]+,[^)]+,[^)]+,[^)]+\)'

# Test 2: Search for any remaining references to erc20Keeper in the package
echo "Checking for remaining references to erc20Keeper:"
rg --type go 'erc20Keeper' ./x/crosschain

# Test 3: Look for any TODO or FIXME comments related to this change
echo "Checking for TODO or FIXME comments related to erc20Keeper removal:"
rg --type go -i 'TODO|FIXME' -C 2 | rg -i 'erc20|ERC20'

Length of output: 4734

x/crosschain/keeper/keeper_v1_test.go (1)

169-173: 💡 Codebase verification

SetToken method is no longer utilized and should be removed

The SetToken method in x/crosschain/keeper/keeper_v1_test.go is defined but not invoked in any test cases after being commented out. To maintain code cleanliness and ensure comprehensive test coverage, it is recommended to:

  1. Remove the SetToken method entirely if it is no longer needed.
  2. Update or remove any related tests that previously relied on this method to prevent potential confusion or maintenance issues.
🔗 Analysis chain

Consider the impact of commenting out the SetToken method

The commented-out SetToken method aligns with the PR objective of refactoring the many-to-one logic. However, this change raises some concerns:

  1. Test coverage may be impacted by removing this functionality without a replacement.
  2. Any tests calling this method might now silently skip important setup steps.

Consider the following suggestions:

  1. If the method is no longer needed, remove it entirely and update all calling tests.
  2. If the functionality is still required but in a different form, provide a placeholder implementation or update the method to reflect the new logic.
  3. Ensure all tests that previously relied on this method are updated or adjusted accordingly.

To help identify potential issues, please run the following script:

This will help identify any remaining calls to SetToken that might need to be updated.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for calls to SetToken method in test files
echo "Searching for SetToken method calls:"
rg --type go "SetToken\(" ./x/crosschain/keeper/

Length of output: 382

tests/amino_test.go (1)

174-181: 💡 Codebase verification

Issues Found: Remaining Usage of Removed Parameters

The parameters EnableEVMHook and IbcTimeout are still referenced in the following files:

  • x/erc20/types/legacy.pb.go
  • api/fx/erc20/v1/legacy.pulsar.go

This indicates that the removal from tests/amino_test.go is incomplete and may lead to inconsistencies or runtime issues.

Please address these remaining usages by either removing or updating them to ensure consistency across the codebase.

🔗 Analysis chain

Approve changes and verify impact of parameter removal.

The simplification of the Params struct in the MsgUpdateParams message aligns with the PR objective of refactoring the many-to-one logic. The removal of EnableEVMHook and IbcTimeout parameters streamlines the ERC20 module's configuration.

Please verify the following:

  1. The removal of EnableEVMHook and IbcTimeout parameters doesn't lead to loss of important functionality.
  2. If these parameters have been moved elsewhere, ensure that appropriate tests are in place for their new location.

Run the following script to check for any remaining usage of the removed parameters:

If these parameters are still in use elsewhere in the codebase, please update those occurrences or provide an explanation for their retention.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of removed ERC20 parameters

# Test: Search for EnableEVMHook usage
echo "Searching for EnableEVMHook usage:"
rg --type go 'EnableEVMHook'

# Test: Search for IbcTimeout usage
echo "Searching for IbcTimeout usage:"
rg --type go 'IbcTimeout'

Length of output: 3397

Makefile (1)

145-145: 💡 Codebase verification

Reduce the allowed number of linter suppressions further.

The current count of nolint or #nosec comments is 0, which is less than the allowed 26. Consider lowering the allowed count to better enforce linter rules and maintain code quality.

🔗 Analysis chain

Approve reduction in linter suppressions with verification.

The change from 29 to 26 allowed nolint or #nosec comments is a positive step towards improving code quality. This reduction suggests that some previously suppressed linter warnings have been addressed.

To ensure this change is intentional and accurate, please run the following command:

This script will help verify if the new count accurately reflects the current state of the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Count the actual number of nolint and #nosec comments in Go files
actual_count=$(find . -name '*.go' -type f | xargs grep -c 'nolint\|#nosec' | awk '{sum+=$1} END {print sum}')
echo "Actual count of nolint and #nosec comments: $actual_count"

# Compare with the new allowed count
if [ "$actual_count" -eq 26 ]; then
    echo "The new count matches the actual number of suppressions."
elif [ "$actual_count" -lt 26 ]; then
    echo "The actual count is less than 26. Consider further reducing the allowed count."
else
    echo "Warning: The actual count is higher than 26. Please review and update suppressions or adjust the allowed count."
fi

Length of output: 422

app/genesis.json (1)

225-225: 💡 Codebase verification

Incomplete removal of ERC20 parameters

The removal of enable_evm_hook and ibc_timeout parameters in app/genesis.json is not fully reflected across the codebase. The parameters are still referenced in the following files:

  • x/erc20/types/legacy.pb.go:

    • EnableEVMHook field in LegacyParams struct.
    • IbcTimeout field in LegacyParams struct.
  • api/fx/erc20/v1/legacy.pulsar.go:

    • Multiple references to enable_evm_hook and ibc_timeout in various functions and methods.

This incomplete removal may lead to inconsistencies and potential functionality issues.

🔗 Analysis chain

Verify implications of ERC20 parameter simplification

The simplification of the erc20 parameters aligns with the PR objective of refactoring the many-to-one logic. However, the removal of enable_evm_hook and ibc_timeout parameters may have significant implications:

  1. The absence of enable_evm_hook might affect EVM hook functionality.
  2. Removing ibc_timeout could impact IBC timeout settings.

Please confirm that these changes are intentional and properly handled in the corresponding code. Run the following script to check for any remaining references to the removed parameters:

Consider updating the related documentation to reflect these changes in the ERC20 module configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for references to removed ERC20 parameters
echo "Searching for 'enable_evm_hook' references:"
rg --type go "enable_evm_hook"
echo "Searching for 'ibc_timeout' references in ERC20 context:"
rg --type go -C 3 "ibc_timeout" | rg -C 3 "erc20"

Length of output: 8206

x/erc20/keeper/params.go (1)

9-10: 🛠️ Refactor suggestion

Consider wrapping the error to provide more context

When returning an error, it's helpful to include additional context to aid in debugging. Consider updating the error handling as follows:

 if err != nil {
-    return false, err
+    return false, fmt.Errorf("failed to get params: %w", err)
 }

This change provides more information about where the error occurred, making it easier to trace issues.

📝 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.

	if err != nil {
		return false, fmt.Errorf("failed to get params: %w", err)
proto/fx/erc20/v1/genesis.proto (1)

4-4: ⚠️ Potential issue

Fix import statement: 'types.proto' does not exist

The import statement on line 4 references fx/erc20/v1/types.proto, but according to the static analysis hints, this file does not exist. This will cause a compilation error. Please ensure that types.proto is present at the specified location or update the import path to the correct file.

🧰 Tools
🪛 buf

4-4: import "fx/erc20/v1/types.proto": file does not exist

(COMPILE)

x/erc20/keeper/genesis.go (4)

35-35: 🛠️ Refactor suggestion

Add context to the returned error from k.Params.Get

When an error occurs while retrieving parameters, wrapping the error with context can facilitate debugging.

Apply this diff to include additional context:

	if err != nil {
-		return nil, err
+		return nil, fmt.Errorf("failed to get params: %w", err)
	}
📝 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.

		return nil, fmt.Errorf("failed to get params: %w", err)

14-15: 🛠️ Refactor suggestion

Add context to the returned error from k.Params.Set

When returning an error from k.Params.Set, consider wrapping it with additional context to aid in debugging and error tracing.

Apply this diff to wrap the error with additional context:

	if err := k.Params.Set(ctx, data.Params); err != nil {
-		return err
+		return fmt.Errorf("failed to set params: %w", err)
	}
📝 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.

	if err := k.Params.Set(ctx, data.Params); err != nil {
		return fmt.Errorf("failed to set params: %w", err)

32-32: 💡 Codebase verification

🔍 Handle Error Returns from ExportGenesis in Affected Modules

Several modules call ExportGenesis without handling the returned error. Please update these calls to properly handle errors:

  • x/tron/module.go
  • x/polygon/module.go
  • x/optimism/module.go
  • x/migrate/module.go
  • x/layer2/module.go
  • x/eth/module.go
  • x/avalanche/module.go
  • x/arbitrum/module.go
  • x/bsc/module.go
🔗 Analysis chain

Ensure all calls to ExportGenesis handle the new error return value

The ExportGenesis function now returns an error. Please verify that all callers of this function are updated to handle the error appropriately.

Run the following script to find all usages of ExportGenesis:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all calls to `ExportGenesis` to ensure they handle the error.

# Test: Search for function calls to `ExportGenesis`.
rg --type go 'ExportGenesis\(' -A 2

Length of output: 3909


26-26: ⚠️ Potential issue

Simplify error handling and wrap the error correctly

Instead of using err.Error(), pass err directly and use %w to wrap the error. This allows for error unwrapping and better propagation of the original error.

Apply this diff to correct the error wrapping:

	return fmt.Errorf("register default denom error %s", err.Error())
+	return fmt.Errorf("register default denom error: %w", err)

Committable suggestion was skipped due to low confidence.

x/erc20/keeper/bridge_token.go (3)

16-18: 🛠️ Refactor suggestion

Consider adding error context in GetBridgeToken

Currently, the function returns errors from k.BridgeToken.Get directly. To provide better context when an error occurs, consider wrapping the error with additional information.

You can modify the function as follows:

 func (k Keeper) GetBridgeToken(ctx context.Context, baseDenom, chainName string) (types.BridgeToken, error) {
-	return k.BridgeToken.Get(ctx, collections.Join(baseDenom, chainName))
+	key := collections.Join(baseDenom, chainName)
+	bridgeToken, err := k.BridgeToken.Get(ctx, key)
+	if err != nil {
+		return types.BridgeToken{}, fmt.Errorf("failed to get bridge token for baseDenom %s and chainName %s: %w", baseDenom, chainName, err)
+	}
+	return bridgeToken, nil
 }
📝 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.

func (k Keeper) GetBridgeToken(ctx context.Context, baseDenom, chainName string) (types.BridgeToken, error) {
	key := collections.Join(baseDenom, chainName)
	bridgeToken, err := k.BridgeToken.Get(ctx, key)
	if err != nil {
		return types.BridgeToken{}, fmt.Errorf("failed to get bridge token for baseDenom %s and chainName %s: %w", baseDenom, chainName, err)
	}
	return bridgeToken, nil
}

20-22: 🛠️ Refactor suggestion

Enhance error handling in GetBaseDenom

The function currently returns the error from k.DenomIndex.Get directly. To improve debugging and provide more context, consider wrapping the error with additional information.

Here's how you might adjust the function:

 func (k Keeper) GetBaseDenom(ctx context.Context, token string) (string, error) {
-	return k.DenomIndex.Get(ctx, token)
+	baseDenom, err := k.DenomIndex.Get(ctx, token)
+	if err != nil {
+		return "", fmt.Errorf("failed to get base denom for token %s: %w", token, err)
+	}
+	return baseDenom, nil
 }
📝 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.

func (k Keeper) GetBaseDenom(ctx context.Context, token string) (string, error) {
	baseDenom, err := k.DenomIndex.Get(ctx, token)
	if err != nil {
		return "", fmt.Errorf("failed to get base denom for token %s: %w", token, err)
	}
	return baseDenom, nil
}

39-43: 🛠️ Refactor suggestion

Ensure consistent error handling in AddBridgeToken

In the AddBridgeToken function, the error from k.DenomIndex.Set is returned directly without checking. For consistency with previous error handling, consider capturing and checking the error before returning.

Modify the code as follows:

 if err = k.BridgeToken.Set(ctx, key, bridgeToken); err != nil {
     return err
 }
-	return k.DenomIndex.Set(ctx, bridgeToken.BridgeDenom(), baseDenom)
+	if err = k.DenomIndex.Set(ctx, bridgeToken.BridgeDenom(), baseDenom); err != nil {
+		return err
+	}
+	return nil
📝 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.

	if err = k.BridgeToken.Set(ctx, key, bridgeToken); err != nil {
		return err
	}
	if err = k.DenomIndex.Set(ctx, bridgeToken.BridgeDenom(), baseDenom); err != nil {
		return err
	}
	return nil
}
x/crosschain/precompile/expected_keepers.go (1)

23-23: 💡 Codebase verification

Inconsistent Parameter Name Updates in BridgeCoinSupply Calls

It appears that not all calls to BridgeCoinSupply have updated the parameter name from tokenOrDenom to token. Specifically:

  • x/crosschain/keeper/grpc_query.go still uses req.GetDenom() as the second argument.

Please update all instances to use token to ensure consistency and prevent potential issues.

🔗 Analysis chain

Ensure consistent update of parameter name in BridgeCoinSupply

The parameter has been changed from tokenOrDenom to token, which simplifies the method signature. Please verify that all calls to BridgeCoinSupply in the codebase have been updated to reflect this change to prevent any potential issues.

You can run the following script to check all usages of BridgeCoinSupply:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all calls to BridgeCoinSupply use the updated parameter name.

rg --type go 'BridgeCoinSupply\(' -A 3

Length of output: 1733

x/erc20/keeper/msg_server.go (3)

14-14: 🛠️ Refactor suggestion

Consider asserting interface implementation with pointer type

Currently, the interface assertion uses the value type:

var _ types.MsgServer = msgServer{}

Given that NewMsgServerImpl returns a pointer to msgServer, it would be more consistent to assert the interface implementation with the pointer type. This ensures that both the value and pointer types satisfy the types.MsgServer interface.

Apply this diff to update the assertion:

-var _ types.MsgServer = msgServer{}
+var _ types.MsgServer = &msgServer{}

26-31: 🛠️ Refactor suggestion

Use pointer receivers for methods to avoid unnecessary copying

The methods ConvertCoin, UpdateParams, and ToggleTokenConversion have value receivers (s msgServer). This means the msgServer struct is copied on each method call, which can lead to unnecessary memory allocations, especially if the struct becomes larger in the future.

Consider changing the method receivers to pointer receivers (s *msgServer) to avoid copying and to allow the methods to mutate the receiver if needed in the future.

Apply this diff to update the method receivers:

-func (s msgServer) ConvertCoin(goCtx context.Context, msg *types.MsgConvertCoin) (*types.MsgConvertCoinResponse, error) {
+func (s *msgServer) ConvertCoin(goCtx context.Context, msg *types.MsgConvertCoin) (*types.MsgConvertCoinResponse, error) {

-func (s msgServer) UpdateParams(c context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
+func (s *msgServer) UpdateParams(c context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {

-func (s msgServer) ToggleTokenConversion(c context.Context, req *types.MsgToggleTokenConversion) (*types.MsgToggleTokenConversionResponse, error) {
+func (s *msgServer) ToggleTokenConversion(c context.Context, req *types.MsgToggleTokenConversion) (*types.MsgToggleTokenConversionResponse, error) {

Also applies to: 34-40, 45-54


29-29: ⚠️ Potential issue

Handle errors from AccAddressFromBech32 instead of panicking

The use of sdk.MustAccAddressFromBech32(msg.Sender) will panic if msg.Sender is an invalid Bech32 address, which is undesirable in a production environment. It's better practice to handle the error gracefully and return a meaningful error message to the caller.

Apply this diff to handle the potential error:

-sender := sdk.MustAccAddressFromBech32(msg.Sender)
+sender, err := sdk.AccAddressFromBech32(msg.Sender)
+if err != nil {
+    return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "invalid sender address: %v", err)
+}

This change ensures that any invalid addresses are caught and an appropriate error is returned without causing a panic.

Committable suggestion was skipped due to low confidence.

x/crosschain/precompile/keeper.go (2)

36-38: ⚠️ Potential issue

Potential misuse of tokenAddr as sender in SendCoins call.

In the SendCoins method call, tokenAddr.Bytes() is used as the sender address. Since tokenAddr represents the ERC20 token contract address, using it as the sender may not be appropriate and could lead to unexpected behavior or permission issues.

Consider using the erc20ModuleAddress.Bytes() as the sender, which represents the module account responsible for handling ERC20 tokens.

Apply this diff to correct the sender address:

 if erc20Token.Denom == fxtypes.DefaultDenom {
-	err = c.bankKeeper.SendCoins(ctx, tokenAddr.Bytes(), holder.Bytes(), sdk.NewCoins(baseCoin))
+	err = c.bankKeeper.SendCoins(ctx, erc20ModuleAddress.Bytes(), holder.Bytes(), sdk.NewCoins(baseCoin))
 	return baseCoin, err
 }

Committable suggestion was skipped due to low confidence.


19-20: 💡 Codebase verification

Multiple references to erc20Keeper found after removal

  • Found references to erc20Keeper in the following files:
    • x/crosschain/keeper/outgoing_tx.go
    • x/crosschain/keeper/send_to_fx.go
    • x/crosschain/keeper/many_to_one.go
    • x/crosschain/keeper/grpc_query.go
    • x/crosschain/keeper/bridge_token.go
    • x/crosschain/keeper/bridge_call_out.go
    • x/crosschain/keeper/bridge_call_in.go
    • x/crosschain/keeper/keeper_test.go
    • x/crosschain/keeper/keeper.go
🔗 Analysis chain

Verify the impact of removing erc20Keeper from Keeper struct.

The erc20Keeper field has been removed from the Keeper struct, which simplifies the struct definition. Please ensure that all references to erc20Keeper within this file and related files have been updated accordingly to prevent any nil pointer dereferences or compilation errors.

Run the following script to check for any remaining references to erc20Keeper:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for references to 'erc20Keeper' in the codebase.
rg --type go 'erc20Keeper'

Length of output: 3544

tests/erc20_suite.go (3)

35-36: ⚠️ Potential issue

Implement the Erc20TokenAddress method to return the correct token address

The Erc20TokenAddress method currently contains a TODO comment and returns an empty common.Address. This needs to be implemented to correctly retrieve the ERC20 token address based on the provided denomination. Without this implementation, any functionality relying on this method will not operate properly.

Would you like assistance in implementing this method?


51-52: ⚠️ Potential issue

Ensure Erc20TokenAddress is implemented before using it in ConvertCoin

In the ConvertCoin method, you are calling Erc20TokenAddress(coin.Denom) to obtain the ERC20 token address. However, since Erc20TokenAddress is not yet implemented and returns an empty address, this will lead to incorrect behavior in your balance checks and subsequent operations. Please implement Erc20TokenAddress before using it here.


59-60: ⚠️ Potential issue

Correct the assertion to verify the recipient's ERC20 balance increase after conversion

The assertion on line 60 currently checks that afterBalanceOf is equal to beforeBalanceOf, which implies that the recipient's ERC20 token balance remains unchanged after the conversion. However, after converting coins to ERC20 tokens, the recipient's ERC20 balance should increase by the amount converted.

Please modify the assertion to verify that the recipient's ERC20 balance has increased by coin.Amount.

Apply this diff to fix the assertion:

-	suite.Require().Equal(afterBalanceOf.String(), beforeBalanceOf.String())
+	suite.Require().Equal(afterBalanceOf.Sub(beforeBalanceOf).String(), coin.Amount.String())
📝 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.

	suite.Require().Equal(beforeBalance.Sub(afterBalance).String(), coin.Amount.String())
	suite.Require().Equal(afterBalanceOf.Sub(beforeBalanceOf).String(), coin.Amount.String())
proto/fx/erc20/v1/query.proto (3)

42-42: ⚠️ Potential issue

Changing field types without changing field numbers may break backward compatibility

In QueryTokenPairsResponse, the type of field 1 has been changed from TokenPair to ERC20Token. Altering the type of an existing field while keeping the same field number can cause deserialization issues for clients expecting the original type, leading to runtime errors.

To maintain backward compatibility, consider adding the new field with a new field number and deprecating the old field. Here's how you can adjust the message:

 message QueryTokenPairsResponse {
   option deprecated = true;
+  repeated TokenPair token_pairs = 1 [ (gogoproto.nullable) = false, deprecated = true ];
+  repeated ERC20Token erc20_tokens = 2 [ (gogoproto.nullable) = false ];
   // pagination defines the pagination in the response.
   cosmos.base.query.v1beta1.PageResponse pagination = 2;
 }

Committable suggestion was skipped due to low confidence.


14-19: ⚠️ Potential issue

Consider formally deprecating RPC methods using option deprecated = true;

The methods TokenPairs and TokenPair are marked as deprecated through comments. While comments inform developers, it's recommended to use option deprecated = true; within the RPC method definitions to formally deprecate them. This provides a clearer signal to tools and compilers that the methods are deprecated.

Apply this diff to deprecate the RPC methods:

 service Query {
   // Deprecated: TokenPairs Retrieves registered token pairs
+  option deprecated = true;
   rpc TokenPairs(QueryTokenPairsRequest) returns (QueryTokenPairsResponse) {
     option (google.api.http).get = "/fx/erc20/v1/token_pairs";
   }

   // Deprecated: TokenPair Retrieves a registered token pair
+  option deprecated = true;
   rpc TokenPair(QueryTokenPairRequest) returns (QueryTokenPairResponse) {
     option (google.api.http).get = "/fx/erc20/v1/token_pairs/{token}";
   }

   // Params retrieves the erc20 module params
   rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
     option (google.api.http).get = "/fx/erc20/v1/params";
   }
 }

Committable suggestion was skipped due to low confidence.


59-59: ⚠️ Potential issue

Changing field types without changing field numbers may break backward compatibility

In QueryTokenPairResponse, the type of field 1 has been changed from TokenPair to ERC20Token. This modification can disrupt clients that rely on the original message structure, causing potential deserialization failures.

To preserve backward compatibility, add the new field with a different field number and deprecate the old one. Here's the suggested modification:

 message QueryTokenPairResponse {
   option deprecated = true;
+  TokenPair token_pair = 1 [ (gogoproto.nullable) = false, deprecated = true ];
+  ERC20Token erc20_token = 2 [ (gogoproto.nullable) = false ];
 }

Committable suggestion was skipped due to low confidence.

x/erc20/keeper/grpc_query.go (3)

70-70: ⚠️ Potential issue

Wrap Internal Errors with Appropriate gRPC Status Codes

In both TokenPair and Params methods, errors returned from s.k.ERC20Token.Get and s.k.Params.Get are directly passed back to the client without wrapping them in gRPC status errors. This might expose internal error details and doesn't provide clear status codes to the client. Wrap these errors with appropriate gRPC status codes to enhance error handling.

Apply these diffs to wrap the errors:

// In TokenPair method
-		return nil, err
+		return nil, status.Errorf(codes.Internal, "failed to retrieve ERC20 token: %v", err)
// In Params method
-		return nil, err
+		return nil, status.Errorf(codes.Internal, "failed to retrieve parameters: %v", err)

Also applies to: 80-80


65-67: ⚠️ Potential issue

Handle Specific Errors When Retrieving Denom Index

In the TokenPair method, when s.k.DenomIndex.Get fails, you default baseDenom to req.Token regardless of the error type. This might mask underlying issues other than a missing key, such as database errors. Explicitly handle the case where the key is not found, and handle other errors appropriately to prevent unintended behavior.

Modify the code to handle errors specifically:

baseDenom, err := s.k.DenomIndex.Get(ctx, req.Token)
if err != nil {
	if errors.Is(err, types.ErrKeyNotFound) {
		baseDenom = req.Token
	} else {
		return nil, status.Errorf(codes.Internal, "failed to get base denomination: %v", err)
	}
}

38-38: ⚠️ Potential issue

Use Appropriate gRPC Error Code for Pagination Errors

In the TokenPairs method, when handling pagination errors, you return an InvalidArgument error code. Pagination errors might not be due to invalid arguments but could result from internal issues. Consider using codes.Internal to represent unexpected internal errors more accurately.

Apply this diff to adjust the error code:

-		return nil, status.Errorf(codes.InvalidArgument, "paginate: %v", err)
+		return nil, status.Errorf(codes.Internal, "paginate: %v", err)
📝 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.

		return nil, status.Errorf(codes.Internal, "paginate: %v", err)
x/crosschain/keeper/bridge_token.go (3)

66-72: 🛠️ Refactor suggestion

Consider renaming the function for clarity

The function GetBaseDenomByErc20 returns an ERC20Token, not just the base denomination. For clarity, consider renaming the function to reflect that it returns an ERC20Token.


25-27: ⚠️ Potential issue

Fix grammatical error in error message

The error message "denom decimals not match %d, expect %d" is grammatically incorrect. It should be "denom decimals do not match %d, expected %d".

Apply this diff to fix the error message:

-return types.ErrInvalid.Wrapf("%s denom decimals not match %d, expect %d",
+return types.ErrInvalid.Wrapf("%s denom decimals do not match %d, expected %d",
📝 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.

	if claim.Symbol == fxtypes.DefaultDenom && uint64(fxtypes.DenomUnit) != claim.Decimals {
		return types.ErrInvalid.Wrapf("%s denom decimals do not match %d, expected %d",
			fxtypes.DefaultDenom, claim.Decimals, fxtypes.DenomUnit)

33-34: ⚠️ Potential issue

Correct grammatical error in error message

The error message "bridge token contract not match %s, expect %s" is grammatically incorrect. It should be "bridge token contract does not match %s, expected %s".

Apply this diff to fix the error message:

-return types.ErrInvalid.Wrapf("bridge token contract not match %s, expect %s", bridgeToken.Contract, claim.TokenContract)
+return types.ErrInvalid.Wrapf("bridge token contract does not match %s, expected %s", bridgeToken.Contract, claim.TokenContract)
📝 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.

	if bridgeToken.Contract != claim.TokenContract {
		return types.ErrInvalid.Wrapf("bridge token contract does not match %s, expected %s", bridgeToken.Contract, claim.TokenContract)
proto/fx/erc20/v1/tx.proto (1)

78-79: 💡 Codebase verification

⚠️ Potential issue

Backward Compatibility Issue: Reassignment of Field Number 1

The field number 1 in MsgToggleTokenConversionResponse was previously assigned to pair and has been reassigned to erc20_token. This change can cause deserialization errors for existing clients expecting pair in field 1.

Recommended Actions:

  • Mark the previous field as reserved to prevent future conflicts and maintain backward compatibility.
🔗 Analysis chain

Potential backward compatibility issue due to changing field numbers in Protobuf message

Reassigning field numbers in Protobuf messages can cause backward compatibility issues with clients that expect the previous message format. The field number 1 is now assigned to erc20_token in MsgToggleTokenConversionResponse. If this field number was previously used for a different field, it could lead to deserialization errors for existing clients.

Please ensure that you are not reusing field numbers. Consider marking the removed fields as reserved to prevent future conflicts and maintain backward compatibility.

Run the following script to verify previous field assignments in MsgToggleTokenConversionResponse:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify previous field numbers in 'MsgToggleTokenConversionResponse'

# Test: Extract the previous definition to check field numbers. Expect: Identify any conflicts with field number 1.

git show HEAD~1:proto/fx/erc20/v1/tx.proto | rg -A 5 'message MsgToggleTokenConversionResponse'

Length of output: 275

x/crosschain/types/target.go (2)

110-111: 🛠️ Refactor suggestion

Use sdk.AccAddressFromBech32 for address validation

To validate a Bech32 address more accurately, consider using sdk.AccAddressFromBech32 instead of sdk.GetFromBech32.

Apply this diff to use the recommended function:

-_, err := sdk.GetFromBech32(receive, i.Bech32Prefix)
+_, err := sdk.AccAddressFromBech32(receive)
+if err == nil && !strings.HasPrefix(receive, i.Bech32Prefix) {
+	err = fmt.Errorf("address does not have expected prefix: %s", i.Bech32Prefix)
+}
📝 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.

		_, err := sdk.AccAddressFromBech32(receive)
		if err == nil && !strings.HasPrefix(receive, i.Bech32Prefix) {
			err = fmt.Errorf("address does not have expected prefix: %s", i.Bech32Prefix)
		}
		return err

35-36: ⚠️ Potential issue

Handle errors returned by hex.DecodeString

Ignoring the error from hex.DecodeString can lead to unexpected behavior if targetStr is not a valid hex string. It's important to handle this error to ensure the function behaves correctly.

Apply this diff to handle the error:

 targetByte, err := hex.DecodeString(targetStr)
-if err != nil {
-	// ignore hex decode error
-}
+if err != nil {
+	return nil, fmt.Errorf("hex decode error: %w", err)
+}
 targetStr = string(targetByte)

Committable suggestion was skipped due to low confidence.

x/crosschain/keeper/bridge_call_in.go (1)

31-36: ⚠️ Potential issue

Ensure equal lengths of msg.TokenContracts and msg.Amounts to prevent index out of range errors

Before iterating, it's important to verify that len(msg.TokenContracts) == len(msg.Amounts) to avoid potential index out of range panics if the slices are of different lengths.

You can add the following check:

+	if len(msg.TokenContracts) != len(msg.Amounts) {
+		return types.ErrInvalid.Wrap("TokenContracts and Amounts lengths mismatch")
+	}
📝 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.

	if len(msg.TokenContracts) != len(msg.Amounts) {
		return types.ErrInvalid.Wrap("TokenContracts and Amounts lengths mismatch")
	}
	for i, tokenAddr := range msg.TokenContracts {
		bridgeToken, err := k.DepositBridgeToken(ctx, receiverAddr.Bytes(), msg.Amounts[i], tokenAddr)
		if err != nil {
			return err
		}
		baseCoin, err := k.BridgeTokenToBaseCoin(ctx, receiverAddr.Bytes(), msg.Amounts[i], bridgeToken)
x/crosschain/precompile/bridge_call.go (1)

74-77: ⚠️ Potential issue

Improve error message for invalid router

When GetRoute fails to find a matching route, the error message "invalid router" is not very descriptive. Providing more context can aid in debugging.

Consider updating the error message to include the module name:

if !ok {
-    return errors.New("invalid router")
+    return fmt.Errorf("invalid router for module: %s", fxTarget.GetModuleName())
}

Ensure that the "fmt" package is imported to use fmt.Errorf.

📝 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.

		crosschainKeeper, ok := m.router.GetRoute(fxTarget.GetModuleName())
		if !ok {
			return fmt.Errorf("invalid router for module: %s", fxTarget.GetModuleName())
		}
proto/fx/erc20/v1/legacy.proto (2)

22-26: ⚠️ Potential issue

Type inconsistency for the 'amount' field in MsgConvertERC20

The amount field is declared as a string, but it uses custom types and scalar options that correspond to integer types (cosmos.Int, cosmossdk.io/math.Int). This may lead to serialization issues or runtime errors due to type mismatch.

Consider updating the field type to align with the specified custom types:

-string amount = 2 [
+cosmos.base.v1beta1.Int amount = 2 [
   (cosmos_proto.scalar) = "cosmos.Int",
   (gogoproto.customtype) = "cosmossdk.io/math.Int",
   (gogoproto.nullable) = false
 ];

Alternatively, if cosmos.base.v1beta1.Int is not available, you might define a new type or adjust the existing custom type annotations to match the intended usage.

Committable suggestion was skipped due to low confidence.


54-54: 💡 Codebase verification

⚠️ Potential issue

Inconsistent (gogoproto.equal) Option in Proposal Messages

  • ToggleTokenConversionProposal sets option (gogoproto.equal) = true; while other proposal messages have it set to false.
🔗 Analysis chain

Inconsistent usage of (gogoproto.equal) option

In the RegisterCoinProposal message, the option (gogoproto.equal) = false; is set. However, in ToggleTokenConversionProposal (line 71) and other proposal messages, the usage of this option varies. Consistent use of equality options is important for predictable behavior in generated code.

You can verify the usage across all proposal messages with the following script:

Please ensure that the (gogoproto.equal) option is consistently applied across all proposal messages unless there is a specific reason for the difference.


Action Required: Correct and Re-run Verification Script

Please use the following updated script to verify the usage of (gogoproto.equal) in all proposal messages:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the usage of `(gogoproto.equal)` in proposal messages.

# Test: List proposal messages and their `(gogoproto.equal)` settings. Expect: Consistent values.
rg 'message (\w+Proposal) \{[\s\S]+?option \(gogoproto.equal\) = (\w+);' -or '$1: $2' proto/

Length of output: 225


Script:

# 
#!/bin/bash
# Description: Check the usage of `(gogoproto.equal)` in proposal messages.

# Test: List proposal messages and their `(gogoproto.equal)` settings. Expect: Consistent values.
rg 'message\s+\w+Proposal\s+\{[^}]*?option\s+\(gogoproto\.equal\)\s+=\s+\w+;' proto/

Length of output: 86


Script:

#!/bin/bash
# Description: List all proposal messages and their `(gogoproto.equal)` settings.

# Find all proposal messages
rg 'message\s+\w+Proposal\s*\{' proto/ -A 5

Length of output: 2933

x/crosschain/precompile/crosschain.go (2)

73-74: 🛠️ Refactor suggestion

Simplify comparison for better readability

You can simplify the comparison when determining isOriginToken by using value.Sign() > 0, which improves readability.

Apply this change:

-isOriginToken := value.Cmp(big.NewInt(0)) == 1
+isOriginToken := value.Sign() > 0
📝 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.

		isOriginToken := value.Sign() > 0
		if isOriginToken {

78-80: ⚠️ Potential issue

Clarify the error message for non-zero token address

The error message "token is not zero address" might be unclear to users. Consider providing a more descriptive message to explain the requirement.

Update the error message for clarity:

-	return errors.New("token is not zero address")
+	return errors.New("token address must be zero address when transferring origin tokens")
📝 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.

			if !fxcontract.IsZeroEthAddress(args.Token) {
				return errors.New("token address must be zero address when transferring origin tokens")
			}
x/erc20/keeper/keeper.go (1)

34-34: ⚠️ Potential issue

Initialize the Schema field in the Keeper struct

The Schema field is declared in the Keeper struct but is not initialized in the NewKeeper function. To ensure the collections are properly registered and functional, initialize Schema using sb.Build() in the return statement.

Apply this diff to fix the issue:

 return Keeper{
     cdc:            cdc,
     storeService:   storeService,
     accountKeeper:  ak,
     bankKeeper:     bk,
     evmKeeper:      evmKeeper,
     evmErc20Keeper: evmErc20Keeper,
     contractOwner:  common.BytesToAddress(moduleAddress),
     authority:      authority,
+    Schema:         sb.Build(),
     Params:         collections.NewItem(sb, types.ParamsKey2, "params", codec.CollValue[types.Params](cdc)),
     ERC20Token:     collections.NewMap(sb, types.ERC20TokenKey, "erc20_token", collections.StringKey, codec.CollValue[types.ERC20Token](cdc)),
     BridgeToken:    collections.NewMap(sb, types.BridgeTokenKey, "bridge_token", collections.PairKeyCodec(collections.StringKey, collections.StringKey), codec.CollValue[types.BridgeToken](cdc)),
     IBCToken:       collections.NewMap(sb, types.IBCTokenKey, "ibc_token", collections.PairKeyCodec(collections.StringKey, collections.StringKey), codec.CollValue[types.IBCToken](cdc)),
     DenomIndex:     collections.NewMap(sb, types.DenomIndexKey, "denom_index", collections.StringKey, collections.StringValue),
     Cache:          collections.NewMap(sb, types.CacheKey, "cache", collections.StringKey, collections.NoValue{}),
 }

Also applies to: 59-74

x/erc20/keeper/erc20_token.go (7)

65-95: ⚠️ Potential issue

Add checks for existing ERC20 addresses

In AddERC20Token, there is no verification to ensure that the erc20Addr isn't already registered with a different denomination, which could lead to conflicts.

Introduce a check to prevent registering the same ERC20 address multiple times:

if existingDenom, err := k.DenomIndex.Get(ctx, erc20Addr.String()); err == nil {
    return types.ERC20Token{}, sdkerrors.ErrInvalidRequest.Wrapf("ERC20 address %s is already registered with denom %s", erc20Addr.String(), existingDenom)
}

Place this check before setting the DenomIndex to maintain data integrity.


97-99: ⚠️ Potential issue

Enhance error messaging in GetERC20Token

When an ERC20 token is not found, return a descriptive error to aid debugging.

Update the method:

func (k Keeper) GetERC20Token(ctx context.Context, baseDenom string) (types.ERC20Token, error) {
-    return k.ERC20Token.Get(ctx, baseDenom)
+    token, err := k.ERC20Token.Get(ctx, baseDenom)
+    if err != nil {
+        return types.ERC20Token{}, sdkerrors.ErrNotFound.Wrapf("ERC20 token with denom %s not found", baseDenom)
+    }
+    return token, nil
}

This provides clear feedback when a token lookup fails.

📝 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.

func (k Keeper) GetERC20Token(ctx context.Context, baseDenom string) (types.ERC20Token, error) {
    token, err := k.ERC20Token.Get(ctx, baseDenom)
    if err != nil {
        return types.ERC20Token{}, sdkerrors.ErrNotFound.Wrapf("ERC20 token with denom %s not found", baseDenom)
    }
    return token, nil
}

21-26: ⚠️ Potential issue

Handle potential errors from DeployUpgradableToken

In RegisterNativeCoin, the error from DeployUpgradableToken might lack context.

Wrap the error to provide more information:

erc20Addr, err := k.DeployUpgradableToken(sdkCtx, k.contractOwner, name, symbol, decimals)
if err != nil {
-    return types.ERC20Token{}, err
+    return types.ERC20Token{}, sdkerrors.Wrap(err, "failed to deploy upgradable token")
}

This aids in debugging deployment issues.

📝 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.

	sdkCtx := sdk.UnwrapSDKContext(ctx)
	erc20Addr, err := k.DeployUpgradableToken(sdkCtx, k.contractOwner, name, symbol, decimals)
	if err != nil {
		return types.ERC20Token{}, sdkerrors.Wrap(err, "failed to deploy upgradable token")
	}


40-63: ⚠️ Potential issue

Separate error handling in RegisterNativeERC20

Similar to the previous comment, in RegisterNativeERC20, errors from GetEnableErc20 should be handled distinctly from the disabled state.

Update the error handling as follows:

func (k Keeper) RegisterNativeERC20(ctx sdk.Context, erc20Addr common.Address) (types.ERC20Token, error) {
-    erc20, err := k.GetEnableErc20(ctx)
-    if err != nil || !erc20 {
-        return types.ERC20Token{}, types.ErrERC20Disabled.Wrap("module is currently disabled by governance")
-    }
+    erc20Enabled, err := k.GetEnableErc20(ctx)
+    if err != nil {
+        return types.ERC20Token{}, err
+    }
+    if !erc20Enabled {
+        return types.ERC20Token{}, types.ErrERC20Disabled.Wrap("module is currently disabled by governance")
+    }

    name, symbol, decimals, err := k.ERC20BaseInfo(ctx, erc20Addr)
    // ...
}

This provides clearer error feedback for potential issues during execution.

📝 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.

func (k Keeper) RegisterNativeERC20(ctx sdk.Context, erc20Addr common.Address) (types.ERC20Token, error) {
	erc20Enabled, err := k.GetEnableErc20(ctx)
	if err != nil {
		return types.ERC20Token{}, err
	}
	if !erc20Enabled {
		return types.ERC20Token{}, types.ErrERC20Disabled.Wrap("module is currently disabled by governance")
	}

	name, symbol, decimals, err := k.ERC20BaseInfo(ctx, erc20Addr)
	if err != nil {
		return types.ERC20Token{}, err
	}

	erc20Token, err := k.AddERC20Token(ctx, name, symbol, decimals, erc20Addr, types.OWNER_EXTERNAL)
	if err != nil {
		return types.ERC20Token{}, err
	}

	ctx.EventManager().EmitEvent(sdk.NewEvent(
		types.EventTypeRegisterERC20,
		sdk.NewAttribute(types.AttributeKeyDenom, erc20Token.Denom),
		sdk.NewAttribute(types.AttributeKeyTokenAddress, erc20Token.Erc20Address),
	))

	return erc20Token, nil
}

116-121: 🛠️ Refactor suggestion

Unwrap sdk.Context consistently

For consistency and readability, unwrap sdk.Context at the beginning of methods that require it.

Modify the method:

func (k Keeper) ToggleTokenConvert(ctx context.Context, token string) (types.ERC20Token, error) {
+   sdkCtx := sdk.UnwrapSDKContext(ctx)

    baseDenom, err := k.DenomIndex.Get(ctx, token)
    // ...
-   sdk.UnwrapSDKContext(ctx).EventManager().EmitEvent(sdk.NewEvent(
+   sdkCtx.EventManager().EmitEvent(sdk.NewEvent(
        // ...
    ))
    return erc20Token, nil
}

This approach enhances code clarity and uniformity.

Committable suggestion was skipped due to low confidence.


101-122: ⚠️ Potential issue

Handle unrecognized tokens in ToggleTokenConvert

If token is neither an ERC20 address nor a base denomination, the method might behave unexpectedly.

Add validation to handle unrecognized tokens:

baseDenom, err := k.DenomIndex.Get(ctx, token)
if err != nil {
    baseDenom = token
}
+if !k.ERC20Token.Has(ctx, baseDenom) {
+    return types.ERC20Token{}, sdkerrors.ErrNotFound.Wrapf("token %s is not registered", token)
+}

This ensures the method gracefully handles invalid input.

📝 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.

func (k Keeper) ToggleTokenConvert(ctx context.Context, token string) (types.ERC20Token, error) {
	baseDenom, err := k.DenomIndex.Get(ctx, token)
	if err != nil {
		baseDenom = token
	}
	if !k.ERC20Token.Has(ctx, baseDenom) {
		return types.ERC20Token{}, sdkerrors.ErrNotFound.Wrapf("token %s is not registered", token)
	}
	erc20Token, err := k.ERC20Token.Get(ctx, baseDenom)
	if err != nil {
		return types.ERC20Token{}, sdkerrors.ErrNotFound
	}
	erc20Token.Enabled = !erc20Token.Enabled

	if err = k.ERC20Token.Set(ctx, baseDenom, erc20Token); err != nil {
		return types.ERC20Token{}, err
	}

	sdk.UnwrapSDKContext(ctx).EventManager().EmitEvent(sdk.NewEvent(
		types.EventTypeToggleTokenRelay,
		sdk.NewAttribute(types.AttributeKeyDenom, erc20Token.Denom),
		sdk.NewAttribute(types.AttributeKeyTokenAddress, erc20Token.Erc20Address),
	))
	return erc20Token, nil
}

15-38: ⚠️ Potential issue

Improve error handling in RegisterNativeCoin

Currently, the method conflates errors from GetEnableErc20 with the module being disabled. This could mask underlying errors. Separate the error handling to provide clearer messages.

Apply the following changes:

func (k Keeper) RegisterNativeCoin(ctx context.Context, name, symbol string, decimals uint8) (types.ERC20Token, error) {
-    erc20, err := k.GetEnableErc20(ctx)
-    if err != nil || !erc20 {
-        return types.ERC20Token{}, types.ErrERC20Disabled.Wrap("module is currently disabled by governance")
-    }
+    erc20Enabled, err := k.GetEnableErc20(ctx)
+    if err != nil {
+        return types.ERC20Token{}, err
+    }
+    if !erc20Enabled {
+        return types.ERC20Token{}, types.ErrERC20Disabled.Wrap("module is currently disabled by governance")
+    }

    sdkCtx := sdk.UnwrapSDKContext(ctx)
    erc20Addr, err := k.DeployUpgradableToken(sdkCtx, k.contractOwner, name, symbol, decimals)
    // ...
}

This change ensures that genuine errors are not misrepresented as the module being disabled.

📝 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.

func (k Keeper) RegisterNativeCoin(ctx context.Context, name, symbol string, decimals uint8) (types.ERC20Token, error) {
	erc20Enabled, err := k.GetEnableErc20(ctx)
	if err != nil {
		return types.ERC20Token{}, err
	}
	if !erc20Enabled {
		return types.ERC20Token{}, types.ErrERC20Disabled.Wrap("module is currently disabled by governance")
	}

	sdkCtx := sdk.UnwrapSDKContext(ctx)
	erc20Addr, err := k.DeployUpgradableToken(sdkCtx, k.contractOwner, name, symbol, decimals)
	if err != nil {
		return types.ERC20Token{}, err
	}

	erc20Token, err := k.AddERC20Token(ctx, name, symbol, decimals, erc20Addr, types.OWNER_MODULE)
	if err != nil {
		return types.ERC20Token{}, err
	}

	sdkCtx.EventManager().EmitEvent(sdk.NewEvent(
		types.EventTypeRegisterCoin,
		sdk.NewAttribute(types.AttributeKeyDenom, erc20Token.Denom),
		sdk.NewAttribute(types.AttributeKeyTokenAddress, erc20Token.Erc20Address),
	))
	return erc20Token, nil
}
x/crosschain/types/expected_keepers.go (2)

46-60: ⚠️ Potential issue

Inconsistent use of context types in Erc20Keeper methods

The methods added to the Erc20Keeper interface use context.Context as the context parameter, whereas existing methods in this interface use sdk.Context. For consistency and to adhere to the conventions of the Cosmos SDK, consider replacing context.Context with sdk.Context in the method signatures.


69-71: ⚠️ Potential issue

Use sdk.Context instead of context.Context in EvmERC20Keeper

The TotalSupply method in the EvmERC20Keeper interface uses context.Context as the context parameter. To maintain consistency with other interfaces and to utilize SDK-specific functionalities, it is advisable to use sdk.Context instead.

x/crosschain/keeper/many_to_one.go (3)

164-166: ⚠️ Potential issue

Handle the error returned by DeleteCache

In the AfterIBCAckSuccess function, the error returned by k.erc20Keeper.DeleteCache is currently ignored, as indicated by the TODO comment. Proper error handling ensures that issues are not silently overlooked.

Consider updating the code to handle the error appropriately, for example:

func (k Keeper) AfterIBCAckSuccess(ctx sdk.Context, ibcChannel string, ibcSequence uint64) {
	ibcTransferKey := types.NewIBCTransferKey(ibcChannel, ibcSequence)
-	_ = k.erc20Keeper.DeleteCache(ctx, ibcTransferKey) // todo: need to handle error
+	if err := k.erc20Keeper.DeleteCache(ctx, ibcTransferKey); err != nil {
+		k.Logger(ctx).Error("Failed to delete IBC transfer cache", "error", err, "channel", ibcChannel, "sequence", ibcSequence)
+	}
}
📝 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.

func (k Keeper) AfterIBCAckSuccess(ctx sdk.Context, ibcChannel string, ibcSequence uint64) {
	ibcTransferKey := types.NewIBCTransferKey(ibcChannel, ibcSequence)
	if err := k.erc20Keeper.DeleteCache(ctx, ibcTransferKey); err != nil {
		k.Logger(ctx).Error("Failed to delete IBC transfer cache", "error", err, "channel", ibcChannel, "sequence", ibcSequence)
	}
}

75-87: 🛠️ Refactor suggestion

Combine conditions for clarity in WithdrawBridgeToken

In the WithdrawBridgeToken function, the conditions checking bridgeToken.IsOrigin() and bridgeToken.IsNative both result in an early return. Combining these conditions can enhance readability and reduce code complexity.

Apply this diff to combine the conditions:

func (k Keeper) WithdrawBridgeToken(ctx context.Context, holder sdk.AccAddress, amount sdkmath.Int, bridgeToken erc20types.BridgeToken) error {
	bridgeCoins := sdk.NewCoins(sdk.NewCoin(bridgeToken.BridgeDenom(), amount))
	if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, holder, k.moduleName, bridgeCoins); err != nil {
		return err
	}
-	if bridgeToken.IsOrigin() {
+	if bridgeToken.IsOrigin() || bridgeToken.IsNative {
		return nil
	}
-	if bridgeToken.IsNative {
-		return nil
-	}
	return k.bankKeeper.BurnCoins(ctx, k.moduleName, bridgeCoins)
}
📝 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.

// WithdrawBridgeToken put bridge token to k.moduleName
func (k Keeper) WithdrawBridgeToken(ctx context.Context, holder sdk.AccAddress, amount sdkmath.Int, bridgeToken erc20types.BridgeToken) error {
	bridgeCoins := sdk.NewCoins(sdk.NewCoin(bridgeToken.BridgeDenom(), amount))
	if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, holder, k.moduleName, bridgeCoins); err != nil {
		return err
	}
	if bridgeToken.IsOrigin() || bridgeToken.IsNative {
		return nil
	}
	return k.bankKeeper.BurnCoins(ctx, k.moduleName, bridgeCoins)
}

16-32: 🛠️ Refactor suggestion

Simplify redundant check for bridgeToken.IsNative

In the BridgeTokenToBaseCoin function, after checking bridgeToken.IsNative and returning early, the subsequent check if !bridgeToken.IsNative at line 26 is redundant since the code will only reach this point if bridgeToken.IsNative is false. Removing this redundant check can simplify the code.

Apply this diff to remove the redundant if statement:

func (k Keeper) BridgeTokenToBaseCoin(ctx context.Context, holder sdk.AccAddress, amount sdkmath.Int, bridgeToken erc20types.BridgeToken) (sdk.Coin, error) {
	baseCoin := sdk.NewCoin(bridgeToken.Denom, amount)
	if bridgeToken.IsNative {
		return baseCoin, nil
	}
	bridgeCoins := sdk.NewCoins(sdk.NewCoin(bridgeToken.BridgeDenom(), amount))
	if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, holder, types.ModuleName, bridgeCoins); err != nil {
		return sdk.Coin{}, err
	}
	baseCoins := sdk.NewCoins(baseCoin)
-	if !bridgeToken.IsNative {
		if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, baseCoins); err != nil {
			return sdk.Coin{}, err
		}
-	}
	err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, holder, baseCoins)
	return baseCoin, err
}
📝 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.

func (k Keeper) BridgeTokenToBaseCoin(ctx context.Context, holder sdk.AccAddress, amount sdkmath.Int, bridgeToken erc20types.BridgeToken) (sdk.Coin, error) {
	baseCoin := sdk.NewCoin(bridgeToken.Denom, amount)
	if bridgeToken.IsNative {
		return baseCoin, nil
	}
	bridgeCoins := sdk.NewCoins(sdk.NewCoin(bridgeToken.BridgeDenom(), amount))
	if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, holder, types.ModuleName, bridgeCoins); err != nil {
		return sdk.Coin{}, err
	}
	baseCoins := sdk.NewCoins(baseCoin)
	if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, baseCoins); err != nil {
		return sdk.Coin{}, err
	}
	err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, holder, baseCoins)
	return baseCoin, err
}
x/erc20/keeper/convert.go (6)

178-185: ⚠️ Potential issue

Ensure atomicity in minting and transferring coins

After minting coins to the module account in ConvertERC20NativeToken, coins are sent to the receiver. If an error occurs during SendCoinsFromModuleToAccount, the module account retains the minted coins, leading to inconsistencies.

Implement error handling or state rollback to maintain atomicity:

  • Use a transactional approach if supported.
  • Alternatively, consider burning the minted coins in case of a failure to send them to the receiver.

152-158: ⚠️ Potential issue

Handle potential nil pointer dereference in ERC20Burn

In ConvertERC20NativeCoin, ensure that all parameters passed to ERC20Burn are valid and not nil. Specifically, verify that amount.BigInt() does not result in a nil value, which could cause a panic.

Add validation for amount:

func (k Keeper) ConvertERC20NativeCoin(ctx context.Context, erc20Token types.ERC20Token, sender common.Address, receiver sdk.AccAddress, amount sdkmath.Int) error {
    erc20Contract := erc20Token.GetERC20Contract()

+   if !amount.IsPositive() {
+       return errors.New("amount must be positive")
+   }

    if err := k.evmErc20Keeper.ERC20Burn(ctx, erc20Contract, k.contractOwner, sender, amount.BigInt()); err != nil {
        return err
    }
    // ...
📝 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.

func (k Keeper) ConvertERC20NativeCoin(ctx context.Context, erc20Token types.ERC20Token, sender common.Address, receiver sdk.AccAddress, amount sdkmath.Int) error {
	erc20Contract := erc20Token.GetERC20Contract()

	if !amount.IsPositive() {
		return errors.New("amount must be positive")
	}

	if err := k.evmErc20Keeper.ERC20Burn(ctx, erc20Contract, k.contractOwner, sender, amount.BigInt()); err != nil {
		return err
	}


26-32: ⚠️ Potential issue

Validate coin.Amount is greater than zero

In the BaseCoinToEvm function, there's no check to ensure that coin.Amount is positive. Converting a zero or negative amount doesn't make sense in this context and may lead to unintended behavior.

Consider adding a validation for coin.Amount:

func (k Keeper) BaseCoinToEvm(ctx context.Context, holder common.Address, coin sdk.Coin) (string, error) {
+    if !coin.Amount.IsPositive() {
+        return "", errors.New("coin amount must be greater than zero")
+    }
    erc20Address, err := k.ConvertCoin(ctx, holder.Bytes(), holder, coin)
    if err != nil {
        return "", err
    }
    return erc20Address, nil
}
📝 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.

func (k Keeper) BaseCoinToEvm(ctx context.Context, holder common.Address, coin sdk.Coin) (string, error) {
    if !coin.Amount.IsPositive() {
        return "", errors.New("coin amount must be greater than zero")
    }
    erc20Address, err := k.ConvertCoin(ctx, holder.Bytes(), holder, coin)
    if err != nil {
        return "", err
    }
    return erc20Address, nil
}

17-24: ⚠️ Potential issue

Handle potential nil pointer dereference for amount

In the EvmToBaseCoin function, amount is used without checking if it's nil. If amount is nil, calling NewIntFromBigInt(amount) will result in a panic. It's important to validate amount before using it.

Apply this diff to check for a nil amount:

func (k Keeper) EvmToBaseCoin(ctx context.Context, holder common.Address, amount *big.Int, tokenAddr string) (sdk.Coin, error) {
+    if amount == nil {
+        return sdk.Coin{}, errors.New("amount cannot be nil")
+    }
    sdkInt := sdkmath.NewIntFromBigInt(amount)
    baseDenom, err := k.ConvertERC20(ctx, holder, holder.Bytes(), tokenAddr, sdkInt)
    if err != nil {
        return sdk.Coin{}, err
    }
    return sdk.NewCoin(baseDenom, sdkInt), nil
}
📝 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.

func (k Keeper) EvmToBaseCoin(ctx context.Context, holder common.Address, amount *big.Int, tokenAddr string) (sdk.Coin, error) {
    if amount == nil {
        return sdk.Coin{}, errors.New("amount cannot be nil")
    }
    sdkInt := sdkmath.NewIntFromBigInt(amount)
    baseDenom, err := k.ConvertERC20(ctx, holder, holder.Bytes(), tokenAddr, sdkInt)
    if err != nil {
        return sdk.Coin{}, err
    }
    return sdk.NewCoin(baseDenom, sdkInt), nil
}

34-73: ⚠️ Potential issue

Check for zero receiver address in ConvertCoin

The receiver parameter in the ConvertCoin function could potentially be the zero address. Transferring tokens to the zero address can result in loss of funds. It's crucial to validate the receiver address.

Add a check for the zero address:

func (k Keeper) ConvertCoin(ctx context.Context, sender sdk.AccAddress, receiver common.Address, coin sdk.Coin) (erc20Addr string, err error) {
+    if receiver == (common.Address{}) {
+        return "", errors.New("receiver address cannot be the zero address")
+    }
    erc20Token, err := k.MintingEnabled(ctx, receiver.Bytes(), true, coin.Denom)
    if err != nil {
        return erc20Addr, err
    }
    // ...
📝 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.

func (k Keeper) ConvertCoin(ctx context.Context, sender sdk.AccAddress, receiver common.Address, coin sdk.Coin) (erc20Addr string, err error) {
    if receiver == (common.Address{}) {
        return "", errors.New("receiver address cannot be the zero address")
    }
    erc20Token, err := k.MintingEnabled(ctx, receiver.Bytes(), true, coin.Denom)
    if err != nil {
        return erc20Addr, err
    }

    // Check ownership and execute conversion
    switch {
    case erc20Token.IsNativeCoin():
        err = k.ConvertCoinNativeCoin(ctx, erc20Token, sender, receiver, coin)
    case erc20Token.IsNativeERC20():
        err = k.ConvertCoinNativeERC20(ctx, erc20Token, sender, receiver, coin)
    default:
        return erc20Addr, types.ErrUndefinedOwner
    }
    if err != nil {
        return erc20Addr, err
    }

    defer func() {
        telemetry.IncrCounterWithLabels(
            []string{"tx", "msg", "convert", "coin", "total"},
            1,
            []metrics.Label{
                telemetry.NewLabel("denom", erc20Token.Denom),
                telemetry.NewLabel("erc20", erc20Token.Erc20Address),
            },
        )
    }()

    sdk.UnwrapSDKContext(ctx).EventManager().EmitEvent(sdk.NewEvent(
        types.EventTypeConvertCoin,
        sdk.NewAttribute(sdk.AttributeKeySender, sender.String()),
        sdk.NewAttribute(types.AttributeKeyReceiver, receiver.String()),
        sdk.NewAttribute(sdk.AttributeKeyAmount, coin.Amount.String()),
        sdk.NewAttribute(types.AttributeKeyDenom, coin.Denom),
        sdk.NewAttribute(types.AttributeKeyTokenAddress, erc20Token.Erc20Address),
    ))
    return erc20Token.Erc20Address, nil
}

100-102: ⚠️ Potential issue

Ensure sender has sufficient balance before transferring coins

In ConvertCoinNativeERC20, before calling SendCoinsFromAccountToModule, confirm that the sender's account has enough balance of the specified coins to prevent unexpected failures.

Consider adding a balance check:

func (k Keeper) ConvertCoinNativeERC20(ctx context.Context, erc20Token types.ERC20Token, sender sdk.AccAddress, receiver common.Address, coin sdk.Coin) error {
+    if !k.bankKeeper.HasBalance(ctx, sender, coin) {
+        return errors.New("sender has insufficient balance")
+    }
    // ...

Committable suggestion was skipped due to low confidence.

x/crosschain/keeper/outgoing_tx.go (2)

103-103: ⚠️ Potential issue

Handle potential errors from k.erc20Keeper.HasCache properly.

In the conditional statement if found, err := k.erc20Keeper.HasCache(ctx, key); err == nil && found {, any error returned by HasCache is ignored. To prevent silent failures, consider handling the error explicitly when err != nil.

Apply this diff to handle errors appropriately:

-if found, err := k.erc20Keeper.HasCache(ctx, key); err == nil && found {
+found, err := k.erc20Keeper.HasCache(ctx, key)
+if err != nil {
+    return err
+}
+if found {
📝 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.

		found, err := k.erc20Keeper.HasCache(ctx, key)
		if err != nil {
		    return err
		}
		if found {

16-22: 💡 Codebase verification

Inconsistent Fee Handling in BaseCoinToBridgeToken and WithdrawBridgeToken Calls

  • In x/crosschain/keeper/outgoing_tx.go, BaseCoinToBridgeToken includes fee in the amount (amount.Add(fee)), whereas WithdrawBridgeToken does not include fee (amount.Amount).
  • In contrast, x/crosschain/keeper/bridge_call_out.go excludes fee in both BaseCoinToBridgeToken and WithdrawBridgeToken calls.
🔗 Analysis chain

Ensure correct handling of fees in token conversion and withdrawal.

In BuildOutgoingTxBatch, the k.BaseCoinToBridgeToken function is called with amount.Add(fee). Please verify that including the fee in the amount during the base coin to bridge token conversion is intentional and aligns with the business logic.

Similarly, in k.WithdrawBridgeToken, only amount.Amount is passed. Should the fee.Amount also be included in the withdrawal process to ensure consistency?

Run the following script to check for consistency in fee handling across similar function calls:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify how fees are handled in BaseCoinToBridgeToken and WithdrawBridgeToken across the codebase.
# Expected: Confirm whether fees are consistently included or excluded in these function calls.

# Search for calls to BaseCoinToBridgeToken
rg 'k\.BaseCoinToBridgeToken\([^)]*\)' -A 2

# Search for calls to WithdrawBridgeToken
rg 'k\.WithdrawBridgeToken\([^)]*\)' -A 2

Length of output: 984

x/crosschain/precompile/contract_test.go (1)

212-212: 🛠️ Refactor suggestion

Consider unexporting SendEvmTx if it's only used within the package

The function SendEvmTx is now exported. If it's intended for internal use within the precompile_test package and not accessed externally, consider renaming it back to sendEvmTx to keep it unexported, adhering to Go's naming conventions and promoting encapsulation.

x/crosschain/keeper/bridge_call_out.go (7)

8-8: ⚠️ Potential issue

Unused Import of the "time" Package

The time package is imported on line 8 but is not used in the code. Consider removing it to clean up the imports.

-	"time"
📝 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.



284-304: ⚠️ Potential issue

Add Nil Check for fxTarget in CrossChainBaseCoin

Similar to BridgeCallBaseCoin, the fxTarget parameter in CrossChainBaseCoin is used without checking for nil. Adding a nil check will prevent potential nil pointer dereferences.

 func (k Keeper) CrossChainBaseCoin(
 	ctx sdk.Context,
 	from sdk.AccAddress,
 	receipt string,
 	amount, fee sdk.Coin,
 	fxTarget *types.FxTarget,
 	memo string,
 	originToken bool,
 ) error {
+	if fxTarget == nil {
+		return sdkerrors.ErrInvalidRequest.Wrap("fxTarget is nil")
+	}

 	var cacheKey string
📝 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.

	fxTarget *types.FxTarget,
	memo string,
	originToken bool,
) error {
	if fxTarget == nil {
		return sdkerrors.ErrInvalidRequest.Wrap("fxTarget is nil")
	}

	var cacheKey string
	if fxTarget.IsIBC() {
		sequence, err := k.IBCTransfer(ctx, from.Bytes(), receipt, amount, fxTarget.IBCChannel, memo)
		if err != nil {
			return err
		}
		cacheKey = types.NewIBCTransferKey(fxTarget.IBCChannel, sequence)
	} else {
		batchNonce, err := k.BuildOutgoingTxBatch(ctx, from, receipt, amount, fee)
		if err != nil {
			return err
		}
		cacheKey = types.NewOriginTokenKey(fxTarget.GetModuleName(), batchNonce)
	}

	if originToken {
		return k.erc20Keeper.SetCache(ctx, cacheKey)

142-145: ⚠️ Potential issue

Handle Errors Properly in RefundOutgoingBridgeCall

The error from k.erc20Keeper.BaseCoinToEvm is checked, but the returned value is ignored. If the function returns a value that's important for subsequent logic, ensure it's handled appropriately. If not needed, clarify by using an underscore.

-		_, err := k.erc20Keeper.BaseCoinToEvm(ctx, common.BytesToAddress(refund.Bytes()), coin)
+		if _, err := k.erc20Keeper.BaseCoinToEvm(ctx, common.BytesToAddress(refund.Bytes()), coin); err != nil {
+			return err
+		}
📝 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.

		if _, err := k.erc20Keeper.BaseCoinToEvm(ctx, common.BytesToAddress(refund.Bytes()), coin); err != nil {
			return err
		}

247-273: ⚠️ Potential issue

Add Nil Check for fxTarget to Prevent Nil Pointer Dereference

In the BridgeCallBaseCoin function, fxTarget is dereferenced without checking if it is nil. This could lead to a nil pointer dereference if fxTarget is nil. Consider adding a nil check at the beginning of the function.

 func (k Keeper) BridgeCallBaseCoin(
 	ctx sdk.Context,
 	from, refund, to common.Address,
 	coins sdk.Coins,
 	data, memo []byte,
 	fxTarget *types.FxTarget,
 	originTokenAmount sdkmath.Int,
 ) (uint64, error) {
+	if fxTarget == nil {
+		return 0, sdkerrors.ErrInvalidRequest.Wrap("fxTarget is nil")
+	}
📝 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.

	fxTarget *types.FxTarget,
	originTokenAmount sdkmath.Int,
) (uint64, error) {
	if fxTarget == nil {
		return 0, sdkerrors.ErrInvalidRequest.Wrap("fxTarget is nil")
	}
	if fxTarget.IsIBC() {
		if !coins.IsValid() || len(coins) != 1 {
			return 0, sdkerrors.ErrInvalidCoins.Wrapf("ibc transfer with coins: %s", coins.String())
		}
		baseCoin := coins[0]
		toAddr, err := fxTarget.ReceiveAddrToStr(to.Bytes())
		if err != nil {
			return 0, err
		}
		ibcCoin, err := k.BaseCoinToIBCCoin(ctx, from.Bytes(), baseCoin, fxTarget.IBCChannel)
		if err != nil {
			return 0, err
		}
		sequence, err := k.IBCTransfer(ctx, from.Bytes(), toAddr, ibcCoin, fxTarget.IBCChannel, string(memo))
		if err != nil {
			return 0, err
		}
		if originTokenAmount.IsPositive() {
			ibcTransferKey := types.NewIBCTransferKey(fxTarget.IBCChannel, sequence)
			if err = k.erc20Keeper.SetCache(ctx, ibcTransferKey); err != nil {
				return 0, err
			}
		}
		return sequence, nil

320-321: 💡 Codebase verification

⚠️ Potential issue

Incorrect Usage of transfertypes.ModuleName as Source Port

The usage of transfertypes.ModuleName as the source port in NewMsgTransfer is inconsistent with the standard practice of using transfertypes.PortID for IBC transfers.

  • Location: x/crosschain/keeper/bridge_call_out.go, Lines: 320-321
🔗 Analysis chain

Verify Correct Usage of transfertypes.ModuleName as Source Port

In the NewMsgTransfer invocation, transfertypes.ModuleName is used as the source port. Typically, transfertypes.PortID should be used as the source port in IBC transfers.

 			transfertypes.NewMsgTransfer(
-				transfertypes.ModuleName,
+				transfertypes.PortID,
 				channel,

Run the following script to verify the correct source port:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the usage of `NewMsgTransfer` to ensure `transfertypes.PortID` is used as the source port.

rg --type go 'NewMsgTransfer\(' -A 5

Length of output: 381


254-273: ⚠️ Potential issue

Handle Multiple Coins Appropriately in IBC Transfer

In the IBC transfer logic, only the first coin from the coins array is being used (baseCoin := coins[0]). If multiple coins are passed, the rest will be ignored, which might lead to unexpected behavior. Consider validating that only one coin is provided or handling multiple coins appropriately.

 if fxTarget.IsIBC() {
 	if !coins.IsValid() || len(coins) != 1 {
 		return 0, sdkerrors.ErrInvalidCoins.Wrapf("ibc transfer with coins: %s", coins.String())
 	}
+	if len(coins) > 1 {
+		return 0, sdkerrors.ErrInvalidRequest.Wrap("IBC transfer supports only one coin at a time")
+	}
 	baseCoin := coins[0]

Committable suggestion was skipped due to low confidence.


317-317: 🛠️ Refactor suggestion

Consider Making IBC Transfer Timeout Configurable

The timeout for IBC transfers is hardcoded to 12 hours. To enhance flexibility and accommodate different network conditions, consider making the timeout configurable.

-func (k Keeper) IBCTransfer(
+const defaultIBCTimeout = 12 * time.Hour
+
+func (k Keeper) IBCTransferWithTimeout(
 	ctx sdk.Context,
 	from sdk.AccAddress,
 	to string,
 	amount sdk.Coin,
 	channel string,
 	memo string,
+	timeout time.Duration,
 ) (uint64, error) {
-	timeout := 12 * time.Hour
+	if timeout == 0 {
+		timeout = defaultIBCTimeout
+	}
 	transferResponse, err := k.ibcTransferKeeper.Transfer(ctx,
 		transfertypes.NewMsgTransfer(
 			transfertypes.ModuleName,
 			channel,
 			amount,
 			from.String(),
 			to,
 			ibcclienttypes.ZeroHeight(),
 			uint64(ctx.BlockTime().Add(timeout).UnixNano()),
 			memo,
 		),
 	)

Committable suggestion was skipped due to low confidence.

x/crosschain/keeper/grpc_query.go (4)

212-215: ⚠️ Potential issue

Ensure consistent verification of bridge token existence

The call to k.erc20Keeper.GetBridgeToken is used to verify the existence of the bridge token associated with the base denom and chain name. Make sure that this check is necessary and that the error handling is consistent with the rest of the code. If the purpose is to confirm registration, handle errors appropriately as mentioned earlier.


289-289: ⚠️ Potential issue

Implement the BridgeTokens method or remove the TODO comment

The BridgeTokens method currently contains a TODO comment indicating that it needs implementation. To maintain code quality and readability, consider implementing the method or, if it's not required at the moment, provide a more detailed plan or remove it to prevent confusion.

Would you like assistance in implementing this method or creating a stub that clarifies the intended functionality?


208-210: ⚠️ Potential issue

Handle GetBaseDenom errors with appropriate status codes

Similar to the previous function, when k.erc20Keeper.GetBaseDenom returns an error, it might not always indicate that the denom was not found. Ensure that the error handling reflects the actual cause by returning suitable gRPC status codes.

Suggested change:

 if err != nil {
+   if errors.Is(err, types.ErrDenomNotFound) {
        return nil, status.Error(codes.NotFound, err.Error())
+   }
+   return nil, status.Error(codes.Internal, err.Error())
 }
📝 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.

	baseDenom, err := k.erc20Keeper.GetBaseDenom(ctx, req.Token)
	if err != nil {
		if errors.Is(err, types.ErrDenomNotFound) {
			return nil, status.Error(codes.NotFound, err.Error())
		}
		return nil, status.Error(codes.Internal, err.Error())
	}

196-198: ⚠️ Potential issue

Use more precise error codes when handling GetBridgeToken errors

When k.erc20Keeper.GetBridgeToken returns an error, it is wrapped with codes.NotFound regardless of the underlying cause. This might not be accurate if the error is due to reasons other than the token not being found. Consider differentiating error types to return more appropriate gRPC status codes.

Suggested change:

 if err != nil {
+   if errors.Is(err, types.ErrTokenNotFound) {
        return nil, status.Error(codes.NotFound, err.Error())
+   }
+   return nil, status.Error(codes.Internal, err.Error())
 }

Committable suggestion was skipped due to low confidence.

x/crosschain/keeper/msg_server_test.go (1)

877-877: ⚠️ Potential issue

Rename function to 'TestBondedOracle' to ensure it is executed as a test

In Go's testing framework, test functions must start with Test to be recognized and executed by the go test command. Currently, BondedOracle will not run as a test. Renaming the function ensures it is included during testing and maintains consistency with the other tests in the suite.

Apply this diff to rename the function:

-func (suite *KeeperTestSuite) BondedOracle() {
+func (suite *KeeperTestSuite) TestBondedOracle() {
📝 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.

func (suite *KeeperTestSuite) TestBondedOracle() {
api/fx/erc20/v1/genesis.pulsar.go (2)

11-11: ⚠️ Potential issue

Unused import of durationpb.

The import statement _ "google.golang.org/protobuf/types/known/durationpb" at line 11 appears to be unused in this file. Consider removing it to clean up the code.


1019-1020: ⚠️ Potential issue

Removal of fields from Params struct may impact backward compatibility.

The Params struct has had the fields EnableEvmHook and IbcTimeout removed, leaving only EnableErc20 (lines 1019-1020 and 1050-1053). This change might affect backward compatibility with existing configurations or serialized data. Please ensure that appropriate migration logic is in place to handle this change without disrupting existing deployments.

Also applies to: 1050-1053

api/fx/erc20/v1/types.pulsar.go (1)

1-2: 💡 Codebase verification

⚠️ Potential issue

Multiple Code Generation Tools Detected

The file api/fx/erc20/v1/types.pulsar.go contains code generated by both protoc-gen-go-pulsar and protoc-gen-go. Using different code generators within the same file may lead to maintenance issues or unexpected behavior.

🔗 Analysis chain

Inconsistent code generation tools used in the same file

The file begins with code generated by protoc-gen-go-pulsar (line 1) and later includes code generated by protoc-gen-go (lines 1690-1694). Mixing different code generators in the same file may lead to maintenance issues or unexpected behavior. Please verify if this is intentional.

Run the following script to check for multiple code generation tool annotations in the file:

Also applies to: 1690-1694

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that only one code generation tool is used per file.
# Expected: Only one unique code generator annotation in the file.

# Search for lines indicating code generation tools
rg --type go '^// Code generated by' api/fx/erc20/v1/types.pulsar.go | sort | uniq -c

Length of output: 208

Copy link

@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: 16

🧹 Outside diff range and nitpick comments (34)
x/erc20/types/errors.go (1)

Remain usages of removed error variables found.

The ErrABIUnpack error variable is still used in the following files:

  • x/evm/types/errors.go
  • x/evm/keeper/erc20.go
  • x/evm/keeper/contract_code.go

Please verify whether these usages are intentional and ensure that retaining ErrABIUnpack does not conflict with the removal of the other error variables.

🔗 Analysis chain

Line range hint 1-10: Verify the impact of removed error variables.

Several error variables have been removed according to the AI summary: ErrInternalTokenPair, ErrTokenPairNotFound, ErrUnexpectedEvent, ErrABIUnpack, ErrInvalidMetadata, and ErrERC20TokenPairDisabled. Please ensure that:

  1. These errors are no longer needed in the codebase.
  2. All cases previously using these errors are now properly handled.
  3. The removal of these errors doesn't introduce any gaps in error handling or reporting.

To help verify the impact, you can run the following script:

This script will help identify any remaining usage of the removed error variables and potential unhandled error cases.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of the removed error variables

# Test: Search for usage of removed error variables
echo "Searching for usage of removed error variables:"
rg --type go -i "ErrInternalTokenPair|ErrTokenPairNotFound|ErrUnexpectedEvent|ErrABIUnpack|ErrInvalidMetadata|ErrERC20TokenPairDisabled"

# Test: Search for potential unhandled error cases
echo "Searching for potential unhandled error cases:"
rg --type go -i "error.*token.*pair|error.*unexpected.*event|error.*abi.*unpack|error.*invalid.*metadata"

Length of output: 11796

x/erc20/keeper/params.go (2)

9-18: Approve new CheckEnableErc20 method with a minor suggestion.

The new CheckEnableErc20 method effectively encapsulates the logic for checking if the ERC20 module is enabled. It properly handles potential errors from parameter retrieval and uses a custom error type for clear error messaging.

Consider wrapping the error returned from k.Params.Get(ctx) to provide more context:

 func (k Keeper) CheckEnableErc20(ctx context.Context) error {
 	params, err := k.Params.Get(ctx)
 	if err != nil {
-		return err
+		return fmt.Errorf("failed to get params: %w", err)
 	}
 	if !params.EnableErc20 {
 		return types.ErrDisabled.Wrap("erc20 module is disabled")
 	}
 	return nil
 }

This change would provide more information about where the error occurred, which can be helpful for debugging.


1-18: Summary of changes and potential impact.

The modifications to params.go represent a significant refactoring of parameter management in the ERC20 module:

  1. The shift from SDK-specific context to standard Go context improves compatibility and aligns with modern Go practices.
  2. The new CheckEnableErc20 method provides a focused way to check if the ERC20 module is enabled.
  3. The removal of several methods (GetParams, SetParams, GetEnableEVMHook, GetIbcTimeout) suggests a broader change in how parameters are accessed and managed throughout the module.

These changes likely improve the module's structure and maintainability. However, they may have far-reaching implications across the codebase. Ensure that all affected parts of the code have been updated accordingly, and consider updating the module's documentation to reflect these significant changes in parameter management.

Consider creating a comprehensive guide or updating existing documentation to explain the new parameter management approach. This will help other developers understand and correctly use the new system.

x/erc20/keeper/cache.go (2)

13-15: LGTM: SetCache method is correctly implemented, but could benefit from a comment.

The SetCache method is well-implemented:

  1. It correctly uses the context for potential cancellation or timeout handling.
  2. The method signature (returning an error) is appropriate for a cache set operation.
  3. It properly delegates to the underlying Cache implementation.
  4. The use of collections.NoValue{} suggests this is being used as a set rather than a key-value store.

Consider adding a brief comment explaining the use of collections.NoValue{} to improve code readability. For example:

// SetCache adds the key to the cache. It uses NoValue{} as we're using the cache as a set, not a key-value store.
func (k Keeper) SetCache(ctx context.Context, key string) error {
    return k.Cache.Set(ctx, key, collections.NoValue{})
}

17-19: LGTM: DeleteCache method is correctly implemented, but consider naming consistency.

The DeleteCache method is well-implemented:

  1. It correctly uses the context for potential cancellation or timeout handling.
  2. The method signature (returning an error) is appropriate for a cache delete operation.
  3. It properly delegates to the underlying Cache implementation.

Consider renaming the method to RemoveCache to maintain consistency with the underlying Remove method. This would improve code readability and reduce potential confusion. For example:

func (k Keeper) RemoveCache(ctx context.Context, key string) error {
    return k.Cache.Remove(ctx, key)
}

Alternatively, if DeleteCache is the preferred naming convention in your project, consider adding a comment explaining the naming difference:

// DeleteCache removes the key from the cache. It calls the underlying Remove method.
func (k Keeper) DeleteCache(ctx context.Context, key string) error {
    return k.Cache.Remove(ctx, key)
}
x/erc20/keeper/bridge_token.go (1)

23-42: LGTM with a minor suggestion: AddBridgeToken method is well-implemented.

The AddBridgeToken method is thorough in its implementation, checking for existing tokens, constructing a new BridgeToken object, and updating both BridgeToken and DenomIndex collections. The error handling is generally good, but there's room for a small improvement.

Consider wrapping the error returned from k.DenomIndex.Set() on line 41 to provide more context:

- return k.DenomIndex.Set(ctx, bridgeToken.BridgeDenom(), baseDenom)
+ if err := k.DenomIndex.Set(ctx, bridgeToken.BridgeDenom(), baseDenom); err != nil {
+     return fmt.Errorf("failed to set DenomIndex: %w", err)
+ }
+ return nil

This change would make it easier to debug if an error occurs during the DenomIndex update.

x/erc20/keeper/msg_server.go (4)

20-23: LGTM: Well-implemented constructor function

The NewMsgServerImpl function correctly initializes and returns a new msgServer instance. This is a good practice for object creation.

Consider returning msgServer directly instead of &msgServer for consistency with the interface declaration on line 14:

func NewMsgServerImpl(k Keeper) types.MsgServer {
-	return &msgServer{
+	return msgServer{
		k: k,
	}
}

26-31: LGTM: Correct implementation of ConvertCoin method

The ConvertCoin method is correctly implemented for the msgServer type. It properly unwraps the context, processes the message, and calls the corresponding method on the encapsulated Keeper.

Consider wrapping the error returned from s.k.ConvertCoin with additional context:

func (s msgServer) ConvertCoin(c context.Context, msg *types.MsgConvertCoin) (*types.MsgConvertCoinResponse, error) {
	ctx := sdk.UnwrapSDKContext(c)
	sender := sdk.MustAccAddressFromBech32(msg.Sender)
	receiver := common.HexToAddress(msg.Receiver)
-	_, err := s.k.ConvertCoin(ctx, sender, receiver, msg.Coin)
-	return &types.MsgConvertCoinResponse{}, err
+	_, err := s.k.ConvertCoin(ctx, sender, receiver, msg.Coin)
+	if err != nil {
+		return nil, errorsmod.Wrap(err, "failed to convert coin")
+	}
+	return &types.MsgConvertCoinResponse{}, nil
}

This provides more context in case of an error, which can be helpful for debugging.


34-42: LGTM: Correct implementation of UpdateParams method

The UpdateParams method is correctly implemented for the msgServer type. It properly checks the authority and updates the parameters using the encapsulated Keeper's Params.

For consistency with other methods, consider unwrapping the context at the beginning of the method:

func (s msgServer) UpdateParams(c context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) {
	if s.k.authority != req.Authority {
		return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", s.k.authority, req.Authority)
	}
-	ctx := sdk.UnwrapSDKContext(c)
+	ctx := sdk.UnwrapSDKContext(c)
	if err := s.k.Params.Set(ctx, req.Params); err != nil {
		return nil, err
	}
	return &types.MsgUpdateParamsResponse{}, nil
}

This makes the context unwrapping consistent across all methods in the file.


45-53: LGTM: Correct implementation of ToggleTokenConversion method

The ToggleTokenConversion method is correctly implemented for the msgServer type. It properly checks the authority and calls the corresponding method on the encapsulated Keeper.

Consider the following improvements for consistency and better error handling:

  1. Unwrap the context at the beginning of the method.
  2. Wrap the error returned from s.k.ToggleTokenConvert with additional context.
func (s msgServer) ToggleTokenConversion(c context.Context, req *types.MsgToggleTokenConversion) (*types.MsgToggleTokenConversionResponse, error) {
+	ctx := sdk.UnwrapSDKContext(c)
	if s.k.authority != req.Authority {
		return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", s.k.authority, req.Authority)
	}
-	erc20Token, err := s.k.ToggleTokenConvert(c, req.Token)
+	erc20Token, err := s.k.ToggleTokenConvert(ctx, req.Token)
	if err != nil {
-		return nil, err
+		return nil, errorsmod.Wrap(err, "failed to toggle token conversion")
	}
	return &types.MsgToggleTokenConversionResponse{Erc20Token: erc20Token}, nil
}

These changes improve consistency with other methods and provide more context in case of an error.

x/crosschain/precompile/keeper.go (2)

23-23: LGTM: Method signature improved for clarity and specificity.

The changes to the method signature enhance its descriptiveness and clarity:

  1. Renaming from EvmTokenToBase to EvmTokenToBaseCoin better describes the method's functionality.
  2. Renaming the parameter from token to tokenAddr is more precise.
  3. Adding sdk.Coin to the return type provides more specific information about the result.

These changes align well with good coding practices and improve the API's clarity.

Consider updating any existing documentation or comments related to this method to reflect these changes.


24-48: LGTM: Method logic improved and error handling enhanced.

The changes in the method body improve the code's clarity and error handling:

  1. Simplified logic for retrieving erc20Token enhances readability.
  2. Updated conditional checks using erc20Token properties align with the new structure.
  3. The new error case for invalid ERC20 token ownership improves error specificity.

These changes contribute to more robust and maintainable code.

Consider wrapping the error returned from crossChainKeeper.GetBaseDenomByErc20 to provide more context:

erc20Token, err := crossChainKeeper.GetBaseDenomByErc20(ctx, tokenAddr)
if err != nil {
    return sdk.Coin{}, fmt.Errorf("failed to get base denom for ERC20 token %s: %w", tokenAddr, err)
}

This change would make debugging easier by providing more information about where the error occurred.

x/erc20/keeper/grpc_query.go (3)

26-42: LGTM: Improved TokenPairs implementation with a minor suggestion

The updated TokenPairs method is well-implemented. The use of query.CollectionPaginate is an improvement over the previous prefix store approach. The response structure change to Erc20Tokens aligns well with the updated data model.

Consider wrapping the error returned from query.CollectionPaginate with additional context:

 if err != nil {
-    return nil, status.Error(codes.Internal, err.Error())
+    return nil, status.Errorf(codes.Internal, "failed to paginate ERC20 tokens: %v", err)
 }

This will provide more informative error messages for debugging.


47-70: LGTM: Well-implemented TokenPair method with a suggestion

The updated TokenPair method is well-structured and handles both Ethereum addresses and SDK denoms effectively. The use of DenomIndex and ERC20Token stores is efficient.

Consider adding a more specific error message when the ERC20 token is not found:

 erc20Token, err := s.k.ERC20Token.Get(c, baseDenom)
 if err != nil {
-    return nil, status.Error(codes.NotFound, err.Error())
+    return nil, status.Errorf(codes.NotFound, "ERC20 token not found for base denom %s: %v", baseDenom, err)
 }

This will provide more context in the error message, which can be helpful for debugging and client-side error handling.


Line range hint 1-79: Overall: Excellent refactoring of the query server implementation

The changes in this file represent a significant improvement in the query server implementation for the ERC20 module. The introduction of the queryServer struct with an encapsulated Keeper promotes better separation of concerns and modularity. The updated methods (TokenPairs, TokenPair, and Params) are more efficient and align well with the new data structures.

Key improvements:

  1. Better abstraction with the queryServer struct
  2. More efficient pagination in TokenPairs using query.CollectionPaginate
  3. Improved token pair retrieval logic in TokenPair
  4. Simplified parameter retrieval in Params

These changes should result in a more maintainable and performant query server implementation.

Consider adding unit tests for the new queryServer methods to ensure their correctness and to guard against future regressions.

x/crosschain/keeper/bridge_token.go (3)

15-36: LGTM: Improved token validation and error handling.

The refactored AddBridgeTokenExecuted function now leverages erc20Keeper for token validation, which aligns with the overall goal of centralizing ERC20 token management. The error messages are more specific and informative.

However, consider wrapping the error returned from k.erc20Keeper.HasToken to provide more context:

if err != nil {
    return fmt.Errorf("failed to check if bridge token exists: %w", err)
}

This will help in debugging by providing more information about where the error occurred.


41-66: LGTM: Improved handling of IBC and bridge tokens.

The refactored BridgeCoinSupply function now clearly separates the logic for IBC and bridge tokens, which improves readability and maintainability. The use of erc20Keeper methods for token information retrieval is consistent with the overall refactoring strategy.

Consider adding more context to the error returned from k.erc20Keeper.GetBaseDenom:

baseDenom, err := k.erc20Keeper.GetBaseDenom(ctx, token)
if err != nil {
    return sdk.Coin{}, fmt.Errorf("failed to get base denom for token %s: %w", token, err)
}

This will provide more information about which token caused the error, aiding in debugging.


69-74: LGTM: Improved ERC20 token information retrieval.

The refactored GetBaseDenomByErc20 function now returns a more comprehensive erc20types.ERC20Token instead of just a string and boolean. This change provides more detailed information about the ERC20 token, which is beneficial for consumers of this function.

Consider adding more context to the errors returned:

baseDenom, err := k.erc20Keeper.GetBaseDenom(ctx, erc20Addr.String())
if err != nil {
    return erc20types.ERC20Token{}, fmt.Errorf("failed to get base denom for ERC20 address %s: %w", erc20Addr.String(), err)
}

token, err := k.erc20Keeper.GetERC20Token(ctx, baseDenom)
if err != nil {
    return erc20types.ERC20Token{}, fmt.Errorf("failed to get ERC20 token for base denom %s: %w", baseDenom, err)
}
return token, nil

This will provide more detailed error messages, which can be helpful for debugging.

x/crosschain/precompile/crosschain.go (4)

58-61: Improved target address parsing and validation.

The introduction of crosschaintypes.ParseFxTarget enhances the robustness of target address handling. This change is a positive step towards better input validation.

Consider wrapping the error returned by ParseFxTarget with additional context to aid in debugging:

 fxTarget, err := crosschaintypes.ParseFxTarget(fxtypes.Byte32ToString(args.Target))
 if err != nil {
-    return err
+    return fmt.Errorf("failed to parse target address: %w", err)
 }

66-68: Enhanced external address validation.

The addition of ValidateExternalAddr improves the security and reliability of the cross-chain operation by ensuring the validity of the external address.

Consider wrapping the error returned by ValidateExternalAddr with additional context:

 if err = fxTarget.ValidateExternalAddr(args.Receipt); err != nil {
-    return err
+    return fmt.Errorf("invalid external address: %w", err)
 }

70-74: Improved logic for handling origin tokens and amount validation.

The introduction of isOriginToken and the simplified calculation of totalAmount enhance the readability and maintainability of the code.

Consider adding a comment to explain the significance of value.Sign() > 0:

+ // isOriginToken is true when the transaction includes a non-zero value,
+ // indicating that the origin token is being used.
 isOriginToken := value.Sign() > 0

78-80: Added validation for token address when using origin token.

This check ensures consistency between the use of origin tokens and the provided token address, preventing potential misuse.

Consider adding a comment to explain why the token address should be zero for origin tokens:

+ // For origin token transactions, the token address should be zero
+ // as the native token is being used.
 if !fxcontract.IsZeroEthAddress(args.Token) {
     return errors.New("token is not zero address")
 }
x/erc20/keeper/keeper.go (3)

21-40: LGTM: Keeper struct updated with collections-based fields.

The changes to the Keeper struct, including the replacement of storeKey with storeService and the addition of new fields using the collections package, are well-structured and align with modern Cosmos SDK practices.

Consider adding inline documentation for each new field to explain their purpose and usage, especially for the collections.Map fields. This will help other developers understand the structure more easily.


46-46: LGTM: NewKeeper function updated correctly.

The NewKeeper function has been properly updated to use storeService and initialize the new collection-based fields. The use of collections.NewSchemaBuilder and the subsequent initialization of collection fields are well-implemented.

Consider wrapping the error returned from sb.Build() with additional context before panicking. This could help with debugging in case of schema building failures. For example:

schema, err := sb.Build()
if err != nil {
    panic(fmt.Errorf("failed to build erc20 keeper schema: %w", err))
}

Also applies to: 58-80


88-116: LGTM: MintingEnabled method implemented correctly.

The new MintingEnabled method is well-structured and implements necessary checks before allowing ERC20 minting. It properly handles different scenarios and returns appropriate errors.

Consider grouping related checks together for better readability. For example, you could move the bankKeeper.BlockedAddr check right after the erc20Token.Enabled check, as they are both related to the receiver's eligibility. This would make the logical flow of the checks more apparent:

if !erc20Token.Enabled {
    return erc20Token, types.ErrDisabled.Wrapf("token %s is disabled", erc20Token.Denom)
}

if k.bankKeeper.BlockedAddr(receiver.Bytes()) {
    return erc20Token, sdkerrors.ErrUnauthorized.Wrapf("%s is not allowed to receive transactions", receiver)
}

if !k.bankKeeper.IsSendEnabledDenom(ctx, erc20Token.Denom) {
    return erc20Token, banktypes.ErrSendDisabled.Wrapf("minting '%s' denom is currently disabled", tokenName)
}
x/crosschain/types/expected_keepers.go (2)

68-70: New EvmERC20Keeper interface added for EVM-specific ERC20 operations.

The introduction of the EvmERC20Keeper interface with the TotalSupply method is a good addition for handling EVM-specific ERC20 operations. The method signature is appropriate, using context.Context and returning a *big.Int for precise handling of token supplies.

Consider adding a brief comment above the interface to explain its purpose and how it differs from the Erc20Keeper interface. This would improve the overall documentation and make it easier for other developers to understand the distinction between these interfaces.


74-74: New SetDenomTrace method added to IBCTransferKeeper interface.

The addition of the SetDenomTrace method to the IBCTransferKeeper interface is a good improvement. It complements the existing GetDenomTrace method, allowing for both setting and retrieving denom traces, which is crucial for IBC transfers.

For consistency, consider updating the GetDenomTrace method signature to use sdk.Context instead of context.Context, matching the newly added SetDenomTrace method. This would ensure a uniform approach across the interface.

x/crosschain/keeper/many_to_one.go (4)

16-32: LGTM! Consider adding a comment for clarity.

The BridgeTokenToBaseCoin function looks well-implemented. It correctly handles the conversion of bridge tokens to base coins, taking into account whether the token is an origin token or not. The error handling is appropriate.

Consider adding a brief comment explaining the purpose of this function and the difference in handling between origin and non-origin tokens. This would improve code readability and maintainability.


35-52: LGTM! Consider adding error wrapping.

The BaseCoinToBridgeToken function is well-implemented. It correctly handles the conversion of base coins to bridge tokens, taking into account whether the token is native or not. The error handling is appropriate.

Consider wrapping errors with additional context using fmt.Errorf or a similar method. This would provide more information about where and why an error occurred, making debugging easier. For example:

if err != nil {
    return bridgeToken, fmt.Errorf("failed to get bridge token: %w", err)
}

55-72: LGTM! Consider adding a comment for clarity.

The DepositBridgeToken function is well-implemented. It correctly handles the deposit of bridge tokens, taking into account whether the token is an origin token or not. The error handling is appropriate.

Consider adding a brief comment explaining the purpose of this function and the difference in handling between origin and non-origin tokens. This would improve code readability and maintainability.


126-135: LGTM! Consider adding logging for better traceability.

The IBCCoinToEvm function is well-implemented. It correctly handles the conversion of IBC coins to EVM-compatible tokens, including the case where the base denomination is not found.

Consider adding some logging statements to improve traceability, especially in the case where the base denomination is not found. This could help with debugging and monitoring. For example:

if baseDenom == "" {
    k.Logger(ctx).Info("Base denomination not found for IBC coin", "denom", ibcCoin.Denom)
    return nil
}
x/crosschain/keeper/grpc_query.go (3)

195-199: LGTM! Consider enhancing error handling.

The changes to DenomToToken method look good. Using erc20Keeper.GetBridgeToken improves encapsulation and potentially efficiency. The error handling is consistent with gRPC status codes.

Consider adding more context to the error message:

- return nil, status.Error(codes.NotFound, err.Error())
+ return nil, status.Errorf(codes.NotFound, "bridge token not found for denom %s: %v", req.Denom, err)

This will provide more informative error messages for debugging and logging purposes.


206-214: LGTM! Consider optimizing for performance.

The changes to TokenToDenom method look good. Using erc20Keeper.GetBaseDenom and erc20Keeper.GetBridgeToken improves encapsulation. The error handling is consistent with gRPC status codes.

Consider combining the two keeper calls to improve performance:

baseDenom, bridgeToken, err := k.erc20Keeper.GetBaseDenomAndBridgeToken(c, req.Token, req.ChainName)
if err != nil {
    return nil, status.Errorf(codes.NotFound, "token not found or not bridged: %v", err)
}
return &types.QueryTokenToDenomResponse{Denom: baseDenom}, nil

This would require implementing a new method GetBaseDenomAndBridgeToken in the erc20Keeper, but it could potentially reduce database lookups and improve overall performance.


295-299: LGTM! Consider enhancing error handling.

The changes to BridgeCoinByDenom method look good. Using k.BridgeCoinSupply instead of k.GetBridgeCoinSupply suggests a refactoring in the keeper, which is fine. The error handling is consistent with gRPC status codes.

Consider adding more context to the error message:

- return nil, status.Error(codes.Internal, err.Error())
+ return nil, status.Errorf(codes.Internal, "failed to get bridge coin supply for denom %s: %v", req.GetDenom(), err)

This will provide more informative error messages for debugging and logging purposes.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0593bff and 2fb3ebf.

📒 Files selected for processing (24)
  • x/crosschain/keeper/bridge_token.go (1 hunks)
  • x/crosschain/keeper/grpc_query.go (2 hunks)
  • x/crosschain/keeper/many_to_one.go (1 hunks)
  • x/crosschain/keeper/outgoing_tx.go (3 hunks)
  • x/crosschain/mock/expected_keepers_mocks.go (13 hunks)
  • x/crosschain/precompile/bridge_call.go (1 hunks)
  • x/crosschain/precompile/crosschain.go (1 hunks)
  • x/crosschain/precompile/expected_keepers.go (2 hunks)
  • x/crosschain/precompile/keeper.go (1 hunks)
  • x/crosschain/types/errors.go (0 hunks)
  • x/crosschain/types/expected_keepers.go (2 hunks)
  • x/crosschain/types/target.go (1 hunks)
  • x/erc20/keeper/bridge_token.go (1 hunks)
  • x/erc20/keeper/cache.go (1 hunks)
  • x/erc20/keeper/convert.go (1 hunks)
  • x/erc20/keeper/erc20_token.go (1 hunks)
  • x/erc20/keeper/genesis.go (1 hunks)
  • x/erc20/keeper/grpc_query.go (1 hunks)
  • x/erc20/keeper/ibc_token.go (1 hunks)
  • x/erc20/keeper/keeper.go (1 hunks)
  • x/erc20/keeper/msg_server.go (1 hunks)
  • x/erc20/keeper/params.go (1 hunks)
  • x/erc20/types/errors.go (1 hunks)
  • x/erc20/types/msg.go (1 hunks)
💤 Files with no reviewable changes (1)
  • x/crosschain/types/errors.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • x/crosschain/keeper/outgoing_tx.go
  • x/crosschain/precompile/bridge_call.go
  • x/crosschain/precompile/expected_keepers.go
  • x/crosschain/types/target.go
  • x/erc20/keeper/ibc_token.go
🧰 Additional context used
🔇 Additional comments (64)
x/erc20/types/errors.go (3)

8-8: LGTM: Error variable renamed appropriately.

The renaming of ErrERC20Disabled to ErrDisabled is a good change. It maintains the same error message while making the variable name more concise.


9-9: LGTM: Error variable renamed and message updated.

The renaming of ErrTokenPairAlreadyExists to ErrExists is a good change. The error message has been updated to be more generic ("token already exists"), which could make it more versatile if used in different contexts.


10-10: LGTM: Error message updated for clarity.

The error message for ErrUndefinedOwner has been updated from "undefined owner of contract pair" to "undefined owner of erc20 contract". This change provides more specific context, which is beneficial for error handling and debugging.

x/erc20/keeper/params.go (1)

4-4: Approve import changes and note context usage shift.

The import changes reflect a shift from using the SDK-specific context to the standard Go context. This change aligns with modern Go practices and potentially improves compatibility with other Go packages.

x/erc20/keeper/cache.go (3)

3-7: LGTM: Imports are appropriate for the implemented functionality.

The import statements are correct and necessary for the cache operations implemented in this file. The use of cosmossdk.io/collections is consistent with a Cosmos SDK based project.


9-11: LGTM: HasCache method is correctly implemented.

The HasCache method is well-designed:

  1. It correctly uses the context for potential cancellation or timeout handling.
  2. The method signature (returning bool and error) is appropriate for a cache lookup operation.
  3. It properly delegates to the underlying Cache implementation.

1-19: LGTM: Overall structure and consistency are excellent.

The file cache.go demonstrates a well-structured and consistent implementation of cache operations:

  1. It provides a complete set of basic cache operations (check existence, set, and delete).
  2. All methods are consistently defined on the Keeper struct.
  3. The use of context in all methods allows for proper cancellation and timeout handling.
  4. Error handling is consistent across all methods.
  5. The code is clean, concise, and follows good Go practices.

This implementation fits well within the keeper package and appears to be part of a larger ERC20 token handling system.

x/erc20/keeper/genesis.go (6)

12-14: Improved error handling in InitGenesis

The function signature now returns an error, allowing for better error propagation. The use of k.Params.Set with error checking is a good practice.


20-20: Enhanced error handling for module account check

Replacing the panic with an error return is a good practice for better error handling and system stability.


31-35: Improved error handling in ExportGenesis

The function now properly handles errors during parameter retrieval, which is a good practice. The signature change to return an error is consistent with the improvements in error handling throughout the file.


1-38: Summary of changes and areas for verification

The changes in this file significantly improve error handling and simplify implementations. Key improvements include:

  1. Both InitGenesis and ExportGenesis now return errors, allowing for better error propagation.
  2. The use of k.Params.Set and k.Params.Get with error checking enhances robustness.
  3. Panic statements have been replaced with error returns, improving system stability.

However, some areas require further verification:

  1. The removal of the token pair initialization loop in InitGenesis. Ensure this functionality is not needed or has been moved elsewhere.
  2. The simplification of the exported genesis state in ExportGenesis. Verify that all necessary data is still being included.

These changes align with best practices for error handling and code simplification, but it's crucial to ensure that no critical functionality has been lost in the process.

#!/bin/bash
# Description: Check for potential impacts of the changes

# Search for uses of InitGenesis and ExportGenesis
rg --type go 'InitGenesis|ExportGenesis' -g '!*_test.go'

# Search for token pair or ERC20 token handling
rg --type go 'TokenPair|ERC20Token' -g '!*_test.go'

36-38: Verify completeness of exported genesis state

The exported genesis state now only includes the Params field. Ensure that this is sufficient and that no other important data needs to be included in the genesis state.


23-27: Verify the removal of token pair initialization

The loop that previously added token pairs has been removed. Ensure that this functionality is not needed or has been moved elsewhere in the codebase.

x/erc20/keeper/bridge_token.go (5)

3-9: LGTM: Import statements are appropriate and concise.

The import statements are well-organized and include only the necessary packages for the functionality provided in this file.


11-13: LGTM: HasToken method is concise and correct.

The HasToken method efficiently checks for the existence of a token in the DenomIndex collection. The method signature and implementation are appropriate for its purpose.


15-17: LGTM: GetBridgeToken method is well-implemented.

The GetBridgeToken method efficiently retrieves a BridgeToken using a composite key created from baseDenom and chainName. The use of collections.Join for key creation is a good practice for maintaining consistency in key generation.


19-21: LGTM: GetBaseDenom method is concise and correct.

The GetBaseDenom method efficiently retrieves the base denomination for a given token from the DenomIndex collection. The implementation is straightforward and appropriate for its purpose.


1-42: Overall, the implementation is solid and well-structured.

The bridge_token.go file introduces a set of methods for managing bridge tokens within the ERC20 module. The implementation is consistent with the AI-generated summary and follows good coding practices. The methods are concise, focused, and handle their responsibilities effectively.

Key points:

  1. Proper use of the cosmossdk.io/collections package for data management.
  2. Consistent error handling throughout the methods.
  3. Efficient use of composite keys for BridgeToken lookups.

The only suggestion for improvement is a minor enhancement to error handling in the AddBridgeToken method, as noted in the previous comment.

x/erc20/keeper/msg_server.go (2)

14-14: LGTM: Correct interface implementation declaration

The change correctly declares that msgServer{} implements the types.MsgServer interface, which is consistent with the refactoring approach.


16-18: LGTM: Well-structured msgServer definition

The msgServer struct is well-defined, encapsulating a Keeper instance. This design promotes modularity and separation of concerns, allowing for better organization of the message handling logic.

x/crosschain/precompile/keeper.go (2)

4-4: LGTM: Import statements updated appropriately.

The new imports for "fmt" and auth types are consistent with the changes made in the file. The "fmt" package is used for error formatting, and the auth types import is needed for module address handling.

Also applies to: 9-9


50-51: LGTM: Improved method flow and error handling.

The changes in the final part of the method enhance its structure and error handling:

  1. Moving the SendCoinsFromModuleToAccount call to the end ensures it's only executed after all other operations have succeeded.
  2. Directly returning the error from this call simplifies the error handling logic.

These changes contribute to a more logical flow of operations and cleaner error propagation.

x/erc20/keeper/grpc_query.go (3)

15-19: LGTM: Good implementation of the queryServer struct

The introduction of the queryServer struct and its implementation of types.QueryServer is a good design choice. It encapsulates the Keeper and provides a clear separation of concerns.


21-23: LGTM: Well-designed constructor function

The NewQueryServer function is a clean and effective constructor. It properly initializes the queryServer struct and returns the correct interface type.


73-79: LGTM: Simplified Params method

The updated Params method is concise and effective. It directly retrieves parameters from the Params store, which is a clean and efficient approach.

x/crosschain/keeper/bridge_token.go (3)

11-11: LGTM: New import aligns with ERC20 integration.

The addition of the erc20types import is consistent with the refactoring towards better ERC20 token management integration.


Line range hint 1-74: Comprehensive testing needed for extensive refactoring.

The changes in this file represent a significant refactoring of the bridge token management logic, with a focus on better integration with erc20Keeper. While these changes appear to improve code organization and potentially reduce duplication, they also represent a substantial modification to the existing system.

Given the extent of these changes, it's crucial to ensure:

  1. Comprehensive unit tests are in place or updated to cover all modified and new functionality.
  2. Integration tests are performed to verify the correct interaction between this module and the erc20 module.
  3. End-to-end tests are conducted to ensure that the overall system behavior remains correct, especially for critical operations involving bridge tokens.

Additionally, consider updating the module's documentation to reflect these architectural changes, particularly the shift towards centralized ERC20 token management through erc20Keeper.

To assist in verifying test coverage, please run the following script:


Line range hint 1-74: Verify the impact of removed functions.

Several functions have been removed from this file, including GetBridgeDenomByContract, GetContractByBridgeDenom, HasBridgeToken, AddBridgeToken, IteratorBridgeDenomWithContract, and GetAllTokens. While this aligns with the refactoring towards using erc20Keeper, it's crucial to ensure that:

  1. The functionality of these removed functions is adequately replaced by erc20Keeper methods.
  2. All call sites to these removed functions have been updated accordingly.
  3. The removal doesn't introduce any breaking changes for external consumers of this package.

To verify the impact, please run the following script:

x/crosschain/precompile/crosschain.go (2)

82-83: Updated coin sending logic for origin tokens.

The creation and sending of baseCoin for origin token transactions have been implemented correctly.

Please verify that crosschaintypes.GetAddress().Bytes() is the correct source address for sending coins. Run the following script to check its usage across the codebase:

#!/bin/bash
# Description: Check the usage of crosschaintypes.GetAddress().Bytes() as a source address

# Test: Search for other occurrences of GetAddress().Bytes() being used as a source address
rg --type go -e 'crosschaintypes\.GetAddress\(\)\.Bytes\(\).*SendCoins'

# Test: Check the implementation of GetAddress() to understand its purpose
ast-grep --lang go --pattern $'func GetAddress() sdk.AccAddress {
  $$$
}'

93-96: Updated cross-chain base coin logic with improved flexibility.

The separate creation of amount and fee coins, along with the updated CrossChainBaseCoin call, provides better handling of different coin denominations and origin token scenarios.

Please verify that the CrossChainBaseCoin method has been updated to handle the new fxTarget and isOriginToken parameters correctly. Run the following script to check its implementation:

✅ Verification successful

Verification Successful: CrossChainBaseCoin method correctly updated.

The CrossChainBaseCoin method has been updated to include the fxTarget and isOriginToken parameters across relevant files, ensuring consistent and improved handling of different coin denominations and origin token scenarios.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of CrossChainBaseCoin method

# Test: Search for the CrossChainBaseCoin method definition
ast-grep --lang go --pattern $'func ($_) CrossChainBaseCoin($_) {
  $$$
}'

# Test: Check for any other calls to CrossChainBaseCoin to ensure consistency
rg --type go -e 'CrossChainBaseCoin\('

Length of output: 686

x/erc20/keeper/keeper.go (2)

4-4: LGTM: New imports added correctly.

The new imports for context, collections, and store are appropriate for the changes made in this file.

Also applies to: 7-8


1-116: Verify the impact of removed methods.

Several methods have been removed from the Keeper struct, including GetAuthority, ModuleAddress, and TransferAfter. While these changes align with the refactoring towards collections-based management, it's crucial to ensure that the removed functionality is either no longer needed or has been appropriately replaced elsewhere in the codebase.

Please run the following script to check for any remaining usage of the removed methods:

If any usages are found, please ensure they are updated or removed as necessary.

✅ Verification successful

Verification Successful: Removed Keeper methods are unused.

The shell script confirmed that GetAuthority, ModuleAddress, and TransferAfter are no longer used within the Keeper struct. Their implementations in other parts of the codebase do not impact this removal.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of removed Keeper methods

# Test: Search for usage of removed methods
echo "Searching for usage of removed methods:"
rg --type go 'Keeper\.(GetAuthority|ModuleAddress|TransferAfter)'

# Test: Check if these methods are implemented elsewhere
echo "Checking if removed methods are implemented elsewhere:"
rg --type go '(func.*GetAuthority|func.*ModuleAddress|func.*TransferAfter)'

Length of output: 3055

x/crosschain/types/expected_keepers.go (2)

46-59: Improved Erc20Keeper interface with enhanced token management and caching capabilities.

The new methods added to the Erc20Keeper interface significantly improve its functionality:

  1. Introduction of caching methods (HasCache, SetCache, DeleteCache) which can potentially optimize performance.
  2. Enhanced token management with methods like HasToken, GetBaseDenom, GetERC20Token, GetBridgeToken, and GetIBCToken.
  3. Addition of BaseCoinToEvm method for coin conversion.

These changes provide a more granular and flexible approach to token handling in the crosschain module. The consistent naming convention and clear method signatures contribute to improved readability and maintainability.


Line range hint 1-93: Significant refactoring of keeper interfaces for improved ERC20 and IBC operations.

The changes in this file represent a substantial refactoring of the keeper interfaces, particularly for ERC20 and IBC operations. Key points:

  1. Removal of several methods from the Erc20Keeper interface (e.g., GetTokenPair, ConvertCoin, ConvertERC20).
  2. Addition of new methods to Erc20Keeper for enhanced token management and caching.
  3. Introduction of a new EvmERC20Keeper interface.
  4. Update to the IBCTransferKeeper interface with a new SetDenomTrace method.

These changes suggest a shift in the architecture of the crosschain module, likely aimed at improving efficiency and flexibility in handling ERC20 tokens and IBC transfers.

To ensure these changes are properly implemented and don't introduce breaking changes, please run the following verification script:

This script will help identify any areas of the codebase that might need updates due to these interface changes.

x/crosschain/keeper/many_to_one.go (2)

75-84: LGTM! Well-implemented withdrawal logic.

The WithdrawBridgeToken function is correctly implemented. It appropriately handles the withdrawal of bridge tokens, taking into account whether the token is an origin/native token or not. The error handling is suitable, and the logic for burning non-origin, non-native tokens is correct.


166-171: LGTM! Well-implemented token retrieval.

The GetBridgeToken function is correctly implemented. It appropriately uses the erc20Keeper to first get the base denomination and then retrieve the bridge token. The error handling is suitable.

x/erc20/types/msg.go (7)

34-34: Clearer error message for sender address validation — Good improvement!

The updated error message specifies "sender address," enhancing clarity when debugging address-related issues.


37-37: Improved specificity in receiver address error message — Looks great!

By explicitly mentioning "receiver address" in the error message, it becomes easier to identify and resolve issues with the receiver's address.


40-40: Enhanced error message for coin denomination validation — Well done!

Providing "coin denom" in the error message offers better insight into denomination-related errors.


50-50: Specific error message for authority address validation — Good job!

Including "authority address" in the error message enhances clarity when the authority address is invalid.


53-53: Improved error message for parameter validation — Nice enhancement!

By specifying "params" in the error message, it becomes clearer that there's an issue with the parameters provided.


68-68: Clear error message for authority address in token conversion — Looks good!

The updated message improves clarity by indicating the error originates from the "authority address."


72-72: Detailed error message for token denomination validation — Excellent!

Explicitly mentioning "token denom" helps in quickly identifying issues with the token denomination during validation.

x/erc20/keeper/convert.go (2)

77-81: Clarify the purpose of sending coins to erc20Contract.Bytes()

In the conditional block, coins are sent from the module to erc20Contract.Bytes(). Ensure that this address is correct and that sending coins to this address is intended, as misuse could result in loss of funds.

Please confirm that erc20Contract.Bytes() returns the intended address.


53-61: Ensure ctx contains SDKContext to prevent panics

When unwrapping the ctx using sdk.UnwrapSDKContext(ctx), ensure that the context indeed contains an SDKContext to avoid potential panics if the context is not properly set.

Run the following script to verify that all contexts passed into ConvertCoin are properly wrapped:

x/crosschain/mock/expected_keepers_mocks.go (19)

19-24: Imports updated to reflect refactored types

The import statements have been correctly updated to align with the new package structures and type aliases, ensuring that the correct types are used throughout the mocks.


52-55: Updated return type in GetDelegation method

The GetDelegation method now returns types1.Delegation, which aligns with the updated staking module types. The return value assertion has been updated accordingly.


67-70: Updated return type in GetUnbondingDelegation method

The GetUnbondingDelegation method now returns types1.UnbondingDelegation, reflecting the updated staking types.


82-85: Updated return type in GetValidator method

The GetValidator method now returns types1.Validator, ensuring consistency with the updated staking module's types.


120-123: Updated method signature in BeginRedelegate

The BeginRedelegate method in MockStakingMsgServer now accepts *types1.MsgBeginRedelegate and returns *types1.MsgBeginRedelegateResponse, aligning with the new staking message types.


135-138: Updated method signature in Delegate

The Delegate method now uses *types1.MsgDelegate and returns *types1.MsgDelegateResponse, consistent with the updated staking messages.


150-153: Updated method signature in Undelegate

The Undelegate method now uses *types1.MsgUndelegate and returns *types1.MsgUndelegateResponse, reflecting changes in the staking module.


188-191: Updated method signature in WithdrawDelegatorReward

The WithdrawDelegatorReward method in MockDistributionMsgServer now uses *types0.MsgWithdrawDelegatorReward and returns *types0.MsgWithdrawDelegatorRewardResponse, aligning with the updated distribution module types.


346-358: Added new method BaseCoinToEvm in MockErc20Keeper

The BaseCoinToEvm method has been correctly added to MockErc20Keeper, with appropriate parameters and return types. This addition aligns with the updates in the ERC20 keeper interface.


361-372: Added new method DeleteCache in MockErc20Keeper

The DeleteCache method has been added with correct parameters and is properly recorded in the mock recorder, ensuring consistency with the ERC20 keeper's functionality.


375-387: Added new method GetBaseDenom in MockErc20Keeper

The GetBaseDenom method is implemented appropriately and aligns with the expected interface requirements.


390-402: Added new method GetBridgeToken in MockErc20Keeper

The GetBridgeToken method has been added with correct parameters and return types, facilitating bridge token retrieval as per the updated ERC20 module interface.


405-417: Added new method GetERC20Token in MockErc20Keeper

The GetERC20Token method is properly added, allowing for retrieval of ERC20 tokens, and is consistent with the module's expectations.


420-432: Added new method GetIBCToken in MockErc20Keeper

The GetIBCToken method has been implemented to handle IBC token retrieval, aligning with the cross-chain functionality enhancements.


435-447: Added new method HasCache in MockErc20Keeper

The HasCache method is added correctly, enabling cache existence checks within the ERC20 keeper.


450-462: Added new method HasToken in MockErc20Keeper

The HasToken method has been introduced to verify the existence of tokens, consistent with the updated token management logic.


465-476: Added new method SetCache in MockErc20Keeper

The SetCache method is appropriately added, allowing for cache manipulation within the mock keeper.


531-568: Introduced MockEvmERC20Keeper interface

The new mock interface MockEvmERC20Keeper has been added along with its TotalSupply method. The mock is set up correctly, facilitating testing of EVM ERC20 interactions.


Line range hint 593-618: Updated MockIBCTransferKeeper with new methods

  • The GetDenomTrace method now returns types2.DenomTrace, aligning with the updated IBC transfer types.
  • The SetDenomTrace method has been added to the mock, ensuring that denom traces can be set as required by the interface.

x/erc20/keeper/params.go Show resolved Hide resolved
x/crosschain/precompile/keeper.go Show resolved Hide resolved
x/crosschain/keeper/many_to_one.go Show resolved Hide resolved
x/crosschain/keeper/many_to_one.go Show resolved Hide resolved
x/crosschain/keeper/many_to_one.go Show resolved Hide resolved
x/erc20/keeper/convert.go Show resolved Hide resolved
x/erc20/keeper/convert.go Show resolved Hide resolved
x/erc20/keeper/convert.go Show resolved Hide resolved
x/erc20/keeper/erc20_token.go Show resolved Hide resolved
x/erc20/keeper/erc20_token.go Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant