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

feat: update token handling to improve security #914

Merged
merged 3 commits into from
Jan 16, 2025

Conversation

zakir-code
Copy link
Contributor

@zakir-code zakir-code commented Jan 16, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced upgrade testing with new validation functions for token metadata and ERC20 tokens.
    • Added migration functions for ERC20 tokens and metadata related to the Pundi AI project.
  • Bug Fixes

    • Improved error handling during testnet contract redeployment.
    • Updated metadata display and denomination handling.
  • Chores

    • Adjusted linter script to allow additional "nolint" suppressions.
    • Standardized FX denomination representation in token migration logic.

Copy link

coderabbitai bot commented Jan 16, 2025

Walkthrough

This pull request introduces enhancements to the upgrade process and testing framework across multiple files. The changes focus on improving token migration, metadata validation, and upgrade testing capabilities. Key modifications include adding new validation functions in the test suite, introducing migration functions for ERC20 tokens and metadata, and standardizing denomination handling. The updates aim to strengthen the robustness of the upgrade process for both testnet and mainnet environments.

Changes

File Change Summary
app/upgrade_test.go Added two new validation functions: checkMetadataValidate() and checkPundiAIFXERC20Token() to enhance upgrade testing. Updated Test_UpgradeTestnet and checkAppUpgrade to include these validations.
app/upgrades/v8/upgrade.go Introduced migration functions: migrateMetadataDisplay(), migrateErc20FXToPundiAI(), and migrateMetadataFXToPundiAI(). Enhanced error handling in upgradeTestnet and upgradeMainnet.
scripts/linter.sh Increased "nolint" suppression count from 22 to 23.
x/erc20/migrations/v8/keys.go Added fxDenom variable using uppercase fxtypes.FXDenom to improve readability in migrateTokenPair.
x/erc20/migrations/v8/migrate.go Introduced fxDenom variable in MigrateToken and addBridgeToken methods to standardize denomination checks.

Sequence Diagram

sequenceDiagram
    participant Upgrade as Upgrade Process
    participant Metadata as Metadata Migration
    participant ERC20 as ERC20 Token Migration
    participant Validator as Test Validator

    Upgrade->>Metadata: Migrate Metadata Display
    Upgrade->>ERC20: Migrate FX to Pundi AI Tokens
    Upgrade->>Validator: Perform Upgrade Checks
    Validator->>Metadata: Validate Metadata
    Validator->>ERC20: Verify Token Existence
Loading

Possibly related PRs

Poem

🐰 Hop, hop, upgrade we go!
Tokens dancing, metadata in flow
Migrations smooth as silk so bright
Testing prowess reaching new height
CodeRabbit's magic makes it right! 🚀

Finishing Touches

  • 📝 Generate Docstrings (Beta)

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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

Actionable comments posted: 3

🧹 Nitpick comments (5)
x/erc20/migrations/v8/keys.go (1)

67-67: LGTM! Consider extracting the token pair migration logic.

The introduction of fxDenom improves code maintainability. However, the token pair migration logic could be extracted into a separate helper function to improve readability and testability.

Consider extracting the token pair migration logic into a separate function:

func (m Migrator) migrateTokenPair(ctx sdk.Context, store storetypes.KVStore) error {
    fxDenom := strings.ToUpper(fxtypes.FXDenom)
    iterator := storetypes.KVStorePrefixIterator(store, KeyPrefixTokenPair)
    defer iterator.Close()
    for ; iterator.Valid(); iterator.Next() {
-       var tokenPair types.ERC20Token
-       m.cdc.MustUnmarshal(iterator.Value(), &tokenPair)
-       md, found := m.bankKeeper.GetDenomMetaData(ctx, tokenPair.GetDenom())
-       if !found {
-           return sdkerrors.ErrKeyNotFound.Wrapf("metadata not found: %s", tokenPair.GetDenom())
-       }
-       if md.Base == fxDenom || md.Base == strings.ToLower(md.Symbol) {
-           if err := m.keeper.ERC20Token.Set(ctx, md.Base, tokenPair); err != nil {
-               return err
-           }
-           if err := m.keeper.DenomIndex.Set(ctx, tokenPair.Erc20Address, md.Base); err != nil {
-               return err
-           }
-           continue
-       }
-       // ... rest of the migration logic
+       if err := m.migrateTokenPairEntry(ctx, iterator.Value(), fxDenom); err != nil {
+           return err
+       }
    }
    return nil
}

