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

test(evm): unit tests for evm_ante #1912

Merged
merged 16 commits into from
Jun 11, 2024
Merged

test(evm): unit tests for evm_ante #1912

merged 16 commits into from
Jun 11, 2024

Conversation

onikonychev
Copy link
Contributor

@onikonychev onikonychev commented Jun 5, 2024

Summary by CodeRabbit

  • New Features

    • Introduced EthEmitEventDecorator to handle event emission for Ethereum transactions.
    • Added EthValidateBasicDecorator for basic validation of Ethereum transactions.
    • Implemented CanTransferDecorator to check sender's transfer eligibility based on EVM rules.
    • Added AnteDecEthGasConsume for validating intrinsic gas and managing gas consumption.
  • Bug Fixes

    • Enhanced error message formatting for better readability in various components.
  • Tests

    • Added comprehensive test suites for new decorators and functionalities, including event emission, basic validation, gas consumption, fee checking, and sender sequence increment.
  • Chores

    • Included -v flag in test-coverage-integration target for verbose output in test coverage reports.

Copy link
Contributor

coderabbitai bot commented Jun 5, 2024

Walkthrough

The recent changes introduce a variety of enhancements and new features focused on Ethereum transaction handling within the Cosmos SDK. These include restructuring error messages for clarity, adding new decorators for event emission, fee checking, and gas consumption, and implementing comprehensive test suites to validate these functionalities. The updates aim to improve the robustness and readability of the Ethereum Virtual Machine (EVM) integration in the application.

Changes

File(s) Change Summary
CHANGELOG.md Added unit tests for evm_ante_sigverify.
app/evmante_sigverify.go Restructured error messages for invalid message types and rejected unprotected Ethereum transactions.
app/evmante_emit_event.go Introduced EthEmitEventDecorator for handling event emissions in Ethereum transactions.
app/evmante_setup_ctx.go Refactored transaction validation and event emission logic, removed unused imports and structs.
app/evmante_setup_ctx_test.go Added test case TestEthSetupContextDecorator.
app/evmante_validate_basic.go Introduced EthValidateBasicDecorator for basic validation of Ethereum transactions.
app/evmante_emit_event_test.go Added test suite for EthEmitEventDecorator.
app/evmante_gas_wanted_test.go Added test suite for GasWantedDecorator.
app/evmante_validate_basic_test.go Added test cases for Ethereum transaction validation.
x/evm/tx.go Added a comment to the EvmTxArgs struct definition.
app/evmante_fee_checker.go Reformatted error messages and improved readability.
app/evmante_fee_checker_test.go Added test suite for NewDynamicFeeChecker.
app/evmante_fees.go Reformatted error message string for readability.
app/evmante_fees_test.go Added test suite for EthMinGasPriceDecorator.
app/evmante_can_transfer.go Introduced CanTransferDecorator for transfer validation in Ethereum transactions.
app/evmante_can_transfer_test.go Added test suite for CanTransferDecorator.
app/evmante_gas_consume.go Introduced functionality for gas validation and fee management in Ethereum transactions.
app/evmante_gas_consume_test.go Added test suite for gas consumption scenarios.
app/evmante_handler_test.go Added test cases for AnteHandler in EVM context.
app/evmante_increment_sender_seq.go Introduced AnteDecEthIncrementSenderSequence for handling sender sequence increment.
app/evmante_increment_sender_seq_test.go Added test suite for incrementing sender sequence in Ethereum transactions.
app/evmante_reject_msgs_test.go Added test suite for preventing Ethereum transaction messages.
app/evmante_verify_eth_acc_test.go Added functions happyTransfertTx and nonEvmMsgTx, removed commented-out test function.
contrib/make/test.mk Added -v flag to go test command in test-coverage-integration target.

Poem

In lines of code, where changes flow,
Ethereum's strength begins to grow.
With decorators new and tests so bright,
We ensure transactions are handled right.
From gas to fees, each step refined,
In Cosmos, Ethereum's stars aligned.
🐇✨🚀


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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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 as 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.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration 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.

@onikonychev onikonychev marked this pull request as ready for review June 5, 2024 17:19
@onikonychev onikonychev requested a review from a team as a code owner June 5, 2024 17:19
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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between bbcc6f8 and cba648f.

Files selected for processing (3)
  • CHANGELOG.md (1 hunks)
  • app/evmante_sigverify.go (1 hunks)
  • app/evmante_sigverify_test.go (1 hunks)
Additional comments not posted (5)
app/evmante_sigverify.go (2)

45-48: Improved error message formatting for invalid message types enhances clarity.


56-58: Enhanced error handling for unprotected Ethereum transactions is a good security practice.

app/evmante_sigverify_test.go (2)

14-15: Introduction of global variables InvalidChainID and RandomAddress for test setup is a good practice for reusability.


17-88: Comprehensive test coverage for various Ethereum transaction scenarios enhances the robustness of the signature verification process.

CHANGELOG.md (1)

70-70: The changelog entry for PR #1912 is correctly formatted and placed. It succinctly captures the essence of the changes made—adding unit tests for evm_ante_sigverify.

Copy link

codecov bot commented Jun 5, 2024

Codecov Report

Attention: Patch coverage is 77.91045% with 74 lines in your changes missing coverage. Please review.

