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(staking/precompile): split into method and abi #785

Merged
merged 1 commit into from
Oct 25, 2024

Conversation

zakir-code
Copy link
Contributor

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

Summary by CodeRabbit

  • New Features

    • Introduced new ABI types for enhanced modularity in staking operations, including AllowanceSharesABI, ApproveSharesABI, DelegateV2ABI, and others.
    • Added comprehensive error handling for share transfers and validator management.
    • Enhanced event emission logic for share transfers and redelegation processes.
  • Bug Fixes

    • Improved error handling across various methods to ensure consistent behavior during contract interactions.
  • Refactor

    • Restructured multiple methods to encapsulate ABI-related functionality, improving code organization and readability.
    • Renamed several types and methods for clarity and consistency within the staking module.
  • Tests

    • Updated test cases to reflect changes in method names and types, ensuring continued validation of staking functionalities.

Copy link

coderabbitai bot commented Oct 25, 2024

Walkthrough

The pull request implements significant structural changes across multiple files in the staking precompile package. The primary focus is on introducing new ABI types (e.g., AllowanceSharesABI, ApproveSharesABI, etc.) to encapsulate ABI-related functionality, enhancing modularity and separation of concerns. Existing method structures are refactored to utilize these new types, while maintaining the core logic and error handling of the methods. Additionally, several test files are updated to reflect changes in method names and types, ensuring consistency across the codebase.

Changes

File Path Change Summary
x/staking/precompile/allowance_shares.go Updated AllowanceSharesMethod to use AllowanceSharesABI. Refactored methods for ABI handling.
x/staking/precompile/approve_shares.go Introduced ApproveSharesABI for ABI handling, refactored methods accordingly.
x/staking/precompile/contract_test.go Renamed fields in PrecompileTestSuite for consistency in naming conventions.
x/staking/precompile/delegate.go Updated DelegateV2Method to use DelegateV2ABI, refactored methods for ABI handling.
x/staking/precompile/delegation.go Refactored DelegationMethod to use DelegationABI, updating methods for ABI handling.
x/staking/precompile/delegation_rewards.go Updated DelegationRewardsMethod to use DelegationRewardsABI, with refactored methods.
x/staking/precompile/keeper.go Added new Validator struct and methods for managing shares and validators.
x/staking/precompile/redelegate.go Renamed RedelegateMethodV2 to RedelegateV2Method, introduced RedelegateABI, refactored methods.
x/staking/precompile/redelegate_test.go Updated test to reflect renaming of method used for packing input.
x/staking/precompile/slashing_info.go Updated SlashingInfoMethod to use SlashingABI, refactored methods for ABI handling.
x/staking/precompile/transfer_shares.go Renamed TransferShare to TransferSharesMethod, introduced TransferSharesABI, refactored methods.
x/staking/precompile/undelegate.go Introduced UndelegateABI, refactored UndelegateV2Method methods for ABI handling.
x/staking/precompile/validator_list.go Updated ValidatorListMethod to use ValidatorListABI, refactored methods for ABI handling.
x/staking/precompile/validator_list_test.go Updated valList type in tests from []precompile.ValidatorList to []precompile.Validator.
x/staking/precompile/withdraw.go Updated WithdrawMethod to use WithdrawABI, refactored methods for ABI handling.

Possibly related PRs

  • refactor(precompile/staking): replace PackRetErr with PackRetErrV2 #777: The changes in the main PR regarding the restructuring of ABI handling in AllowanceSharesMethod and the introduction of AllowanceSharesABI are conceptually similar to the updates in the error handling mechanism in the retrieved PR, which also involves a shift in how ABI-related functionality is managed.

Poem

🐇 In the meadow where we play,
New structures bloom, bright as day.
ABI types, a joyful cheer,
Modular code, we hold so dear.
Hopping through the lines we write,
Staking dreams take graceful flight! 🌼


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.

@fx0x55
Copy link
Contributor

fx0x55 commented Oct 25, 2024

@coderabbitai review

Copy link

coderabbitai bot commented Oct 25, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 14

🧹 Outside diff range and nitpick comments (17)
x/staking/precompile/slashing_info.go (2)

63-71: Consider using a constant for the method name.

While the implementation is correct, using a string literal "slashingInfo" could lead to runtime errors if mistyped or if the method name changes. Consider defining it as a constant.

+const (
+    MethodSlashingInfo = "slashingInfo"
+)

 func NewSlashingABI() SlashingABI {
     return SlashingABI{
-        Method: stakingABI.Methods["slashingInfo"],
+        Method: stakingABI.Methods[MethodSlashingInfo],
     }
 }

Line range hint 91-98: Add type assertion error handling in UnpackOutput.

The type assertions unpack[0].(bool) and unpack[1].(*big.Int) could panic if the types don't match. Consider adding explicit type checks.

 func (m SlashingABI) UnpackOutput(data []byte) (bool, *big.Int, error) {
     unpack, err := m.Method.Outputs.Unpack(data)
     if err != nil {
         return false, nil, err
     }
+    jailed, ok := unpack[0].(bool)
+    if !ok {
+        return false, nil, fmt.Errorf("expected bool for jailed, got %T", unpack[0])
+    }
+    missed, ok := unpack[1].(*big.Int)
+    if !ok {
+        return false, nil, fmt.Errorf("expected *big.Int for missed, got %T", unpack[1])
+    }
-    return unpack[0].(bool), unpack[1].(*big.Int), nil
+    return jailed, missed, nil
 }
x/staking/precompile/delegation.go (2)

66-74: Consider using a constant for the method name

While the implementation is clean, using a string literal "delegation" for the method name could be fragile. Consider defining it as a package-level constant to ensure consistency and make updates easier.