+func (m Migrator) migrateTokenPairEntry(ctx sdk.Context, value []byte, fxDenom string) error {
+    var tokenPair types.ERC20Token
+    m.cdc.MustUnmarshal(value, &tokenPair)
+    md, found := m.bankKeeper.GetDenomMetaData(ctx, tokenPair.GetDenom())
+    if !found {
+        return sdkerrors.ErrKeyNotFound.Wrapf("metadata not found: %s", tokenPair.GetDenom())
+    }
+    if md.Base == fxDenom || md.Base == strings.ToLower(md.Symbol) {
+        if err := m.keeper.ERC20Token.Set(ctx, md.Base, tokenPair); err != nil {
+            return err
+        }
+        if err := m.keeper.DenomIndex.Set(ctx, tokenPair.Erc20Address, md.Base); err != nil {
+            return err
+        }
+        return nil
+    }
+    // ... rest of the migration logic
+    return nil
+}

Also applies to: 77-77

x/erc20/migrations/v8/migrate.go (1)

77-82: Improve error handling and readability in bridge token logic.

While the introduction of fxDenom improves maintainability, the bridge token logic could benefit from better error handling and readability improvements.

Consider these improvements:

  1. Extract the bridge token validation logic into a separate function.
  2. Add detailed error messages for each failure case.
  3. Use early returns to reduce nesting.
func (m Migrator) addBridgeToken(ctx sdk.Context, base, alias string) error {
    fxDenom := strings.ToUpper(fxtypes.FXDenom)
    if getExcludeBridgeToken(ctx, alias) {
        return nil
    }
+    // Extract validation into a separate function
+    if err := m.validateBridgeToken(ctx, base, alias); err != nil {
+        return fmt.Errorf("bridge token validation failed: %w", err)
+    }
    for _, ck := range m.crosschainKeepers {
-        canAddFxBridgeToken := base == fxDenom && ck.ModuleName() == ethtypes.ModuleName
-        canAddBridgeToken := strings.HasPrefix(alias, ck.ModuleName())
+        if !m.canAddBridgeToken(ctx, ck, base, alias, fxDenom) {
+            continue
+        }
        // ... rest of the function
    }
    return nil
}
app/upgrade_test.go (2)

576-587: Enhance metadata validation test coverage.

While the test validates basic metadata properties, it could benefit from additional test cases.

Consider adding these test cases:

func checkMetadataValidate(t *testing.T, ctx sdk.Context, myApp *app.App) {
    t.Helper()

    myApp.BankKeeper.IterateAllDenomMetaData(ctx, func(metadata banktypes.Metadata) bool {
        if len(metadata.DenomUnits) <= 1 {
            return false
        }
        require.NoError(t, metadata.Validate())
        require.NotEqual(t, metadata.Display, metadata.Base)
+        // Add more assertions
+        require.NotEmpty(t, metadata.Description, "metadata description should not be empty")
+        require.NotEmpty(t, metadata.Symbol, "metadata symbol should not be empty")
+        require.True(t, len(metadata.DenomUnits) >= 2, "metadata should have at least 2 denom units")
        return false
    })
}

589-598: Enhance ERC20 token validation test coverage.

The test could be more comprehensive in validating token properties.

Consider expanding the test:

func checkPundiAIFXERC20Token(t *testing.T, ctx sdk.Context, myApp *app.App) {
    t.Helper()

    has, err := myApp.Erc20Keeper.ERC20Token.Has(ctx, fxtypes.DefaultDenom)
    require.NoError(t, err)
    require.True(t, has)
+    // Add token property validations
+    token, err := myApp.Erc20Keeper.ERC20Token.Get(ctx, fxtypes.DefaultDenom)
+    require.NoError(t, err)
+    require.NotEmpty(t, token.Erc20Address, "ERC20 address should not be empty")
+    require.Equal(t, fxtypes.DefaultDenom, token.Denom, "token denom should match")

    has, err = myApp.Erc20Keeper.ERC20Token.Has(ctx, strings.ToUpper(fxtypes.FXDenom))
    require.NoError(t, err)
    require.False(t, has)
}
scripts/linter.sh (1)