Project coverage is 64.76%. Comparing base (42a8b65) to head (8a50e0e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1912      +/-   ##
==========================================
+ Coverage   63.05%   64.76%   +1.71%     
==========================================
  Files         245      250       +5     
  Lines       15871    15963      +92     
==========================================
+ Hits        10007    10339     +332     
+ Misses       5122     4871     -251     
- Partials      742      753      +11     
Files Coverage Δ
app/evmante_emit_event.go 100.00% <100.00%> (ø)
app/evmante_fees.go 88.88% <100.00%> (+88.88%) ⬆️
app/evmante_gas_wanted.go 100.00% <ø> (ø)
app/evmante_sigverify.go 100.00% <100.00%> (+100.00%) ⬆️
x/evm/tx.go 85.02% <ø> (ø)
app/evmante_setup_ctx.go 66.66% <0.00%> (+66.66%) ⬆️
app/evmante_verify_eth_acc.go 85.71% <85.71%> (ø)
app/evmante_increment_sender_seq.go 70.00% <70.00%> (ø)
app/evmante_can_transfer.go 78.84% <78.84%> (ø)
app/evmante_validate_basic.go 88.23% <88.23%> (ø)
... and 2 more

... and 2 files with indirect coverage changes

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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between cba648f and af87b51.

Files selected for processing (2)
  • CHANGELOG.md (1 hunks)
  • app/evmante_gas_wanted_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
Additional comments not posted (1)
app/evmante_gas_wanted_test.go (1)

12-106: Comprehensive and well-structured unit tests for GasWantedDecorator.

The test cases are well-organized and cover a variety of scenarios, including transactions with different gas limits and block gas settings. The use of table-driven tests enhances maintainability and readability. Good job on ensuring that each test case is isolated by resetting the TestDeps and committing the stateDB changes.

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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between af87b51 and a862309.

Files selected for processing (4)
  • app/evmante_emit_event.go (1 hunks)
  • app/evmante_setup_ctx.go (3 hunks)
  • app/evmante_setup_ctx_test.go (1 hunks)
  • app/evmante_validate_basic.go (1 hunks)
Additional comments not posted (4)
app/evmante_setup_ctx_test.go (1)

12-42: Comprehensive test coverage for EthSetupContextDecorator.

This test function effectively checks various critical aspects such as error handling, gas meter setup, and gas config resets, ensuring robust functionality.

app/evmante_setup_ctx.go (1)

33-36: Improved error handling for invalid transaction types.

The updated error message provides clear feedback on the expected transaction type, enhancing the robustness of the transaction handling process.

app/evmante_emit_event.go (1)

35-36: Robust error handling for invalid Ethereum transaction messages.

The error handling ensures that only valid Ethereum transaction messages are processed, which is crucial for the integrity of event emission.

app/evmante_validate_basic.go (1)

37-70: Comprehensive validation and error handling for Ethereum transactions.

The method effectively ensures that Ethereum transactions meet the required standards and handles errors appropriately, which is essential for transaction integrity.

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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between a862309 and 9b20a6c.

Files selected for processing (2)
  • app/evmante_emit_event.go (1 hunks)
  • app/evmante_emit_event_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • app/evmante_emit_event.go
Additional comments not posted (4)
app/evmante_emit_event_test.go (4)

13-78: Comprehensive test coverage for EthEmitEventDecorator.

The test function TestEthEmitEventDecorator effectively covers both failure and success scenarios. It checks for the correct event type and attributes, ensuring robust functionality of the event emission process.


40-47: Proper setup and initialization for test cases.

The initialization with evmtest.NewTestDeps() and the commitment of the state database with stateDB.Commit() are correctly placed to ensure a consistent state before each test case runs.


14-38: Well-structured test cases.

The use of table-driven tests enhances maintainability and clarity. Each test case is clearly defined with a setup function and expected outcomes, facilitating easy additions or modifications in the future.


49-75: Thorough assertions and error handling in tests.

The assertions within the test cases are comprehensive, checking for the presence of errors, the correctness of the event type, and the presence of specific transaction attributes. This thoroughness ensures that the decorator behaves as expected under various conditions.

@onikonychev onikonychev added the ⚠️ do not merge On hold for merge or not desired label Jun 7, 2024
@onikonychev onikonychev changed the title test(evm): unit tests for evm_ante_sigverify test(evm): unit tests for evm_ante Jun 10, 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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 9b20a6c and f807e6f.

Files selected for processing (9)
  • CHANGELOG.md (1 hunks)
  • app/evmante_emit_event.go (1 hunks)
  • app/evmante_emit_event_test.go (1 hunks)
  • app/evmante_gas_wanted_test.go (1 hunks)
  • app/evmante_setup_ctx_test.go (1 hunks)
  • app/evmante_sigverify.go (1 hunks)
  • app/evmante_validate_basic.go (1 hunks)
  • app/evmante_validate_basic_test.go (1 hunks)
  • x/evm/tx.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • x/evm/tx.go
Files skipped from review as they are similar to previous changes (7)
  • CHANGELOG.md
  • app/evmante_emit_event.go
  • app/evmante_emit_event_test.go
  • app/evmante_gas_wanted_test.go
  • app/evmante_setup_ctx_test.go
  • app/evmante_sigverify.go
  • app/evmante_validate_basic.go
Additional comments not posted (1)
app/evmante_validate_basic_test.go (1)

20-244: The structure and organization of TestEthValidateBasicDecorator are well-executed, providing clear and comprehensive test coverage for various transaction scenarios.

Comment on lines 246 to 286
func buildEthMsg(
chainID *big.Int,
gasLimit uint64,
from string,
to *common.Address,

) *evm.MsgEthereumTx {
ethContractCreationTxParams := &evm.EvmTxArgs{
ChainID: chainID,
Nonce: 1,
Amount: big.NewInt(10),
GasLimit: gasLimit,
GasPrice: big.NewInt(1),
To: to,
}
tx := evm.NewTx(ethContractCreationTxParams)
tx.From = from
return tx
}

func buildTx(
deps *evmtest.TestDeps,
ethExtentions bool,
msg sdk.Msg,
gasLimit uint64,
fees sdk.Coins,
) sdk.Tx {
txBuilder, _ := deps.EncCfg.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
if ethExtentions {
option, _ := codectypes.NewAnyWithValue(&evm.ExtensionOptionsEthereumTx{})
txBuilder.SetExtensionOptions(option)
}
err := txBuilder.SetMsgs(msg)
if err != nil {
panic(err)
}
txBuilder.SetGasLimit(gasLimit)
txBuilder.SetFeeAmount(fees)

return txBuilder.GetTx()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The utility functions buildEthMsg and buildTx are well-implemented, enhancing test readability and maintainability. Consider adding error handling in buildTx instead of using panic for a more graceful error management.

- panic(err)
+ if err != nil {
+     return nil, err
+ }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func buildEthMsg(
chainID *big.Int,
gasLimit uint64,
from string,
to *common.Address,
) *evm.MsgEthereumTx {
ethContractCreationTxParams := &evm.EvmTxArgs{
ChainID: chainID,
Nonce: 1,
Amount: big.NewInt(10),
GasLimit: gasLimit,
GasPrice: big.NewInt(1),
To: to,
}
tx := evm.NewTx(ethContractCreationTxParams)
tx.From = from
return tx
}
func buildTx(
deps *evmtest.TestDeps,
ethExtentions bool,
msg sdk.Msg,
gasLimit uint64,
fees sdk.Coins,
) sdk.Tx {
txBuilder, _ := deps.EncCfg.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
if ethExtentions {
option, _ := codectypes.NewAnyWithValue(&evm.ExtensionOptionsEthereumTx{})
txBuilder.SetExtensionOptions(option)
}
err := txBuilder.SetMsgs(msg)
if err != nil {
panic(err)
}
txBuilder.SetGasLimit(gasLimit)
txBuilder.SetFeeAmount(fees)
return txBuilder.GetTx()
}
func buildEthMsg(
chainID *big.Int,
gasLimit uint64,
from string,
to *common.Address,
) *evm.MsgEthereumTx {
ethContractCreationTxParams := &evm.EvmTxArgs{
ChainID: chainID,
Nonce: 1,
Amount: big.NewInt(10),
GasLimit: gasLimit,
GasPrice: big.NewInt(1),
To: to,
}
tx := evm.NewTx(ethContractCreationTxParams)
tx.From = from
return tx
}
func buildTx(
deps *evmtest.TestDeps,
ethExtentions bool,
msg sdk.Msg,
gasLimit uint64,
fees sdk.Coins,
) (sdk.Tx, error) {
txBuilder, _ := deps.EncCfg.TxConfig.NewTxBuilder().(authtx.ExtensionOptionsTxBuilder)
if ethExtentions {
option, _ := codectypes.NewAnyWithValue(&evm.ExtensionOptionsEthereumTx{})
txBuilder.SetExtensionOptions(option)
}
err := txBuilder.SetMsgs(msg)
if err != nil {
return nil, err
}
txBuilder.SetGasLimit(gasLimit)
txBuilder.SetFeeAmount(fees)
return txBuilder.GetTx(), nil
}

@onikonychev onikonychev removed the ⚠️ do not merge On hold for merge or not desired label Jun 10, 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: 2

Outside diff range and nitpick comments (1)
app/evmante_fee_checker.go (1)

29-31: Consider removing or updating the TODO comment.

The TODO comment suggests that this code might be temporary or experimental. If this is not the case, consider updating or removing the comment to avoid confusion.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between f807e6f and 93ca583.

Files selected for processing (2)
  • app/evmante_fee_checker.go (4 hunks)
  • app/evmante_fee_checker_test.go (1 hunks)
Additional comments not posted (2)
app/evmante_fee_checker_test.go (1)

11-97: Comprehensive and well-structured test suite for NewDynamicFeeChecker.

The test cases cover various scenarios including happy and sad paths, which is crucial for ensuring robustness. The use of table-driven tests enhances readability and maintainability.

app/evmante_fee_checker.go (1)

56-59: Excellent error handling for negative priority prices.

The use of errors.Wrapf to provide detailed error messages enhances the debuggability of the system.

Comment on lines +70 to +78
return nil, 0, errors.Wrapf(
errortypes.ErrInsufficientFee,
"gas prices too low, got: %s%s required: %s%s. "+
"Please retry using a higher gas price or a higher fee",
feeCap,
denom,
baseFeeInt,
denom,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure error messages are clear and actionable.

The error message could be more user-friendly by specifying the actual and required values more clearly. Consider rephrasing to enhance clarity.

- "gas prices too low, got: %s%s required: %s%s. Please retry using a higher gas price or a higher fee",
+ "Gas prices too low. Current: %s%s, required: %s%s. Please increase the gas price or fee and try again.",
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
return nil, 0, errors.Wrapf(
errortypes.ErrInsufficientFee,
"gas prices too low, got: %s%s required: %s%s. "+
"Please retry using a higher gas price or a higher fee",
feeCap,
denom,
baseFeeInt,
denom,
)
return nil, 0, errors.Wrapf(
errortypes.ErrInsufficientFee,
"Gas prices too low. Current: %s%s, required: %s%s. Please increase the gas price or fee and try again.",
feeCap,
denom,
baseFeeInt,
denom,
)

Comment on lines +127 to +130
return nil, 0, errors.Wrapf(
errortypes.ErrInsufficientFee,
"insufficient fees; got: %s required: %s", feeCoins, requiredFees,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure consistency in error messaging.

The error message format should be consistent with other parts of the application. Consider using a similar structure as used in other error messages for uniformity.

- "insufficient fees; got: %s required: %s",
+ "Insufficient fees. Provided: %s, required: %s.",
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
return nil, 0, errors.Wrapf(
errortypes.ErrInsufficientFee,
"insufficient fees; got: %s required: %s", feeCoins, requiredFees,
)
return nil, 0, errors.Wrapf(
errortypes.ErrInsufficientFee,
"Insufficient fees. Provided: %s, required: %s.", feeCoins, requiredFees,
)

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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 93ca583 and 52ef738.

Files selected for processing (2)
  • app/evmante_fees.go (1 hunks)
  • app/evmante_fees_test.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • app/evmante_fees.go
Additional comments not posted (1)
app/evmante_fees_test.go (1)

11-103: Comprehensive and well-structured unit tests for EthMinGasPriceDecorator.

The test cases cover various scenarios including both happy and sad paths. The use of table-driven tests enhances maintainability and readability. Ensure that all edge cases for gas price calculations and fee validations are covered, especially with varying transaction complexities and gas price fluctuations.

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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 52ef738 and ec4dfca.

Files selected for processing (7)
  • app/evmante_can_transfer.go (1 hunks)
  • app/evmante_can_transfer_test.go (1 hunks)
  • app/evmante_gas_consume.go (1 hunks)
  • app/evmante_gas_consume_test.go (1 hunks)
  • app/evmante_increment_sender_seq.go (1 hunks)
  • app/evmante_verify_eth_acc.go (1 hunks)
  • app/evmante_verify_eth_acc_test.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • app/evmante_verify_eth_acc_test.go
Additional comments not posted (3)
app/evmante_can_transfer.go (2)

18-22: The introduction of CanTransferDecorator is well-documented with comments explaining its purpose.


82-90: Check for potential integer overflow.

app/evmante_gas_consume.go (1)

23-32: Initialization of AnteDecEthGasConsume is clear and concise.

Comment on lines 34 to 73
func (issd AnteDecEthIncrementSenderSequence) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evm.MsgEthereumTx)
if !ok {
return ctx, errors.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evm.MsgEthereumTx)(nil))
}

txData, err := evm.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, errors.Wrap(err, "failed to unpack tx data")
}

