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

fix: use snapshot to support revert #90

Merged
merged 2 commits into from
Oct 29, 2024
Merged

Conversation

beer-1
Copy link
Collaborator

@beer-1 beer-1 commented Oct 28, 2024

Description

Closes: #XXXX


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title, you can find examples of the prefixes below:
  • confirmed ! in the type prefix if API or client breaking change
  • targeted the correct branch
  • provided a link to the relevant issue or specification
  • reviewed "Files changed" and left comments if necessary
  • included the necessary unit and integration tests
  • updated the relevant documentation or specification, including comments for documenting Go code
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic, API design and naming, documentation is accurate, tests and test coverage

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new StateDB interface for enhanced state management in EVM operations.
    • Added prepareSDKContext function for improved context preparation during EVM execution.
    • New MockStateDB implementations for testing EVM state management.
    • Added execute_cosmos function to the Counter contract for executing cosmos-related operations.
  • Improvements

    • Refactored context handling in various components to utilize stateDB instead of context.
    • Enhanced error handling and gas management in the CosmosPrecompile and ERC20RegistryPrecompile contracts.
  • Tests

    • Updated tests to align with the new state management approach, improving clarity and error handling.
    • Introduced a new test for validating the behavior of the execute_cosmos function.
  • Documentation

    • Added method for accessing context from snapshots in the Snapshot struct.

@beer-1 beer-1 self-assigned this Oct 28, 2024
@beer-1 beer-1 requested a review from a team as a code owner October 28, 2024 10:14
Copy link

coderabbitai bot commented Oct 28, 2024

Walkthrough

The pull request introduces several modifications to the keeper package, specifically enhancing context management for Ethereum Virtual Machine (EVM) execution. A new function, prepareSDKContext, is added to centralize context preparation, while existing methods are updated to utilize a state database instead of a context object. This includes changes to method signatures and the introduction of mock implementations for testing. Overall, the changes aim to improve the organization and clarity of context handling within the EVM framework without altering the fundamental logic of the existing methods.

Changes

File Path Change Summary
x/evm/keeper/context.go - Added func prepareSDKContext(ctx sdk.Context) (sdk.Context, error).
- Removed comment from CreateEVM about SDK context preparation.
- Updated buildBlockContext to use stateDB instead of ctx for precompiles.
x/evm/keeper/precompiles.go - Updated toMap method signature from ctx context.Context to stateDB types.StateDB.
- Changed usage from WithContext(ctx) to WithStateDB(stateDB) within the method body.
x/evm/precompiles/cosmos/common_test.go - Added mock implementations for EVM state management interfaces, including MockStateDB, MockAccountKeeper, MockBankKeeper, etc., with various methods for simulating state interactions.
x/evm/precompiles/cosmos/contract.go - Replaced ctx field in CosmosPrecompile struct with stateDB types.StateDB.
- Renamed WithContext to WithStateDB and updated method logic to utilize stateDB.
x/evm/precompiles/cosmos/contract_test.go - Updated tests to replace WithContext(ctx) calls with WithStateDB(stateDB).
- Removed extensive mock implementations for AccountKeeper, BankKeeper, etc.
x/evm/precompiles/erc20_registry/common_test.go - Introduced MockStateDB for testing with methods for state management and snapshots, including Snapshot, RevertToSnapshot, etc.
x/evm/precompiles/erc20_registry/contract.go - Replaced ctx field in ERC20RegistryPrecompile with stateDB types.StateDB.
- Renamed WithContext to WithStateDB and updated the logic in ExtendedRun for state management and error handling.
x/evm/precompiles/erc20_registry/contract_test.go - Simplified error handling in tests, focusing on specific error checks instead of gas usage, and updated context setup to use NewMockStateDB(ctx).
x/evm/state/snapshot.go - Added func (s *Snapshot) Context() sdk.Context to return the context of the Snapshot.
x/evm/state/statedb.go - Introduced func (s *StateDB) ContextOfSnapshot(i int) sdk.Context to retrieve context associated with a snapshot index.
x/evm/types/expected_keeper.go - Added new interface StateDB extending vm.StateDB with ContextOfSnapshot(i int) sdk.Context.
- Removed WithContext interface and added WithStateDB interface.

Possibly related PRs

🐰 In the warren where code does bloom,

Changes hop with a joyful zoom!

Contexts prepared, state in sight,

EVM dances, all feels right!

With mocks and tests, we leap and play,

Hooray for updates, hip-hip-hooray! 🎉


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

codecov bot commented Oct 28, 2024

Codecov Report

Attention: Patch coverage is 71.05263% with 11 lines in your changes missing coverage. Please review.

Project coverage is 28.24%. Comparing base (5a41c08) to head (cbd91fd).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
x/evm/contracts/counter/Counter.go 0.00% 6 Missing ⚠️
x/evm/state/statedb.go 40.00% 2 Missing and 1 partial ⚠️
x/evm/state/snapshot.go 0.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #90      +/-   ##
==========================================
+ Coverage   28.22%   28.24%   +0.02%     
==========================================
  Files         124      124              
  Lines       13736    13756      +20     
==========================================
+ Hits         3877     3886       +9     
- Misses       9307     9317      +10     
- Partials      552      553       +1     
Files with missing lines Coverage Δ
x/evm/keeper/context.go 74.92% <100.00%> (-0.08%) ⬇️
x/evm/keeper/precompiles.go 85.36% <100.00%> (ø)
x/evm/precompiles/cosmos/contract.go 50.21% <100.00%> (+0.64%) ⬆️
x/evm/precompiles/erc20_registry/contract.go 52.83% <100.00%> (+2.33%) ⬆️
x/evm/state/snapshot.go 81.81% <0.00%> (-18.19%) ⬇️
x/evm/state/statedb.go 64.26% <40.00%> (-0.30%) ⬇️
x/evm/contracts/counter/Counter.go 0.00% <0.00%> (ø)

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