Line range hint 4-11: Consider enhancing pattern tracking for security context.

The pattern limits array could be improved to better track and manage security-critical suppressions:

Consider these improvements:

 patternLimits=(
-  "nolint:23"
+  # Format: "pattern:limit:category:description"
+  "nolint:23:general:Generic code suppressions"
+  "nolint-security:0:security:Security-related suppressions"
   "#nosec:5"
   "CrossChain:4"
   "cross chain:0"
   "GetERC1967Proxy:4"
 )

This would:

  1. Separate security-critical suppressions from general ones
  2. Document the rationale for each limit
  3. Enable stricter enforcement of security-related suppressions
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4801922 and a0e656e.

📒 Files selected for processing (5)
  • app/upgrade_test.go (5 hunks)
  • app/upgrades/v8/upgrade.go (3 hunks)
  • scripts/linter.sh (1 hunks)
  • x/erc20/migrations/v8/keys.go (2 hunks)
  • x/erc20/migrations/v8/migrate.go (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary
🔇 Additional comments (1)
scripts/linter.sh (1)

6-6: Verify the necessity of increasing nolint suppressions.

Increasing the allowed count of linter suppressions in a security-focused PR requires careful consideration. Each "nolint" directive potentially bypasses important checks that could catch security issues.

Let's identify the new suppression and verify its necessity:

Could you please:

  1. Justify why this additional suppression is necessary
  2. Confirm that the suppressed check doesn't impact security
  3. Consider if there's an alternative approach that doesn't require suppressing the linter
✅ Verification successful

Increasing nolint limit is reasonable and doesn't impact security.

The additional suppression allowance is justified as:

  • Most existing suppressions are for cyclomatic complexity in core Cosmos SDK code
  • No security-critical linter rules are being suppressed
  • Complex functions are either well-tested SDK code or marked for future refactoring
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find the new nolint suppression and its context

# Get the diff that introduced the new nolint
git log -p --full-diff -S "nolint" .

# List all current nolint suppressions for review
rg "nolint" --type go --glob '!*.pb.go' --glob '!*.pulsar.go' --glob '!*.sol.go' --glob '!legacy.go' -C 2

Length of output: 7335

app/upgrades/v8/upgrade.go Outdated Show resolved Hide resolved
app/upgrades/v8/upgrade.go Show resolved Hide resolved
app/upgrades/v8/upgrade.go Show resolved Hide resolved
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: 1

🧹 Nitpick comments (1)
app/upgrades/v8/upgrade.go (1)

590-608: Add validation for metadata updates.

The function correctly validates metadata after modification but should also:

  1. Validate metadata before modification
  2. Log the changes being made

Apply this diff to improve the implementation:

 func migrateMetadataDisplay(ctx sdk.Context, bankKeeper bankkeeper.Keeper) error {
 	mds := bankKeeper.GetAllDenomMetaData(ctx)
 	for _, md := range mds {
+		if err := md.Validate(); err != nil {
+			return fmt.Errorf("invalid metadata before migration for denom %s: %w", md.Base, err)
+		}
 		if md.Display != md.Base || len(md.DenomUnits) <= 1 {
 			continue
 		}
+		oldDisplay := md.Display
 		for _, dus := range md.DenomUnits {
 			if dus.Denom != md.Base {
 				md.Display = dus.Denom
 				break
 			}
 		}
 		if err := md.Validate(); err != nil {
 			return err
 		}
+		ctx.Logger().Info("migrated metadata display", 
+			"denom", md.Base,
+			"old_display", oldDisplay,
+			"new_display", md.Display)
 		bankKeeper.SetDenomMetaData(ctx, md)
 	}
 	return nil
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0e656e and e7d6645.

📒 Files selected for processing (1)
  • app/upgrades/v8/upgrade.go (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary
🔇 Additional comments (4)
app/upgrades/v8/upgrade.go (4)

88-90: LGTM! Error handling improvement.

Good addition of explicit error handling for the redeployTestnetContract call.


610-621: Add validation for token migration.

The function should validate the token state before and after migration.


623-634: Add validation for metadata migration.

The function should validate the metadata state before and after migration.


94-100: Verify the migration order.

The order of migrations is important. Please verify that:

  1. migrateMetadataDisplay must run before token migrations
  2. migrateErc20FXToPundiAI must run before migrateMetadataFXToPundiAI
✅ Verification successful

Migration order is correctly implemented

The current implementation follows the required order:

  1. migrateMetadataDisplay runs first (independent display field updates)
  2. migrateErc20FXToPundiAI runs before metadata migration (token mapping)
  3. migrateMetadataFXToPundiAI runs last (depends on new token mapping)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any dependencies between these functions in the codebase
# Look for any shared state or resources between these functions

# Check if any function modifies metadata that another function reads
rg -A 5 "SetDenomMetaData|GetAllDenomMetaData"

# Check if any function modifies ERC20 tokens that another function reads
rg -A 5 "GetERC20Token|ERC20Token.Set|ERC20Token.Remove"

Length of output: 13242

app/upgrades/v8/upgrade.go Outdated Show resolved Hide resolved
app/upgrades/v8/upgrade.go Outdated Show resolved Hide resolved
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: 0

🧹 Nitpick comments (1)
app/upgrades/v8/upgrade.go (1)

590-608: Add context to validation errors.

While the function includes validation, error context would help debugging issues.

 		if err := md.Validate(); err != nil {
-			return err
+			return fmt.Errorf("invalid metadata for denom %s: %w", md.Base, err)
 		}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7d6645 and c6a24cd.

📒 Files selected for processing (1)
  • app/upgrades/v8/upgrade.go (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Mergify Merge Protections
  • GitHub Check: Summary
🔇 Additional comments (5)
app/upgrades/v8/upgrade.go (5)

88-100: LGTM! Error handling and migration sequence look good.

The changes properly handle errors from contract redeployment and add token migration steps in a logical order.


183-191: LGTM! Consistent error handling and migration sequence.

The changes maintain consistent error handling by returning toVM and add token migration steps in the same order as testnet.


610-621: Add validation for ERC20 token migration.


623-634: Add validation for metadata migration.


Line range hint 88-191: Verify upgrade safety against potential exploits.

The upgrade process involves sensitive token migration operations. Please ensure:

  1. The upgrade can't be front-run or exploited
  2. Token balances are preserved during migration
  3. No double-spending possibilities exist
✅ Verification successful

Upgrade implementation follows security best practices

The verification shows the upgrade process is properly secured:

  • All token operations use proper keeper methods with balance checks
  • Operations are atomic with proper error handling
  • Module-scoped operations prevent unauthorized access
  • Proper validation checks are in place for metadata updates
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential security issues in the upgrade process

# Look for balance checks before migrations
rg -A 2 "GetBalance.*ModuleName" 

# Check for proper event emission during migrations
rg "EmitEvent.*migration"

# Verify no direct balance modifications without proper checks
ast-grep --pattern 'MintCoins($_, $_, $_)'

Length of output: 791


Script:

#!/bin/bash
# Check for token burning and minting operations
rg -A 3 "BurnCoins|SendCoins|TransferFrom" app/upgrades/v8/

# Check for access controls and authorization
ast-grep --pattern 'func $_(ctx sdk.Context, $$$) {
  $$$
  RequireAuth($$$)
  $$$
}'

# Look for broader event patterns
rg -A 2 "ctx\.EventManager\(\)\.EmitEvent" app/upgrades/v8/

Length of output: 1517


Script:

#!/bin/bash
# Check upgrade handler access controls
ast-grep --pattern 'func upgrade$_(ctx sdk.Context, $$$) {
  $$$
}'

# Look for validation checks
rg -A 3 "ValidateBasic|Validate|require\." app/upgrades/v8/

# Check for transaction boundaries
rg -A 3 "WithTransient|WithCache" app/upgrades/v8/

Length of output: 389

@nulnut nulnut merged commit c749ceb into main Jan 16, 2025
13 checks passed
@nulnut nulnut deleted the nulnut/update-token-info branch January 16, 2025 10:24
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.

2 participants