// increase sequence of sender
acc := issd.AccountKeeper.GetAccount(ctx, msgEthTx.GetFrom())
if acc == nil {
return ctx, errors.Wrapf(
errortypes.ErrUnknownAddress,
"account %s is nil", gethcommon.BytesToAddress(msgEthTx.GetFrom().Bytes()),
)
}
nonce := acc.GetSequence()

// we merged the nonce verification to nonce increment, so when tx includes multiple messages
// with same sender, they'll be accepted.
if txData.GetNonce() != nonce {
return ctx, errors.Wrapf(
errortypes.ErrInvalidSequence,
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
)
}

if err := acc.SetSequence(nonce + 1); err != nil {
return ctx, errors.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
}

issd.AccountKeeper.SetAccount(ctx, acc)
}

return next(ctx, tx, simulate)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Optimize error handling for clarity and maintainability.

The error messages could be more descriptive and specific to the context of the failure. This would improve debugging and maintainability.


Consider handling potential panics from type assertions and method calls.

The function assumes that certain type assertions and method calls will not fail (e.g., msg.(*evm.MsgEthereumTx)). It's safer to handle these potential panics by checking the returned values before usage.

Comment on lines 11 to 97
func (s *TestSuite) TestNewDynamicFeeChecker() {
testCases := []struct {
name string
txSetup func(deps *evmtest.TestDeps) sdk.FeeTx
ctxSetup func(deps *evmtest.TestDeps)
wantErr string
wantFee int64
wantPriority int64
}{
{
name: "happy: genesis tx with sufficient fee",
ctxSetup: func(deps *evmtest.TestDeps) {
gasPrice := sdk.NewInt64Coin("unibi", 1)
deps.Ctx = deps.Ctx.
WithBlockHeight(0).
WithMinGasPrices(
sdk.NewDecCoins(sdk.NewDecCoinFromCoin(gasPrice)),
).
WithIsCheckTx(true)
},
txSetup: func(deps *evmtest.TestDeps) sdk.FeeTx {
txMsg := happyCreateContractTx(deps)
txBuilder := deps.EncCfg.TxConfig.NewTxBuilder()
tx, err := txMsg.BuildTx(txBuilder, eth.EthBaseDenom)
s.Require().NoError(err)
return tx
},
wantErr: "",
wantFee: gasLimitCreateContract().Int64(),
wantPriority: 0,
},
{
name: "sad: genesis tx insufficient fee",
ctxSetup: func(deps *evmtest.TestDeps) {
gasPrice := sdk.NewInt64Coin("unibi", 2)
deps.Ctx = deps.Ctx.
WithBlockHeight(0).
WithMinGasPrices(
sdk.NewDecCoins(sdk.NewDecCoinFromCoin(gasPrice)),
).
WithIsCheckTx(true)
},
txSetup: func(deps *evmtest.TestDeps) sdk.FeeTx {
txMsg := happyCreateContractTx(deps)
txBuilder := deps.EncCfg.TxConfig.NewTxBuilder()
tx, err := txMsg.BuildTx(txBuilder, eth.EthBaseDenom)
s.Require().NoError(err)
return tx
},
wantErr: "insufficient fee",
},
{
name: "happy: tx with sufficient fee",
txSetup: func(deps *evmtest.TestDeps) sdk.FeeTx {
txMsg := happyCreateContractTx(deps)
txBuilder := deps.EncCfg.TxConfig.NewTxBuilder()
tx, err := txMsg.BuildTx(txBuilder, eth.EthBaseDenom)
s.Require().NoError(err)
return tx
},
wantErr: "",
wantFee: gasLimitCreateContract().Int64(),
wantPriority: 0,
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
deps := evmtest.NewTestDeps()
checker := app.NewDynamicFeeChecker(deps.K)

if tc.ctxSetup != nil {
tc.ctxSetup(&deps)
}

fee, priority, err := checker(deps.Ctx, tc.txSetup(&deps))

if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)
s.Require().Equal(tc.wantFee, fee.AmountOf("unibi").Int64())
s.Require().Equal(tc.wantPriority, priority)
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Enhance test coverage for edge cases.

The current tests cover basic scenarios. Consider adding more edge cases, such as boundary values for fees and gas prices, to ensure robustness.

Comment on lines 31 to 93
// AnteHandle creates an EVM from the message and calls the BlockContext CanTransfer function to
// see if the address can execute the transaction.
func (ctd CanTransferDecorator) AnteHandle(
ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler,
) (sdk.Context, error) {
params := ctd.EvmKeeper.GetParams(ctx)
ethCfg := evm.EthereumConfig(ctd.EvmKeeper.EthChainID(ctx))
signer := gethcore.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()))

for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evm.MsgEthereumTx)
if !ok {
return ctx, errors.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evm.MsgEthereumTx)(nil))
}