+const (
+    DelegationMethod = "delegation"
+)

 func NewDelegationABI() DelegationABI {
     return DelegationABI{
-        Method: stakingABI.Methods["delegation"],
+        Method: stakingABI.Methods[DelegationMethod],
     }
 }

Line range hint 94-102: Consider using named return values for better readability

The UnpackOutput method could benefit from named return values to make the return values more self-documenting.

-func (m DelegationABI) UnpackOutput(data []byte) (*big.Int, *big.Int, error) {
+func (m DelegationABI) UnpackOutput(data []byte) (shares *big.Int, amount *big.Int, err error) {
     unpack, err := m.Method.Outputs.Unpack(data)
     if err != nil {
         return nil, nil, err
     }
     shares := unpack[0].(*big.Int)
     amount := unpack[1].(*big.Int)
     return shares, amount, nil
}
x/staking/precompile/approve_shares.go (2)

67-77: Consider adding validation in NewApproveSharesABI.

While the implementation is clean, consider adding validation to ensure stakingABI contains the required method and event to prevent potential panics.

 func NewApproveSharesABI() ApproveSharesABI {
+    method, exists := stakingABI.Methods["approveShares"]
+    if !exists {
+        panic("approveShares method not found in stakingABI")
+    }
+    event, exists := stakingABI.Events["ApproveShares"]
+    if !exists {
+        panic("ApproveShares event not found in stakingABI")
+    }
     return ApproveSharesABI{
-        Method: stakingABI.Methods["approveShares"],
-        Event:  stakingABI.Events["ApproveShares"],
+        Method: method,
+        Event:  event,
     }
 }

Line range hint 113-121: Consider caching the IStakingFilterer instance.

Creating a new filterer for each event unpacking could be inefficient. Consider caching the filterer instance as a field in the ABI struct since it's stateless.

 type ApproveSharesABI struct {
     abi.Method
     abi.Event
+    filterer *fxcontract.IStakingFilterer
 }

 func NewApproveSharesABI() ApproveSharesABI {
+    filterer, err := fxcontract.NewIStakingFilterer(common.Address{}, nil)
+    if err != nil {
+        panic(fmt.Sprintf("failed to create staking filterer: %v", err))
+    }
     return ApproveSharesABI{
         Method: stakingABI.Methods["approveShares"],
         Event:  stakingABI.Events["ApproveShares"],
+        filterer: filterer,
     }
 }

 func (m ApproveSharesABI) UnpackEvent(log *ethtypes.Log) (*fxcontract.IStakingApproveShares, error) {
     if log == nil {
         return nil, errors.New("empty log")
     }
-    filterer, err := fxcontract.NewIStakingFilterer(common.Address{}, nil)
-    if err != nil {
-        return nil, err
-    }
-    return filterer.ParseApproveShares(*log)
+    return m.filterer.ParseApproveShares(*log)
 }
x/staking/precompile/delegate.go (2)

72-82: Consider adding validation in NewDelegateV2ABI.

While the implementation is clean, consider adding validation to ensure stakingABI contains the required "delegateV2" method and "DelegateV2" event to prevent potential runtime panics.

 func NewDelegateV2ABI() DelegateV2ABI {
+	method, exists := stakingABI.Methods["delegateV2"]
+	if !exists {
+		panic("delegateV2 method not found in stakingABI")
+	}
+	event, exists := stakingABI.Events["DelegateV2"]
+	if !exists {
+		panic("DelegateV2 event not found in stakingABI")
+	}
 	return DelegateV2ABI{
-		Method: stakingABI.Methods["delegateV2"],
-		Event:  stakingABI.Events["DelegateV2"],
+		Method: method,
+		Event:  event,
 	}
 }

Line range hint 118-127: Consider caching the IStakingFilterer instance.

Creating a new filterer for each event unpacking could be inefficient. Consider caching the filterer instance or moving it to a package-level variable since it's stateless.

+var stakingFilterer *fxcontract.IStakingFilterer
+
+func init() {
+	var err error
+	stakingFilterer, err = fxcontract.NewIStakingFilterer(common.Address{}, nil)
+	if err != nil {
+		panic(fmt.Sprintf("failed to create staking filterer: %v", err))
+	}
+}
+
 func (m DelegateV2ABI) UnpackEvent(log *ethtypes.Log) (*fxcontract.IStakingDelegateV2, error) {
 	if log == nil {
 		return nil, errors.New("empty log")
 	}
-	filterer, err := fxcontract.NewIStakingFilterer(common.Address{}, nil)
-	if err != nil {
-		return nil, err
-	}
-	return filterer.ParseDelegateV2(*log)
+	return stakingFilterer.ParseDelegateV2(*log)
 }
x/staking/precompile/withdraw.go (1)

Line range hint 123-133: Consider optimizing filterer creation.

The current implementation creates a new filterer for each event unpacking. Consider caching the filterer instance as a field in WithdrawABI to improve performance, especially when processing multiple events.

 type WithdrawABI struct {
     abi.Method
     abi.Event
+    filterer *fxcontract.IStakingFilterer
 }

 func NewWithdrawABI() WithdrawABI {
+    filterer, err := fxcontract.NewIStakingFilterer(common.Address{}, nil)
+    if err != nil {
+        panic(fmt.Sprintf("failed to create staking filterer: %v", err))
+    }
     return WithdrawABI{
         Method: stakingABI.Methods["withdraw"],
         Event:  stakingABI.Events["Withdraw"],
+        filterer: filterer,
     }
 }

 func (m WithdrawABI) UnpackEvent(log *ethtypes.Log) (*fxcontract.IStakingWithdraw, error) {
     if log == nil {
         return nil, errors.New("empty log")
     }
-    filterer, err := fxcontract.NewIStakingFilterer(common.Address{}, nil)
-    if err != nil {
-        return nil, err
-    }
-    return filterer.ParseWithdraw(*log)
+    return m.filterer.ParseWithdraw(*log)
 }
x/staking/precompile/undelegate.go (1)

Line range hint 120-130: Enhance error message in UnpackEvent.

The error message "empty log" could be more descriptive to help with debugging.

 func (m UndelegateABI) UnpackEvent(log *ethtypes.Log) (*fxcontract.IStakingUndelegateV2, error) {
     if log == nil {
-        return nil, errors.New("empty log")
+        return nil, errors.New("cannot unpack UndelegateV2 event: nil log provided")
     }
     filterer, err := fxcontract.NewIStakingFilterer(common.Address{}, nil)
     if err != nil {
         return nil, err
     }
     return filterer.ParseUndelegateV2(*log)
 }
x/staking/precompile/redelegate.go (1)

Line range hint 43-75: Consider enhancing error handling for event emission.

While the implementation is solid, consider wrapping the event emission in a separate error check to ensure proper handling of event-related failures.

Here's a suggested improvement:

- data, topic, err := m.NewRedelegationEvent(contract.Caller(), args.ValidatorSrc, args.ValidatorDst, args.Amount, resp.CompletionTime.Unix())
- if err != nil {
-   return err
- }
- fxcontract.EmitEvent(evm, stakingAddress, data, topic)
+ if data, topic, err := m.NewRedelegationEvent(contract.Caller(), args.ValidatorSrc, args.ValidatorDst, args.Amount, resp.CompletionTime.Unix()); err != nil {
+   return fmt.Errorf("failed to create redelegation event: %w", err)
+ } else {
+   fxcontract.EmitEvent(evm, stakingAddress, data, topic)
+ }
x/staking/precompile/validator_list_test.go (1)

116-122: LGTM! Consider extracting validator info retrieval logic.

The changes look good - the new Validator type is more focused and the implementation correctly handles validator information retrieval and error checking.

Consider extracting the validator info retrieval logic into a helper function for better readability:

+func getValidatorWithMissedBlocks(ctx sdk.Context, validator stakingtypes.Validator, sk types.StakingKeeper, slk types.SlashingKeeper) (precompile.Validator, error) {
+    consAddr, err := validator.GetConsAddr()
+    if err != nil {
+        return precompile.Validator{}, err
+    }
+    info, err := slk.GetValidatorSigningInfo(ctx, consAddr)
+    if err != nil {
+        return precompile.Validator{}, err
+    }
+    return precompile.Validator{
+        ValAddr:      validator.OperatorAddress,
+        MissedBlocks: info.MissedBlocksCounter,
+    }, nil
+}

 valList := make([]precompile.Validator, 0, len(valsByPower))
 for _, validator := range valsByPower {
-    consAddr, err := validator.GetConsAddr()
-    suite.Require().NoError(err)
-    info, err := suite.App.SlashingKeeper.GetValidatorSigningInfo(suite.Ctx, consAddr)
-    suite.Require().NoError(err)
-    valList = append(valList, precompile.Validator{
-        ValAddr:      validator.OperatorAddress,
-        MissedBlocks: info.MissedBlocksCounter,
-    })
+    val, err := getValidatorWithMissedBlocks(suite.Ctx, validator, suite.App.StakingKeeper, suite.App.SlashingKeeper)
+    suite.Require().NoError(err)
+    valList = append(valList, val)
 }
x/staking/precompile/transfer_shares.go (2)

Line range hint 216-225: Initialize IStakingFilterer with Appropriate Parameters

The UnpackEvent function initializes IStakingFilterer with a zero address and a nil backend, which may not be appropriate and could lead to errors when parsing events.

Consider providing the correct contract address and a valid backend:

 func (m transferShareABI) UnpackEvent(log *ethtypes.Log) (*fxcontract.IStakingTransferShares, error) {
 	if log == nil {
 		return nil, errors.New("empty log")
 	}
-	filterer, err := fxcontract.NewIStakingFilterer(common.Address{}, nil)
+	filterer, err := fxcontract.NewIStakingFilterer(stakingAddress, evm.Backend)
 	if err != nil {
 		return nil, err
 	}
 	return filterer.ParseTransferShares(*log)
 }

Ensure that stakingAddress and evm.Backend are accessible in this context.


106-114: Ensure Consistent Struct Initialization Across Methods

For consistency and readability, align the struct initialization in NewTransferFromSharesMethod with that in NewTransferSharesMethod.

 func NewTransferFromSharesMethod(keeper *Keeper) *TransferFromSharesMethod {
 	return &TransferFromSharesMethod{
 		Keeper:                keeper,
-		TransferFromSharesABI: NewTransferFromSharesABI(),
+		TransferFromSharesABI: NewTransferFromSharesABI(),
 	}
 }

Ensure that any additional fields or initializations are consistently ordered.

x/staking/precompile/keeper.go (3)

56-56: Improve error message for clarity

The error message "from has receiving redelegation" might be unclear to users. Consider rephrasing it to provide more context, such as "cannot transfer shares: delegator has an ongoing redelegation to this validator".


60-62: Enhance error message for insufficient shares

The error message "insufficient shares(%s < %s)" could be made more user-friendly. Rephrase it to "insufficient shares: available %s, required %s" for better clarity.


256-262: Consider integrating validatorListPower into main logic

The validatorListPower function simply extracts operator addresses from validators. If it's only used once, consider integrating this logic directly where needed to reduce unnecessary abstraction.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1be0d09 and 138a42d.

📒 Files selected for processing (15)
  • x/staking/precompile/allowance_shares.go (2 hunks)
  • x/staking/precompile/approve_shares.go (2 hunks)
  • x/staking/precompile/contract_test.go (2 hunks)
  • x/staking/precompile/delegate.go (2 hunks)
  • x/staking/precompile/delegation.go (2 hunks)
  • x/staking/precompile/delegation_rewards.go (2 hunks)
  • x/staking/precompile/keeper.go (2 hunks)
  • x/staking/precompile/redelegate.go (2 hunks)
  • x/staking/precompile/redelegate_test.go (1 hunks)
  • x/staking/precompile/slashing_info.go (2 hunks)
  • x/staking/precompile/transfer_shares.go (6 hunks)
  • x/staking/precompile/undelegate.go (2 hunks)
  • x/staking/precompile/validator_list.go (3 hunks)
  • x/staking/precompile/validator_list_test.go (1 hunks)
  • x/staking/precompile/withdraw.go (2 hunks)
🔇 Additional comments (36)
x/staking/precompile/slashing_info.go (3)

15-15: LGTM! Good separation of concerns.

The change to embed SlashingABI instead of abi.Method improves code organization by isolating ABI-related functionality.


20-21: LGTM! Constructor properly initializes all fields.

The initialization of both Keeper and SlashingABI fields is correct and follows Go conventions.


Line range hint 63-98: Verify consistency with other precompile refactorings.

The refactoring pattern looks good. Let's verify that similar changes have been applied consistently across other precompile files.

✅ Verification successful

Refactoring pattern is consistent across precompile files

The verification shows that the SlashingABI implementation follows the same pattern used consistently across all precompile files in the x/staking/precompile directory:

  • All 11 precompile files define their respective *ABI structs
  • Each has a corresponding New*ABI() constructor
  • All implement the same method signatures for PackInput, UnpackInput, PackOutput, and UnpackOutput
  • The method implementations follow the same pattern of handling ABI encoding/decoding
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if other precompile files follow the same pattern
# Test: Look for similar ABI type definitions and method signatures

# Check for other *ABI type definitions
echo "Checking for other ABI type definitions..."
rg -l "type \w+ABI struct" x/staking/precompile/

# Check for NewABI constructors
echo "Checking for NewABI constructors..."
rg -l "func New\w+ABI\(\)" x/staking/precompile/

# Check for Pack/Unpack method signatures on ABI types
echo "Checking for Pack/Unpack methods..."
rg "func \([a-z] \w+ABI\) (Pack|Unpack)(Input|Output)" x/staking/precompile/

Length of output: 6800

x/staking/precompile/delegation.go (2)

17-17: LGTM! Clean separation of concerns

The refactoring to embed DelegationABI improves code organization by isolating ABI-related functionality while maintaining clean initialization in the constructor.

Also applies to: 22-23


Line range hint 66-102: Verify complete migration to DelegationABI

Let's ensure all references to the old Method field have been updated to use DelegationABI.

x/staking/precompile/delegation_rewards.go (4)

17-17: LGTM! Good improvement in type safety

The change from raw abi.Method to a dedicated DelegationRewardsABI type improves type safety while maintaining the same functionality. The constructor properly initializes the new field.

Also applies to: 22-23


72-74: LGTM! Clean type definition

The embedding of abi.Method follows Go best practices and provides a good foundation for ABI-specific functionality.


Line range hint 82-105: LGTM! Well-structured ABI methods

The implementation is solid with:

  • Appropriate use of value receivers
  • Consistent error handling
  • Clean integration with the system's type parsing

76-80: Verify stakingABI initialization

The constructor looks good, but let's verify that stakingABI is properly initialized elsewhere in the package.

✅ Verification successful

stakingABI is properly initialized and used consistently

The variable stakingABI is correctly initialized in x/staking/precompile/contract.go as a package-level variable:

var (
    stakingAddress = common.HexToAddress(contract.StakingAddress)
    stakingABI     = contract.MustABIJson(contract.IStakingMetaData.ABI)
)

It's used consistently across multiple ABI constructors in the package for different staking operations (delegate, undelegate, rewards, etc.).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for stakingABI initialization
rg -l "var\s+stakingABI\s*=" 
rg -l "stakingABI\s*:?=\s*abi\.JSON"

Length of output: 69


Script:

#!/bin/bash
# Let's try a broader search for stakingABI
rg "stakingABI" -A 3 -B 3

# Also search for any abi.JSON initialization patterns
rg "abi\.JSON" -A 3 -B 3

# Look for files that might contain ABI definitions
fd "abi.*\.go$"

Length of output: 6085

x/staking/precompile/approve_shares.go (2)

20-20: LGTM! Good separation of concerns.

The refactoring improves code organization by moving ABI-related functionality to a dedicated type while maintaining clean initialization in the constructor.

Also applies to: 25-26


67-70: Verify consistent ABI type usage across the codebase.

Let's verify that other staking precompile methods follow the same pattern of separating ABI functionality.

✅ Verification successful

Let me generate another script to search more specifically for the ABI usage pattern in the staking precompile files:


Based on the search results, I can now provide a final response:

ABI struct definition follows consistent pattern across staking precompiles

The ApproveSharesABI struct follows the same pattern used consistently across all staking precompile methods:

  • All ABI structs embed abi.Method
  • Those that emit events also embed abi.Event
  • Each ABI struct has a corresponding New*ABI() constructor function
  • Other precompile methods like WithdrawABI, DelegateV2ABI, RedelegateABI, etc. follow the exact same pattern
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent ABI type usage across staking precompile files
# Expected: All precompile methods should have their own ABI type

# Test: Search for other *ABI struct definitions
echo "Checking for ABI type definitions:"
ast-grep --pattern 'type $_ABI struct {
  $$$
}'

