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(evm): commit temporary state on precompile start, avoiding bug stemming from uncommitted, dirty journal entries in the EVM StateDB #2086

Merged
merged 17 commits into from
Oct 24, 2024

Conversation

Unique-Divine
Copy link
Member

@Unique-Divine Unique-Divine commented Oct 21, 2024

Purpose / Abstract

Fixing Dirty State Application

The statedb.StateDB struct enforces ether balance changes with journal entries using a setter. In order to maintain consistency between the StateDB and the broader multistore when precompiled contracts transfer ether, the StateDB needs to be manually modified.

This was implemented inside of "precompile/funtoken.go", where I wrapped both calls on the Bank keeper with a safer function that adds a balance change statedb.JournalChange to the db in the event that the asset minted, burned, or sent is a NIBI (ether).

Reverts

Since a revert rolls back changes and fails the transaction, this operation is generally safe. The transaction handler in the Cosmos-SDK already branches a cached context off at the beginning of the transaction lifecycle, and that outermost context is only written if the entire transaction is going to succeed. That's why panics and other errors within gRPC TxMsgs don't require any direct cleanup. If reverting fails the transaction, it means the precompile changes will get reverted as well.

The problem is that Revert in the EVM can be caught with try/catch for external contract calls.

Dynamic gas to handle large contract input

There was already a function for this used in the Wasm precompile. It's been added to the FunToken one for consistency.

Completion Checklist

  • Fix the main critical issue
  • Self-review: Document public functions. Refactor for clarity. Address coderabbit.ai bot comments.
  • Add test case with dirty journal entires on the StateDB

@Unique-Divine Unique-Divine marked this pull request as ready for review October 22, 2024 02:41
@Unique-Divine Unique-Divine requested a review from a team as a code owner October 22, 2024 02:41
Copy link
Contributor

coderabbitai bot commented Oct 22, 2024

Walkthrough

This pull request includes extensive modifications across various files in the NibiruChain project, focusing on enhancing functionality, error handling, and clarity. Key changes involve restructuring the changelog, updating method signatures to include additional return values, and refining error handling in transaction processing and state management. New utility functions and test cases are introduced, while existing ones are adjusted for improved readability and maintainability. The changes aim to streamline interactions with the Ethereum Virtual Machine (EVM) and enhance the robustness of the codebase.

Changes

File Path Change Summary
CHANGELOG.md Restructured to improve clarity; sections renamed and split; new entries for features and bug fixes added; reintroduced "State Machine Breaking" section with refactoring details.
x/evm/evmtest/erc20.go Updated AssertERC20BalanceEqual to use string comparison; added BigPow function for power calculations.
x/evm/evmtest/test_deps.go Added GoCtx() method to TestDeps struct to return a compatible context.Context.
x/evm/evmtest/tx.go Replaced GenerateAndSignEthTxMsg with GenerateEthTxMsgAndSigner; added CallContractTx for contract calls; updated transaction signing logic.
x/evm/keeper/erc20.go Updated erc20Calls methods to return an additional evmObj *vm.EVM; refined error handling and transaction configuration in CallContractWithInput.
x/evm/keeper/funtoken_from_coin_test.go Enhanced error handling and assertion consistency in tests for CreateFunToken and ConvertCoinToEvm.
x/evm/keeper/funtoken_from_erc20_test.go Renamed test method to reflect focus on Bank addresses; updated logging and error handling.
x/evm/logs.go Removed NewTransactionLogs function; retained other log-related methods.
x/evm/logs_test.go Enhanced test cases for transaction logs validation; modified copy creation logic for transaction logs.
x/evm/precompile/funtoken.go Added ABI method; refactored Run and RequiredGas methods for improved error handling and control flow; added new helper functions for minting and sending coins.
x/evm/precompile/funtoken_test.go Updated import for Ethereum common package; modified test methods to reflect new function signatures.
x/evm/precompile/oracle.go Updated RequiredGas and Run methods for improved error handling; adjusted method names for clarity.
x/evm/precompile/precompile.go Introduced OnRunStartResult struct and OnRunStart function for precompile execution preparation; enhanced error handling.
x/evm/precompile/wasm.go Refactored Run method for better error handling; added new methods for managing precompile execution.
x/evm/statedb/interfaces.go Updated AppendJournalEntry method to accept JournalChange type instead of JournalEntry.
x/evm/statedb/journal.go Renamed JournalEntry to JournalChange; introduced new types for journal changes; enhanced methods for dirty entries inspection.
x/evm/statedb/state_object.go Renamed fields in stateObject struct for clarity; updated method calls to reflect new field names.
x/evm/statedb/statedb.go Updated StateDB struct to enhance context handling and standardize field names; refactored Commit method.
x/evm/statedb/config.go Removed NewTxConfig function; clarified parameter naming in NewEmptyTxConfig.
x/evm/statedb/statedb_test.go Updated transaction configuration handling to use struct literals; enhanced logging for transaction details.
x/evm/keeper/grpc_query.go Updated return values for ApplyEvmMsg method calls to include additional return values; refactored TraceBlock method for clarity.
x/evm/keeper/grpc_query_test.go Modified test cases to handle additional return values in function calls; maintained error handling consistency.
x/evm/keeper/funtoken_from_coin.go Updated return signature of deployERC20ForBankCoin method to include an additional blank identifier.
x/evm/keeper/msg_server.go Modified EthereumTx and ApplyEvmMsg methods to return an additional evmObj for improved error reporting.
x/evm/precompile/test/export.go Introduced functions for testing Wasm contracts; added a new type for query responses.
x/evm/precompile/wasm_test.go Removed previous setup functions; updated test methods to utilize new functions from the test package.
x/evm/statedb/journal_test.go Implemented tests for EVM state database, focusing on snapshots and dirty entries.
x/evm/keeper/erc20_test.go Reformatted ERC20 method calls for improved readability.
x/evm/keeper/vm_config.go Changed TxConfig return type from a function call to a struct literal.

Possibly related PRs

  • feat(evm): add oracle precompile #2056: The changes in this PR involve significant updates to the CHANGELOG.md, including the addition of a new section for the Oracle precompile, which aligns with the main PR's restructuring of the changelog to improve clarity and organization.

Suggested labels

x: evm

Suggested reviewers

  • onikonychev

🐇 In the code we hop and play,
With changes bright as a sunny day.
From logs to tests, we make it right,
Improving paths, oh what a sight!
So let us code, and let us cheer,
For every fix brings us near! 🐇


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 22, 2024

Codecov Report

Attention: Patch coverage is 72.36842% with 84 lines in your changes missing coverage. Please review.

Project coverage is 64.48%. Comparing base (dd27f4b) to head (65b2cd6).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
x/evm/precompile/funtoken.go 62.50% 19 Missing and 2 partials ⚠️
x/evm/evmtest/tx.go 64.28% 12 Missing and 3 partials ⚠️
x/evm/errors.go 0.00% 10 Missing ⚠️
x/evm/precompile/precompile.go 50.00% 7 Missing and 3 partials ⚠️
x/evm/statedb/statedb.go 79.16% 7 Missing and 3 partials ⚠️
x/evm/keeper/erc20.go 72.72% 6 Missing ⚠️
x/evm/keeper/msg_server.go 58.33% 5 Missing ⚠️
x/evm/statedb/journal.go 69.23% 4 Missing ⚠️
x/evm/evmtest/erc20.go 25.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2086      +/-   ##
==========================================
+ Coverage   63.98%   64.48%   +0.50%     
==========================================
  Files         270      270              
  Lines       21092    21185      +93     
==========================================
+ Hits        13495    13662     +167     
+ Misses       6660     6573      -87     
- Partials      937      950      +13     
Files with missing lines Coverage Δ
x/evm/evmtest/test_deps.go 100.00% <100.00%> (+8.33%) ⬆️
x/evm/keeper/funtoken_from_coin.go 78.18% <100.00%> (ø)
x/evm/keeper/grpc_query.go 79.92% <100.00%> (-0.04%) ⬇️
x/evm/keeper/vm_config.go 79.59% <100.00%> (ø)
x/evm/logs.go 100.00% <ø> (ø)
x/evm/precompile/errors.go 63.33% <100.00%> (+9.16%) ⬆️
x/evm/precompile/oracle.go 54.00% <100.00%> (+4.81%) ⬆️
x/evm/precompile/wasm.go 52.32% <100.00%> (+2.61%) ⬆️
x/evm/statedb/config.go 100.00% <100.00%> (ø)
x/evm/statedb/state_object.go 98.47% <100.00%> (ø)
... and 9 more

Copy link
Contributor

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

🧹 Outside diff range and nitpick comments (11)
x/evm/evmtest/erc20.go (1)

26-26: Approve the change with a minor suggestion for improvement.

The modification enhances the readability of error messages in ERC20 balance assertions, which is beneficial for debugging. However, to maintain efficiency while keeping the improved error message, consider using a hybrid approach:

-	assert.Equal(t, expectedBalance.String(), actualBalance.String(), "expected %s, got %s", expectedBalance, actualBalance)
+	assert.True(t, expectedBalance.Cmp(actualBalance) == 0, "expected %s, got %s", expectedBalance, actualBalance)

This change retains the efficient Cmp method for the actual comparison while still providing the readable error message with string representations.

x/evm/precompile/funtoken_test.go (2)

129-133: LGTM: Improved contract call simulation.

The change to use evmtest.CallContractTx is a good improvement. It likely provides a more comprehensive simulation of a contract call, including nonce retrieval, transaction message generation, and signing.

Consider adding a comment explaining the benefits of using evmtest.CallContractTx over the direct CallContractWithInput for better code documentation.


140-141: LGTM: Improved balance comparison.

The modification to compare string representations of the amounts in the balance assertion is a good change. It ensures consistent type comparison and aligns with updates in other parts of the codebase.

Consider extracting the expected balance "420" into a constant or variable at the beginning of the test function for better readability and easier maintenance.

x/evm/keeper/funtoken_from_erc20_test.go (3)

Line range hint 213-226: LGTM: Consistent terminology update

The changes from "Cosmos" to "Bank" in the comments and function calls are consistent with the overall refactoring. This improves clarity and accurately represents the module being tested.

Consider adding a brief comment explaining the significance of the bankSend function call to improve test readability.


Line range hint 234-247: LGTM: Good addition of error case testing

The new test case for sending too many tokens improves the overall test coverage by checking error handling. This is a valuable addition to ensure the system behaves correctly under invalid conditions.

Consider enhancing the error check on line 247 to be more specific:

-s.Require().Error(err, evmResp.String())
+s.Require().ErrorContains(err, "insufficient balance", "Expected an insufficient balance error")
+s.T().Logf("Error response: %s", evmResp.String())

This change would make the test more robust by checking for a specific error message and provide more detailed logging.


Line range hint 268-278: LGTM: Good addition of reverse error case testing

The new test case for sending too many Bank tokens back to ERC20 improves the overall test coverage by checking error handling in the reverse direction. This is a valuable addition to ensure the system behaves correctly under invalid conditions in both conversion directions.

Consider enhancing the error check on line 278 to be more specific and informative:

-s.Require().Error(err)
+s.Require().ErrorContains(err, "insufficient balance", "Expected an insufficient balance error when converting more coins than available")
+s.T().Logf("Error response: %s", err.Error())

This change would make the test more robust by checking for a specific error message and provide more detailed logging, which can be helpful for debugging and understanding test failures.

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

285-285: Approve the change with a minor suggestion for consistency.

The change improves readability by directly comparing the balance string to "0". This is clearer than the previous Cmp method usage. However, for consistency with big.Int comparisons elsewhere in the codebase, consider using balance.Sign() == 0 instead. This maintains precision while still being readable.

Consider updating the line to:

-s.Require().Equal("0", balance.String())
+s.Require().Zero(balance.Sign(), "Expected zero balance")

This change maintains the precision of big.Int comparisons while still being clear and readable.

x/evm/precompile/oracle.go (1)

Line range hint 75-77: Fix Inconsistent Error Message for Argument Count

The error message in decomposeQueryExchangeRateArgs incorrectly states that 3 arguments are expected, whereas the function checks for exactly 1 argument. This mismatch can lead to confusion when debugging.

Apply this diff to correct the error message:

	if len(args) != 1 {
-		err = fmt.Errorf("expected 3 arguments but got %d", len(args))
+		err = fmt.Errorf("expected 1 argument but got %d", len(args))
		return
	}
x/evm/statedb/journal.go (1)

165-165: Remove Debug Print Statement

The fmt.Printf("TODO: UD-DEBUG: PrecompileSnapshotBeforeRun.Revert called\n") statement appears to be a debug print left in the code. It's advisable to remove this to prevent unnecessary console output in production.

Apply this diff to remove the debug statement:

-	fmt.Printf("TODO: UD-DEBUG: PrecompileSnapshotBeforeRun.Revert called\n")
x/evm/evmtest/tx.go (2)

23-24: Organize Import Statements

The import statements at lines 23-24 could be organized for better readability by grouping them logically (standard library packages, third-party packages, and project-specific packages).

Apply this diff to reorganize the imports:

 import (
+	"encoding/json"
+	"fmt"
+	"math/big"
+	"testing"
+
+	"github.com/cosmos/cosmos-sdk/crypto/keyring"
+	sdkmath "cosmossdk.io/math"
+
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	gethcommon "github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/common/hexutil"
+	gethcore "github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/crypto"
+	gethparams "github.com/ethereum/go-ethereum/params"
+	"github.com/stretchr/testify/require"
+
+	srvconfig "github.com/NibiruChain/nibiru/v2/app/server/config"
+	"github.com/NibiruChain/nibiru/v2/x/evm"
+	"github.com/NibiruChain/nibiru/v2/x/evm/embeds"
+	"github.com/NibiruChain/nibiru/v2/x/evm/statedb"
 )

Line range hint 267-301: Improve Documentation and Error Handling in GenerateEthTxMsgAndSigner

The function GenerateEthTxMsgAndSigner can benefit from enhanced documentation and consistent error handling.

  • Update the function comments to match Go documentation conventions.
  • Ensure all error returns provide context.

Apply this diff to improve the documentation:

 // GenerateEthTxMsgAndSigner estimates gas, sets gas limit, and returns the Ethereum transaction message and signers.
 //
 // Usage:
 //
 //	```go
 //	evmTxMsg, gethSigner, krSigner, err := GenerateEthTxMsgAndSigner(
 //	    jsonTxArgs, deps, sender,
 //	)
 //	err := evmTxMsg.Sign(gethSigner, sender.KeyringSigner)
 //	```
 func GenerateEthTxMsgAndSigner(
 	jsonTxArgs evm.JsonTxArgs, deps *TestDeps, sender EthPrivKeyAcc,
 ) (evmTxMsg *evm.MsgEthereumTx, gethSigner gethcore.Signer, krSigner keyring.Signer, err error) {
 	estimateArgs, err := json.Marshal(&jsonTxArgs)
 	if err != nil {
 		return nil, nil, nil, fmt.Errorf("failed to marshal jsonTxArgs: %w", err)
 	}
 	res, err := deps.App.EvmKeeper.EstimateGas(
 		sdk.WrapSDKContext(deps.Ctx),
 		&evm.EthCallRequest{
 			Args:            estimateArgs,
 			GasCap:          srvconfig.DefaultEthCallGasLimit,
 			ProposerAddress: []byte{},
 			ChainId:         deps.App.EvmKeeper.EthChainID(deps.Ctx).Int64(),
 		},
 	)
 	if err != nil {
 		return nil, nil, nil, fmt.Errorf("failed to estimate gas: %w", err)
 	}
 	jsonTxArgs.Gas = (*hexutil.Uint64)(&res.Gas)

 	evmTxMsg = jsonTxArgs.ToMsgEthTx()
 	gethSigner = gethcore.LatestSignerForChainID(deps.App.EvmKeeper.EthChainID(deps.Ctx))
 	return evmTxMsg, gethSigner, sender.KeyringSigner, nil
 }
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 220-222: x/evm/evmtest/tx.go#L220-L222
Added lines #L220 - L222 were not covered by tests


[warning] 225-225: x/evm/evmtest/tx.go#L225
Added line #L225 was not covered by tests


[warning] 237-248: x/evm/evmtest/tx.go#L237-L248
Added lines #L237 - L248 were not covered by tests


[warning] 250-255: x/evm/evmtest/tx.go#L250-L255
Added lines #L250 - L255 were not covered by tests


[warning] 257-261: x/evm/evmtest/tx.go#L257-L261
Added lines #L257 - L261 were not covered by tests


[warning] 263-264: x/evm/evmtest/tx.go#L263-L264
Added lines #L263 - L264 were not covered by tests


[warning] 280-280: x/evm/evmtest/tx.go#L280
Added line #L280 was not covered by tests


[warning] 283-283: x/evm/evmtest/tx.go#L283
Added line #L283 was not covered by tests

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 3348e14 and 55f75c1.