baseFee := ctd.EvmKeeper.GetBaseFee(ctx)

coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
if err != nil {
return ctx, errors.Wrapf(
err,
"failed to create an ethereum core.Message from signer %T", signer,
)
}

if baseFee == nil {
return ctx, errors.Wrap(
evm.ErrInvalidBaseFee,
"base fee is supported but evm block context value is nil",
)
}
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
return ctx, errors.Wrapf(
errortypes.ErrInsufficientFee,
"max fee per gas less than block base fee (%s < %s)",
coreMsg.GasFeeCap(), baseFee,
)
}

// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
cfg := &statedb.EVMConfig{
ChainConfig: ethCfg,
Params: params,
CoinBase: gethcommon.Address{},
BaseFee: baseFee,
}

stateDB := statedb.New(ctx, &ctd.EvmKeeper, statedb.NewEmptyTxConfig(gethcommon.BytesToHash(ctx.HeaderHash().Bytes())))
evm := ctd.EvmKeeper.NewEVM(ctx, coreMsg, cfg, evm.NewNoOpTracer(), stateDB)

// check that caller has enough balance to cover asset transfer for **topmost** call
// NOTE: here the gas consumed is from the context with the infinite gas meter
if coreMsg.Value().Sign() > 0 && !evm.Context.CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
return ctx, errors.Wrapf(
errortypes.ErrInsufficientFunds,
"failed to transfer %s from address %s using the EVM block context transfer function",
coreMsg.Value(),
coreMsg.From(),
)
}
}