# Test: Search for corresponding method structs using these ABI types
echo -e "\nChecking for method structs using ABI types:"
ast-grep --pattern 'type $_Method struct {
  $$$
  $_ABI
  $$$
}'

Length of output: 510945


Script:

#!/bin/bash
# Search specifically in staking precompile files for ABI usage patterns
echo "Checking staking precompile files for ABI usage:"
rg -l "ABI" x/staking/precompile/

echo -e "\nChecking ABI struct definitions and usage in staking precompile files:"
rg -A 5 "type.*ABI struct" x/staking/precompile/

Length of output: 5664

x/staking/precompile/delegate.go (1)

20-28: LGTM! Well-structured refactoring of DelegateV2Method.

The restructuring improves encapsulation by grouping ABI-related fields into a dedicated type while maintaining clean initialization in the constructor.

x/staking/precompile/withdraw.go (4)

21-21: LGTM! Good encapsulation of ABI-related fields.

The consolidation of ABI-related fields into a single WithdrawABI type improves code organization and follows the single responsibility principle.


26-27: LGTM! Clean constructor initialization.

The constructor properly initializes both the keeper and the new WithdrawABI field while maintaining backward compatibility.


89-121: LGTM! Well-structured ABI method implementations.

The ABI-related methods are properly implemented with appropriate error handling and type safety.