📒 Files selected for processing (18)
  • CHANGELOG.md (1 hunks)
  • x/evm/evmtest/erc20.go (1 hunks)
  • x/evm/evmtest/test_deps.go (2 hunks)
  • x/evm/evmtest/tx.go (6 hunks)
  • x/evm/keeper/erc20.go (1 hunks)
  • x/evm/keeper/funtoken_from_coin_test.go (1 hunks)
  • x/evm/keeper/funtoken_from_erc20_test.go (5 hunks)
  • x/evm/logs.go (0 hunks)
  • x/evm/logs_test.go (1 hunks)
  • x/evm/precompile/funtoken.go (3 hunks)
  • x/evm/precompile/funtoken_test.go (3 hunks)
  • x/evm/precompile/oracle.go (2 hunks)
  • x/evm/precompile/precompile.go (3 hunks)
  • x/evm/precompile/wasm.go (2 hunks)
  • x/evm/statedb/interfaces.go (1 hunks)
  • x/evm/statedb/journal.go (8 hunks)
  • x/evm/statedb/state_object.go (1 hunks)
  • x/evm/statedb/statedb.go (4 hunks)
💤 Files with no reviewable changes (1)
  • x/evm/logs.go
🧰 Additional context used
🪛 GitHub Check: codecov/patch
x/evm/evmtest/test_deps.go

[warning] 60-61: x/evm/evmtest/test_deps.go#L60-L61
Added lines #L60 - L61 were not covered by tests

x/evm/evmtest/tx.go

[warning] 129-131: x/evm/evmtest/tx.go#L129-L131
Added lines #L129 - L131 were not covered by tests


[warning] 161-161: x/evm/evmtest/tx.go#L161
Added line #L161 was not covered by tests


[warning] 166-166: x/evm/evmtest/tx.go#L166
Added line #L166 was not covered by tests


[warning] 170-171: x/evm/evmtest/tx.go#L170-L171
Added lines #L170 - L171 were not covered by tests


[warning] 174-174: x/evm/evmtest/tx.go#L174
Added line #L174 was not covered by tests


[warning] 184-184: x/evm/evmtest/tx.go#L184
Added line #L184 was not covered by tests


[warning] 220-222: x/evm/evmtest/tx.go#L220-L222
Added lines #L220 - L222 were not covered by tests


[warning] 225-225: x/evm/evmtest/tx.go#L225
Added line #L225 was not covered by tests


[warning] 237-248: x/evm/evmtest/tx.go#L237-L248
Added lines #L237 - L248 were not covered by tests


[warning] 250-255: x/evm/evmtest/tx.go#L250-L255
Added lines #L250 - L255 were not covered by tests


[warning] 257-261: x/evm/evmtest/tx.go#L257-L261
Added lines #L257 - L261 were not covered by tests


[warning] 263-264: x/evm/evmtest/tx.go#L263-L264
Added lines #L263 - L264 were not covered by tests


[warning] 280-280: x/evm/evmtest/tx.go#L280
Added line #L280 was not covered by tests


[warning] 283-283: x/evm/evmtest/tx.go#L283
Added line #L283 was not covered by tests


[warning] 295-295: x/evm/evmtest/tx.go#L295
Added line #L295 was not covered by tests


[warning] 299-301: x/evm/evmtest/tx.go#L299-L301
Added lines #L299 - L301 were not covered by tests

x/evm/precompile/funtoken.go

[warning] 66-67: x/evm/precompile/funtoken.go#L66-L67
Added lines #L66 - L67 were not covered by tests


[warning] 69-70: x/evm/precompile/funtoken.go#L69-L70
Added lines #L69 - L70 were not covered by tests

x/evm/precompile/precompile.go

[warning] 143-145: x/evm/precompile/precompile.go#L143-L145
Added lines #L143 - L145 were not covered by tests


[warning] 163-164: x/evm/precompile/precompile.go#L163-L164
Added lines #L163 - L164 were not covered by tests


[warning] 168-170: x/evm/precompile/precompile.go#L168-L170
Added lines #L168 - L170 were not covered by tests


[warning] 173-174: x/evm/precompile/precompile.go#L173-L174
Added lines #L173 - L174 were not covered by tests

x/evm/precompile/wasm.go

[warning] 104-105: x/evm/precompile/wasm.go#L104-L105
Added lines #L104 - L105 were not covered by tests

x/evm/statedb/journal.go

[warning] 161-172: x/evm/statedb/journal.go#L161-L172
Added lines #L161 - L172 were not covered by tests


[warning] 175-176: x/evm/statedb/journal.go#L175-L176
Added lines #L175 - L176 were not covered by tests

x/evm/statedb/statedb.go

[warning] 512-519: x/evm/statedb/statedb.go#L512-L519
Added lines #L512 - L519 were not covered by tests


[warning] 525-532: x/evm/statedb/statedb.go#L525-L532
Added lines #L525 - L532 were not covered by tests

🪛 Gitleaks
x/evm/statedb/statedb.go

529-529: Identified a Vault Service Token, potentially compromising infrastructure security and access to sensitive credentials.

(vault-service-token)

🔇 Additional comments (29)
x/evm/statedb/interfaces.go (1)

17-17: Approve the change to AppendJournalEntry method signature.

The change from JournalEntry to JournalChange aligns with the PR objectives and the broader restructuring of the statedb package. This semantic shift in representing journal entries should improve clarity and maintainability.

To ensure this change doesn't introduce any inconsistencies, please run the following script to verify that all implementations and usages of ExtStateDB have been updated accordingly:

x/evm/evmtest/test_deps.go (1)

4-5: LGTM! Consider indirect testing for the new method.

The addition of the GoCtx() method is a valuable enhancement to the TestDeps struct, providing a convenient way to obtain a context.Context from the existing sdk.Context. This change improves compatibility with Go's standard library and other packages that expect a context.Context.

While direct unit tests may not be necessary for this test utility file, it's important to ensure that the new method is indirectly tested through its usage in other test files. This will help maintain the reliability of the testing infrastructure.

To verify the usage and indirect testing of the new GoCtx() method, you can run the following script:

If the script doesn't return any results, consider adding usage of GoCtx() in relevant test files to ensure it's working as expected.

Would you like assistance in adding example usage or indirect tests for the GoCtx() method?

Also applies to: 59-62

✅ Verification successful

Verified! The GoCtx() method is properly utilized in existing test files, ensuring adequate test coverage through indirect testing.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of the new GoCtx() method in test files

# Test: Search for usage of GoCtx() method in test files
rg -t go --glob '*_test.go' 'GoCtx\(\)'

Length of output: 687

x/evm/logs_test.go (1)

196-199: LGTM! Consider verifying consistency across the codebase.

The changes improve clarity by directly initializing the evm.TransactionLogs struct and ensure a consistent hexadecimal representation of the hash. This is a good refactor.

To ensure consistency, please run the following script to check for any other occurrences of NewTransactionLogs that might need similar updates:

x/evm/precompile/funtoken_test.go (4)

8-8: LGTM: Improved import alias for clarity.

Renaming the Ethereum common package import to gethcommon is a good practice. It helps avoid potential naming conflicts and makes the code more readable by clearly indicating the source of the imported package.


52-52: LGTM: Consistent updates to use renamed import.

The changes in the TestFailToPackABI function correctly use the renamed gethcommon package for address conversion. This maintains consistency with the import changes and doesn't alter the test logic.

Also applies to: 58-58, 64-64


136-136: LGTM: Added VM error check.

The addition of s.Require().Empty(resp.VmError) is a valuable improvement. It ensures that the VM didn't encounter any errors during the contract call, adding an extra layer of validation to the test.


Line range hint 1-142: Overall assessment: Well-structured and improved test file.

The changes in this file are consistent and improve the quality of the tests. The renaming of imports, updates to function calls, and modifications in assertions enhance clarity and robustness. The suggestions provided are minor and aimed at further improving readability and maintainability.

x/evm/keeper/funtoken_from_erc20_test.go (3)

163-163: LGTM: Improved function name clarity

The function name change from TestSendFromEvmToCosmos to TestSendFromEvmToBank accurately reflects the test's purpose and aligns with the PR objectives. This change improves code clarity and maintainability.


Line range hint 249-267: LGTM: Consistent refactoring and comprehensive balance checks

The changes in this section maintain consistency with the overall refactoring from "Cosmos" to "Bank". The test logic remains intact, ensuring continued coverage of the coin conversion functionality. The balance checks are comprehensive, covering both ERC20 and Bank balances, which is crucial for verifying the correctness of the conversion process.


Line range hint 1-290: Overall assessment: Improved test coverage and clarity

The changes in this file consistently refactor the terminology from "Cosmos" to "Bank", improving clarity and accurately representing the modules being tested. The addition of new error cases for both sending tokens to Bank and converting tokens back to ERC20 significantly enhances the test coverage, ensuring robust error handling in both directions.

The modifications align well with the PR objectives of addressing issues related to the EVM StateDB and improve the overall quality of the test suite. The suggested minor improvements in error checking and logging will further enhance the test robustness and debuggability.

Great job on maintaining and improving the test suite!

x/evm/statedb/state_object.go (2)

175-175: Improved clarity in balance change tracking

The renaming of prev to prevWei in the balanceChange struct is a good improvement. It explicitly indicates that the previous balance is stored in Wei, which is consistent with the AccountWei representation used in the EVM context. This change enhances code readability and reduces potential confusion about the unit of the stored balance.


Line range hint 1-292: Well-structured implementation of Ethereum account state management

The overall implementation of Ethereum account state management in this file is well-structured and follows good practices. Key points:

  1. Clear separation between native (unibi) and Wei balance representations.
  2. Comprehensive methods for managing account attributes (balance, nonce, code, storage).
  3. Efficient use of caching and dirty state tracking.
  4. Proper journaling for state changes, allowing for reverting and snapshotting.

The code demonstrates a good understanding of EVM requirements and Cosmos SDK integration. Keep up the good work!

CHANGELOG.md (7)

Line range hint 15-136: Comprehensive update to the Unreleased section

The Unreleased section has been significantly expanded with a wide range of changes, including new features, improvements, bug fixes, and dependency updates. This level of detail is excellent for tracking the project's progress and upcoming changes.

Some notable additions include:

  • Numerous improvements to the Ethereum Virtual Machine (EVM) integration
  • Updates to various modules such as oracle, perp, and devgas
  • Multiple dependency updates

Line range hint 138-141: Clear versioning and release information

The changelog properly follows the Keep a Changelog format and adheres to Semantic Versioning. This is good practice and helps users understand the nature of changes between versions.


Line range hint 143-306: Detailed breakdown of changes for v1.0.0

The changelog for v1.0.0 is well-organized and comprehensive, covering various aspects of the release including features, state machine breaking changes, and improvements. This level of detail is very helpful for users and developers.


Line range hint 308-374: Thorough documentation of changes for v0.21.11 and v0.21.10

These sections provide a good overview of the changes in these versions, including links to specific pull requests. This level of detail helps in tracking the evolution of the project.


Line range hint 376-706: Comprehensive changelog for v0.19.4 and earlier versions

The changelog continues to provide detailed information about changes, improvements, and bug fixes for earlier versions. This historical record is valuable for understanding the project's development over time.


Line range hint 708-1120: Consistent format and detail level maintained for older versions

The changelog maintains a consistent format and level of detail even for older versions, which is commendable. It shows a commitment to good documentation practices throughout the project's history.


Line range hint 1-1120: Overall assessment of CHANGELOG.md

This CHANGELOG.md file is exemplary in its structure, consistency, and level of detail. It effectively communicates the project's evolution over time, making it easier for users and developers to understand changes between versions.