return next(ctx, tx, simulate)
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure robust error handling and clear error messages.

The error messages are clear, but consider adding more specific logging for debugging purposes, especially around the Ethereum transaction handling in lines 48-54 and 82-90.

Comment on lines +45 to +167
// there's no need to verify it again during ReCheckTx
//
// Use new context with gasWanted = 0
// Otherwise, there's an error on txmempool.postCheck (tendermint)
// that is not bubbled up. Thus, the Tx never runs on DeliverMode
// Error: "gas wanted -1 is negative"
newCtx := ctx.WithGasMeter(eth.NewInfiniteGasMeterWithLimit(gasWanted))
return next(newCtx, tx, simulate)
}

evmParams := anteDec.EvmKeeper.GetParams(ctx)
evmDenom := evmParams.GetEvmDenom()

var events sdk.Events

// Use the lowest priority of all the messages as the final one.
minPriority := int64(math.MaxInt64)
baseFee := anteDec.EvmKeeper.GetBaseFee(ctx)

for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evm.MsgEthereumTx)
if !ok {
return ctx, errors.Wrapf(
errortypes.ErrUnknownRequest,
"invalid message type %T, expected %T",
msg, (*evm.MsgEthereumTx)(nil),
)
}
from := msgEthTx.GetFrom()

txData, err := evm.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, errors.Wrap(err, "failed to unpack tx data")
}

if ctx.IsCheckTx() && anteDec.maxGasWanted != 0 {
// We can't trust the tx gas limit, because we'll refund the unused gas.
if txData.GetGas() > anteDec.maxGasWanted {
gasWanted += anteDec.maxGasWanted
} else {
gasWanted += txData.GetGas()
}
} else {
gasWanted += txData.GetGas()
}

fees, err := keeper.VerifyFee(txData, evmDenom, baseFee, ctx.IsCheckTx())
if err != nil {
return ctx, errors.Wrapf(err, "failed to verify the fees")
}

if err = anteDec.deductFee(ctx, fees, from); err != nil {
return ctx, err
}

events = append(events,
sdk.NewEvent(
sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeyFee, fees.String()),
),
)

priority := evm.GetTxPriority(txData, baseFee)

if priority < minPriority {
minPriority = priority
}
}

ctx.EventManager().EmitEvents(events)

blockGasLimit := eth.BlockGasLimit(ctx)

// return error if the tx gas is greater than the block limit (max gas)