77-87: Consider adding safety checks in NewWithdrawABI.

While the implementation is clean, consider adding validation to ensure stakingABI is properly initialized before accessing its methods and events.

Consider adding error handling:

 func NewWithdrawABI() WithdrawABI {
+    method, exists := stakingABI.Methods["withdraw"]
+    if !exists {
+        panic("withdraw method not found in stakingABI")
+    }
+    event, exists := stakingABI.Events["Withdraw"]
+    if !exists {
+        panic("Withdraw event not found in stakingABI")
+    }
     return WithdrawABI{
-        Method: stakingABI.Methods["withdraw"],
-        Event:  stakingABI.Events["Withdraw"],
+        Method: method,
+        Event:  event,
     }
 }
x/staking/precompile/undelegate.go (3)

21-21: LGTM! Good refactoring of ABI-related fields.

The consolidation of ABI-related fields into a single UndelegateABI type improves encapsulation and follows the Single Responsibility Principle.


26-27: LGTM! Constructor properly initializes the new structure.

The constructor correctly initializes both the Keeper and UndelegateABI fields, maintaining a clean initialization pattern.


82-92: Consider adding validation in NewUndelegateV2ABI.

While the implementation is good, consider adding validation to ensure stakingABI is properly initialized and the required method and event exist.

Example validation:

 func NewUndelegateV2ABI() UndelegateABI {
+    method, exists := stakingABI.Methods["undelegateV2"]
+    if !exists {
+        panic("undelegateV2 method not found in stakingABI")
+    }
+    event, exists := stakingABI.Events["UndelegateV2"]
+    if !exists {
+        panic("UndelegateV2 event not found in stakingABI")
+    }
     return UndelegateABI{
-        Method: stakingABI.Methods["undelegateV2"],
-        Event:  stakingABI.Events["UndelegateV2"],
+        Method: method,
+        Event:  event,
     }
 }