Minor suggestions for improvement:

  1. Consider adding links to relevant issues or pull requests for each change, where applicable, to provide more context.
  2. For future entries, you might want to standardize the formatting of pull request numbers (e.g., always use the #XXX format).
x/evm/precompile/oracle.go (3)

27-27: Gas Calculation Now Utilizes Oracle ABI

The RequiredGas function correctly calculates the gas requirement based on the input and the Oracle contract's ABI. This dynamic approach ensures that gas estimation is accurate for different function calls.


40-41: Improved Error Handling with Deferred Function

The use of defer ErrPrecompileRun(err, p)() enhances the error handling mechanism by ensuring that any panic or error within the Run method is properly captured and reported. This aligns with best practices for robust error management.


45-45: Simplified Retrieval of Method, Args, and Context

Assigning method, args, ctx from the result of OnRunStart improves code readability and maintains consistency with the new context management pattern introduced in the precompile package.

x/evm/precompile/funtoken.go (2)

34-34: Improved gas calculation in RequiredGas function

The RequiredGas function now accurately calculates the gas cost using the contract's ABI, enhancing precision in gas estimation.


47-54: Refactored error handling and initialization in Run method

The introduction of ErrPrecompileRun(err, p)() in the defer statement and the use of OnRunStart streamline error handling and improve code readability in the Run method.

x/evm/precompile/precompile.go (1)

172-174: Handle error during context commit appropriately

In the OnRunStart function, if stateDB.CommitContext(cacheCtx) returns an error, you wrap it and return. Ensure that any necessary cleanup or state rollback is performed to maintain consistency, as failing to commit could leave the system in an unpredictable state.

Please verify if additional steps are needed to safely handle this error scenario. If cleanup is required, consider implementing it to prevent potential issues.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 173-174: x/evm/precompile/precompile.go#L173-L174
Added lines #L173 - L174 were not covered by tests

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

269-276: Well-Documented Explanation of Access List Reversion

The additional comments clearly explain how accessListAddAccountChange and accessListAddSlotChange interact during reversion. This enhances the readability and maintainability of the code.

x/evm/evmtest/tx.go (2)

174-174: Check for VM Errors After Transaction Execution

After executing the Ethereum transaction, it's good practice to check for VM errors and handle them appropriately.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 174-174: x/evm/evmtest/tx.go#L174
Added line #L174 was not covered by tests


225-225: Check for VM Errors After Transaction Execution

After executing the transaction, check for any VM errors to ensure the transaction was successful.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 225-225: x/evm/evmtest/tx.go#L225
Added line #L225 was not covered by tests

x/evm/precompile/wasm.go (1)

75-75: Adoption of ErrPrecompileRun Enhances Error Handling

The introduction of ErrPrecompileRun in the Run method improves error handling by providing structured error context without relying on reflection.

Comment on lines +66 to +67
return nil, err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add unit tests for critical error handling paths

Static analysis indicates that lines 66-67 and 69-70 are not covered by tests. These error handling paths are crucial for ensuring robustness. Please consider adding unit tests to cover these scenarios and prevent potential regressions.

Would you like assistance in creating unit tests for these error conditions?

Also applies to: 69-70

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 66-67: x/evm/precompile/funtoken.go#L66-L67
Added lines #L66 - L67 were not covered by tests

x/evm/precompile/precompile.go Outdated Show resolved Hide resolved
x/evm/precompile/precompile.go Show resolved Hide resolved
x/evm/statedb/journal.go Outdated Show resolved Hide resolved
x/evm/statedb/journal.go Outdated Show resolved Hide resolved
x/evm/statedb/statedb.go Show resolved Hide resolved
x/evm/statedb/statedb.go Outdated Show resolved Hide resolved
x/evm/statedb/statedb.go Outdated Show resolved Hide resolved
x/evm/statedb/statedb.go Outdated Show resolved Hide resolved
x/evm/statedb/statedb.go Outdated Show resolved Hide resolved
Copy link
Contributor

@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 (6)
CHANGELOG.md (5)

Line range hint 43-139: The "Unreleased" section provides a comprehensive overview of recent changes, but could benefit from some structural improvements.

The organization of changes into "Nibiru EVM", "State Machine Breaking (Other)", and "Non-breaking/Compatible Improvements" is helpful for users to understand the impact of changes. However, consider the following suggestions:

  1. Add dates to the "Before Audit 2" and "Before Audit 1" subsections to provide better context for when these changes occurred.
  2. Ensure consistency in the formatting of pull request links. Some entries use full URLs while others use the shorter #XXXX format.
  3. Consider grouping similar changes together within each section for easier readability.

Line range hint 139-185: The "State Machine Breaking (Other)" section could benefit from clearer organization and labeling.

While it's good to separate state machine breaking changes, consider the following improvements:

  1. Clearly label each change as "BREAKING" at the beginning of the line for easy identification.
  2. Consider merging the "For next mainnet version" and "Dapp modules" subsections if there's significant overlap in the types of changes.
  3. Provide more context on the impact of these breaking changes, especially for major refactors like removing modules or changing data structures.

Line range hint 187-236: The "Non-breaking/Compatible Improvements" section could be better organized for readability.

To improve this section:

  1. Consider categorizing changes into subsections such as "Features", "Refactoring", "Testing", and "Dependencies".
  2. Ensure consistent formatting for pull request references (e.g., always use the #XXXX format).
  3. For dependency updates, consider grouping them together in a separate subsection or at the end of this section.

These changes would make it easier for users to quickly scan and understand the nature of the improvements.


Line range hint 238-284: The "Dependencies" section needs cleanup and a more concise format.

To improve this section:

  1. Remove duplicate entries (e.g., entries for github.com/CosmWasm/wasmvm, google.golang.org/grpc, etc.).
  2. Consider using a table format or a more concise list for dependency updates, including the package name, version change, and PR number.
  3. Group similar updates together (e.g., all GitHub Actions related updates).

Example format:

- github.com/CosmWasm/wasmvm: 1.2.1 -> 1.4.0 (#1354, #1507, #1564)
- google.golang.org/grpc: 1.53.0 -> 1.58.2 (#1395, #1437, #1443, #1497, #1525, #1568, #1582, #1598)

This would make the section more readable and eliminate redundancy.


Line range hint 286-1037: The previous release entries are well-structured, but could benefit from some minor improvements for consistency.

Positive aspects:

  1. Including links to releases and commits is excellent for traceability.
  2. Categorizing changes (e.g., "Features", "Bug Fixes", "Improvements") helps users quickly understand the nature of changes.

Suggestions for improvement:

  1. Maintain consistent section headers across all releases. For example, some releases use "API Breaking" while others use "Breaking Changes".
  2. Consider adding a brief summary of key changes at the beginning of each release entry, especially for major versions.
  3. Ensure all pull request references use the same format (preferably the #XXXX format for consistency and brevity).

Overall, the changelog provides a comprehensive history of changes, which is crucial for users and developers. Implementing these minor improvements will enhance its readability and consistency.

x/evm/precompile/wasm.go (1)

103-105: Remove Redundant Error Check

The error check at lines 103-105 is redundant since any errors should already be handled within each case of the switch statement.

You can remove these lines to simplify the code:

if err != nil {
    return nil, err
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 55f75c1 and 516aece.

📒 Files selected for processing (3)
  • CHANGELOG.md (3 hunks)
  • x/evm/precompile/funtoken.go (3 hunks)
  • x/evm/precompile/wasm.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • x/evm/precompile/funtoken.go
🧰 Additional context used
🔇 Additional comments (1)
x/evm/precompile/wasm.go (1)

107-110: ⚠️ Potential issue

Add Error Handling for OnRunEnd

The error returned by OnRunEnd at line 107 is not being checked. This could lead to unhandled errors affecting state consistency.

Update the code to handle the error:

if err := OnRunEnd(res.StateDB, res.SnapshotBeforeRun, p.Address()); err != nil {
    return nil, err
}

Likely invalid or redundant comment.

x/evm/precompile/wasm.go Outdated Show resolved Hide resolved
x/evm/precompile/wasm.go Outdated Show resolved Hide resolved
x/evm/precompile/wasm.go Outdated Show resolved Hide resolved
Copy link
Contributor

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

🧹 Outside diff range and nitpick comments (10)
x/evm/precompile/errors.go (1)

12-22: Approve the addition of ErrPrecompileRun with minor suggestions.

The new ErrPrecompileRun function is a valuable addition that will standardize error handling for precompiled contracts. It effectively adds context to errors, which will aid in debugging. However, consider the following suggestions for improvement:

  1. The use of reflection might have a slight performance impact. If the set of precompiled contracts is known and limited, consider using a type switch or a map of type names instead.

  2. The function creates a new error rather than modifying the original. This approach might lead to loss of the original error's type information. Consider wrapping the original error instead of creating a new one.

Here's a potential refactoring to address these points:

func ErrPrecompileRun(err error, p vm.PrecompiledContract) func() {
	return func() {
		if err != nil {
			precompileType := getPrecompileTypeName(p)
			err = fmt.Errorf("precompile error: failed to run %s: %w", precompileType, err)
		}
	}
}

func getPrecompileTypeName(p vm.PrecompiledContract) string {
	switch p.(type) {
	case *PrecompileA:
		return "PrecompileA"
	case *PrecompileB:
		return "PrecompileB"
	// Add other precompile types here
	default:
		return reflect.TypeOf(p).Name()
	}
}

This refactoring suggestion maintains the use of reflection as a fallback, ensuring compatibility with any new precompile types that might be added in the future.

x/evm/precompile/precompile.go (3)

137-157: LGTM: Well-structured OnRunStartResult with clear documentation.

The OnRunStartResult struct is a well-designed addition that encapsulates all necessary information for precompile execution. It provides a clean interface for managing state, context, and execution details.

Consider adding a brief comment above the struct definition to explain its overall purpose and when it's used in the precompile execution flow.


159-212: LGTM: Well-implemented OnRunStart function with comprehensive setup.

The OnRunStart function effectively encapsulates the complex setup required for precompile execution. It handles input decoding, context creation, and state snapshot management in a clean and organized manner.

Consider wrapping the error returned from stateDB.CommitContext to provide more context:

if err = stateDB.CommitContext(cacheCtx); err != nil {
    return res, fmt.Errorf("failed to commit dirty journal entries to cache context: %w", err)
}

This will make debugging easier by providing more specific information about where the error occurred.


234-244: LGTM: Clear categorization of precompile methods.

The precompileMethodIsTxMap provides a concise and effective way to categorize precompile methods as transactions or queries. This is crucial for proper gas cost calculation and overall system behavior.

Consider adding a brief comment above the map explaining its purpose and how it's used in the RequiredGas function. This will improve maintainability and make it easier for future developers to understand the map's role in the system.

x/evm/precompile/wasm.go (2)

Line range hint 36-67: Improved error handling and execution flow in Run method.

The refactoring of the Run method enhances error handling and introduces a more structured approach to executing precompiled contracts. The use of OnRunStart and OnRunEnd improves the management of the execution lifecycle.

Consider wrapping the OnRunEnd call in a defer statement to ensure it's always called, even if an error occurs during the execution of the precompile logic:

 defer ErrPrecompileRun(err, p)()
 res, err := OnRunStart(evm, contract, p.ABI())
 if err != nil {
     return nil, err
 }
+defer func() {
+    if endErr := OnRunEnd(res.StateDB, res.SnapshotBeforeRun, p.Address()); endErr != nil {
+        err = endErr
+    }
+    res.WriteCtx()
+}()

 method, args, ctx := res.Method, res.Args, res.Ctx
 // ... rest of the method ...
-if err := OnRunEnd(res.StateDB, res.SnapshotBeforeRun, p.Address()); err != nil {
-    return nil, err
-}
-res.WriteCtx()
 return

This ensures that OnRunEnd is always called and the context is always written back, even if an error occurs during the execution of the precompile logic.


79-81: Added ABI method to precompileWasm struct.

The new ABI method provides a centralized way to access the ABI for the Wasm precompile. This addition improves consistency and makes it easier to update the ABI in the future.

Consider adding a brief comment to explain the purpose of this method:

+// ABI returns the Application Binary Interface (ABI) for the Wasm precompile contract.
 func (p precompileWasm) ABI() *gethabi.ABI {
     return embeds.SmartContract_Wasm.ABI
 }
x/evm/statedb/journal.go (1)

96-132: LGTM: PrecompileSnapshotBeforeRun implementation looks good.

The new PrecompileSnapshotBeforeRun struct and its methods are well-implemented and address the issue of reverting precompile changes that affect other modules. The comments provide a clear explanation of its purpose and functionality.

Consider the following suggestions for potential improvements:

  1. Add error handling or logging in the Revert method to capture any issues that might occur during the reversion process.
  2. Consider adding a method to create a new PrecompileSnapshotBeforeRun instance, which could include any necessary validation or initialization logic.
x/evm/statedb/statedb.go (3)

Line range hint 466-502: Improved context management and error handling in CommitContext

The renaming of Commit to CommitContext and the addition of the ctx parameter enhance flexibility in context management. The improved error handling is a positive change.

However, there's a minor issue in the error formatting:

Please update the error messages to include the original error:

-	return errorf("failed to delete account: %w")
+	return errorf("failed to delete account: %w", err)
-	return errorf("failed to set account: %w")
+	return errorf("failed to set account: %w", err)

496-502: Update function comments to match the 'Commit' method

The addition of the Commit method that calls CommitContext is good for maintaining backwards compatibility. However, the comments for this method should be updated to refer to [Commit] instead of [CommitContext].

Here's the suggested change:

-// Commit writes the dirty journal state changes to the EVM Keeper. The
-// StateDB object cannot be reused after [CommitContext] has completed. A new
-// object needs to be created from the EVM.
+// Commit writes the dirty journal state changes to the EVM Keeper. The
+// StateDB object cannot be reused after [Commit] has completed. A new
+// object needs to be created from the EVM.

513-523: Well-implemented caching mechanism for precompiles

The CacheCtxForPrecompile method is a good addition for managing caching contexts in precompiled contracts. It properly initializes the cache context and provides necessary components for state management.

Consider adding unit tests for this new method to ensure its correctness and prevent potential regressions in the future.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 516aece and 0374dfd.

📒 Files selected for processing (7)
  • x/evm/precompile/errors.go (1 hunks)
  • x/evm/precompile/oracle.go (1 hunks)
  • x/evm/precompile/oracle_test.go (2 hunks)
  • x/evm/precompile/precompile.go (2 hunks)
  • x/evm/precompile/wasm.go (2 hunks)
  • x/evm/statedb/journal.go (12 hunks)
  • x/evm/statedb/statedb.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • x/evm/precompile/oracle.go
🧰 Additional context used
🪛 Gitleaks
x/evm/statedb/statedb.go

540-540: Identified a Vault Service Token, potentially compromising infrastructure security and access to sensitive credentials.

(vault-service-token)

🔇 Additional comments (25)
x/evm/precompile/oracle_test.go (3)

30-30: LGTM: Consistent method name update.

This change aligns with the previous update, ensuring consistency across different test cases within the TestOracle_FailToPackABI function. The method name has been correctly updated to OracleMethod_queryExchangeRate.


67-67: LGTM: Consistent method name update in ABI unpacking.

The change from OracleMethod_QueryExchangeRate to OracleMethod_queryExchangeRate in the TestOracle_HappyPath function maintains consistency with the previous updates. This ensures that the method name used for unpacking the ABI response aligns with the updated method name used elsewhere in the codebase.


Line range hint 24-67: Summary: Consistent method name updates across test cases.

The changes in this file consistently update the method name from OracleMethod_QueryExchangeRate to OracleMethod_queryExchangeRate across different test functions and use cases. These updates improve alignment between the test file and the implementation file, enhancing overall code consistency without altering the functional behavior of the tests.

x/evm/precompile/errors.go (1)

12-22: Document usage and ensure consistent application of ErrPrecompileRun.

The introduction of ErrPrecompileRun is a positive step towards standardizing error handling for precompiled contracts. To maximize its benefits:

  1. Consider adding a comment explaining the intended usage pattern, e.g.:

    // ErrPrecompileRun is intended to be used in a defer pattern:
    // defer ErrPrecompileRun(err, p)()
  2. Ensure that this function is consistently used across all precompiled contract implementations in the codebase.

To verify consistent usage, you can run the following script:

This script will help identify any precompiled contracts that might not be using the new error handling mechanism.

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

27-30: LGTM: Import additions are appropriate.

The new imports for sdk and statedb are necessary and correctly align with the new functionality introduced in this file.


214-232: LGTM: Well-implemented OnRunEnd function for state consistency.

The OnRunEnd function is a crucial addition that ensures proper state management after precompile execution. It effectively handles saving the state snapshot to the journal, which is essential for maintaining consistency across various scenarios, including reverts and multi-precompile transactions.

The implementation and documentation are clear and comprehensive.


Line range hint 1-244: Overall assessment: Significant improvements in precompile execution management

The changes introduced in this file represent a substantial enhancement to the precompile package. The new OnRunStartResult struct, along with the OnRunStart and OnRunEnd functions, provide a robust framework for managing precompile execution, state isolation, and consistency. The code is well-structured, thoroughly documented, and introduces important safeguards against potential state inconsistencies.

Key improvements:

  1. Better encapsulation of precompile execution setup and teardown.
  2. Improved state management and isolation.
  3. Clear categorization of precompile methods for gas cost calculation.

While the implementation is solid, consider addressing the following to further enhance the code:

  1. Add brief comments explaining the overall purpose of new structures and maps.
  2. Improve error wrapping in some areas for better debugging.
  3. Ensure comprehensive test coverage, especially for critical error paths.

These changes significantly improve the robustness and maintainability of the precompile package.


159-212: Increase test coverage for critical error paths

While the implementation of OnRunStart looks solid, it's important to ensure that all critical error paths are covered by tests. This includes scenarios such as:

  1. Failure to decode input
  2. Failure to load the SDK context from the EVM StateDB
  3. Failure to commit dirty journal entries

Adding comprehensive unit tests for these scenarios will improve the robustness and reliability of the precompile execution flow.

To help verify the current test coverage, you can run the following command:

This will show the current test coverage for the OnRunStart function. If the coverage is below 80%, consider adding more test cases to cover the critical error paths.

x/evm/precompile/wasm.go (3)

71-73: Simplified precompileWasm struct definition.

The precompileWasm struct has been streamlined to contain only a Wasm field. This simplification suggests improved encapsulation of functionality within the Wasm type.


75-77: Added Address method to precompileWasm struct.

The new Address method provides a clear way to obtain the precompile's address. This addition improves code readability and maintainability by centralizing the address definition.


83-86: Updated RequiredGas method to use ABI method.

The RequiredGas method now uses p.ABI() instead of directly accessing embeds.SmartContract_Wasm.ABI. This change improves consistency and maintainability by centralizing the ABI access.

x/evm/statedb/journal.go (11)

24-25: LGTM: New imports added correctly.

The new imports for store and sdk from the Cosmos SDK are correctly added and aliased. These are likely necessary for the new PrecompileSnapshotBeforeRun functionality.


Line range hint 29-37: LGTM: JournalEntry renamed to JournalChange.

The renaming of JournalEntry to JournalChange is consistent and provides a clearer description of the interface's purpose. The updated comment accurately reflects this change while maintaining clarity about the interface's functionality.


43-43: LGTM: Journal entries type updated.

The entries field in the journal struct has been correctly updated to use []JournalChange, maintaining consistency with the interface renaming.


67-67: LGTM: Append method parameter type updated.

The append method's parameter type has been correctly updated from JournalEntry to JournalChange, maintaining consistency with the interface renaming.


Line range hint 134-152: LGTM: createObjectChange implementation is correct.

The createObjectChange struct and its methods are well-implemented. The Revert method correctly deletes the state object for the account, and the Dirtied method returns the appropriate address. The comment clearly explains the purpose of this struct.


Line range hint 153-172: LGTM: resetObjectChange implementation is correct.

The resetObjectChange struct and its methods are well-implemented. The Revert method correctly sets the state object to its previous version, and the Dirtied method appropriately returns nil. The comment clearly explains the purpose of this struct.


Line range hint 173-214: LGTM: suicideChange and balanceChange updates improve clarity and functionality.

The updates to suicideChange and balanceChange structs are well-implemented:

  1. The addition of prevbalance to suicideChange allows for more accurate state reversion.
  2. Renaming prev to prevWei in balanceChange improves clarity.

These changes are consistent with the overall refactoring and enhance the functionality of the journal system.


Line range hint 215-275: LGTM: nonceChange, codeChange, and storageChange implementations are correct and consistent.

The new nonceChange, codeChange, and storageChange structs are well-implemented:

  1. Each struct correctly implements the JournalChange interface.
  2. The Revert methods appropriately restore the previous state.
  3. The Dirtied methods return the correct account address.

The comments clearly explain the purpose of each struct, maintaining consistency with the overall design of the journal system.


Line range hint 276-311: LGTM: refundChange and addLogChange implementations are correct and consistent.

The new refundChange and addLogChange structs are well-implemented:

  1. Both correctly implement the JournalChange interface.
  2. The Revert methods appropriately handle their respective state changes.
  3. The Dirtied methods correctly return nil as these changes don't affect specific accounts.

The comments clearly explain the purpose of each struct, maintaining consistency with the overall design of the journal system.


Line range hint 312-357: LGTM: accessListAddAccountChange and accessListAddSlotChange implementations are correct and well-documented.

The new accessListAddAccountChange and accessListAddSlotChange structs are well-implemented:

  1. Both correctly implement the JournalChange interface.
  2. The Revert methods appropriately handle their respective access list changes.
  3. The Dirtied methods correctly return nil as these changes don't affect account state directly.

The comments provide clear explanations of each struct's purpose and the relationship between them, which is particularly helpful for understanding the two-step process of adding an (address, slot) combination to the access list.


Line range hint 1-357: Overall: Excellent refactoring and extension of the journal system.

The changes in this file significantly improve the journal system:

  1. Renaming JournalEntry to JournalChange provides better clarity on the interface's purpose.
  2. New structs for various state changes (e.g., PrecompileSnapshotBeforeRun, createObjectChange, resetObjectChange, etc.) enhance the system's ability to handle different types of state modifications.
  3. Consistent implementation of the JournalChange interface across all new structs ensures a uniform approach to state reversion.
  4. Clear and detailed comments throughout the file explain the purpose and functionality of each new component.

These changes should result in a more robust and flexible state management system for the EVM implementation.

x/evm/statedb/statedb.go (3)

33-47: Excellent additions to enhance StateDB functionality

The new fields cacheCtx, writeCacheCtxFn, and precompileSnapshotsCount along with their clear explanations improve the StateDB struct's capability to handle precompiled contracts and caching. These changes appear to be well-thought-out and properly documented.


Line range hint 1-546: Overall excellent improvements to StateDB

The changes in this file significantly enhance the functionality of StateDB for handling precompiled contracts and improving state management. The new methods and fields are well-documented and align with the PR objectives.

Key improvements:

  1. Enhanced context management with CacheCtxForPrecompile
  2. Improved state management for precompiled contracts with SavePrecompileSnapshotToJournal
  3. Better error handling in the CommitContext method

Suggestions for further improvement:

  1. Add unit tests for the new methods CacheCtxForPrecompile and SavePrecompileSnapshotToJournal
  2. Consider making maxPrecompileCalls configurable
  3. Update comments for the Commit method to differentiate it from CommitContext

Overall, these changes represent a significant improvement to the codebase.

🧰 Tools
🪛 Gitleaks

540-540: Identified a Vault Service Token, potentially compromising infrastructure security and access to sensitive credentials.

(vault-service-token)


525-544: Robust implementation of precompile snapshot management

The SavePrecompileSnapshotToJournal method is a well-implemented addition that enhances state management for precompiled contracts. The limit check on precompileSnapshotsCount is a good safeguard against potential abuse.

Consider adding unit tests for this new method to ensure its correctness and prevent potential regressions.

The static analysis tool flagged a potential Vault Service Token on line 540. While this appears to be a false positive (as the line contains a comparison against maxPrecompileCalls), it's worth double-checking to ensure no sensitive information is inadvertently included. Please run the following command to verify:

🧰 Tools
🪛 Gitleaks

540-540: Identified a Vault Service Token, potentially compromising infrastructure security and access to sensitive credentials.

(vault-service-token)

x/evm/statedb/statedb.go Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
x/evm/precompile/oracle.go (1)

Inconsistent error message for expected arguments

The error message in x/evm/precompile/oracle.go still expects 3 arguments instead of 1. Please update all related error messages to ensure consistency.

  • x/evm/precompile/oracle.go: expected 3 arguments but got %d
🔗 Analysis chain

Line range hint 93-93: Corrected error message in decomposeQueryExchangeRateArgs

The error message has been updated to correctly state the expected number of arguments (1 instead of 3). This improves the accuracy of error reporting and will help developers debug issues more effectively.

To ensure consistency, please run the following command to check for any similar error messages that might need updating:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar error messages about expected arguments
rg "expected \d+ arguments but got"

Length of output: 129

x/evm/precompile/wasm.go (2)

73-75: Approve simplified precompileWasm struct with a suggestion for documentation.

The simplification of the precompileWasm struct improves code clarity. However, adding documentation would enhance understanding of its purpose and usage.

Consider adding a comment to explain the purpose of the precompileWasm struct and its Wasm field. For example:

// precompileWasm represents a precompiled contract for WebAssembly (Wasm) execution in the EVM.
type precompileWasm struct {
    // Wasm contains the necessary components for Wasm contract operations.
    Wasm Wasm
}

97-104: Approve update to PrecompileWasm function with a suggestion for return type.

The modification to return a precompileWasm struct aligns with the updated struct definition and ensures proper implementation of the vm.PrecompiledContract interface.

Consider updating the function signature to explicitly return precompileWasm for improved clarity:

func PrecompileWasm(keepers keepers.PublicKeepers) precompileWasm {
    // ... (existing implementation)
}

This change makes it clear that the function returns a specific implementation of vm.PrecompiledContract.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0374dfd and 8d7fcd3.

📒 Files selected for processing (4)
  • x/evm/precompile/errors.go (1 hunks)
  • x/evm/precompile/funtoken.go (3 hunks)
  • x/evm/precompile/oracle.go (1 hunks)
  • x/evm/precompile/wasm.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • x/evm/precompile/errors.go
  • x/evm/precompile/funtoken.go
🧰 Additional context used
🔇 Additional comments (6)
x/evm/precompile/oracle.go (3)

27-27: Improved gas calculation for precompiled contract

The update to use RequiredGas(input, embeds.SmartContract_Oracle.ABI) is a good improvement. This change allows for more accurate and dynamic gas calculation based on the contract's ABI, which is a best practice for precompiled contracts.


39-51: Improved error handling and method execution in Run

The changes in the Run method are well-implemented:

  1. The new error handling using ErrPrecompileRun simplifies the code and improves consistency.
  2. The introduction of OnRunStart centralizes common operations, enhancing maintainability.
  3. The switch case update aligns with the constant name change, maintaining consistency.

These improvements enhance the overall structure and readability of the code.


31-31: Naming convention update for Oracle method constant

The renaming of OracleMethod_QueryExchangeRate to OracleMethod_queryExchangeRate improves consistency with Go naming conventions for constants. This is a good change.

To ensure consistency across the codebase, please run the following command to check for any remaining occurrences of the old name:

x/evm/precompile/wasm.go (3)

77-83: Approve new Address and ABI methods.

The addition of Address() and ABI() methods enhances the functionality of the precompileWasm struct, aligning it with the vm.PrecompiledContract interface requirements.

As mentioned in a previous review comment, please add documentation to the ABI() method to improve code readability and maintainability.


85-88: Approve update to RequiredGas method.

The modification to use p.ABI() instead of directly accessing embeds.SmartContract_Wasm.ABI improves consistency and maintainability by centralizing ABI access through the ABI() method.


Line range hint 37-69: Approve changes to the Run method with a suggestion for verification.

The refactoring of the Run method improves error handling and introduces a more structured approach to running precompiles. The use of OnRunStart and OnRunEnd functions enhances execution management and state consistency.

Please verify that all callers of this method have been updated to handle the removal of the bz []byte return value. Run the following script to find potential callers:

✅ Verification successful

Verified: No external callers of precompileWasm.Run found.

The Run method in precompileWasm is only invoked within test files. There are no production code dependencies affected by the removal of the bz []byte return value.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find potential callers of the Run method
rg -i 'precompileWasm.*Run\s*\(' -g '!x/evm/precompile/wasm.go'

Length of output: 65


Script:

#!/bin/bash
# Broader search for Run method invocations
rg -i 'Run\s*\('

# Use ast-grep to find method calls to Run on precompileWasm
ast-grep 'precompileWasm.Run($_)' --lang go

Length of output: 17267


Script:

#!/bin/bash
# Correct usage of ast-grep to find method calls to Run on precompileWasm
ast-grep 'precompileWasm.Run($_)' --lang go

# Alternatively, use rg with a more precise pattern to match method receivers
rg -i 'precompileWasm\.Run\s*\('

Length of output: 200

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (12)
x/evm/evmtest/erc20.go (1)

103-107: Approve the addition of BigPow function with a minor suggestion.

The BigPow function is a useful utility for EVM-related calculations, especially when dealing with token amounts and decimals. Its implementation is correct and efficient.

Consider adding a simple example in the function's comment to illustrate its usage:

// BigPow multiplies "amount" by 10 to the "pow10Exp".
// For example, BigPow(big.NewInt(5), 18) returns 5 * 10^18.
func BigPow(amount *big.Int, pow10Exp uint8) (powAmount *big.Int) {
    // ... (existing implementation)
}

This addition would enhance the function's documentation and make it more developer-friendly.

x/evm/errors.go (1)

77-87: Improved error handling, with minor suggestions for further enhancement.

The changes to NewExecErrorWithReason function significantly improve error handling and provide more consistent and informative error messages. The new approach handles different scenarios effectively, including cases where unpacking fails but a result is still available.

Consider the following minor improvements:

  1. Move the reason variable declaration inside the first if block since it's only used there:
 errPrefix := "execution reverted"
 if errUnpack == nil {
+    reason, _ := abi.UnpackRevert(result)
     reasonStr := reason
     err = fmt.Errorf("%s with reason \"%v\"", errPrefix, reasonStr)
 } else if string(result) != "" {
  1. Differentiate error messages for unpacked and raw results:
 if errUnpack == nil {
     reason, _ := abi.UnpackRevert(result)
-    err = fmt.Errorf("%s with reason \"%v\"", errPrefix, reasonStr)
+    err = fmt.Errorf("%s with unpacked reason \"%v\"", errPrefix, reason)
 } else if string(result) != "" {
     reasonStr := string(result)
-    err = fmt.Errorf("%s with reason \"%v\"", errPrefix, reasonStr)
+    err = fmt.Errorf("%s with raw reason \"%v\"", errPrefix, reasonStr)
 }
  1. Consider using error wrapping for better error handling up the call stack:
 if errUnpack == nil {
     reason, _ := abi.UnpackRevert(result)
-    err = fmt.Errorf("%s with unpacked reason \"%v\"", errPrefix, reason)
+    err = fmt.Errorf("%s with unpacked reason: %w", errPrefix, errors.New(reason))
 } else if string(result) != "" {
     reasonStr := string(result)
-    err = fmt.Errorf("%s with raw reason \"%v\"", errPrefix, reasonStr)
+    err = fmt.Errorf("%s with raw reason: %w", errPrefix, errors.New(reasonStr))
 } else {
-    err = errors.New(errPrefix)
+    err = fmt.Errorf("%s: %w", errPrefix, errors.New("no additional information"))
 }

These changes would further improve the clarity and utility of the error messages while maintaining the robust error handling you've implemented.

x/evm/evmtest/tx.go (5)

128-130: LGTM: Improved transaction generation and error handling

The changes enhance the transaction generation process by separating it from signing and adding immediate error checking. This improves the overall robustness of the function.

Consider consolidating the error checks for both generation and signing:

 ethTxMsg, gethSigner, krSigner, err := GenerateEthTxMsgAndSigner(txArgs, deps, deps.Sender)
-require.NoError(t, err)
-err = ethTxMsg.Sign(gethSigner, krSigner)
-require.NoError(t, err)
+require.NoError(t, err)
+require.NoError(t, ethTxMsg.Sign(gethSigner, krSigner))

This minor refactor would make the code slightly more concise while maintaining the same functionality.


160-170: Simplify error handling in DeployContract

The changes improve the transaction generation and signing process. However, the error handling structure can be simplified for better readability and maintainability.

Consider refactoring the error handling as follows:

 ethTxMsg, gethSigner, krSigner, err := GenerateEthTxMsgAndSigner(
 	evm.JsonTxArgs{
 		Nonce: (*hexutil.Uint64)(&nonce),
 		Input: (*hexutil.Bytes)(&bytecodeForCall),
 		From:  &deps.Sender.EthAddr,
 	}, deps, deps.Sender,
 )
 if err != nil {
 	return nil, errors.Wrap(err, "failed to generate eth tx msg")
-} else if err := ethTxMsg.Sign(gethSigner, krSigner); err != nil {
+}
+if err := ethTxMsg.Sign(gethSigner, krSigner); err != nil {
 	return nil, errors.Wrap(err, "failed to sign eth tx msg")
 }

This change eliminates the else if clause, making the error handling more straightforward and easier to read.


193-197: LGTM: Enhanced DeployAndExecuteERC20Transfer function

The changes improve the function by providing more return values and using the new GenerateEthTxMsgAndSigner method. The contract address calculation move enhances readability.

Consider consolidating the error checks for both generation and signing, similar to the suggestion for ExecuteNibiTransfer:

 erc20Transfer, gethSigner, krSigner, err := GenerateEthTxMsgAndSigner(txArgs, deps, deps.Sender)
-require.NoError(t, err)
-err = erc20Transfer.Sign(gethSigner, krSigner)
-require.NoError(t, err)
+require.NoError(t, err)
+require.NoError(t, erc20Transfer.Sign(gethSigner, krSigner))

This minor refactor would make the code slightly more concise while maintaining the same functionality.

Also applies to: 205-205, 223-225


235-261: LGTM: New CallContractTx function

The new CallContractTx function provides a clean abstraction for calling a contract, which will improve code reusability and readability in tests. It correctly uses the new GenerateEthTxMsgAndSigner method and handles errors appropriately.

Consider using errors.Wrap for consistency with error handling in other functions:

 if err != nil {
-		err = fmt.Errorf("CallContract error during tx generation: %w", err)
+		return nil, nil, errors.Wrap(err, "CallContract error during tx generation")
 		return
 	}

 	err = ethTxMsg.Sign(gethSigner, krSigner)
 	if err != nil {
-		err = fmt.Errorf("CallContract error during signature: %w", err)
+		return nil, nil, errors.Wrap(err, "CallContract error during signature")
 		return
 	}

This change would make the error handling consistent with other parts of the codebase and provide stack traces for easier debugging.


Line range hint 263-297: LGTM: New GenerateEthTxMsgAndSigner function

The new GenerateEthTxMsgAndSigner function centralizes the logic for generating Ethereum transactions and signers, which will improve consistency across the codebase. The inclusion of a usage example in the documentation is excellent and enhances code understandability.

Consider using named return values for clarity and to ensure all return values are set in error cases:

 func GenerateEthTxMsgAndSigner(
 	jsonTxArgs evm.JsonTxArgs, deps *TestDeps, sender EthPrivKeyAcc,
-) (evmTxMsg *evm.MsgEthereumTx, gethSigner gethcore.Signer, krSigner keyring.Signer, err error) {
+) (evmTxMsg *evm.MsgEthereumTx, gethSigner gethcore.Signer, krSigner keyring.Signer, err error) {
 	estimateArgs, err := json.Marshal(&jsonTxArgs)
 	if err != nil {
-		return
+		return nil, nil, nil, err
 	}
 	// ... (rest of the function)
 	if err != nil {
-		return
+		return nil, nil, nil, err
 	}
 	// ... (rest of the function)
 }

This change ensures that all return values are explicitly set in error cases, improving code clarity and preventing potential issues with uninitialized return values.

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

794-794: Consider capturing the third return value

The evmtest.DeployAndExecuteERC20Transfer function now returns three values, but the third value is being discarded. Consider capturing this value and using it if it contains relevant information for the test.

-txMsg, predecessors, _ := evmtest.DeployAndExecuteERC20Transfer(deps, s.T())
+txMsg, predecessors, thirdValue := evmtest.DeployAndExecuteERC20Transfer(deps, s.T())

873-873: Consider capturing discarded return values

The evmtest.DeployAndExecuteERC20Transfer function now returns three values, but the second and third values are being discarded. Consider capturing these values and using them if they contain relevant information for the test.

-txMsg, _, _ := evmtest.DeployAndExecuteERC20Transfer(deps, s.T())
+txMsg, secondValue, thirdValue := evmtest.DeployAndExecuteERC20Transfer(deps, s.T())
x/evm/evmtest/tx_test.go (3)

1-1: Correct the company name in the copyright

The company name appears to be misspelled. It should be "Nibiru Labs, Inc." instead of "Nibi, Inc."

Apply this diff to correct the company name:

-// Copyright (c) 2023-2024 Nibi, Inc.
+// Copyright (c) 2023-2024 Nibiru Labs, Inc.

26-26: Provide a descriptive message for error handling

When checking for errors with s.Require().NoError, consider providing a descriptive message to aid in debugging if the test fails.

Apply this diff to include an error message:

-s.Require().NoError(err, deployResp)
+s.Require().NoError(err, "Failed to deploy contract: %v", err)

78-86: Assert the recipient's balance after the transfer

To fully verify the transfer, add an assertion to check that the recipient's bank balance has increased by the transferred amount.

Apply this diff to assert the recipient's balance:

 evmtest.AssertBankBalanceEqual(
     s.T(), deps, evm.EVMBankDenom, deps.Sender.EthAddr, big.NewInt(69_000),
 )
+
+// Assert recipient's bank balance
+evmtest.AssertBankBalanceEqual(
+    s.T(), deps, evm.EVMBankDenom, to, big.NewInt(420),
+)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8d7fcd3 and eb87c3e.

📒 Files selected for processing (6)
  • x/evm/errors.go (1 hunks)
  • x/evm/evmtest/erc20.go (2 hunks)
  • x/evm/evmtest/tx.go (7 hunks)
  • x/evm/evmtest/tx_test.go (1 hunks)
  • x/evm/keeper/grpc_query.go (1 hunks)
  • x/evm/keeper/grpc_query_test.go (2 hunks)
🧰 Additional context used
🔇 Additional comments (5)
x/evm/evmtest/erc20.go (1)

26-26: Consider the implications of string comparison for balance assertion.

The change from numerical comparison to string comparison for ERC20 balances might have both advantages and drawbacks:

Pros:

  • Improved readability in test failure messages.
  • Avoids potential issues with big.Int comparison semantics.

Cons:

  • Potential loss of precision for very large numbers due to string representation.
  • Slight performance overhead due to string conversion.

To ensure this change doesn't introduce any regressions, please run the following script to check for any existing tests that might be affected:

Consider adding a comment explaining the rationale behind this change to help future maintainers understand the decision.

x/evm/evmtest/tx.go (2)

23-24: LGTM: Keyring import added

The addition of the keyring import is consistent with the changes in transaction handling and signing observed throughout the file.


Line range hint 1-345: Overall assessment: Significant improvements in transaction handling

The changes in this file represent a substantial improvement in the handling of Ethereum transactions within the test environment. Key enhancements include:

  1. Centralization of transaction generation and signing logic with the new GenerateEthTxMsgAndSigner function.
  2. Improved error handling and reporting across various functions.
  3. Addition of the CallContractTx function for a cleaner abstraction of contract interactions.
  4. Consistent use of the new transaction generation method throughout the file.

These changes align well with the PR objectives of addressing issues related to the Ethereum Virtual Machine (EVM) StateDB. The modifications should lead to more robust and maintainable test code, potentially reducing the likelihood of bugs stemming from inconsistent transaction handling.

While the changes are generally excellent, consider implementing the minor suggestions provided in the individual comments to further enhance code clarity and consistency.

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

666-673: LGTM! Improved context setup.

The refactoring of the context setup into a single chained method call enhances readability and conciseness. The functionality remains unchanged while the code becomes more maintainable.


666-673: Summary: Improved context setup in TraceBlock method

The changes in this file are focused on refactoring the context setup in the TraceBlock method. This refactoring improves code readability and maintainability without altering the functionality. The rest of the file, including other methods and the TraceEthTxMsg function, remains unchanged and continues to work correctly with the modified context.

@NibiruChain NibiruChain deleted a comment from coderabbitai bot Oct 22, 2024
x/evm/keeper/erc20.go Outdated Show resolved Hide resolved
Copy link
Contributor

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

🧹 Outside diff range and nitpick comments (16)
x/evm/statedb/journal_test.go (3)

24-24: Consider defining the funding amount as a named constant.

The magic number 69_420 should be defined as a constant with a meaningful name that reflects its purpose in the test.

+const testFundingAmount = 69_420
-		sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewInt(69_420))),
+		sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewInt(testFundingAmount))),

34-66: Consider documenting the counter value progression.

The test uses specific counter values (0 -> 7 -> 12) but doesn't document why these specific values were chosen. Consider adding a comment explaining the test scenario or using named constants.

+	// Test increments: 0 (initial) -> +7 -> +5 = 12 (final)
	stateTransitions := []Transition{

81-81: Document the expected journal entries count.

The test expects exactly 13 journal entries but doesn't explain why this number is expected. Consider adding a comment explaining the breakdown of journal entries or define it as a named constant.

+	// 13 entries: 1 for initial state + 7 for first increment + 5 for second increment
	s.Require().Len(entries, 13, "expect 13 journal entries")
x/evm/keeper/funtoken_from_coin.go (1)

Line range hint 81-87: Consider explicit error wrapping with context

While the error handling includes wrapping, consider adding more context about the deployment state:

- return gethcommon.Address{}, errors.Wrap(err, "failed to deploy ERC20 contract")
+ return gethcommon.Address{}, errors.Wrapf(err, "failed to deploy ERC20 contract for bank coin %s", bankCoin.Name)
x/evm/precompile/wasm_test.go (1)

Line range hint 309-313: Consider enhancing error message specificity.

While the error handling is correct, consider making the error messages more specific to the EVM context for better debugging. For example, include whether the error occurred during precompile execution or state transition.

CHANGELOG.md (3)

58-59: Verify the precompile state fix description

The description of PR #2086 could be more detailed to explain:

  1. The root cause of the stale state issue
  2. The specific impact on precompile execution
  3. How committing state at precompile start fixes the issue

Consider expanding the description to:

- fix(evm-precompiles): It is possible for the `Run` function of a custom precompile to retrieve stale state because EVM state changes can occur before the precompile is called that are recorded as entries in the StateDB journal for the transaction without being reflected in the `sdk.Context`. This pull request makes sure that state is committed as expected.
+ fix(evm-precompiles): Fixed a critical issue where custom precompile's `Run` function could retrieve stale state. This occurred because EVM state changes before the precompile call were recorded in the StateDB journal but not reflected in the `sdk.Context`. The fix ensures state consistency by committing temporary state at precompile start, preventing any uncommitted journal entries from causing incorrect state reads. This resolves potential issues with precompile execution operating on outdated state.

43-51: Improve changelog section organization

The "Before Audit 2" section would benefit from better organization:

  1. Group related changes together (e.g., all ERC20/FunToken changes)
  2. Add subsection headers for different types of changes
  3. Include the audit timeline/scope information in a more structured way

Consider restructuring as:

#### Nibiru EVM | Before Audit 2 [Nov, 2024]

##### Audit Context
The codebase underwent a Code4rena Zenith Audit from 2024-10-07 to 2024-11-01, including both primary review and mitigation periods. The following changes were made after that audit in preparation for a second audit in November 2024.

##### Critical Fixes
- [#2086](https://github.com/NibiruChain/nibiru/pull/2086) - fix(evm-precompiles): Fixed state consistency issues in precompile execution...

##### ERC20 Improvements  
- [#2074](https://github.com/NibiruChain/nibiru/pull/2074) - fix(evm-keeper): Improved ERC20 metadata handling during FunToken creation...

##### Gas Optimizations
- [#2076](https://github.com/NibiruChain/nibiru/pull/2076) - fix(evm-gas-fees): Optimized gas price calculations...

Line range hint 1-42: Enhance changelog header documentation

The changelog header comments could be improved to better guide contributors on changelog maintenance.

Add the following sections to the header:

<!--
Additional Guidelines:

1. Version Sections:
   - Use ### for major versions (v1.0.0)
   - Use #### for minor versions (v1.1.0)
   - Use ##### for patch versions (v1.1.1)

2. Change Categories:
   - Group changes into consistent categories:
     - 🚨 Critical - Breaking changes requiring immediate attention
     - 🔒 Security - Security related changes
     - 🔄 State Machine Breaking
     - 🛠 Features
     - 🐛 Bug Fixes
     - ⚡️ Performance
     - 📚 Documentation

3. Pull Request References:
   - Always include PR links in format [#1234](url)
   - Add context about why changes were made
-->
x/evm/precompile/precompile.go (1)

154-154: Correct typo in documentation comment.

There's a minor typo in the comment for OnRunStart:

  • "It handles decoding the input data according the to contract ABI..." should be "It handles decoding the input data according to the contract ABI..."
x/evm/keeper/erc20.go (3)

61-62: Consider handling the unused evmObj return value from CallContractWithInput

The function CallContractWithInput now returns an additional evmObj *vm.EVM, which is currently being ignored in:

  • Mint function (lines 61-62)
  • Transfer function (line 83)
  • Burn function (lines 123-124)
  • CallContract function (lines 155-156)

If the evmObj is unnecessary for the current implementation, consider explicitly acknowledging the unused return value to improve code clarity. This can be done by assigning it to the blank identifier _.

Apply this diff to acknowledge the unused return value:

-	evmResp, _, err = e.CallContractWithInput(ctx, from, &contract, true, input)
+	evmResp, _, err = e.CallContractWithInput(ctx, from, &contract, true, input) // evmObj is intentionally ignored

// Similarly for the other functions:

-	resp, _, err := e.CallContractWithInput(ctx, from, &contract, true, input)
+	resp, _, err := e.CallContractWithInput(ctx, from, &contract, true, input) // evmObj is intentionally ignored

-	evmResp, _, err = e.CallContractWithInput(ctx, from, &contract, commit, input)
+	evmResp, _, err = e.CallContractWithInput(ctx, from, &contract, commit, input) // evmObj is intentionally ignored

-	evmResp, _, err = k.CallContractWithInput(ctx, fromAcc, contract, commit, contractInput)
+	evmResp, _, err = k.CallContractWithInput(ctx, fromAcc, contract, commit, contractInput) // evmObj is intentionally ignored

Also applies to: 83-83, 123-124, 155-156


217-218: Use errors.Wrap instead of errors.Wrapf when no formatting is needed

At lines 217-218, errors.Wrapf is used without any formatting directives. Replace errors.Wrapf with errors.Wrap for clearer intent.

Apply this diff:

-		err = errors.Wrapf(err, "failed to load evm config")
+		err = errors.Wrap(err, "failed to load evm config")

229-230: Use errors.Wrap instead of errors.Wrapf when no formatting is needed

At lines 229-230, errors.Wrapf is used without any formatting directives. Use errors.Wrap instead to accurately reflect that no formatting is required.

Apply this diff:

-		err = errors.Wrapf(err, "failed to apply EVM message")
+		err = errors.Wrap(err, "failed to apply EVM message")
x/evm/keeper/msg_server.go (3)

Line range hint 292-323: Consistent return values in error cases

In several error return statements, evmObj is returned even when errors occur. This might be acceptable if evmObj provides useful context even during errors. However, if evmObj is not fully initialized or may be nil, it's safer to return nil for evmObj in error cases to avoid unintended consequences.

Consider returning nil for evmObj in error cases to prevent potential nil pointer dereferences.

Suggested changes:

    core.ErrIntrinsicGas,
    "apply message msg.Gas = %d, intrinsic gas = %d.",
    leftoverGas, intrinsicGas,
)

372-372: Handle errors during stateDB commit

In the ApplyEvmMsg function, if an error occurs during stateDB.Commit(), the function returns the error. Ensure that any necessary cleanup or rollback is performed in this case to maintain state consistency.

Consider adding logging or additional error handling to capture the context of the commit failure.

if err := stateDB.Commit(); err != nil {
    k.Logger(ctx).Error("stateDB commit failed", "error", err)
    return nil, evmObj, fmt.Errorf("failed to commit stateDB: %w", err)
}

381-385: Improve error messages for gas calculations

The error messages in returns at lines 381 and 385 could be more informative by including the relevant variable values.

Ensure that the error messages clearly convey the cause of the error.

Example:

x/evm/precompile/test/export.go (1)

58-64: Consistent Usage of s.Require().NoError for Critical Errors

Inconsistent use of s.NoError(err) and s.Require().NoError(err) can lead to tests continuing after critical errors. For example, at line 58 you use s.NoError(err), but subsequent code depends on err being nil. Use s.Require().NoError(err) consistently to ensure the test halts upon encountering an error that impacts subsequent assertions.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between eb87c3e and 7cc070b.

📒 Files selected for processing (17)
  • CHANGELOG.md (3 hunks)
  • x/evm/keeper/erc20.go (8 hunks)
  • x/evm/keeper/funtoken_from_coin.go (1 hunks)
  • x/evm/keeper/grpc_query.go (5 hunks)
  • x/evm/keeper/msg_server.go (10 hunks)
  • x/evm/precompile/funtoken.go (3 hunks)
  • x/evm/precompile/funtoken_test.go (4 hunks)
  • x/evm/precompile/oracle.go (1 hunks)
  • x/evm/precompile/oracle_test.go (2 hunks)
  • x/evm/precompile/precompile.go (2 hunks)
  • x/evm/precompile/test/export.go (1 hunks)
  • x/evm/precompile/wasm.go (6 hunks)
  • x/evm/precompile/wasm_test.go (8 hunks)
  • x/evm/statedb/journal.go (12 hunks)
  • x/evm/statedb/journal_test.go (1 hunks)
  • x/evm/statedb/state_object.go (4 hunks)
  • x/evm/statedb/statedb.go (11 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • x/evm/keeper/grpc_query.go
  • x/evm/precompile/funtoken.go
  • x/evm/precompile/oracle.go
  • x/evm/precompile/oracle_test.go
  • x/evm/precompile/wasm.go
  • x/evm/statedb/journal.go
  • x/evm/statedb/state_object.go
  • x/evm/statedb/statedb.go
🧰 Additional context used
🔇 Additional comments (17)
x/evm/statedb/journal_test.go (2)

29-32: LGTM! Well-structured Transition type.

The Transition struct is well-designed with clear function signatures for running transitions and performing assertions.


70-86: Test appears incomplete.

The test sets up multiple state transitions but only executes the first one. Consider either:

  1. Executing all transitions in a loop, or
  2. Documenting why only the first transition is executed

Additionally, verify that this partial execution adequately tests the StateDB journal functionality as mentioned in the PR objectives.

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

81-84: Verify state handling in CallContractWithInput

The addition of a blank identifier suggests CallContractWithInput now returns an additional value, likely related to state management. While this change aligns with the PR's objective of improving StateDB management, we should ensure proper state handling.

Let's verify the CallContractWithInput implementation:


Line range hint 1-91: Verify state consistency after ERC20 deployment

Given the PR's focus on fixing StateDB issues, we should ensure that the state remains consistent after ERC20 deployment, particularly:

  1. The contract deployment state is properly committed
  2. The nonce increment is properly handled
  3. The ERC20 address calculation remains valid

Let's verify the state handling:

✅ Verification successful

Let me gather more information about the contract deployment and state handling.


Based on the extensive code analysis, I can now provide a final response regarding the state consistency verification.

State handling in ERC20 deployment is properly implemented

The code analysis reveals that the state handling during ERC20 deployment is properly implemented with multiple safeguards:

  1. The nonce handling is correct:

    • GetAccNonce is used to calculate the contract address before deployment
    • The nonce increment happens automatically through the EVM state transitions
  2. The contract deployment state is properly managed:

    • CallContractWithInput is used with commit=true parameter
    • The StateDB changes are properly committed through the EVM execution path
    • The state changes are tracked in the journal and committed atomically
  3. The ERC20 address calculation remains valid:

    • The address is pre-calculated using the current nonce
    • The nonce increment and contract deployment happen in the same transaction
    • The state changes are atomic through the StateDB commit mechanism
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for nonce handling patterns
rg -A 5 'GetAccNonce|SetAccNonce'

# Look for state commit patterns around contract deployment
ast-grep --pattern 'func $$$CallContractWithInput$$$'

Length of output: 2355


Script:

#!/bin/bash
# Look for CallContractWithInput implementation
rg -A 10 "CallContractWithInput.*\(" 

# Check for StateDB related code
rg -A 5 "StateDB|CommitStateDB"

# Look for contract deployment patterns
ast-grep --pattern 'func $$$CallContract$$$'

Length of output: 79701

x/evm/precompile/funtoken_test.go (4)

8-8: LGTM: Clear import alias for ethereum/go-ethereum/common package

The rename from common to gethcommon improves code clarity by explicitly indicating the package's origin.


52-64: LGTM: Consistent updates to use renamed import

The changes correctly update all HexToAddress calls to use the renamed gethcommon import while maintaining the original test logic and error scenarios.


140-142: LGTM: Robust balance comparison using string representation

Converting to string representation before comparison is a safer approach for comparing SDK.Int values, avoiding potential issues with different numeric types.


129-136: LGTM: Enhanced contract call implementation with better error handling

The switch to evmtest.CallContractTx improves the test by adding VM error validation and aligns with the PR's goal of better state management.

Let's verify the implementation of the new helper function:

✅ Verification successful

Let me gather more context about the implementation by checking the rest of the function and related dependencies.


Let me get one more piece of information to see how the transaction is executed after signing.


I now have enough information to verify the implementation and generate the final response.

Verified: CallContractTx implementation is robust and well-structured

The evmtest.CallContractTx helper function provides a comprehensive implementation that:

  • Properly manages nonces from the state DB
  • Handles gas estimation through GenerateEthTxMsgAndSigner
  • Implements proper transaction signing
  • Executes the transaction via EvmKeeper.EthereumTx
  • Returns detailed response including VM errors

The switch to this helper in the test is indeed an improvement as it encapsulates all the necessary contract interaction steps with proper error handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the implementation of CallContractTx
rg -A 10 "func CallContractTx" "x/evm/evmtest/"

Length of output: 673


Script:

#!/bin/bash
# Get the full implementation of CallContractTx and related functions
rg -A 20 "func CallContractTx" "x/evm/evmtest/"

# Check for GenerateEthTxMsgAndSigner implementation
rg -A 15 "func GenerateEthTxMsgAndSigner" "x/evm/evmtest/"

Length of output: 2101


Script:

#!/bin/bash
# Look for the rest of CallContractTx implementation
rg -B 5 -A 15 "err = ethTxMsg.Sign\(gethSigner, krSigner\)" "x/evm/evmtest/"

Length of output: 1986

x/evm/precompile/wasm_test.go (5)

14-14: LGTM: Import addition aligns with test package refactoring.

The addition of the test package import is consistent with the refactoring effort to consolidate test utilities.


27-27: LGTM: Test refactoring maintains functionality while improving structure.

The changes appropriately use the new test package utilities and follow the correct pattern for contract calls.

Also applies to: 55-58


96-105: Great improvement in test readability and maintainability!

The refactoring effectively:

  • Documents state transitions with clear comments
  • Reduces code duplication through test utilities
  • Makes the test flow more understandable

139-142: LGTM: Consistent error handling and type usage.

The changes appropriately use the refactored response type and follow the established error handling pattern.

Also applies to: 162-164


55-58: Verify test coverage for StateDB commit behavior.

While the tests cover various aspects of WASM precompile execution, consider adding specific test cases that verify the StateDB commit behavior at the start of precompiles, which is the main objective of this PR.

Would you like help in adding test cases specifically for verifying StateDB commit behavior?

Also applies to: 84-87, 139-142, 309-313

x/evm/precompile/precompile.go (1)

136-203: LGTM!

The introduction of OnRunStartResult and OnRunStart enhances the precompile execution flow. The implementation is clear and correctly handles input decomposition, context retrieval, and error handling.

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

223-224: Duplicate assignment of TxIndex and LogIndex may cause inconsistencies

You have assigned both txConfig.TxIndex and txConfig.LogIndex to k.EvmState.BlockLogSize.GetOr(ctx, 0) at lines 223-224. As previously noted, TxIndex represents the index of the transaction within the block, while LogIndex is the index of the log within the transaction. Using the same value for both can lead to inaccuracies.

Please refer to the previous review comments for detailed guidance on this issue.

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

Line range hint 266-401: Consistent error handling and evmObj usage

The ApplyEvmMsg function now returns evmObj *vm.EVM along with the response and error. In error cases, evmObj may not be fully initialized, which could lead to nil pointer dereferences if not handled carefully.

Ensure that wherever evmObj is used after calling ApplyEvmMsg, it is checked for nil to prevent potential runtime panics.

Check all usages of evmObj after calling ApplyEvmMsg to ensure it is not nil before accessing its fields or methods.


81-82: Update to use consistent logging methods

Ensure that the usage of k.EvmState.CalcBloomFromLogs aligns with the rest of the codebase and that the context ctx is appropriately passed.

The code updates seem consistent with the overall codebase.

x/evm/statedb/journal_test.go Outdated Show resolved Hide resolved
x/evm/statedb/journal_test.go Outdated Show resolved Hide resolved
x/evm/statedb/journal_test.go Outdated Show resolved Hide resolved
x/evm/keeper/erc20.go Outdated Show resolved Hide resolved
x/evm/keeper/msg_server.go Outdated Show resolved Hide resolved
x/evm/precompile/test/export.go Show resolved Hide resolved
x/evm/precompile/test/export.go Show resolved Hide resolved
x/evm/precompile/test/export.go Show resolved Hide resolved
x/evm/precompile/test/export.go Show resolved Hide resolved
x/evm/precompile/test/export.go Show resolved Hide resolved
@NibiruChain NibiruChain deleted a comment from coderabbitai bot Oct 24, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (13)
x/evm/keeper/erc20_test.go (3)

19-22: Consider improving code formatting for better readability

The function call arguments could be formatted more consistently. Consider aligning the parameters vertically:

-		_, _, err := deps.EvmKeeper.ERC20().Mint(
-			contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS,
-			big.NewInt(69_420), deps.Ctx,
-		)
+		_, _, err := deps.EvmKeeper.ERC20().Mint(
+			contract,
+			deps.Sender.EthAddr,
+			evm.EVM_MODULE_ADDRESS,
+			big.NewInt(69_420),
+			deps.Ctx,
+		)

28-28: Split long line for better readability

The function call is quite long and could be split across multiple lines for better readability:

-		_, _, err := deps.EvmKeeper.ERC20().Mint(contract, evm.EVM_MODULE_ADDRESS, evm.EVM_MODULE_ADDRESS, big.NewInt(69_420), deps.Ctx)
+		_, _, err := deps.EvmKeeper.ERC20().Mint(
+			contract,
+			evm.EVM_MODULE_ADDRESS,
+			evm.EVM_MODULE_ADDRESS,
+			big.NewInt(69_420),
+			deps.Ctx,
+		)

37-37: Split long line for better readability

The function call could be split across multiple lines:

-		_, _, err := deps.EvmKeeper.ERC20().Transfer(contract, deps.Sender.EthAddr, evm.EVM_MODULE_ADDRESS, big.NewInt(9_420), deps.Ctx)
+		_, _, err := deps.EvmKeeper.ERC20().Transfer(
+			contract,
+			deps.Sender.EthAddr,
+			evm.EVM_MODULE_ADDRESS,
+			big.NewInt(9_420),
+			deps.Ctx,
+		)
x/evm/evmmodule/genesis_test.go (1)

57-57: LGTM! Consider documenting the ignored return values.

The changes correctly handle the updated Transfer method signature. For better clarity, consider adding a comment explaining what the ignored return values represent.

Example improvement:

-	_, _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserA, amountToSendA, deps.Ctx)
+	// Ignoring evmObj and result returns as they're not needed for this test
+	_, _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserA, amountToSendA, deps.Ctx)

Also applies to: 61-61

x/evm/precompile/funtoken.go (1)

Line range hint 177-177: Address TODO: Implement EVM event emission.

Event emission is important for transaction transparency and off-chain monitoring.

Would you like me to help implement the EVM event emission for these operations?

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

137-150: Well-designed struct with clear separation of concerns.

The OnRunStartResult struct effectively encapsulates all necessary components for precompile execution, providing a clean interface for state management. The clear documentation and strong typing will help prevent state-related bugs.

Consider adding validation methods to this struct to ensure state consistency, particularly for the StateDB and Ctx fields which are critical for maintaining system integrity.


152-178: Enhance documentation with error scenarios.

While the function documentation is comprehensive, it would be beneficial to document the possible error scenarios that callers should handle.

Add error scenarios to the documentation:

 // Args:
 //   - evm: Instance of the EVM executing the contract
 //   - contract: Precompiled contract being called
 //   - abi: [gethabi.ABI] defining the contract's invokable methods.
+//
+// Returns error when:
+//   - Input data cannot be decoded according to the ABI
+//   - StateDB type assertion fails
+//   - Committing dirty journal entries fails
x/evm/precompile/wasm_test.go (1)

309-312: Consider enhancing error message with more context

While the error handling is good, consider making the error message more descriptive by including the test case name and input parameters.

-s.Require().ErrorContains(err, tc.wantError, "ethTxResp %v", ethTxResp)
+s.Require().ErrorContains(err, tc.wantError, "test case '%s' failed with ethTxResp %v", tc.name, ethTxResp)
x/evm/keeper/msg_server.go (5)

275-275: Standardize error wrapping pattern.

The error wrapping pattern is inconsistent between these returns. Line 275 uses errors.Wrap(err, "intrinsic gas failed") while lines 286-290 use a different format with errors.Wrapf(core.ErrIntrinsicGas, "apply message msg.Gas = %d, intrinsic gas = %d.", leftoverGas, intrinsicGas). Consider standardizing the error wrapping pattern for better consistency.

Also applies to: 286-290


355-357: Align error wrapping with project pattern.

Consider using errors.Wrap instead of fmt.Errorf to maintain consistency with the project's error handling pattern:

-			return nil, evmObj, fmt.Errorf("failed to commit stateDB: %w", err)
+			return nil, evmObj, errors.Wrap(err, "failed to commit stateDB")

Line range hint 689-694: Add validation for contract deployment address.

The contract address is generated but not validated before event emission. Consider adding validation to ensure the generated contract address is valid:

 if recipient == nil { // contract creation
 	contractAddr := crypto.CreateAddress(msg.From(), msg.Nonce())
+	if !gethcommon.IsHexAddress(contractAddr.Hex()) {
+		return errors.Wrap(err, "invalid contract address generated")
+	}
 	_ = ctx.EventManager().EmitTypedEvent(&evm.EventContractDeployed{
 		Sender:       msg.From().Hex(),
 		ContractAddr: contractAddr.String(),
 	})

364-368: Enhance gas overflow error messages.

The error messages for gas overflow could be more descriptive to aid debugging. Consider adding more context:

-		return nil, evmObj, errors.Wrapf(evm.ErrGasOverflow, "minimumGasUsed(%s) is not a uint64", minimumGasUsed.TruncateInt().String())
+		return nil, evmObj, errors.Wrapf(evm.ErrGasOverflow, "minimum gas used (%s) exceeds uint64 max value", minimumGasUsed.TruncateInt().String())

-		return nil, evmObj, errors.Wrapf(evm.ErrGasOverflow, "message gas limit < leftover gas (%d < %d)", msg.Gas(), leftoverGas)
+		return nil, evmObj, errors.Wrapf(evm.ErrGasOverflow, "gas limit underflow: message gas limit (%d) is less than leftover gas (%d)", msg.Gas(), leftoverGas)

Line range hint 593-603: Add pre-transfer balance validation.

Consider adding a validation check for the EVM module's balance before attempting the transfer to fail fast and provide a clearer error message:

+	if evmModuleBalance.Cmp(coin.Amount.BigInt()) < 0 {
+		return nil, errors.Wrapf(err, "insufficient balance in EVM module: has %s, needs %s", evmModuleBalance, coin.Amount)
+	}
 	res, _, err := k.ERC20().Transfer(
 		erc20Addr,
 		evm.EVM_MODULE_ADDRESS,
 		recipient,
 		coin.Amount.BigInt(),
 		ctx,
 	)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7cc070b and be2c0a2.

📒 Files selected for processing (13)
  • CHANGELOG.md (3 hunks)
  • x/evm/evmmodule/genesis_test.go (1 hunks)
  • x/evm/keeper/erc20.go (7 hunks)
  • x/evm/keeper/erc20_test.go (3 hunks)
  • x/evm/keeper/funtoken_from_erc20_test.go (5 hunks)
  • x/evm/keeper/msg_server.go (11 hunks)
  • x/evm/precompile/funtoken.go (4 hunks)
  • x/evm/precompile/precompile.go (2 hunks)
  • x/evm/precompile/wasm_test.go (8 hunks)
  • x/evm/statedb/journal.go (12 hunks)
  • x/evm/statedb/journal_test.go (1 hunks)
  • x/evm/statedb/state_object.go (8 hunks)
  • x/evm/statedb/statedb.go (13 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • x/evm/keeper/funtoken_from_erc20_test.go
  • x/evm/statedb/journal.go
  • x/evm/statedb/journal_test.go
  • x/evm/statedb/statedb.go
🔇 Additional comments (29)
x/evm/keeper/erc20_test.go (2)

Line range hint 1-63: Add test cases for StateDB commit behavior

While the test file covers basic ERC20 operations, it doesn't explicitly verify the PR's main objective of fixing issues with uncommitted, dirty journal entries in the StateDB. Consider adding test cases that:

  1. Verify the StateDB is committed at precompile start
  2. Demonstrate that the EVM and non-EVM state remain in sync after operations
  3. Test scenarios where operations revert to ensure proper state handling

This aligns with the pending item in the PR checklist regarding "test case that reverts the StateDB".

#!/bin/bash
# Description: Check for existing StateDB commit/revert tests

# Search for StateDB-related test cases
rg -B 2 -A 2 "StateDB.*(?:Commit|Revert)" --type go

# Search for test cases involving state synchronization
rg -B 2 -A 2 "(?i)state.*sync" --type go

46-46: Split long line and verify consistent return value handling

The function call could be split across multiple lines for better readability. Additionally, we should verify that the new return value (evmObj) is consistently handled across all ERC20 operations.

-		_, _, err := deps.EvmKeeper.ERC20().Transfer(contract, evm.EVM_MODULE_ADDRESS, deps.Sender.EthAddr, big.NewInt(9_420), deps.Ctx)
+		_, _, err := deps.EvmKeeper.ERC20().Transfer(
+			contract,
+			evm.EVM_MODULE_ADDRESS,
+			deps.Sender.EthAddr,
+			big.NewInt(9_420),
+			deps.Ctx,
+		)
x/evm/precompile/funtoken.go (5)

32-34: LGTM: Clean ABI getter implementation.

The new ABI() method provides a clean way to access the contract ABI, improving code organization.


37-39: LGTM: Improved gas calculation.

The change to use a shared RequiredGas implementation with ABI parameter suggests more accurate gas calculation.


51-53: LGTM: Improved error handling.

The error handling is now more consistent using ErrPrecompileRun, which should provide better error context.


72-73: Verify StateDB commitment behavior.

The addition of StateDB.Commit() addresses the PR objective of fixing uncommitted journal entries. However, we should verify this doesn't affect other precompiles.

✅ Verification successful

Let me try a different search pattern to find precompile implementations.

The first command will help identify precompile structs and their methods, while the second will show where StateDB commits are being used in the codebase. This will give us better context about the commit behavior across precompiles.


Let me search for more specific context about precompile implementations.

This will help us understand the precompile architecture and how StateDB.Commit() is being used in the context of the precompile framework.


Based on the code analysis, I can now provide a final response about the StateDB commitment behavior.

StateDB.Commit() usage is consistent with precompile framework design

The addition of StateDB.Commit() in the funtoken precompile aligns with the framework's design and other precompiles. Key observations:

  • The precompile.go file explicitly documents in OnRunStart() that precompiles should "Use res.StateDB.Commit() before any non-EVM state changes to guarantee the context and [statedb.StateDB] are in sync."
  • Both funtoken and wasm precompiles follow this pattern by calling start.StateDB.Commit() at the end of their Run() methods
  • This ensures that any EVM state changes are properly committed before making Cosmos SDK state modifications
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if other precompiles also commit their state
echo "Searching for other precompile Run methods that might be affected by StateDB commits..."
rg -A 5 "Run\(.*\*vm\.EVM.*\*vm\.Contract" --type go

Length of output: 239


Script:

#!/bin/bash
# Search for precompile Run methods with different pattern
rg -A 10 "type.*Precompile.*struct" --type go

# Also search for StateDB.Commit() usage
rg "StateDB\.Commit\(\)" --type go

Length of output: 552


Script:

#!/bin/bash
# Look at the precompile.go file to understand the base implementation
cat x/evm/precompile/precompile.go

# Look at both funtoken and wasm precompile implementations
cat x/evm/precompile/funtoken.go
cat x/evm/precompile/wasm.go

Length of output: 23164


144-147: Verify ERC20 transfer error handling.

The ERC20 transfer is a critical operation. Ensure proper error handling and state rollback on failure.

✅ Verification successful

Let me try a different pattern to locate the ERC20 transfer implementation.

The previous pattern was too specific. Let's try a broader search to find the relevant code and error handling patterns. This will help us verify the error handling and state rollback mechanisms in place.


Let me try one more search with a different pattern to locate the ERC20 implementation.

I'm broadening the search to first find files containing ERC20 references, then examining their content for transfer-related implementations. This should help us locate the relevant code to verify the error handling mechanisms.


Let me check the specific implementation of the Transfer function and its error handling.

This should help us verify the error handling and state management in the ERC20 transfer implementation.


Let me try one final search with a different pattern to locate the transfer implementation.

This broader search should help us locate the transfer implementation and its error handling patterns across the relevant files.


Based on the code revealed, I can now provide a final response about the ERC20 transfer error handling:

ERC20 transfer implementation has proper error handling in place

The implementation shows appropriate error handling at multiple levels:

  • Input validation through ABI packing
  • Contract call error handling
  • Response unpacking validation
  • All errors are properly propagated with context

The transfer operation is atomic through the EVM transaction mechanism, which ensures state rollback on failure. The implementation in erc20.go shows proper error handling patterns with clear error wrapping and propagation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check ERC20 transfer implementation and error handling
echo "Searching for ERC20 transfer implementation..."
ast-grep --pattern 'func $_($_ *keeper.$_, $_ gethcommon.Address, $_ gethcommon.Address, $_ *big.Int, $_ sdk.Context) ($_, $_, error)'

Length of output: 239


Script:

#!/bin/bash
# Search for ERC20 transfer related code
echo "Searching for ERC20 transfer implementation..."
rg -A 10 "func.*Transfer.*ERC20" 

# Also check for any error handling patterns
echo -e "\nChecking error handling patterns..."
rg "if err.*transfer" -A 3

Length of output: 253


Script:

#!/bin/bash
# Search for ERC20 interface and implementation
echo "Searching for ERC20 related code..."
rg -l "ERC20"

# Then let's examine the content of files that mention ERC20
echo -e "\nChecking specific ERC20 files..."
fd -t f -e go . | xargs rg "Transfer.*ERC20|func.*ERC20" -A 5

Length of output: 11125


Script:

#!/bin/bash
# Look for the Transfer implementation in erc20.go
echo "Checking Transfer implementation..."
rg -A 15 "func.*Transfer.*implements.*ERC20.transfer" x/evm/keeper/erc20.go

# Check for state management and rollback mechanisms
echo -e "\nChecking state management..."
rg "StateDB|stateDB" x/evm/keeper/erc20.go -A 3

Length of output: 281


Script:

#!/bin/bash
# Look for Transfer method in erc20.go with more context
echo "Checking Transfer method..."
rg -B 2 -A 20 "func \(.*\) Transfer" x/evm/keeper/erc20.go

# Also check for any transaction handling patterns
echo -e "\nChecking transaction patterns..."
rg "func \(k \*?Keeper\)" x/evm/keeper/erc20.go -A 3

# Check for any error handling in the funtoken.go where the transfer is called
echo -e "\nChecking funtoken.go error handling..."
rg "Transfer.*err.*return" x/evm/precompile/funtoken.go -A 5

Length of output: 2215

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

27-30: LGTM: Import changes are appropriate.

The new imports are necessary for the added functionality and are used effectively throughout the code.


192-194: Verify state consistency after commit.

The commit operation is crucial for maintaining state consistency. Consider adding verification to ensure the commit was successful and the state is as expected.

x/evm/precompile/wasm_test.go (6)

14-14: LGTM: Good modularization of test utilities

The addition of a dedicated test package helps improve code organization and reusability.


55-57: LGTM: Improved error handling pattern

The contract calls now follow a consistent pattern with explicit error handling and response validation. This makes the test behavior more predictable and easier to debug.

Also applies to: 84-86


99-111: Great improvement in test readability

The test flow is now more explicit with:

  • Clear state transition comments
  • Step-by-step verification
  • Consistent use of test utilities

139-142: LGTM: Consistent error handling

The response handling follows the established pattern with proper error checking and response validation.


162-165: LGTM: Enhanced response validation

Good addition of owner validation alongside the count check, improving test coverage.


Line range hint 1-315: Consider adding StateDB commit verification tests

Given that the PR objectives mention fixing issues with uncommitted, dirty journal entries in the EVM StateDB, consider adding specific test cases that verify:

  1. The temporary state is correctly committed at precompile start
  2. The state remains consistent after precompile execution
  3. The behavior during precompile reversion

This would help ensure the core issue is properly addressed and prevent regressions.

x/evm/statedb/state_object.go (6)

141-142: LGTM: Storage initialization is correct.

The initialization of OriginStorage and DirtyStorage as new maps is properly maintained.


173-175: Improved clarity in balance tracking.

The rename from prev to prevWei better indicates that the value is in wei units, consistent with the AccountWei struct design.


259-264: LGTM: Storage access logic is preserved.

The state access and modification logic remains correct after the field renames. The proper order of checking dirty state before committed state is maintained.

Let's verify no unintended changes to storage access patterns:

#!/bin/bash
# Check storage access patterns
rg "Get(?:Committed)?State|setState" --type go

Also applies to: 270-273, 293-293


118-119: Consider keeping storage fields private to maintain encapsulation.

The change from private (originStorage, dirtyStorage) to public (OriginStorage, DirtyStorage) visibility could allow external components to modify storage state directly, potentially bypassing journal entries. This might lead to inconsistent state or break atomicity guarantees.

Let's check if these fields are accessed from outside the package:

#!/bin/bash
# Search for direct access to OriginStorage or DirtyStorage fields
rg "\.(?:Origin|Dirty)Storage\b" --type go

Consider:

  1. Keeping these fields private
  2. Providing controlled access through methods that maintain proper journaling
  3. If external access is required, document the thread-safety and atomicity guarantees

Line range hint 215-219: Verify journal visibility requirements.

The change from journal to Journal across multiple methods suggests the journal needs to be accessed from outside the package. This could impact the atomicity of state changes.

Let's check the journal usage pattern:

#!/bin/bash
# Search for Journal access patterns
rg "\.Journal\." --type go

Consider documenting:

  1. Why the journal needs to be public
  2. Thread-safety guarantees
  3. Impact on state atomicity

Also applies to: 231-234, 284-288


124-125: ⚠️ Potential issue

Protect critical flags from external modification.

Making DirtyCode and Suicided flags public could lead to security vulnerabilities. The Suicided flag is particularly sensitive as it determines if an account should be deleted during state updates.

Let's verify the usage of these flags:

Consider keeping these flags private and providing controlled access through methods that ensure proper state transitions and journaling.

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

19-19: LGTM: Import addition aligns with PR objectives

The addition of the statedb package import is consistent with the PR's goal of fixing StateDB-related issues.


55-58: Improved state tracking with EVM object return value

The addition of evmObj *vm.EVM as a return value in Mint and Transfer methods enables better state tracking and aligns with the PR's goal of fixing StateDB issues. The error wrapping improvements also enhance debugging capabilities.

Also applies to: 76-79, 81-83, 89-92


213-214: Enhanced error handling with better context

The error handling has been significantly improved with:

  1. More specific error messages for different failure scenarios
  2. Better context through error wrapping
  3. Proper handling of VM-specific errors (OutOfGas, ExecutionReverted)

This makes debugging easier and provides better visibility into failure modes.

Also applies to: 233-234, 240-241, 243-244, 246-247, 255-255, 261-261


219-222: Improved transaction configuration with proper indices

The changes correctly initialize transaction configuration:

  1. Block hash is properly generated from context header
  2. TxIndex now correctly uses BlockTxIndex instead of BlockLogSize
  3. LogIndex is properly tracked

227-229: Verify state synchronization in edge cases

The state management looks correct, but we should verify the synchronization in edge cases:

  1. When a transaction partially succeeds but later reverts
  2. When multiple transactions are processed in the same block

Also applies to: 264-266

✅ Verification successful

Let me try a different search strategy to find relevant test cases and state management patterns.

Let's analyze the test coverage and state management patterns to verify the edge cases mentioned in the review comment.


Based on the search results, I can now provide a conclusive response about the state synchronization concerns in the review comment.

State synchronization is properly handled for transaction reverts and multiple transactions

The codebase shows robust state management for transaction reverts and multiple transactions:

  1. The code uses a temporary context (tmpCtx, commitCtx := ctx.CacheContext()) to isolate state changes during EVM execution
  2. The EVM state management system has comprehensive revert handling:
    • RevertToSnapshot functionality in StateDB
    • Journal system to track and revert state changes
    • Proper handling of reverted transactions through vm.ErrExecutionReverted
  3. Multiple transaction handling is safe because:
    • Each transaction uses an isolated cached context
    • State changes are only committed if the transaction succeeds
    • The journal system ensures atomic state updates

The implementation follows best practices for state management in EVM transactions, making it safe for both reverted transactions and multiple transaction scenarios.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for test cases that verify state synchronization in edge cases
rg -A 10 "TestCase.*Revert" --type go
rg -A 10 "TestCase.*MultipleTransactions" --type go

# Search for potential state management patterns
ast-grep --pattern 'func TestCase$_($_, $_) {
  $$$
  ctx.$_(
    $$$
  )
  $$$
}'

Length of output: 178


Script:

#!/bin/bash
# Search for test cases related to EVM transaction handling and state management
rg -A 10 "Test.*EVM.*Transaction" --type go
rg -A 10 "Test.*State.*" --type go

# Look for revert handling patterns
rg -A 5 "revert" --type go

# Search for specific EVM state management functions
ast-grep --pattern 'func ($_ *Keeper) ApplyEvmMsg($$$) {
  $$$
}'

# Look for context handling in tests
rg -A 5 "WithContext|NewContext" --type go

Length of output: 81835

CHANGELOG.md (3)

53-59: Critical fix for EVM precompile state management.

The changes in PR #2086 address an important issue where the EVM precompile could retrieve stale state due to uncommitted journal entries. This fix ensures proper state synchronization between EVM and non-EVM contexts.


43-61: Well-organized changelog section for Nibiru EVM.

The changelog entries are properly formatted with:

  • Clear PR links
  • Descriptive summaries
  • Proper categorization of changes

143-151: Breaking changes are clearly documented.

The State Machine Breaking section properly documents significant changes:

  • Removal of wasmbinding Custom bindings
  • Changes to inflation parameters
  • Migration to cosmossdk.io/math

x/evm/precompile/precompile.go Show resolved Hide resolved
Copy link
Contributor

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

🧹 Outside diff range and nitpick comments (5)
x/evm/statedb/journal_test.go (2)

28-29: Consider defining magic numbers as constants.

The funding amount 69_420 should be defined as a constant at the package level for better maintainability and reusability.

+const (
+    testFundingAmount = 69_420
+)
 s.Require().NoError(testapp.FundAccount(
     deps.App.BankKeeper,
     deps.Ctx,
     deps.Sender.NibiruAddr,
-    sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewInt(69_420))),
+    sdk.NewCoins(sdk.NewCoin(bankDenom, sdk.NewInt(testFundingAmount))),
 ))

76-81: Enhance test documentation for state changes.

The comments could be more descriptive about why specific numbers of dirties are expected. Consider adding more detailed explanations.

-// 2 dirties from [createObjectChange, balanceChange]
+// Expect 2 dirties: 1 from creating new account (createObjectChange) + 1 from balance modification (balanceChange)
 stateDB.AddBalance(randomAcc, balDelta)
-// 1 dirties from [balanceChange]
+// Expect 1 dirty: only balance modification (balanceChange) as account already exists
 stateDB.AddBalance(randomAcc, balDelta)
-// 1 dirties from [balanceChange]
+// Expect 1 dirty: only balance modification (balanceChange)
 stateDB.SubBalance(randomAcc, balDelta)
x/evm/precompile/funtoken.go (2)

Line range hint 190-190: Address the TODO comment for EVM events

The TODO comment indicates that EVM events should be emitted. This is important for transaction tracking and UI integration.

Would you like me to help implement the EVM event emission for these operations?


194-244: LGTM: Well-structured helper functions with proper state synchronization

The new helper functions properly encapsulate common operations and maintain consistency between bank and EVM balances. The special handling of EVMBankDenom ensures proper state synchronization.

Consider adding documentation comments to explain:

  1. When StateDB balance updates are necessary
  2. The relationship between bank balances and EVM balances
  3. Why EVMBankDenom requires special handling
+// SafeMintCoins mints coins to a module account and updates the StateDB balance
+// if the denomination is EVMBankDenom. This ensures consistency between
+// Cosmos SDK bank balances and EVM account balances.
 func SafeMintCoins(
   ctx sdk.Context,
   moduleName string,
   amt sdk.Coin,
   bk bankkeeper.Keeper,
   db *statedb.StateDB,
 ) error {

+// SafeSendCoinFromModuleToAccount sends coins from a module account to a user account
+// and updates the StateDB balances if the denomination is EVMBankDenom. This ensures
+// consistency between Cosmos SDK bank balances and EVM account balances for both
+// the sender and recipient.
 func SafeSendCoinFromModuleToAccount(
   ctx sdk.Context,
   senderModule string,
   recipientAddr sdk.AccAddress,
   amt sdk.Coin,
   bk bankkeeper.Keeper,
   db *statedb.StateDB,
 ) error {
x/evm/statedb/statedb.go (1)

301-301: Ensure parameter naming consistency for clarity

In the AddBalance method, the parameter name has been changed from amount to wei. Ensure that this naming convention is consistent throughout the codebase to improve readability and indicate that balances are handled in Wei units.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between be2c0a2 and 0e6afd8.

📒 Files selected for processing (4)
  • x/evm/precompile/funtoken.go (8 hunks)
  • x/evm/statedb/journal.go (12 hunks)
  • x/evm/statedb/journal_test.go (1 hunks)
  • x/evm/statedb/statedb.go (14 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • x/evm/statedb/journal.go
🔇 Additional comments (4)
x/evm/statedb/journal_test.go (1)

21-147: Well-structured test suite that aligns with PR objectives.

The test suite effectively validates the StateDB journal functionality with comprehensive coverage of different scenarios:

  1. Basic state transitions
  2. Contract interactions
  3. Precompile calls
  4. Error cases

The tests align well with the PR objective of fixing issues with uncommitted dirty journal entries.

x/evm/precompile/funtoken.go (3)

10-10: LGTM: Clean import changes and ABI method addition

The new imports and ABI method implementation look good. The ABI method provides a clean way to access the contract's interface definition.

Also applies to: 35-37


146-151: Verify ERC20 transfer error handling

The error handling for ERC20 transfer has been improved, but we should verify that failed transfers don't leave the state in an inconsistent state.

#!/bin/bash
# Check if there are any state modifications before the ERC20 transfer
ast-grep --pattern 'func ($x *$type) bankSend($_, $_, $_) ($_, $_) {
  $$$
  $keeper.ERC20().Transfer($$$)
}'

54-76: LGTM: Improved error handling and StateDB commit

The changes properly address the issue with uncommitted journal entries by:

  1. Simplifying error handling with ErrPrecompileRun
  2. Using OnRunStart for consistent state management
  3. Adding StateDB.Commit() to ensure temporary state is committed

Let's verify the StateDB commit behavior:

✅ Verification successful

Let me try a different approach to verify the StateDB commit behavior.

This should help us see the Run method implementations and verify the commit behavior across precompiles.


Let me try one final verification to specifically look at other precompile Run methods.

This should help us see the complete Run method implementations in precompiles to verify the commit behavior consistency.


Let me try one last search with a modified pattern.

This should help us find the Run method implementations in precompile files, regardless of the exact parameter names.


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

StateDB.Commit() is correctly implemented across precompiles

The verification confirms that:

  1. All precompile Run methods (wasm.go, oracle.go, funtoken.go) use the OnRunStart helper
  2. The OnRunStart helper ensures proper StateDB commit handling
  3. There's clear documentation in precompile.go showing this is the recommended pattern
  4. The commit is properly handled both in the helper and at the end of precompile executions

The changes in funtoken.go follow the established pattern and are consistent with other precompiles in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if StateDB.Commit() is consistently called across other precompiles
ast-grep --pattern 'func ($x *$type) Run($_, $_, $_) ($_, $_) {
  $$$
  return $_, $statedb.Commit()
}'

Length of output: 111


Script:

#!/bin/bash
# Search for Run methods in precompile implementations
rg "func.*Run\(.*\).*\{" -A 5

# Also check for Commit calls
rg "StateDB.*Commit\(\)" -B 3

Length of output: 3845


Script:

#!/bin/bash
# Search for all precompile Run method implementations
rg "func \(.*\) Run\(.*evm.*contract.*readonly.*\)" -A 10 x/evm/precompile/

Length of output: 77


Script:

#!/bin/bash
# Search for Run methods in precompile files
rg "func.*Run.*\(" --type go -g "x/evm/precompile/*.go" -B 1 -A 15

Length of output: 5832

x/evm/statedb/statedb.go Show resolved Hide resolved
x/evm/statedb/statedb.go Show resolved Hide resolved
x/evm/statedb/statedb.go Show resolved Hide resolved
x/evm/statedb/statedb.go Show resolved Hide resolved
x/evm/statedb/statedb.go Show resolved Hide resolved
@NibiruChain NibiruChain deleted a comment from coderabbitai bot Oct 24, 2024
x/evm/keeper/erc20.go Outdated Show resolved Hide resolved
x/evm/keeper/erc20.go Outdated Show resolved Hide resolved
@Unique-Divine Unique-Divine enabled auto-merge (squash) October 24, 2024 13:19
@Unique-Divine Unique-Divine merged commit 7c1b12b into main Oct 24, 2024
15 checks passed
@Unique-Divine Unique-Divine deleted the ud/evm-fix-state-not-committed-before-precompile branch October 24, 2024 14:48
Copy link
Contributor

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

🧹 Outside diff range and nitpick comments (2)
x/evm/statedb/journal_test.go (1)

113-116: Consider enhancing error message clarity.

The error message could be more descriptive by including the actual dirty count found.

-			s.FailNow("expected 2 dirty journal changes")
+			s.FailNow(fmt.Sprintf("expected 2 dirty journal changes, got %d", stateDB.DirtiesCount()))
x/evm/statedb/statedb_test.go (1)

516-521: LGTM! Consider enhancing test readability.

The change to use struct literal syntax for TxConfig initialization improves code clarity by making the configuration fields explicit. This aligns well with the PR's objective of addressing StateDB journal entry issues.

Consider adding a brief comment explaining the purpose of these non-default test values:

 	const (
+		// Using non-default values to ensure proper initialization
 		blockNumber = uint64(1)
 		txIdx      = uint(1)
 		logIdx     = uint(1)
 	)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0e6afd8 and 65b2cd6.

📒 Files selected for processing (8)
  • x/evm/keeper/erc20.go (7 hunks)
  • x/evm/keeper/erc20_test.go (1 hunks)
  • x/evm/keeper/msg_server.go (10 hunks)
  • x/evm/keeper/vm_config.go (1 hunks)
  • x/evm/precompile/funtoken.go (8 hunks)
  • x/evm/statedb/config.go (1 hunks)
  • x/evm/statedb/journal_test.go (1 hunks)
  • x/evm/statedb/statedb_test.go (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • x/evm/keeper/erc20_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • x/evm/precompile/funtoken.go
🔇 Additional comments (14)
x/evm/statedb/config.go (2)

23-25: LGTM! Parameter name change improves clarity.

The rename from bhash to blockHash enhances readability and maintains consistency with the struct field name.


Line range hint 23-29: Verify the removal of NewTxConfig function.

The removal of NewTxConfig function is a breaking change. Let's verify that all callers have been updated to use alternative methods.

✅ Verification successful

The search results show references to a different NewTxConfig function from the Cosmos SDK's tx package (tx.NewTxConfig), which is unrelated to the NewTxConfig function being removed from x/evm/statedb/config.go. Let me verify this further.


Let me do one final check to see if there are any references to this function in the test files within the EVM module, as tests are often the primary consumers of such utility functions.


Let me fix the regex syntax error and try one last search.


Based on all the searches performed, I can now provide a final response:

The removal of NewTxConfig appears to be safe

The extensive searches through the codebase have shown:

  1. No direct calls to the removed NewTxConfig function in the EVM module
  2. The only NewTxConfig references found were to a different function from Cosmos SDK's tx package
  3. No imports or usages of the statedb package that would indicate dependency on this function

The function appears to have been unused and its removal is replaced by the new NewEmptyTxConfig function, which provides a simpler interface for creating a TxConfig with just a block hash parameter.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any remaining references to NewTxConfig that might need updating

# Test 1: Look for direct function calls
echo "Searching for NewTxConfig function calls..."
rg "NewTxConfig\(" 

# Test 2: Look for any references in tests
echo "Searching for NewTxConfig in test files..."
rg "NewTxConfig" -g "*_test.go"

# Test 3: Look for any comments or documentation mentioning the function
echo "Searching for NewTxConfig in comments and docs..."
rg "NewTxConfig" -g "*.md"

Length of output: 627


Script:

#!/bin/bash
# Let's verify this by:
# 1. Looking specifically in the evm package for any references
# 2. Looking for the exact function signature with ast-grep

# Search in evm package
echo "Searching in evm package..."
rg "NewTxConfig" x/evm/

# Search for the specific function signature
echo "Searching for the exact function signature..."
ast-grep --pattern 'func NewTxConfig(blockHash $_, txHash $_, txIndex $_, logIndex $_) TxConfig'

Length of output: 288


Script:

#!/bin/bash
# Search specifically in EVM test files
echo "Searching in EVM test files..."
rg "NewTxConfig" x/evm/ -g "*_test.go"

# Also check for any uses of TxConfig struct initialization that might have been using this function
echo "Searching for TxConfig struct usage..."
rg "TxConfig{" x/evm/

Length of output: 302


Script:

#!/bin/bash
# Search for TxConfig struct initialization with proper regex escaping
echo "Searching for TxConfig struct usage..."
rg "TxConfig\s*{" x/evm/

# Also look for any imports of the statedb package which might indicate usage
echo "Searching for statedb imports..."
rg '"x/evm/statedb"' x/evm/

Length of output: 306

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

42-47: LGTM! The refactored TxConfig implementation improves clarity and state management.

The change from using a constructor to a direct struct initialization makes the source of each field value more explicit and ensures proper state access through the keeper.

Let's verify the state access methods being used:

✅ Verification successful

Let me try a different approach to verify the state access methods.


Let me search specifically for the collections package and GetOr method since it appears to be from a custom collections implementation.


Let me try one more search to find the ItemTransient implementation.


Based on the gathered information, I can now generate the final response. The code shows that BlockTxIndex and BlockLogSize are part of the EvmState struct and are implemented as collections.ItemTransient from the github.com/NibiruChain/collections package. The GetOr method is consistently used throughout the codebase to safely retrieve values with a default fallback, and the usage in vm_config.go follows this pattern correctly.

The TxConfig implementation correctly uses transient state values for indices

The code properly retrieves transaction and log indices from the EVM state using the GetOr method, which safely returns a default value of 0 if no value is set. This is the expected behavior for tracking block-level transaction and log indices.

  • BlockTxIndex and BlockLogSize are correctly defined as transient state items in x/evm/keeper/evm_state.go
  • The GetOr method is consistently used across the codebase for safe value retrieval with defaults
  • The usage pattern matches other parts of the codebase, such as in msg_server.go and evmante_emit_event.go
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and usage of EvmState methods

# Test 1: Check for BlockTxIndex definition and usage
rg -A 2 "BlockTxIndex.*=.*struct"

# Test 2: Check for BlockLogSize definition and usage
rg -A 2 "BlockLogSize.*=.*struct"

# Test 3: Check for GetOr method implementation
ast-grep --pattern 'func $_GetOr(ctx $_, $default $_) $_'

Length of output: 131


Script:

#!/bin/bash
# Search for EvmState type definition and its fields
rg -A 10 "type EvmState struct"

# Search for any usage of BlockTxIndex and BlockLogSize
rg "BlockTxIndex|BlockLogSize"

# Look for GetOr method implementations in the codebase
rg -A 3 "func.*GetOr"

# Check the imports in vm_config.go to verify statedb package
rg -A 10 "^import \(" "x/evm/keeper/vm_config.go"

Length of output: 2459


Script:

#!/bin/bash
# Search for collections package import and usage
rg "collections\." -A 2

# Look for ItemTransient type and its methods
rg "type ItemTransient"

# Check if collections is defined in the local codebase
fd collections.go

# Search for GetOr method in collections related files
rg "func.*GetOr" --type go

Length of output: 33363


Script:

#!/bin/bash
# Search for ItemTransient in go.mod dependencies
cat go.mod

# Look for collections package imports
rg "\"collections\"" --type go

# Search for GetOr usage in the codebase
rg "\.GetOr\(" -B 2 -A 2

Length of output: 20326

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

72-95: Well-structured test for journal entry management.

This test case effectively validates the core functionality of managing dirty journal entries and their cleanup after commit, which directly addresses the PR's objective of fixing issues with uncommitted, dirty journal entries.

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

59-60: LGTM: Appropriate handling of return values

The changes correctly handle the return values from CallContractWithInput, discarding the evmObj which is only needed for testing purposes.


121-122: LGTM: Consistent with Mint function implementation

The changes maintain consistency with the Mint function implementation, appropriately handling return values and error cases.


153-154: LGTM: Consistent error handling pattern

The changes maintain consistency with the established pattern of handling return values and errors.


177-177: LGTM: Enhanced return values for better debugging

The addition of evmObj *vm.EVM as a return value improves debugging capabilities and aligns with the PR objectives.


213-214: LGTM: Improved error handling and messages

The changes enhance error handling by:

  • Adding more context to wrapped errors
  • Providing specific error messages for different VM error cases
  • Making error messages more descriptive for debugging

Also applies to: 230-231, 237-238, 240-241, 243-244


252-252: LGTM: Enhanced error handling in success path

The changes improve error handling in the success path by adding more context to errors related to gas usage and event emission.

Also applies to: 258-258


263-263: LGTM: Proper return value handling

The return statement correctly handles all return values in the success case.

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

65-65: LGTM: Updated function call to match new signature.

The change correctly handles the additional return value from ApplyEvmMsg.


249-249: LGTM: Enhanced error context with EVM object.

The changes improve error handling by providing EVM context in error returns and initializing the EVM object earlier in the function flow.

Also applies to: 256-256


Line range hint 689-694: LGTM: Proper contract address calculation in event.

The contract address calculation follows the Ethereum specification using crypto.CreateAddress(from, nonce).

s.T().Log("Set up helloworldcounter.wasm")

wasmContract := test.SetupWasmContracts(&deps, &s.Suite)[1]
fmt.Printf("wasmContract: %s\n", wasmContract)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove debug print statement.

Debug print statements should be removed from production code.

-	fmt.Printf("wasmContract: %s\n", wasmContract)
📝 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
fmt.Printf("wasmContract: %s\n", wasmContract)

Comment on lines +3 to +19
import (
"fmt"
"math/big"
"strings"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/core/vm"

serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config"
"github.com/NibiruChain/nibiru/v2/x/common/testutil/testapp"
"github.com/NibiruChain/nibiru/v2/x/evm"
"github.com/NibiruChain/nibiru/v2/x/evm/embeds"
"github.com/NibiruChain/nibiru/v2/x/evm/evmtest"
"github.com/NibiruChain/nibiru/v2/x/evm/precompile/test"
"github.com/NibiruChain/nibiru/v2/x/evm/statedb"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove duplicate import of test package.

The test package is imported twice - once with an alias (as seen in the code usage) and once without. This is redundant.

-	"github.com/NibiruChain/nibiru/v2/x/evm/precompile/test"
📝 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
import (
"fmt"
"math/big"
"strings"
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/core/vm"
serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config"
"github.com/NibiruChain/nibiru/v2/x/common/testutil/testapp"
"github.com/NibiruChain/nibiru/v2/x/evm"
"github.com/NibiruChain/nibiru/v2/x/evm/embeds"
"github.com/NibiruChain/nibiru/v2/x/evm/evmtest"
"github.com/NibiruChain/nibiru/v2/x/evm/precompile/test"
"github.com/NibiruChain/nibiru/v2/x/evm/statedb"
)
import (
"fmt"
"math/big"
"strings"
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/core/vm"
serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config"
"github.com/NibiruChain/nibiru/v2/x/common/testutil/testapp"
"github.com/NibiruChain/nibiru/v2/x/evm"
"github.com/NibiruChain/nibiru/v2/x/evm/embeds"
"github.com/NibiruChain/nibiru/v2/x/evm/evmtest"
"github.com/NibiruChain/nibiru/v2/x/evm/statedb"
)

Comment on lines +151 to +181
func debugDirtiesCountMismatch(db *statedb.StateDB, t *testing.T) string {
lines := []string{}
dirties := db.Dirties()
stateObjects := db.StateObjects()
for addr, dirtyCountForAddr := range dirties {
lines = append(lines, fmt.Sprintf("Dirty addr: %s, dirtyCountForAddr=%d", addr, dirtyCountForAddr))

// Inspect the actual state object
maybeObj := stateObjects[addr]
if maybeObj == nil {
lines = append(lines, " no state object found!")
continue
}
obj := *maybeObj

lines = append(lines, fmt.Sprintf(" balance: %s", obj.Balance()))
lines = append(lines, fmt.Sprintf(" suicided: %v", obj.Suicided))
lines = append(lines, fmt.Sprintf(" dirtyCode: %v", obj.DirtyCode))

// Print storage state
lines = append(lines, fmt.Sprintf(" len(obj.DirtyStorage) entries: %d", len(obj.DirtyStorage)))
for k, v := range obj.DirtyStorage {
lines = append(lines, fmt.Sprintf(" key: %s, value: %s", k.Hex(), v.Hex()))
origVal := obj.OriginStorage[k]
lines = append(lines, fmt.Sprintf(" origin value: %s", origVal.Hex()))
}
}

t.Log("debugDirtiesCountMismatch:\n", strings.Join(lines, "\n"))
return ""
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider refactoring debugDirtiesCountMismatch function signature.

The function currently returns an empty string which serves no purpose. Consider either:

  1. Making it return void (no return value)
  2. Returning the generated debug string instead of logging it directly

Option 1 (preferred) - Return void:

-func debugDirtiesCountMismatch(db *statedb.StateDB, t *testing.T) string {
+func debugDirtiesCountMismatch(db *statedb.StateDB, t *testing.T) {
     // ... existing code ...
     t.Log("debugDirtiesCountMismatch:\n", strings.Join(lines, "\n"))
-    return ""
}

Option 2 - Return the debug string:

 func debugDirtiesCountMismatch(db *statedb.StateDB, t *testing.T) string {
     // ... existing code ...
-    t.Log("debugDirtiesCountMismatch:\n", strings.Join(lines, "\n"))
-    return ""
+    return fmt.Sprintf("debugDirtiesCountMismatch:\n%s", strings.Join(lines, "\n"))
 }
📝 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 debugDirtiesCountMismatch(db *statedb.StateDB, t *testing.T) string {
lines := []string{}
dirties := db.Dirties()
stateObjects := db.StateObjects()
for addr, dirtyCountForAddr := range dirties {
lines = append(lines, fmt.Sprintf("Dirty addr: %s, dirtyCountForAddr=%d", addr, dirtyCountForAddr))
// Inspect the actual state object
maybeObj := stateObjects[addr]
if maybeObj == nil {
lines = append(lines, " no state object found!")
continue
}
obj := *maybeObj
lines = append(lines, fmt.Sprintf(" balance: %s", obj.Balance()))
lines = append(lines, fmt.Sprintf(" suicided: %v", obj.Suicided))
lines = append(lines, fmt.Sprintf(" dirtyCode: %v", obj.DirtyCode))
// Print storage state
lines = append(lines, fmt.Sprintf(" len(obj.DirtyStorage) entries: %d", len(obj.DirtyStorage)))
for k, v := range obj.DirtyStorage {
lines = append(lines, fmt.Sprintf(" key: %s, value: %s", k.Hex(), v.Hex()))
origVal := obj.OriginStorage[k]
lines = append(lines, fmt.Sprintf(" origin value: %s", origVal.Hex()))
}
}
t.Log("debugDirtiesCountMismatch:\n", strings.Join(lines, "\n"))
return ""
}
func debugDirtiesCountMismatch(db *statedb.StateDB, t *testing.T) {
lines := []string{}
dirties := db.Dirties()
stateObjects := db.StateObjects()
for addr, dirtyCountForAddr := range dirties {
lines = append(lines, fmt.Sprintf("Dirty addr: %s, dirtyCountForAddr=%d", addr, dirtyCountForAddr))
// Inspect the actual state object
maybeObj := stateObjects[addr]
if maybeObj == nil {
lines = append(lines, " no state object found!")
continue
}
obj := *maybeObj
lines = append(lines, fmt.Sprintf(" balance: %s", obj.Balance()))
lines = append(lines, fmt.Sprintf(" suicided: %v", obj.Suicided))
lines = append(lines, fmt.Sprintf(" dirtyCode: %v", obj.DirtyCode))
// Print storage state
lines = append(lines, fmt.Sprintf(" len(obj.DirtyStorage) entries: %d", len(obj.DirtyStorage)))
for k, v := range obj.DirtyStorage {
lines = append(lines, fmt.Sprintf(" key: %s, value: %s", k.Hex(), v.Hex()))
origVal := obj.OriginStorage[k]
lines = append(lines, fmt.Sprintf(" origin value: %s", origVal.Hex()))
}
}
t.Log("debugDirtiesCountMismatch:\n", strings.Join(lines, "\n"))
}

@@ -272,7 +272,7 @@ func (k *Keeper) ApplyEvmMsg(ctx sdk.Context,
intrinsicGas, err := k.GetEthIntrinsicGas(ctx, msg, evmConfig.ChainConfig, contractCreation)
if err != nil {
// should have already been checked on Ante Handler
return nil, errors.Wrap(err, "intrinsic gas failed")
return nil, evmObj, errors.Wrap(err, "intrinsic gas failed")
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider optimizing error handling paths.

The current implementation initializes the EVM object before certain validations (like intrinsic gas checks). If these validations fail, creating the EVM object was unnecessary.

Consider restructuring the code to initialize the EVM object after basic validations:

 func (k *Keeper) ApplyEvmMsg(...) (resp *evm.MsgEthereumTxResponse, evmObj *vm.EVM, err error) {
     var (
         ret   []byte
         vmErr error
     )
 
     stateDB := statedb.New(ctx, k, txConfig)
-    evmObj = k.NewEVM(ctx, msg, evmConfig, tracer, stateDB)
 
     intrinsicGas, err := k.GetEthIntrinsicGas(ctx, msg, evmConfig.ChainConfig, contractCreation)
     if err != nil {
-        return nil, evmObj, errors.Wrap(err, "intrinsic gas failed")
+        return nil, nil, errors.Wrap(err, "intrinsic gas failed")
     }
 
     if leftoverGas < intrinsicGas {
-        return nil, evmObj, errors.Wrapf(...)
+        return nil, nil, errors.Wrapf(...)
     }
 
+    evmObj = k.NewEVM(ctx, msg, evmConfig, tracer, stateDB)

Also applies to: 286-286, 306-306, 336-336, 355-355, 364-364, 368-368, 384-384

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.

[evm] Use dynamic gas computation for the FunToken.sol precompile
2 participants