// NOTE: it's important here to use the gas wanted instead of the gas consumed
// from the tx gas pool. The latter only has the value so far since the
// EthSetupContextDecorator, so it will never exceed the block gas limit.
if gasWanted > blockGasLimit {
return ctx, errors.Wrapf(
errortypes.ErrOutOfGas,
"tx gas (%d) exceeds block gas limit (%d)",
gasWanted,
blockGasLimit,
)
}

// Set tx GasMeter with a limit of GasWanted (i.e. gas limit from the Ethereum tx).
// The gas consumed will be then reset to the gas used by the state transition
// in the EVM.

// FIXME: use a custom gas configuration that doesn't add any additional gas and only
// takes into account the gas consumed at the end of the EVM transaction.
newCtx := ctx.
WithGasMeter(eth.NewInfiniteGasMeterWithLimit(gasWanted)).
WithPriority(minPriority)

// we know that we have enough gas on the pool to cover the intrinsic gas
return next(newCtx, tx, simulate)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Review the logic for gas consumption and error handling.

The logic for handling gas consumption in lines 103-112 seems complex and could be prone to errors. Consider simplifying this logic or adding more comments to explain the reasoning behind these calculations.

Comment on lines +159 to +167
// FIXME: use a custom gas configuration that doesn't add any additional gas and only
// takes into account the gas consumed at the end of the EVM transaction.
newCtx := ctx.
WithGasMeter(eth.NewInfiniteGasMeterWithLimit(gasWanted)).
WithPriority(minPriority)

// we know that we have enough gas on the pool to cover the intrinsic gas
return next(newCtx, tx, simulate)
}
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 with custom gas configuration.

The comment on line 159 suggests a FIXME for using a custom gas configuration. This needs to be addressed to ensure that the gas consumed is accurately accounted for at the end of the EVM transaction.

Comment on lines 12 to 106
func (s *TestSuite) TestGasWantedDecorator() {
testCases := []struct {
name string
ctxSetup func(deps *evmtest.TestDeps)
txSetup func(deps *evmtest.TestDeps) sdk.Tx
wantErr string
}{
{
name: "happy: non fee tx type",
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return happyCreateContractTx(deps)
},
wantErr: "",
},
{
name: "happy: tx without gas, block gas limit 1000",
ctxSetup: func(deps *evmtest.TestDeps) {
cp := &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{MaxGas: 1000},
}
deps.Ctx = deps.Ctx.WithConsensusParams(cp)
},
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return legacytx.StdTx{
Msgs: []sdk.Msg{
happyCreateContractTx(deps),
},
}
},
wantErr: "",
},
{
name: "happy: tx with gas wanted 500, block gas limit 1000",
ctxSetup: func(deps *evmtest.TestDeps) {
cp := &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{MaxGas: 1000},
}
deps.Ctx = deps.Ctx.WithConsensusParams(cp)
},
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return legacytx.StdTx{
Msgs: []sdk.Msg{
happyCreateContractTx(deps),
},
Fee: legacytx.StdFee{Gas: 500},
}
},
wantErr: "",
},
{
name: "sad: tx with gas wanted 1000, block gas limit 500",
ctxSetup: func(deps *evmtest.TestDeps) {
cp := &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{
MaxGas: 500,
},
}
deps.Ctx = deps.Ctx.WithConsensusParams(cp)
},
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return legacytx.StdTx{
Msgs: []sdk.Msg{
happyCreateContractTx(deps),
},
Fee: legacytx.StdFee{Gas: 1000},
}
},
wantErr: "exceeds block gas limit",
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
deps := evmtest.NewTestDeps()
stateDB := deps.StateDB()
anteDec := app.AnteDecoratorGasWanted{}

tx := tc.txSetup(&deps)
s.Require().NoError(stateDB.Commit())

deps.Ctx = deps.Ctx.WithIsCheckTx(true)
if tc.ctxSetup != nil {
tc.ctxSetup(&deps)
}
_, err := anteDec.AnteHandle(
deps.Ctx, tx, false, NextNoOpAnteHandler,
)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Refactor to improve test readability and maintainability.

The test cases could be refactored to use a more structured approach, such as table-driven tests, to improve readability and maintainability.

Comment on lines +35 to +86
// AnteHandle validates checks that the sender balance is greater than the total transaction cost.
// The account will be set to store if it doesn't exist, i.e. cannot be found on store.
// This AnteHandler decorator will fail if:
// - any of the msgs is not a MsgEthereumTx
// - from address is empty
// - account balance is lower than the transaction cost
func (anteDec AnteDecVerifyEthAcc) AnteHandle(
ctx sdk.Context,
tx sdk.Tx,
simulate bool,
next sdk.AnteHandler,
) (newCtx sdk.Context, err error) {
if !ctx.IsCheckTx() {
return next(ctx, tx, simulate)
}

for i, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evm.MsgEthereumTx)
if !ok {
return ctx, errors.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evm.MsgEthereumTx)(nil))
}

txData, err := evm.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, errors.Wrapf(err, "failed to unpack tx data any for tx %d", i)
}

// sender address should be in the tx cache from the previous AnteHandle call
from := msgEthTx.GetFrom()
if from.Empty() {
return ctx, errors.Wrap(errortypes.ErrInvalidAddress, "from address cannot be empty")
}

// check whether the sender address is EOA
fromAddr := gethcommon.BytesToAddress(from)
acct := anteDec.EvmKeeper.GetAccount(ctx, fromAddr)