x/staking/precompile/redelegate.go (4)

19-21: LGTM! Clean struct definition and constructor implementation.

The struct and constructor follow Go best practices with proper field initialization and clear separation of concerns.

Also applies to: 24-28


31-41: LGTM! Clear and concise helper method implementations.

The helper methods are well-implemented with appropriate return values and gas requirements.


77-87: LGTM! Well-structured ABI implementation.

The RedelegateABI struct and its constructor are well-implemented with proper initialization from stakingABI.


Line range hint 19-132: Verify integration with existing staking operations.

The refactoring looks solid, but let's verify the integration with existing staking operations.

✅ Verification successful

Based on the search results, I can now provide a final response since we have comprehensive information about the redelegation functionality across the codebase:

Integration with existing staking operations is properly maintained.

The code shows proper integration with the staking system:

  • The precompile correctly interfaces with the underlying staking module through BeginRedelegate calls
  • Event handling and logging are properly implemented
  • Test coverage exists across multiple scenarios including contract interactions
  • The implementation is consistent with other staking precompiles in the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any direct usage of the old RedelegateMethodV2 type
rg "RedelegateMethodV2" -A 3

# Search for any existing redelegation event handlers
ast-grep --pattern 'func $_(log $_, $_, $_) {
  $$$
  ParseRedelegateV2($$$)
  $$$
}'

Length of output: 116


Script:

#!/bin/bash
# Let's try a broader search for redelegate-related code
rg -i "redelegate" --type go -A 3

# Search for staking precompile registration
rg "RegisterPrecompile.*staking" --type go -A 5

# Look for any test files related to redelegation
fd "test.*go" --exec grep -l "redelegate" {}

Length of output: 119396

x/staking/precompile/redelegate_test.go (1)

116-116: Method renaming looks good, verify consistency.

The renaming from redelegateMethodV2 to redelegateV2Method aligns with the PR's refactoring objectives. The test logic remains unchanged.

Let's verify the consistency of this naming pattern across the codebase:

✅ Verification successful

Method renaming is consistent across the codebase