🧹 Outside diff range and nitpick comments (9)
x/evm/precompiles/erc20_registry/contract_test.go (2)

93-94: LGTM: Improved error handling precision.

The use of require.ErrorIs provides more precise error type checking, which is a good practice for testing specific error conditions.

Consider adding a comment explaining the out-of-gas test case for better test documentation:

+// Verify that the operation fails with out-of-gas when given insufficient gas
 _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.REGISTER_GAS-1, false)
 require.ErrorIs(t, err, vm.ErrOutOfGas)

159-160: Update the misleading comment.

The comment "out of gas panic" is inaccurate as the code is testing for an error, not a panic.

-// out of gas panic
+// verify out-of-gas error for read operation
 _, _, err = registry.ExtendedRun(vm.AccountRef(erc20Addr), bz, precompiles.IS_STORE_REGISTERED_GAS-1, true)
 require.ErrorIs(t, err, vm.ErrOutOfGas)
x/evm/precompiles/erc20_registry/common_test.go (2)

18-26: Add godoc comments for the MockStateDB type.

While the struct fields have inline comments, adding a detailed godoc comment for the MockStateDB type would improve documentation. Consider documenting:

  • The purpose of this mock
  • How it manages context and snapshots
  • Its intended use in tests

Example addition:

+// MockStateDB implements the evmtypes.StateDB interface for testing purposes.
+// It maintains a stack of context snapshots that can be created and reverted,
+// while leaving other StateDB methods unimplemented.
type MockStateDB struct {

36-49: Add bounds check in Snapshot method.

The Snapshot method calculates the snapshot ID without checking if m.snaps is empty. While this works in the current implementation, it's better to be explicit.

 func (m *MockStateDB) Snapshot() int {
 	// get a current snapshot id
-	sid := len(m.snaps) - 1
+	sid := -1
+	if len(m.snaps) > 0 {
+		sid = len(m.snaps) - 1
+	}
x/evm/precompiles/cosmos/common_test.go (4)

34-39: Initialize maps in constructor

The constructor should initialize the snaps slice to avoid potential nil pointer dereferences.

 func NewMockStateDB(ctx sdk.Context) *MockStateDB {
 	return &MockStateDB{
 		ctx:        ctx,
 		initialCtx: ctx,
+		snaps:      make([]*state.Snapshot, 0),
 	}
 }

84-252: Enhance panic messages in unimplemented methods

The panic messages should be more descriptive to aid in debugging.

Example for one method (apply similar pattern to others):

 func (m *MockStateDB) AddAddressToAccessList(addr common.Address) {
-	panic("unimplemented")
+	panic("MockStateDB.AddAddressToAccessList: method not implemented")
 }

256-260: Add constructor for MockAccountKeeper

The struct should have a constructor to properly initialize its fields.

+func NewMockAccountKeeper(ac address.Codec) *MockAccountKeeper {
+	return &MockAccountKeeper{
+		ac:       ac,
+		accounts: make(map[string]sdk.AccountI),
+	}
+}

329-332: Add constructor for ERC20DenomKeeper

The struct should have a constructor to properly initialize its maps.

+func NewMockERC20DenomKeeper() *MockERC20DenomKeeper {
+	return &MockERC20DenomKeeper{
+		denomMap: make(map[string]common.Address),
+		addrMap:  make(map[common.Address]string),
+	}
+}
x/evm/keeper/context.go (1)

Line range hint 208-227: Consider enhancing documentation for context preparation.

While the implementation is solid, consider adding more detailed documentation:

  1. Document the purpose and implications of the recursive depth limit
  2. Add examples of when recursive calls might occur
  3. Explain the role of cosmos messages in the context

Consider adding this documentation above the function:

-// prepare SDK context for EVM execution
-// 1. set cosmos messages to context
-// 2. check recursive depth and increment it (the maximum depth is 16)
+// prepareSDKContext prepares the SDK context for EVM execution by:
+// 1. Initializing an empty slice for cosmos messages in the context, which will
+//    store any Cosmos SDK messages generated during EVM execution
+// 2. Managing recursive depth to prevent stack overflow attacks:
+//    - Tracks the depth of recursive EVM calls
+//    - Enforces a maximum depth of 16 to prevent excessive recursion
+//    - This is particularly important for contract-to-contract calls and
+//      precompile executions that might trigger recursive EVM operations
+//
+// Returns:
+// - Modified context with initialized message slice and updated recursive depth
+// - ErrExceedMaxRecursiveDepth if the maximum recursive depth is exceeded
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 5a41c08 and 9464355.

📒 Files selected for processing (11)
  • x/evm/keeper/context.go (2 hunks)
  • x/evm/keeper/precompiles.go (1 hunks)
  • x/evm/precompiles/cosmos/common_test.go (1 hunks)
  • x/evm/precompiles/cosmos/contract.go (4 hunks)
  • x/evm/precompiles/cosmos/contract_test.go (8 hunks)
  • x/evm/precompiles/erc20_registry/common_test.go (1 hunks)
  • x/evm/precompiles/erc20_registry/contract.go (3 hunks)
  • x/evm/precompiles/erc20_registry/contract_test.go (5 hunks)
  • x/evm/state/snapshot.go (1 hunks)
  • x/evm/state/statedb.go (1 hunks)
  • x/evm/types/expected_keeper.go (1 hunks)
🔇 Additional comments (17)
x/evm/state/snapshot.go (1)

27-29: LGTM! Clean implementation of Context getter.

The new Context() method is well-implemented, providing clean access to the underlying SDK context while maintaining encapsulation. This addition aligns well with the PR's objective of supporting revert functionality through snapshots.

x/evm/keeper/precompiles.go (1)

56-56: LGTM! Verify interface implementation across precompiles.

The change from context.Context to types.StateDB aligns well with supporting snapshot/revert functionality and matches Ethereum's architecture.

Let's verify that all precompiles implement the WithStateDB interface:

✅ Verification successful

Based on the shell script results, I can now generate the final response:

All precompiles correctly implement WithStateDB interface

The verification confirms that both precompile contracts in the codebase implement the required WithStateDB method:

  • ERC20RegistryPrecompile in x/evm/precompiles/erc20_registry/contract.go
  • CosmosPrecompile in x/evm/precompiles/cosmos/contract.go

Both implementations properly handle the state database assignment, making the type assertion in toMap safe.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all precompile contracts implement the WithStateDB interface
# Expected: All precompile contracts should have a WithStateDB method

# Search for all precompile contract definitions
ast-grep --pattern 'type $_ struct {
  $$$
}'  x/evm/precompiles/

# Search for WithStateDB implementations
ast-grep --pattern 'func ($_ $_) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
  $$$
}' x/evm/precompiles/