if acct == nil {
acc := anteDec.AccountKeeper.NewAccountWithAddress(ctx, from)
anteDec.AccountKeeper.SetAccount(ctx, acc)
acct = statedb.NewEmptyAccount()
} else if acct.IsContract() {
return ctx, errors.Wrapf(errortypes.ErrInvalidType,
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
}

if err := keeper.CheckSenderBalance(sdkmath.NewIntFromBigInt(acct.Balance), txData); err != nil {
return ctx, errors.Wrap(err, "failed to check sender balance")
}
}
return next(ctx, tx, simulate)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure consistent error handling and improve error messages.

The error messages could be more consistent and provide more context about the failure, which would aid in debugging and user understanding.

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 (1)
app/evmante_verify_eth_acc_test.go (1)

123-123: Consider renaming happyTransfertTx to happyTransferTx to correct the typo and improve readability.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between ec4dfca and fde2383.

Files selected for processing (11)
  • app/evmante_can_transfer.go (1 hunks)
  • app/evmante_can_transfer_test.go (1 hunks)
  • app/evmante_fee_checker_test.go (1 hunks)
  • app/evmante_gas_consume.go (1 hunks)
  • app/evmante_gas_consume_test.go (1 hunks)
  • app/evmante_handler_test.go (1 hunks)
  • app/evmante_increment_sender_seq.go (1 hunks)
  • app/evmante_increment_sender_seq_test.go (1 hunks)
  • app/evmante_reject_msgs_test.go (1 hunks)
  • app/evmante_validate_basic_test.go (1 hunks)
  • app/evmante_verify_eth_acc_test.go (2 hunks)
Files skipped from review as they are similar to previous changes (5)
  • app/evmante_can_transfer.go
  • app/evmante_fee_checker_test.go
  • app/evmante_gas_consume.go
  • app/evmante_gas_consume_test.go
  • app/evmante_increment_sender_seq.go
Additional comments not posted (3)
app/evmante_can_transfer_test.go (1)

14-109: Enhance test coverage for edge cases as previously suggested. Consider adding more edge cases, such as boundary values for fees and gas prices, to ensure robustness.

app/evmante_verify_eth_acc_test.go (1)

138-146: The implementation of nonEvmMsgTx correctly constructs a non-EVM transaction using the Cosmos SDK's bank module. Good use of utility functions for clarity and maintainability.

app/evmante_validate_basic_test.go (1)

20-243: The TestEthValidateBasicDecorator function comprehensively tests the basic validation of Ethereum transactions with a variety of scenarios. Excellent structuring of test cases and effective use of utility functions.

Comment on lines +10 to +46
func (s *TestSuite) TestAnteDecoratorPreventEtheruemTxMsgs() {
testCases := []struct {
name string
txSetup func(deps *evmtest.TestDeps) sdk.Tx
wantErr string
}{
{
name: "sad: evm message",
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return happyTransfertTx(deps, 0)
},
wantErr: "invalid type",
},
{
name: "happy: non evm message",
txSetup: nonEvmMsgTx,
wantErr: "",
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
deps := evmtest.NewTestDeps()
anteDec := app.AnteDecoratorPreventEtheruemTxMsgs{}
tx := tc.txSetup(&deps)

_, err := anteDec.AnteHandle(
deps.Ctx, tx, false, NextNoOpAnteHandler,
)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure correct spelling in function and decorator names to maintain professionalism and avoid confusion.

- func (s *TestSuite) TestAnteDecoratorPreventEtheruemTxMsgs() {
+ func (s *TestSuite) TestAnteDecoratorPreventEthereumTxMsgs() {
- anteDec := app.AnteDecoratorPreventEtheruemTxMsgs{}
+ anteDec := app.AnteDecoratorPreventEthereumTxMsgs{}
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 (s *TestSuite) TestAnteDecoratorPreventEtheruemTxMsgs() {
testCases := []struct {
name string
txSetup func(deps *evmtest.TestDeps) sdk.Tx
wantErr string
}{
{
name: "sad: evm message",
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return happyTransfertTx(deps, 0)
},
wantErr: "invalid type",
},
{
name: "happy: non evm message",
txSetup: nonEvmMsgTx,
wantErr: "",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
deps := evmtest.NewTestDeps()
anteDec := app.AnteDecoratorPreventEtheruemTxMsgs{}
tx := tc.txSetup(&deps)
_, err := anteDec.AnteHandle(
deps.Ctx, tx, false, NextNoOpAnteHandler,
)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)
})
}
}
func (s *TestSuite) TestAnteDecoratorPreventEthereumTxMsgs() {
testCases := []struct {
name string
txSetup func(deps *evmtest.TestDeps) sdk.Tx
wantErr string
}{
{
name: "sad: evm message",
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return happyTransfertTx(deps, 0)
},
wantErr: "invalid type",
},
{
name: "happy: non evm message",
txSetup: nonEvmMsgTx,
wantErr: "",
},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
deps := evmtest.NewTestDeps()
anteDec := app.AnteDecoratorPreventEthereumTxMsgs{}
tx := tc.txSetup(&deps)
_, err := anteDec.AnteHandle(
deps.Ctx, tx, false, NextNoOpAnteHandler,
)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)
})
}
}