Based on the search results:

  1. No instances of the old method name redelegateMethodV2 were found, confirming complete renaming
  2. The new naming pattern redelegateV2Method is consistent with other method names in the codebase
  3. All method references follow a consistent pattern of accessing properties via Method. notation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining instances of old method name and verify consistent naming pattern
# Test 1: Search for any remaining instances of the old method name
echo "Checking for any remaining instances of old method name..."
rg "redelegateMethodV2"

# Test 2: Verify the naming pattern consistency for other similar methods
echo "Verifying naming pattern consistency..."
rg "Method\." --type go

Length of output: 17385

x/staking/precompile/contract_test.go (2)

45-48: LGTM! Consistent method naming in PrecompileTestSuite struct.

The renaming of fields maintains consistency with the broader refactoring changes, improving code clarity without affecting functionality.


88-88: LGTM! Consistent initialization in SetupTest.

The initialization of redelegateV2Method correctly aligns with the renamed struct field, maintaining test coverage.

x/staking/precompile/validator_list.go (5)

13-13: Embedding ValidatorListABI in ValidatorListMethod

Including ValidatorListABI within ValidatorListMethod appropriately encapsulates the ABI-related functionality, enhancing the modularity of the code.


18-19: Proper initialization of ValidatorListABI

In the NewValidatorListMethod constructor, ValidatorListABI is correctly initialized using NewValidatorListABI(), ensuring that all necessary ABI configurations are set up.


63-69: Well-defined ValidatorListABI struct and constructor

The introduction of the ValidatorListABI struct and its constructor NewValidatorListABI effectively encapsulates the ABI method details, promoting code clarity and separation of concerns.


87-87: Consistent error handling in PackOutput

Ensure that the PackOutput method properly handles errors that may arise from m.Method.Outputs.Pack(valList). Currently, any error would be returned directly, but consider wrapping it with additional context if necessary.


52-52: Verify the accessibility of validatorListPower function

The function validatorListPower is called here. Please ensure that this function is defined within the package and is accessible. If it's defined externally, make sure to import the necessary package.

Run the following script to check if validatorListPower is defined and accessible:

✅ Verification successful

Let me verify if the function is in the same package by checking the package declaration.


Function validatorListPower is properly defined and accessible

The function validatorListPower is defined in x/staking/precompile/keeper.go and both files are in the same precompile package, making the function accessible within validator_list.go. No changes are needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the definition and accessibility of `validatorListPower` function.

# Test: Search for the function definition. Expect: Function should be found within the codebase.
rg '^func\s+validatorListPower\b' -t go

Length of output: 144


Script:

#!/bin/bash
# Check package declarations for both files
echo "=== Package declaration in validator_list.go ==="
rg -A 1 "^package" x/staking/precompile/validator_list.go

echo -e "\n=== Package declaration in keeper.go ==="
rg -A 1 "^package" x/staking/precompile/keeper.go

Length of output: 355

x/staking/precompile/transfer_shares.go (2)

86-87: Verify Correctness of ABI Method and Event References

In NewTransferSharesABI, ensure that the method and event names "transferShares" and "TransferShares" exist in stakingABI.Methods and stakingABI.Events respectively. Incorrect references could lead to runtime errors.


179-180: Verify Correctness of ABI Method and Event References

In NewTransferFromSharesABI, confirm that the method "transferFromShares" and the event "TransferShares" are correctly defined in stakingABI.Methods and stakingABI.Events. Mismatches here could cause issues during ABI interactions.

x/staking/precompile/keeper.go (3)

230-254: Ensure ValidatorListMissedBlock handles empty validator sets gracefully

In the ValidatorListMissedBlock function, if bondedVals is empty, the function may proceed without returning an appropriate response. Verify that the function handles empty inputs and returns an empty list or an informative error as needed.


65-69: ⚠️ Potential issue

Verify correct usage of withdrawAddr for balance calculations

The withdrawAddr is obtained for the to address, but the reward withdrawal is performed for the from delegator. This may lead to incorrect balance calculations when comparing beforeDelBalance and afterDelBalance. Ensure that the withdrawAddr corresponds to the from delegator when calculating balances related to from.


202-204: ⚠️ Potential issue

Correct condition and error message in incrementReferenceCount

The condition historical.ReferenceCount > 2 allows the ReferenceCount to reach 2, which might exceed the maximum allowed value. If 2 is the maximum, consider changing the condition to >= 2. Additionally, clarify the error message for better understanding.

Apply this diff to adjust the condition and error message:

-if historical.ReferenceCount > 2 {
-    return errors.New("reference count should never exceed 2")
+if historical.ReferenceCount >= 2 {
+    return errors.New("reference count cannot exceed 1")
 }

Likely invalid or redundant comment.

Comment on lines +110 to 116
func (m DelegateV2ABI) UnpackOutput(data []byte) (bool, error) {
amount, err := m.Method.Outputs.Unpack(data)
if err != nil {
return false, err
}
return amount[0].(bool), nil
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add type assertion safety check in UnpackOutput.

The type assertion amount[0].(bool) could panic if the unpacked value is not a boolean. Consider adding a type safety check.

 func (m DelegateV2ABI) UnpackOutput(data []byte) (bool, error) {
 	amount, err := m.Method.Outputs.Unpack(data)
 	if err != nil {
 		return false, err
 	}
+	if len(amount) == 0 {
+		return false, errors.New("empty output data")
+	}
+	val, ok := amount[0].(bool)
+	if !ok {
+		return false, errors.New("invalid output type: expected bool")
+	}
-	return amount[0].(bool), nil
+	return val, 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.

Suggested change
func (m DelegateV2ABI) UnpackOutput(data []byte) (bool, error) {
amount, err := m.Method.Outputs.Unpack(data)
if err != nil {
return false, err
}
return amount[0].(bool), nil
}
func (m DelegateV2ABI) UnpackOutput(data []byte) (bool, error) {
amount, err := m.Method.Outputs.Unpack(data)
if err != nil {
return false, err
}
if len(amount) == 0 {
return false, errors.New("empty output data")
}
val, ok := amount[0].(bool)
if !ok {
return false, errors.New("invalid output type: expected bool")
}
return val, nil
}

Comment on lines +105 to 109
func (m RedelegateABI) UnpackInput(data []byte) (*fxstakingtypes.RedelegateV2Args, error) {
args := new(fxstakingtypes.RedelegateV2Args)
err := types.ParseMethodArgs(m.Method, args, data[4:])
return args, err
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding input validation in UnpackInput.

The UnpackInput method could benefit from additional validation before parsing the method arguments.

Here's a suggested improvement:

 func (m RedelegateABI) UnpackInput(data []byte) (*fxstakingtypes.RedelegateV2Args, error) {
+    if len(data) <= 4 {
+        return nil, errors.New("invalid input data length")
+    }
     args := new(fxstakingtypes.RedelegateV2Args)
     err := types.ParseMethodArgs(m.Method, args, data[4:])
     return args, 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.

Suggested change
func (m RedelegateABI) UnpackInput(data []byte) (*fxstakingtypes.RedelegateV2Args, error) {
args := new(fxstakingtypes.RedelegateV2Args)
err := types.ParseMethodArgs(m.Method, args, data[4:])
return args, err
}
func (m RedelegateABI) UnpackInput(data []byte) (*fxstakingtypes.RedelegateV2Args, error) {
if len(data) <= 4 {
return nil, errors.New("invalid input data length")
}
args := new(fxstakingtypes.RedelegateV2Args)
err := types.ParseMethodArgs(m.Method, args, data[4:])
return args, err
}

Comment on lines +59 to +77
func (m AllowanceSharesABI) PackInput(args fxstakingtypes.AllowanceSharesArgs) ([]byte, error) {
arguments, err := m.Method.Inputs.Pack(args.Validator, args.Owner, args.Spender)
if err != nil {
return nil, err
}
return append(m.GetMethodId(), arguments...), nil
return append(m.Method.ID, arguments...), nil
}

func (m *AllowanceSharesMethod) UnpackInput(data []byte) (*fxstakingtypes.AllowanceSharesArgs, error) {
func (m AllowanceSharesABI) UnpackInput(data []byte) (*fxstakingtypes.AllowanceSharesArgs, error) {
args := new(fxstakingtypes.AllowanceSharesArgs)
err := types.ParseMethodArgs(m.Method, args, data[4:])
return args, err
}

func (m *AllowanceSharesMethod) PackOutput(amount *big.Int) ([]byte, error) {
func (m AllowanceSharesABI) PackOutput(amount *big.Int) ([]byte, error) {
return m.Method.Outputs.Pack(amount)
}

func (m *AllowanceSharesMethod) UnpackOutput(data []byte) (*big.Int, error) {
func (m AllowanceSharesABI) UnpackOutput(data []byte) (*big.Int, error) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider using pointer receivers to avoid unnecessary copying

Currently, the methods of AllowanceSharesABI use value receivers. Since abi.Method may be a sizable struct, using pointer receivers can improve performance by preventing unnecessary copying of the struct when methods are called.

Apply this diff to change the method receivers to pointers:

-func (m AllowanceSharesABI) PackInput(args fxstakingtypes.AllowanceSharesArgs) ([]byte, error) {
+func (m *AllowanceSharesABI) PackInput(args fxstakingtypes.AllowanceSharesArgs) ([]byte, error) {

-func (m AllowanceSharesABI) UnpackInput(data []byte) (*fxstakingtypes.AllowanceSharesArgs, error) {
+func (m *AllowanceSharesABI) UnpackInput(data []byte) (*fxstakingtypes.AllowanceSharesArgs, error) {

-func (m AllowanceSharesABI) PackOutput(amount *big.Int) ([]byte, error) {
+func (m *AllowanceSharesABI) PackOutput(amount *big.Int) ([]byte, error) {

-func (m AllowanceSharesABI) UnpackOutput(data []byte) (*big.Int, error) {
+func (m *AllowanceSharesABI) UnpackOutput(data []byte) (*big.Int, 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.

Suggested change
func (m AllowanceSharesABI) PackInput(args fxstakingtypes.AllowanceSharesArgs) ([]byte, error) {
arguments, err := m.Method.Inputs.Pack(args.Validator, args.Owner, args.Spender)
if err != nil {
return nil, err
}
return append(m.GetMethodId(), arguments...), nil
return append(m.Method.ID, arguments...), nil
}
func (m *AllowanceSharesMethod) UnpackInput(data []byte) (*fxstakingtypes.AllowanceSharesArgs, error) {
func (m AllowanceSharesABI) UnpackInput(data []byte) (*fxstakingtypes.AllowanceSharesArgs, error) {
args := new(fxstakingtypes.AllowanceSharesArgs)
err := types.ParseMethodArgs(m.Method, args, data[4:])
return args, err
}
func (m *AllowanceSharesMethod) PackOutput(amount *big.Int) ([]byte, error) {
func (m AllowanceSharesABI) PackOutput(amount *big.Int) ([]byte, error) {
return m.Method.Outputs.Pack(amount)
}
func (m *AllowanceSharesMethod) UnpackOutput(data []byte) (*big.Int, error) {
func (m AllowanceSharesABI) UnpackOutput(data []byte) (*big.Int, error) {
func (m *AllowanceSharesABI) PackInput(args fxstakingtypes.AllowanceSharesArgs) ([]byte, error) {
arguments, err := m.Method.Inputs.Pack(args.Validator, args.Owner, args.Spender)
if err != nil {
return nil, err
}
return append(m.Method.ID, arguments...), nil
}
func (m *AllowanceSharesABI) UnpackInput(data []byte) (*fxstakingtypes.AllowanceSharesArgs, error) {
args := new(fxstakingtypes.AllowanceSharesArgs)
err := types.ParseMethodArgs(m.Method, args, data[4:])
return args, err
}
func (m *AllowanceSharesABI) PackOutput(amount *big.Int) ([]byte, error) {
return m.Method.Outputs.Pack(amount)
}
func (m *AllowanceSharesABI) UnpackOutput(data []byte) (*big.Int, error) {

return m.Method.Outputs.Pack(valList)
}

func (m *ValidatorListMethod) UnpackOutput(data []byte) ([]string, error) {
func (m ValidatorListABI) UnpackOutput(data []byte) ([]string, error) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Type assertion in UnpackOutput should be checked

In UnpackOutput, there's an implicit assumption that unpack[0] will be of type []string. To prevent panics due to type assertion failures, consider adding type checking.

Apply this diff to safely assert the type:

 func (m *ValidatorListABI) UnpackOutput(data []byte) ([]string, error) {
     unpack, err := m.Method.Outputs.Unpack(data)
     if err != nil {
         return nil, err
     }
-    return unpack[0].([]string), nil
+    valList, ok := unpack[0].([]string)
+    if !ok {
+        return nil, fmt.Errorf("unexpected output type, expected []string")
+    }
+    return valList, nil
 }

Committable suggestion was skipped due to low confidence.

Comment on lines +73 to +78
func (m ValidatorListABI) PackInput(args fxstakingtypes.ValidatorListArgs) ([]byte, error) {
arguments, err := m.Method.Inputs.Pack(args.SortBy)
if err != nil {
return nil, err
}
return append(m.GetMethodId(), arguments...), nil
return append(m.Method.ID, arguments...), nil
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider using pointer receivers for methods

The methods associated with ValidatorListABI use value receivers. For consistency and to avoid unnecessary copying of the struct (especially if it grows in size), consider using pointer receivers.

Apply this diff to change the method receivers:

-func (m ValidatorListABI) PackInput(args fxstakingtypes.ValidatorListArgs) ([]byte, error) {
+func (m *ValidatorListABI) PackInput(args fxstakingtypes.ValidatorListArgs) ([]byte, error) {

...

-func (m ValidatorListABI) UnpackInput(data []byte) (*fxstakingtypes.ValidatorListArgs, error) {
+func (m *ValidatorListABI) UnpackInput(data []byte) (*fxstakingtypes.ValidatorListArgs, error) {

Update the receiver for all methods of ValidatorListABI accordingly.

Committable suggestion was skipped due to low confidence.

Comment on lines +19 to +21
type TransferSharesMethod struct {
*Keeper
abi.Method
abi.Event
}

type TransferShares struct {
*TransferShare
TransferSharesABI
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider Embedding Keeper as a Value Receiver Instead of a Pointer

Embedding *Keeper as a pointer may lead to unintended side effects if the Keeper instance is modified elsewhere. Embedding it as a value could enhance safety by preventing unexpected mutations within the TransferSharesMethod struct.

 type TransferSharesMethod struct {
-	*Keeper
+	Keeper
 	TransferSharesABI
 }
📝 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.

Suggested change
type TransferSharesMethod struct {
*Keeper
abi.Method
abi.Event
}
type TransferShares struct {
*TransferShare
TransferSharesABI
type TransferSharesMethod struct {
Keeper
TransferSharesABI

Comment on lines +19 to +22
type Validator struct {
ValAddr string
MissedBlocks int64
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Rename Validator struct to avoid naming conflicts

The Validator struct defined here may conflict with the existing Validator type from the stakingtypes package. To prevent confusion and potential type collisions, consider renaming this struct to something more specific, such as MissedBlocksValidator or ValidatorMissedBlocks.

Comment on lines +34 to +41
//nolint:gocyclo // need to refactor
func (k Keeper) handlerTransferShares(
ctx sdk.Context,
evm *vm.EVM,
valAddr sdk.ValAddress,
from, to common.Address,
sharesInt *big.Int,
) (*big.Int, *big.Int, error) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor handlerTransferShares to reduce cyclomatic complexity

The handlerTransferShares function is quite complex, as indicated by the //nolint:gocyclo comment. Refactoring this function into smaller, modular helper functions would improve readability and maintainability.

Comment on lines +247 to +248
return valList[i].MissedBlocks > valList[j].MissedBlocks
})
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize sorting function for better performance

The sorting function compares MissedBlocks in descending order. For large validator lists, consider using efficient sorting algorithms or built-in functions optimized for performance.

Comment on lines +215 to +217
if historical.ReferenceCount == 0 {
panic("cannot set negative reference count")
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid using panic; return an error instead

Using panic in production code can cause the application to crash unexpectedly. Instead of panicking when the ReferenceCount is zero, consider returning an error to handle the situation gracefully.

Apply this diff to return an error:

 if historical.ReferenceCount == 0 {
-    panic("cannot set negative reference count")
+    return errors.New("reference count cannot be negative")
 }

Committable suggestion was skipped due to low confidence.

@zakir-code zakir-code merged commit daf4ce3 into main Oct 25, 2024
11 checks passed
@zakir-code zakir-code deleted the zakir/staking-pre branch October 25, 2024 09:35
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