Length of output: 6419

x/evm/precompiles/erc20_registry/contract_test.go (3)

78-79: LGTM: State management setup is appropriate.

The transition to using StateDB aligns with the PR's objective of supporting revert functionality through snapshots. The mock state setup is suitable for testing purposes.


110-111: LGTM: Consistent error handling implementation.

The error handling follows the same precise pattern established earlier, maintaining consistency throughout the test suite.


142-143: LGTM: Error handling maintains consistency.

The implementation continues to follow the established pattern for out-of-gas error checking.

x/evm/precompiles/erc20_registry/common_test.go (1)

1-16: LGTM: Well-organized package structure and imports.

The package name follows Go test conventions, and imports are properly grouped.

x/evm/precompiles/cosmos/common_test.go (1)

1-352: Overall implementation looks good

The mock implementations provide a solid foundation for testing the snapshot-based revert functionality. The StateDB implementation correctly handles context management for snapshots, while other mock implementations provide the necessary supporting functionality.

x/evm/keeper/context.go (2)

164-169: LGTM! Context preparation logic looks solid.

The integration of prepareSDKContext in CreateEVM is clean and maintains proper error handling.


196-196: Verify precompile compatibility with stateDB usage.

The change to use stateDB in k.precompiles.toMap looks correct, but we should verify that all precompile implementations support this change.

Let's check for any precompile implementations that might still expect context:

✅ Verification successful

Let me gather more information about the precompile implementations to verify their compatibility with stateDB.


Let me try a different approach to check the precompile implementations.


Let me check one final aspect to ensure all precompiles properly implement the stateDB interface.


Based on the results from our verification scripts, I can now provide a final response:

Precompile implementations correctly support stateDB usage

The verification shows that:

  • Both CosmosPrecompile and ERC20RegistryPrecompile properly implement the WithStateDB method
  • The precompile structs correctly include stateDB types.StateDB field
  • The change to use stateDB in k.precompiles.toMap is consistent with the precompile implementations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for precompile implementations that might still use context
rg -g '!vendor/*' -g '*.go' 'type\s+\w+Precompile\s+struct' -A 10

Length of output: 1532


Script:

#!/bin/bash
# Search for precompile method signatures and their implementations
ast-grep --pattern 'func ($_ *$_Precompile) $_($$$) $$$'

# Also search for any direct context usage in precompile files
rg -g '!vendor/*' -g '*precompile*.go' 'ctx\s+sdk\.Context'

Length of output: 120


Script:

#!/bin/bash
# Search for precompile method implementations and their parameters
rg -g '!vendor/*' -g '*.go' 'func \((\w+)\s+\*\w+Precompile\)' -A 3

# Check how stateDB is used in precompile implementations
rg -g '!vendor/*' -g '*.go' 'stateDB\s+types\.StateDB' -B 2 -A 2

Length of output: 1758


Script:

#!/bin/bash
# Check for the PrecompiledContract interface implementation
rg -g '!vendor/*' -g '*.go' 'type\s+PrecompiledContract\s+interface' -A 10

# Look for any remaining context.Context usage in precompile methods
rg -g '!vendor/*' -g '*precompile*.go' 'context\.Context|sdk\.Context' -B 2 -A 2

Length of output: 159

x/evm/state/statedb.go (1)

592-598: Implementation aligns with snapshot management requirements.

The method correctly integrates with the existing snapshot functionality and supports the revert feature by:

  1. Providing access to historical contexts
  2. Maintaining consistency with Snapshot() and RevertToSnapshot()
  3. Preserving the initial context state

Let's verify the usage of this method:

✅ Verification successful

Let me gather more context about the usage patterns by examining the implementation details.


Let me check the snapshot-related functionality to ensure complete verification.


Implementation correctly supports snapshot management and context retrieval

The verification confirms that ContextOfSnapshot is properly implemented and used as intended:

  • Correctly integrates with Snapshot() and RevertToSnapshot() methods
  • Used in precompiled contracts to manage gas metering and state changes
  • Properly handles the initial context case (i == -1)
  • Maintains consistency in snapshot management across the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for calls to ContextOfSnapshot to understand usage patterns
rg "ContextOfSnapshot" --type go

Length of output: 847


Script:

#!/bin/bash
# Check the implementation in contract files to understand how ContextOfSnapshot is used
rg "ContextOfSnapshot" -A 5 -B 5 x/evm/precompiles/cosmos/contract.go x/evm/precompiles/erc20_registry/contract.go

Length of output: 1924


Script:

#!/bin/bash
# Check Snapshot implementation and related methods
rg "func.*Snapshot" -A 3 x/evm/state/statedb.go

Length of output: 347

x/evm/types/expected_keeper.go (2)

88-91: LGTM

The addition of the StateDB interface that extends vm.StateDB and includes ContextOfSnapshot(i int) sdk.Context enhances state management and snapshot handling.


93-94: Ensure all references to WithContext are updated to WithStateDB

Since the WithContext interface has been replaced by WithStateDB, please verify that all implementations and usages of WithContext have been updated accordingly to prevent any potential issues.

Run the following script to find any remaining references to WithContext:

✅ Verification successful

No remaining references to WithContext found, all implementations use WithStateDB

The search results confirm that:

  1. There are no remaining references to WithContext in the codebase
  2. The WithStateDB interface is properly defined in x/evm/types/expected_keeper.go
  3. All implementations (CosmosPrecompile and ERC20RegistryPrecompile) correctly implement the WithStateDB interface
  4. All usages in tests and the precompiles mapper use the new WithStateDB method

The migration from WithContext to WithStateDB appears to be complete and consistent throughout the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any remaining usages of the old `WithContext` interface.

# Test: Find occurrences of `WithContext`. Expect: No matches found.
rg 'WithContext' --type go -A 5

Length of output: 31


Script:

#!/bin/bash
# Let's try a more comprehensive search approach:

# 1. Search for any WithContext interface or method definitions
ast-grep --pattern 'interface WithContext'
ast-grep --pattern 'func ($_ $_) WithContext'

# 2. Search for any WithContext method calls
ast-grep --pattern '$_.WithContext($_)'

# 3. Search for any WithStateDB interface or method definitions to verify the new pattern
ast-grep --pattern 'interface WithStateDB'
ast-grep --pattern 'func ($_ $_) WithStateDB'

# 4. Search for any WithStateDB method calls
ast-grep --pattern '$_.WithStateDB($_)'

# 5. Let's also do a case-insensitive grep to catch any variations
rg -i "withcontext" --type go

Length of output: 299


Script:

#!/bin/bash
# Let's try a different approach using ripgrep with more context and file type filtering

# 1. Search for any references to WithContext in Go files, case-insensitive with 3 lines of context
rg -i "withcontext" --type go -C 3

# 2. Search for the new WithStateDB pattern to understand the changes
rg -i "withstatedb" --type go -C 3

# 3. Look specifically in the x/evm directory where the change was made
rg -i "withcontext|withstatedb" --type go -C 3 "x/evm/"

# 4. Search for interface definitions containing either pattern
rg "type.*interface.*{" --type go -A 5

Length of output: 15182

x/evm/precompiles/erc20_registry/contract.go (2)

56-57: Confirm gas usage assignment during OutOfGas error

In the recovery block, upon catching an ErrorOutOfGas, you set usedGas = suppliedGas. Ensure this reflects the intended behavior, accurately representing gas consumption when an out-of-gas error occurs. Previously, gas usage might have been calculated differently, and it's important that this assignment aligns with the overall gas accounting strategy.


64-66: Good practice: Reverting state changes on error

Reverting to the snapshot when an error occurs ensures that any state changes made during execution are rolled back, maintaining consistency and preventing unintended side effects.

x/evm/precompiles/cosmos/contract.go (3)

27-27: LGTM!

The interface assertion correctly ensures that CosmosPrecompile implements the types.WithStateDB interface.


32-34: Initialize stateDB field appropriately

The addition of the stateDB field to the CosmosPrecompile struct is appropriate. Ensure that stateDB is properly initialized before it's used to avoid nil pointer dereferences.


106-108: Confirm state rollback works as intended on errors

The defer function rolls back to the snapshot if an error occurs by calling e.stateDB.RevertToSnapshot(snapshot). Ensure that this rollback mechanism effectively reverts any state changes made during execution when err != nil.

m := make(map[common.Address]vm.PrecompiledContract)
for _, p := range ps {
m[p.addr] = p.contract.(types.WithContext).WithContext(ctx)
m[p.addr] = p.contract.(types.WithStateDB).WithStateDB(stateDB)
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.

The unchecked type assertion p.contract.(types.WithStateDB) could cause a panic if a precompile doesn't implement the WithStateDB interface.

Consider adding a safety check:

-		m[p.addr] = p.contract.(types.WithStateDB).WithStateDB(stateDB)
+		if withState, ok := p.contract.(types.WithStateDB); ok {
+			m[p.addr] = withState.WithStateDB(stateDB)
+		} else {
+			panic(fmt.Sprintf("precompile at %s does not implement WithStateDB interface", p.addr))
+		}
📝 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
m[p.addr] = p.contract.(types.WithStateDB).WithStateDB(stateDB)
if withState, ok := p.contract.(types.WithStateDB); ok {
m[p.addr] = withState.WithStateDB(stateDB)
} else {
panic(fmt.Sprintf("precompile at %s does not implement WithStateDB interface", p.addr))
}

Comment on lines +76 to +246

// GetCodeSize implements types.StateDB.
func (m *MockStateDB) GetCodeSize(common.Address) int {
panic("unimplemented")
}

// GetCommittedState implements types.StateDB.
func (m *MockStateDB) GetCommittedState(common.Address, common.Hash) common.Hash {
panic("unimplemented")
}

// GetNonce implements types.StateDB.
func (m *MockStateDB) GetNonce(common.Address) uint64 {
panic("unimplemented")
}

// GetRefund implements types.StateDB.
func (m *MockStateDB) GetRefund() uint64 {
panic("unimplemented")
}

// GetState implements types.StateDB.
func (m *MockStateDB) GetState(common.Address, common.Hash) common.Hash {
panic("unimplemented")
}

// GetStorageRoot implements types.StateDB.
func (m *MockStateDB) GetStorageRoot(addr common.Address) common.Hash {
panic("unimplemented")
}

// GetTransientState implements types.StateDB.
func (m *MockStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash {
panic("unimplemented")
}

// HasSelfDestructed implements types.StateDB.
func (m *MockStateDB) HasSelfDestructed(common.Address) bool {
panic("unimplemented")
}

// PointCache implements types.StateDB.
func (m *MockStateDB) PointCache() *utils.PointCache {
panic("unimplemented")
}

// Prepare implements types.StateDB.
func (m *MockStateDB) Prepare(rules params.Rules, sender common.Address, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) {
panic("unimplemented")
}

// SelfDestruct implements types.StateDB.
func (m *MockStateDB) SelfDestruct(common.Address) {
panic("unimplemented")
}

// Selfdestruct6780 implements types.StateDB.
func (m *MockStateDB) Selfdestruct6780(common.Address) {
panic("unimplemented")
}

// SetCode implements types.StateDB.
func (m *MockStateDB) SetCode(common.Address, []byte) {
panic("unimplemented")
}

// SetNonce implements types.StateDB.
func (m *MockStateDB) SetNonce(common.Address, uint64) {
panic("unimplemented")
}

// SetState implements types.StateDB.
func (m *MockStateDB) SetState(common.Address, common.Hash, common.Hash) {
panic("unimplemented")
}

// SetTransientState implements types.StateDB.
func (m *MockStateDB) SetTransientState(addr common.Address, key common.Hash, value common.Hash) {
panic("unimplemented")
}

// SlotInAccessList implements types.StateDB.
func (m *MockStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) {
panic("unimplemented")
}

// SubBalance implements types.StateDB.
func (m *MockStateDB) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) {
panic("unimplemented")
}

// SubRefund implements types.StateDB.
func (m *MockStateDB) SubRefund(uint64) {
panic("unimplemented")
}

// Witness implements types.StateDB.
func (m *MockStateDB) Witness() *stateless.Witness {
panic("unimplemented")
}
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 enhancing mock implementation.

  1. Make panic messages more descriptive by including the method name:
-	panic("unimplemented")
+	panic("MockStateDB.AddAddressToAccessList: unimplemented")
  1. Consider implementing critical methods that might be needed for basic testing scenarios:
  • GetBalance
  • SetState/GetState
  • AddBalance/SubBalance

This would make the mock more useful for common test cases while keeping other methods unimplemented.

Committable suggestion was skipped due to low confidence.

Comment on lines +51 to +74
// RevertToSnapshot implements types.StateDB.
func (m *MockStateDB) RevertToSnapshot(i int) {
if i == -1 {
m.ctx = m.initialCtx
m.snaps = m.snaps[:0]
return
}

// revert to the snapshot with the given id
snap := m.snaps[i]
m.ctx = snap.Context()

// clear the snapshots after the given id
m.snaps = m.snaps[:i]
}

// ContextOfSnapshot implements types.StateDB.
func (m *MockStateDB) ContextOfSnapshot(i int) sdk.Context {
if i == -1 {
return m.initialCtx
}

return m.snaps[i].Context()
}
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 bounds checking in RevertToSnapshot and ContextOfSnapshot.

Both methods access m.snaps[i] directly without verifying if the index is valid. This could panic if an invalid snapshot ID is provided.

Add validation:

 func (m *MockStateDB) RevertToSnapshot(i int) {
 	if i == -1 {
 		m.ctx = m.initialCtx
 		m.snaps = m.snaps[:0]
 		return
 	}
+	if i < 0 || i >= len(m.snaps) {
+		panic("invalid snapshot index")
+	}
 func (m *MockStateDB) ContextOfSnapshot(i int) sdk.Context {
 	if i == -1 {
 		return m.initialCtx
 	}
+	if i < 0 || i >= len(m.snaps) {
+		panic("invalid snapshot index")
+	}
📝 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
// RevertToSnapshot implements types.StateDB.
func (m *MockStateDB) RevertToSnapshot(i int) {
if i == -1 {
m.ctx = m.initialCtx
m.snaps = m.snaps[:0]
return
}
// revert to the snapshot with the given id
snap := m.snaps[i]
m.ctx = snap.Context()
// clear the snapshots after the given id
m.snaps = m.snaps[:i]
}
// ContextOfSnapshot implements types.StateDB.
func (m *MockStateDB) ContextOfSnapshot(i int) sdk.Context {
if i == -1 {
return m.initialCtx
}
return m.snaps[i].Context()
}
// RevertToSnapshot implements types.StateDB.
func (m *MockStateDB) RevertToSnapshot(i int) {
if i == -1 {
m.ctx = m.initialCtx
m.snaps = m.snaps[:0]
return
}
if i < 0 || i >= len(m.snaps) {
panic("invalid snapshot index")
}
// revert to the snapshot with the given id
snap := m.snaps[i]
m.ctx = snap.Context()
// clear the snapshots after the given id
m.snaps = m.snaps[:i]
}
// ContextOfSnapshot implements types.StateDB.
func (m *MockStateDB) ContextOfSnapshot(i int) sdk.Context {
if i == -1 {
return m.initialCtx
}
if i < 0 || i >= len(m.snaps) {
panic("invalid snapshot index")
}
return m.snaps[i].Context()
}

Comment on lines +1 to +246

// GetCodeSize implements types.StateDB.
func (m *MockStateDB) GetCodeSize(common.Address) int {
panic("unimplemented")
}

// GetCommittedState implements types.StateDB.
func (m *MockStateDB) GetCommittedState(common.Address, common.Hash) common.Hash {
panic("unimplemented")
}

// GetNonce implements types.StateDB.
func (m *MockStateDB) GetNonce(common.Address) uint64 {
panic("unimplemented")
}

// GetRefund implements types.StateDB.
func (m *MockStateDB) GetRefund() uint64 {
panic("unimplemented")
}

// GetState implements types.StateDB.
func (m *MockStateDB) GetState(common.Address, common.Hash) common.Hash {
panic("unimplemented")
}

// GetStorageRoot implements types.StateDB.
func (m *MockStateDB) GetStorageRoot(addr common.Address) common.Hash {
panic("unimplemented")
}

// GetTransientState implements types.StateDB.
func (m *MockStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash {
panic("unimplemented")
}

// HasSelfDestructed implements types.StateDB.
func (m *MockStateDB) HasSelfDestructed(common.Address) bool {
panic("unimplemented")
}

// PointCache implements types.StateDB.
func (m *MockStateDB) PointCache() *utils.PointCache {
panic("unimplemented")
}

// Prepare implements types.StateDB.
func (m *MockStateDB) Prepare(rules params.Rules, sender common.Address, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) {
panic("unimplemented")
}

// SelfDestruct implements types.StateDB.
func (m *MockStateDB) SelfDestruct(common.Address) {
panic("unimplemented")
}

// Selfdestruct6780 implements types.StateDB.
func (m *MockStateDB) Selfdestruct6780(common.Address) {
panic("unimplemented")
}

// SetCode implements types.StateDB.
func (m *MockStateDB) SetCode(common.Address, []byte) {
panic("unimplemented")
}

// SetNonce implements types.StateDB.
func (m *MockStateDB) SetNonce(common.Address, uint64) {
panic("unimplemented")
}

// SetState implements types.StateDB.
func (m *MockStateDB) SetState(common.Address, common.Hash, common.Hash) {
panic("unimplemented")
}

// SetTransientState implements types.StateDB.
func (m *MockStateDB) SetTransientState(addr common.Address, key common.Hash, value common.Hash) {
panic("unimplemented")
}

// SlotInAccessList implements types.StateDB.
func (m *MockStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) {
panic("unimplemented")
}

// SubBalance implements types.StateDB.
func (m *MockStateDB) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) {
panic("unimplemented")
}

// SubRefund implements types.StateDB.
func (m *MockStateDB) SubRefund(uint64) {
panic("unimplemented")
}

// Witness implements types.StateDB.
func (m *MockStateDB) Witness() *stateless.Witness {
panic("unimplemented")
}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Snapshot functionality needs test coverage

The mock implementation provides the necessary snapshot infrastructure, but there are no actual test cases exercising this functionality. While the MockStateDB correctly implements Snapshot(), RevertToSnapshot(), and ContextOfSnapshot(), none of the existing tests in the precompiles packages utilize these methods.

Action items:

  • Add test cases that create and revert snapshots to verify the state management functionality
  • Include tests that validate state consistency across multiple snapshot operations
  • Test edge cases like reverting to initial state (snapshot -1)
🔗 Analysis chain

Verify snapshot functionality in integration tests.

The mock implementation provides good support for testing snapshot-based state management, which aligns with the PR's objective of implementing revert functionality. Consider adding integration tests that:

  1. Create multiple snapshots
  2. Modify state between snapshots
  3. Revert to various snapshot points
  4. Verify state consistency after reverts

This will help ensure the robustness of the snapshot-revert feature.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for existing integration tests that use MockStateDB
rg -l "NewMockStateDB" --type go | grep "_test.go"

Length of output: 228


Script:

#!/bin/bash
# Check how MockStateDB is used in tests, particularly focusing on snapshot functionality
rg "NewMockStateDB|Snapshot|RevertToSnapshot" -A 5 -B 2 x/evm/precompiles/erc20_registry/contract_test.go x/evm/precompiles/erc20_registry/common_test.go x/evm/precompiles/cosmos/contract_test.go x/evm/precompiles/cosmos/common_test.go

Length of output: 11095


Script:

#!/bin/bash
# Let's check if there are any actual test cases that use the snapshot functionality
rg "Snapshot\(\)|RevertToSnapshot\(" --type go -B 5 -A 10 x/evm/precompiles/erc20_registry/contract_test.go x/evm/precompiles/cosmos/contract_test.go

Length of output: 151

Comment on lines +263 to +266
func (k MockAccountKeeper) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI {
str, _ := k.ac.BytesToString(addr.Bytes())
return k.accounts[str]
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle address conversion errors

The BytesToString conversion errors should be handled appropriately.

 func (k MockAccountKeeper) GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI {
-	str, _ := k.ac.BytesToString(addr.Bytes())
+	str, err := k.ac.BytesToString(addr.Bytes())
+	if err != nil {
+		panic(fmt.Sprintf("failed to convert address bytes to string: %v", err))
+	}
 	return k.accounts[str]
 }

Also applies to: 269-273

Comment on lines +48 to +49
snapshot := e.stateDB.Snapshot()
ctx := e.stateDB.ContextOfSnapshot(snapshot).WithGasMeter(storetypes.NewGasMeter(suppliedGas))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure stateDB is initialized before usage

The stateDB is used to create a snapshot and context, but if stateDB is not properly initialized (due to the issue in WithStateDB), this could lead to a nil pointer dereference at runtime. After fixing the receiver in WithStateDB, please verify that stateDB is correctly set before it's used in ExtendedRun.

Comment on lines +34 to +35
func (e ERC20RegistryPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
e.stateDB = stateDB
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix the method receiver in WithStateDB to correctly set stateDB

The method WithStateDB currently uses a value receiver (e ERC20RegistryPrecompile), which means that any modifications to e.stateDB affect only a copy of the struct and do not persist after the method returns. To ensure that stateDB is properly set on the original struct, the receiver should be a pointer.

Apply this diff to fix the receiver type:

-func (e ERC20RegistryPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
+func (e *ERC20RegistryPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
📝 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 (e ERC20RegistryPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
e.stateDB = stateDB
func (e *ERC20RegistryPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
e.stateDB = stateDB

Comment on lines +91 to +93
snapshot := e.stateDB.Snapshot()
ctx := e.stateDB.ContextOfSnapshot(snapshot).WithGasMeter(storetypes.NewGasMeter(suppliedGas))

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Check for nil stateDB to prevent potential panics

In the ExtendedRun method, e.stateDB is used without checking if it's nil. If stateDB is nil, calling e.stateDB.Snapshot() will result in a nil pointer dereference.

Consider adding a check at the beginning of the method:

if e.stateDB == nil {
	return nil, 0, errors.New("stateDB is not initialized")
}

Comment on lines +70 to 72
func (e CosmosPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
e.stateDB = stateDB
return e
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use a pointer receiver for WithStateDB method to update the struct

The WithStateDB method has a value receiver (e CosmosPrecompile), which means any modifications to e will not affect the original instance outside the method. To correctly update the stateDB field of the original CosmosPrecompile instance, change the receiver to a pointer.

Apply this diff to fix the issue:

-func (e CosmosPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
+func (e *CosmosPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
     e.stateDB = stateDB
     return e
}
📝 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 (e CosmosPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
e.stateDB = stateDB
return e
func (e *CosmosPrecompile) WithStateDB(stateDB types.StateDB) vm.PrecompiledContract {
e.stateDB = stateDB
return e

Comment on lines +69 to +70
stateDB := NewMockStateDB(ctx)
cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile)
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 repeated stateDB initialization into a helper function to improve maintainability.

The initialization of stateDB and updating cosmosPrecompile is duplicated across multiple test functions. To reduce code duplication and enhance code readability, consider creating a helper function or updating the setup() function to include stateDB initialization.

Here's a suggested refactor:

 func setup() (sdk.Context, codec.Codec, address.Codec, types.AccountKeeper, types.BankKeeper, precompiles.CosmosPrecompile) {
     // existing setup code...
     ac := codecaddress.NewBech32Codec("init")

+    cosmosPrecompile, err := precompiles.NewCosmosPrecompile(cdc, ac, ak, bk, nil, nil, nil)
+    if err != nil {
+        panic(err)
+    }
+
+    stateDB := NewMockStateDB(ctx)
+    cosmosPrecompile = cosmosPrecompile.WithStateDB(stateDB).(precompiles.CosmosPrecompile)
+
     return ctx, cdc, ac, ak, bk, cosmosPrecompile
 }

Then, update your test functions to receive the cosmosPrecompile instance:

-func Test_CosmosPrecompile_IsBlockedAddress(t *testing.T) {
-    ctx, cdc, ac, ak, bk := setup()
+func Test_CosmosPrecompile_IsBlockedAddress(t *testing.T) {
+    ctx, cdc, ac, ak, bk, cosmosPrecompile := setup()

Also applies to: 115-116, 161-162, 192-193, 223-224, 323-324, 370-371, 412-413

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

🧹 Outside diff range and nitpick comments (4)
x/evm/contracts/counter/Counter.sol (1)

40-49: Add NatSpec documentation for the new function.

The new execute_cosmos function lacks documentation explaining its purpose, parameters, and potential revert conditions. This documentation is crucial for developers integrating with the contract.

Apply this diff to add documentation:

+    /// @notice Executes a cosmos message with optional revert functionality
+    /// @param exec_msg The cosmos message to execute
+    /// @param call_revert If true, the function will revert after execution
+    /// @dev This function interacts with COSMOS_CONTRACT and may revert with "revert" message
     function execute_cosmos(
         string memory exec_msg,
         bool call_revert
     ) external {
x/evm/keeper/context_test.go (3)

260-262: Consider using a named constant for the token amount.

The magic number 1000000000 could be made more readable by declaring it as a constant or variable with a descriptive name like testTokenAmount.

-	amount := math.NewInt(1000000000)
+	const testTokenAmount = 1000000000
+	amount := math.NewInt(testTokenAmount)

276-277: Consider using more specific error assertion.

Instead of using ErrorContains, consider using a more specific assertion to ensure the exact error type is returned.

-	require.ErrorContains(t, err, types.ErrReverted.Error())
+	require.ErrorIs(t, err, types.ErrReverted)

242-300: Consider adding more test cases and documentation.

While the test covers basic success and failure scenarios, consider:

  1. Adding a test case description comment explaining the test's purpose
  2. Testing with different token amounts (e.g., zero, very large amounts)
  3. Testing with invalid message formats
  4. Testing with unauthorized addresses

Example test description:

+// Test_RevertAfterExecuteCosmos verifies that the execute_cosmos function in the Counter contract
+// correctly handles both successful and reverted Cosmos message executions, specifically testing
+// MsgSend behavior and balance changes.
 func Test_RevertAfterExecuteCosmos(t *testing.T) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9464355 and cbd91fd.

📒 Files selected for processing (3)
  • x/evm/contracts/counter/Counter.go (2 hunks)
  • x/evm/contracts/counter/Counter.sol (1 hunks)
  • x/evm/keeper/context_test.go (2 hunks)
🔇 Additional comments (4)
x/evm/contracts/counter/Counter.sol (2)

40-49: Verify snapshot handling for reverts.

Given the PR's objective to implement snapshot support for reverts, we should verify that state changes from COSMOS_CONTRACT.execute_cosmos() are properly handled when call_revert is true.

Run the following script to check snapshot-related patterns:

#!/bin/bash
# Description: Check snapshot handling patterns
# Expected: Find snapshot-related code that handles state reversions

# Search for snapshot-related code
rg -l "snapshot|revert|rollback"

# Search for test files that verify revert behavior
fd -e sol -e go test

Consider implementing a test that verifies:

  1. State changes from the cosmos execution
  2. Complete state reversion when call_revert is true
  3. Proper state persistence when call_revert is false

44-44: Verify error handling for COSMOS_CONTRACT.execute_cosmos call.

The external call to COSMOS_CONTRACT.execute_cosmos() should be checked for potential failures.

Run the following script to check error handling patterns in similar cosmos calls:

✅ Verification successful

Let me gather more specific information about error handling in the Counter contract and related Cosmos contract calls.


Based on the search results, I can now provide a final response since we have clear evidence of the error handling patterns in the Counter contract.

Error handling is already implemented appropriately

The execute_cosmos call is followed by error handling logic through the call_revert parameter, which triggers a revert when needed. The code shows a pattern where failures can be explicitly handled:

COSMOS_CONTRACT.execute_cosmos(exec_msg);
if (call_revert) {
    revert("revert");
}

This implementation allows for controlled error handling based on the execution context, which is sufficient for this use case.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check error handling patterns in cosmos contract calls
# Expected: Find how other functions handle COSMOS_CONTRACT failures

# Search for COSMOS_CONTRACT calls and their error handling
rg -A 5 "COSMOS_CONTRACT\.execute_cosmos"

Length of output: 2156


Script:

#!/bin/bash
# Search for the Counter contract implementation and error handling patterns
rg -A 10 "COSMOS_CONTRACT\.execute_cosmos" x/evm/contracts/counter/Counter.sol

# Check for revert statements in Counter.sol
rg "revert" x/evm/contracts/counter/Counter.sol

# Look at the COSMOS_CONTRACT interface/implementation
rg -A 5 "interface.*COSMOS_CONTRACT" x/evm/contracts/

Length of output: 994

x/evm/keeper/context_test.go (1)

242-254: LGTM: Test setup and contract deployment are well-structured.

The test setup follows consistent patterns with other tests in the file, including proper error handling and assertions.

x/evm/contracts/counter/Counter.go (1)

34-35: LGTM: ABI and bytecode updates for new execute_cosmos method

The ABI and bytecode changes correctly reflect the addition of the new execute_cosmos method with appropriate parameter types.

x/evm/contracts/counter/Counter.sol Show resolved Hide resolved
Comment on lines +295 to +296
_, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil)
require.NoError(t, err, types.ErrReverted.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

Fix incorrect error assertion and remove unnecessary parameter.

The error assertion appears to be incorrect. The types.ErrReverted.Error() parameter is unnecessary since we're expecting success.

-	require.NoError(t, err, types.ErrReverted.Error())
+	require.NoError(t, 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
_, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil)
require.NoError(t, err, types.ErrReverted.Error())
_, _, err = input.EVMKeeper.EVMCall(ctx, caller, contractAddr, inputBz, nil, nil)
require.NoError(t, err)

Comment on lines +267 to +287
// ExecuteCosmos is a paid mutator transaction binding the contract method 0x24c68fce.
//
// Solidity: function execute_cosmos(string exec_msg, bool call_revert) returns()
func (_Counter *CounterTransactor) ExecuteCosmos(opts *bind.TransactOpts, exec_msg string, call_revert bool) (*types.Transaction, error) {
return _Counter.contract.Transact(opts, "execute_cosmos", exec_msg, call_revert)
}

// ExecuteCosmos is a paid mutator transaction binding the contract method 0x24c68fce.
//
// Solidity: function execute_cosmos(string exec_msg, bool call_revert) returns()
func (_Counter *CounterSession) ExecuteCosmos(exec_msg string, call_revert bool) (*types.Transaction, error) {
return _Counter.Contract.ExecuteCosmos(&_Counter.TransactOpts, exec_msg, call_revert)
}

// ExecuteCosmos is a paid mutator transaction binding the contract method 0x24c68fce.
//
// Solidity: function execute_cosmos(string exec_msg, bool call_revert) returns()
func (_Counter *CounterTransactorSession) ExecuteCosmos(exec_msg string, call_revert bool) (*types.Transaction, error) {
return _Counter.Contract.ExecuteCosmos(&_Counter.TransactOpts, exec_msg, call_revert)
}

Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

ExecuteCosmos method bindings need test coverage

While the implementation is correct, there are no specific test cases for the Counter contract's ExecuteCosmos method. However, I found related test coverage:

  • x/evm/precompiles/cosmos/contract_test.go: Contains Test_ExecuteCosmos
  • x/evm/keeper/context_test.go: Contains Test_RevertAfterExecuteCosmos
  • x/evm/keeper/precompiles_test.go: Contains Test_ExecuteCosmosMessage

These tests cover the underlying functionality but not the specific Counter contract bindings. Consider adding integration tests for the Counter contract's ExecuteCosmos method to ensure proper interaction with the precompile.

🔗 Analysis chain

LGTM: ExecuteCosmos method bindings are properly implemented

The new ExecuteCosmos bindings are correctly generated with proper documentation and error handling. The implementation follows the standard go-ethereum binding patterns.

Let's verify the integration test coverage for the new method:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for integration tests covering the new ExecuteCosmos method

# Test: Search for test cases using ExecuteCosmos
rg -l "ExecuteCosmos.*Test" --type go

Length of output: 39


Script:

#!/bin/bash
# Let's try a broader search for test files and ExecuteCosmos references

# Find all test files
echo "=== Test files ==="
fd "_test\.go$"

# Search for any ExecuteCosmos usage
echo -e "\n=== ExecuteCosmos references ==="
rg "ExecuteCosmos" --type go -C 2

# Check if there's a test directory specifically for counter
echo -e "\n=== Counter test files ==="
fd "counter.*test\.go$"

Length of output: 7060

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