Comment on lines +13 to +93
func (s *TestSuite) TestAnteDecEthIncrementSenderSequence() {
testCases := []struct {
name string
beforeTxSetup func(deps *evmtest.TestDeps, sdb *statedb.StateDB)
txSetup func(deps *evmtest.TestDeps) sdk.Tx
wantErr string
wantSeq uint64
}{
{
name: "happy: single message",
beforeTxSetup: func(deps *evmtest.TestDeps, sdb *statedb.StateDB) {
balance := big.NewInt(100)
sdb.AddBalance(deps.Sender.EthAddr, balance)
},
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return happyTransfertTx(deps, 0)
},
wantErr: "",
wantSeq: 1,
},
{
name: "happy: two messages",
beforeTxSetup: func(deps *evmtest.TestDeps, sdb *statedb.StateDB) {
balance := big.NewInt(100)
sdb.AddBalance(deps.Sender.EthAddr, balance)
},
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
txMsgOne := happyTransfertTx(deps, 0)
txMsgTwo := happyTransfertTx(deps, 1)

txBuilder := deps.EncCfg.TxConfig.NewTxBuilder()
s.Require().NoError(txBuilder.SetMsgs(txMsgOne, txMsgTwo))

tx := txBuilder.GetTx()
return tx
},
wantErr: "",
wantSeq: 2,
},
{
name: "sad: account does not exists",
txSetup: func(deps *evmtest.TestDeps) sdk.Tx {
return happyTransfertTx(deps, 0)
},
wantErr: "unknown address",
},
{
name: "sad: tx with non evm message",
txSetup: nonEvmMsgTx,
wantErr: "invalid message",
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
deps := evmtest.NewTestDeps()
stateDB := deps.StateDB()
anteDec := app.NewAnteDecEthIncrementSenderSequence(deps.Chain.AppKeepers)

if tc.beforeTxSetup != nil {
tc.beforeTxSetup(&deps, stateDB)
s.Require().NoError(stateDB.Commit())
}
tx := tc.txSetup(&deps)

_, err := anteDec.AnteHandle(
deps.Ctx, tx, false, NextNoOpAnteHandler,
)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)

if tc.wantSeq > 0 {
seq := deps.Chain.AccountKeeper.GetAccount(deps.Ctx, deps.Sender.NibiruAddr).GetSequence()
s.Require().Equal(tc.wantSeq, seq)
}
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding a test case to verify the behavior when the sequence increment fails due to database errors.

Would you like me to help draft this additional test case?

Comment on lines +18 to +104
func (s *TestSuite) TestAnteHandlerEVM() {
testCases := []struct {
name string
txSetup func(deps *evmtest.TestDeps) sdk.FeeTx
ctxSetup func(deps *evmtest.TestDeps)
beforeTxSetup func(deps *evmtest.TestDeps, sdb *statedb.StateDB)
wantErr string
}{
{
name: "happy: signed tx, sufficient funds",
beforeTxSetup: func(deps *evmtest.TestDeps, sdb *statedb.StateDB) {
sdb.AddBalance(
deps.Sender.EthAddr,
new(big.Int).Add(gasLimitCreateContract(), big.NewInt(100)),
)
},
ctxSetup: func(deps *evmtest.TestDeps) {
gasPrice := sdk.NewInt64Coin("unibi", 1)
cp := &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{
MaxGas: new(big.Int).Add(gasLimitCreateContract(), big.NewInt(100)).Int64(),
},
}
deps.Ctx = deps.Ctx.
WithMinGasPrices(
sdk.NewDecCoins(sdk.NewDecCoinFromCoin(gasPrice)),
).
WithIsCheckTx(true).
WithConsensusParams(cp)
},
txSetup: func(deps *evmtest.TestDeps) sdk.FeeTx {
txMsg := happyTransfertTx(deps, 0)
txBuilder := deps.EncCfg.TxConfig.NewTxBuilder()

gethSigner := deps.Sender.GethSigner(deps.Chain.EvmKeeper.EthChainID(deps.Ctx))
keyringSigner := deps.Sender.KeyringSigner
err := txMsg.Sign(gethSigner, keyringSigner)
s.Require().NoError(err)

tx, err := txMsg.BuildTx(txBuilder, eth.EthBaseDenom)
s.Require().NoError(err)

return tx
},
wantErr: "",
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
deps := evmtest.NewTestDeps()
stateDB := deps.StateDB()

anteHandlerEVM := app.NewAnteHandlerEVM(
deps.Chain.AppKeepers, ante.AnteHandlerOptions{
HandlerOptions: authante.HandlerOptions{
AccountKeeper: deps.Chain.AccountKeeper,
BankKeeper: deps.Chain.BankKeeper,
FeegrantKeeper: deps.Chain.FeeGrantKeeper,
SignModeHandler: deps.EncCfg.TxConfig.SignModeHandler(),
SigGasConsumer: authante.DefaultSigVerificationGasConsumer,
ExtensionOptionChecker: func(*codectypes.Any) bool { return true },
},
})

tx := tc.txSetup(&deps)

if tc.ctxSetup != nil {
tc.ctxSetup(&deps)
}
if tc.beforeTxSetup != nil {
tc.beforeTxSetup(&deps, stateDB)
err := stateDB.Commit()
s.Require().NoError(err)
}

_, err := anteHandlerEVM(
deps.Ctx, tx, false,
)
if tc.wantErr != "" {
s.Require().ErrorContains(err, tc.wantErr)
return
}
s.Require().NoError(err)
})
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding more comprehensive tests for the AnteHandlerEVM, especially focusing on scenarios where multiple handlers interact and on error propagation.

Would you like assistance in drafting these additional test scenarios?

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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between fde2383 and 8a50e0e.

Files selected for processing (1)
  • contrib/make/test.mk (1 hunks)
Files skipped from review due to trivial changes (1)
  • contrib/make/test.mk

@Unique-Divine Unique-Divine merged commit 6511f86 into main Jun 11, 2024
18 checks passed
@Unique-Divine Unique-Divine deleted the on/evm-ante-test branch June 11, 2024 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants