-
Notifications
You must be signed in to change notification settings - Fork 202
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): Use a NibiruBankKeeper to automatically record ether balance changes on the StateDB journal #2095
Conversation
1. Created NibiruBankKeeper with safety around NIBI transfers inside of EthereumTx. 2. The "PrecompileCalled" JournalChange now has a propery implementation and a strong test case to show that reverting the precompile calls works as intended. 3. Remove unneeded functions created for testing with low-level struct fields.
WalkthroughThe pull request includes extensive updates to the Nibiru EVM, primarily reflected in the Changes
Possibly related PRs
Suggested reviewers
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2095 +/- ##
==========================================
+ Coverage 64.58% 64.67% +0.09%
==========================================
Files 271 272 +1
Lines 21237 21290 +53
==========================================
+ Hits 13716 13770 +54
+ Misses 6574 6568 -6
- Partials 947 952 +5
|
go.mod
Outdated
github.com/CosmWasm/wasmd => github.com/NibiruChain/wasmd v0.44.0-nibiru | ||
github.com/cosmos/cosmos-sdk => github.com/NibiruChain/cosmos-sdk v0.47.11-nibiru |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For other reviewers:
cosmos/cosmos-sdk@v0.47.11...NibiruChain:v0.47.11-nibiru
CosmWasm/wasmd@v0.44.0...NibiruChain:v0.44.0-nibiru
Cosmos SDK fork introduces functions Copy()
forCacheMultiStore()
which is then used within precompile to save the state before precompile execution (and potentially revert after).
x/evm/keeper/bank_extension.go
Outdated
func (evmKeeper *Keeper) NewStateDB( | ||
ctx sdk.Context, txConfig statedb.TxConfig, | ||
) *statedb.StateDB { | ||
stateDB := statedb.New(ctx, evmKeeper, txConfig) | ||
evmKeeper.Bank.ResetStateDB(stateDB) | ||
return stateDB | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should evmKeeper
func be hosted in bank extension? Maybe better move it the keeper itself?
x/evm/keeper/erc20.go
Outdated
// Using tmp context to not modify the state in case of evm revert | ||
tmpCtx, commitCtx := ctx.CacheContext() | ||
|
||
evmResp, evmObj, err = k.ApplyEvmMsg( | ||
tmpCtx, evmMsg, evm.NewNoOpTracer(), commit, evmCfg, txConfig, | ||
ctx, evmMsg, evm.NewNoOpTracer(), commit, evmCfg, txConfig, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was here for gas estimation, if I recall correctly, as it used to loop several times during binary search. I believe the line was mislabeled with that comment. I don't think it fixes the precompile-try-catch-revert situation either, so the caching is unnecessary
…pModule.RegisterServices This makes it possible to plug in an alternative bankkeeper.Keeper implementation instead of bankkeeper.BaseKeeper.
f72ef6e
to
9f7160b
Compare
stateDB := deps.StateDB() | ||
stateDB := deps.NewStateDB() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function is renamed from StateDB
to NewStateDB
everywhere to reflect that fact that it's not a getter for an existing StateDB
and instead generates and returns a new pointer for a StateDB
with a fresh journal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We export an instance of the precompiled contract preset to its address as a constant in the Solidity code for convenience. We still need to publish these contracts on npm
(ts-sdk#376) after the API becomes more solidified.
interface IFunToken { ... }
address constant FUNTOKEN_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000800;
IFunToken constant FUNTOKEN_PRECOMPILE = IFunToken(FUNTOKEN_PRECOMPILE_ADDRESS);
This makes it possible to use the functions with strong typing via the imported FUNTOKEN_PRECOMPILE
variable.
appCodec, | ||
keys[evm.StoreKey], | ||
tkeys[evm.TransientKey], | ||
authtypes.NewModuleAddress(govtypes.ModuleName), | ||
app.AccountKeeper, | ||
app.BankKeeper, | ||
nibiruBankKeeper, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Written this way to make sure the EVM keeper and its constructor have the stronger typed NibiruBankKeeper
rather than an a bankkeeper.Keeper
interface
addrBech32 := eth.EthAddrToNibiruAddr(addr) | ||
balance := k.Bank.GetBalance(ctx, addrBech32, evm.EVMBankDenom).Amount.BigInt() | ||
delta := new(big.Int).Sub(amountEvmDenom, balance) | ||
bk := k.Bank.BaseKeeper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Bank.BaseKeeper
needs to be used here because we're inside the setter that the StateDB
uses to commit balances. Using the NibiruBankKeeper
's overrides would double-label and mutate the journal while its being committed, leading to strange behavior.
CHANGELOG.md
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to better about having meaningful changelog entry descriptions and keep it organized rather than simply copying PR titles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Outside diff range and nitpick comments (25)
x/evm/evmtest/eth_test.go (1)
39-44
: Consider expanding test coverage with additional scenarios.The test could be more comprehensive by:
- Adding cases that verify actual balance changes after transfers
- Testing edge cases with large numbers
- Including scenarios that trigger state reversions
This would help ensure the new
NibiruBankKeeper
correctly handles all balance change scenarios.Example addition:
// Test balance changes evmtest.FunTokenBalanceAssert{ FunToken: funtoken, Account: deps.Sender.EthAddr, BalanceBank: big.NewInt(100), BalanceERC20: big.NewInt(100), }.Assert(s.T(), deps) // Perform a transfer // ... transfer code ... // Verify updated balances evmtest.FunTokenBalanceAssert{ FunToken: funtoken, Account: deps.Sender.EthAddr, BalanceBank: big.NewInt(50), BalanceERC20: big.NewInt(50), }.Assert(s.T(), deps)app/evmante/evmante_handler.go (1)
Line range hint
1-28
: Consider adding metrics for ante handler performance.Given that these changes are part of integrating automatic balance tracking with NibiruBankKeeper, and ante handlers are in the critical path for transaction processing:
- Consider adding metrics to monitor the performance impact of these changes, especially for the new balance tracking functionality.
- Monitor the StateDB journal size and operation counts to ensure efficient state management.
- Add telemetry for failed transactions to quickly identify any issues with the new keeper integration.
Would you like help implementing these monitoring suggestions?
x/evm/evmtest/smart_contract_test.go (1)
36-36
: LGTM! Consider extracting common test setupThe change maintains consistency with the state management improvements. Since both test functions use similar setup logic, consider extracting the common nonce initialization into a helper function.
Consider refactoring like this:
func getNonceForTest(deps *evmtest.TestDeps, ethAcc *evmtest.EthPrivateAccount) uint64 { return deps.NewStateDB().GetNonce(ethAcc.EthAddr) }x/evm/evmtest/test_deps.go (1)
Line range hint
48-55
: LGTM! Consider adding documentation.The rename from
StateDB
toNewStateDB
better reflects the constructor nature of this method. This aligns with Go naming conventions and improves code clarity.Consider adding a doc comment to clarify the purpose and usage:
+// NewStateDB creates a new StateDB instance with an empty transaction config. +// The transaction hash is derived from the current context's header hash. func (deps TestDeps) NewStateDB() *statedb.StateDB {app/ante/handler_opts.go (1)
Line range hint
28-47
: Add EvmKeeper validation in ValidateAndClean()The ValidateAndClean() method validates other critical keepers but lacks validation for EvmKeeper. Given the EVM's importance in transaction processing and the recent changes to enhance NIBI transfer recording, this validation should be added.
Add the validation with this diff:
func (opts *AnteHandlerOptions) ValidateAndClean() error { if opts.BankKeeper == nil { return AnteHandlerError("bank keeper") } + if opts.EvmKeeper == nil { + return AnteHandlerError("evm keeper") + } if opts.SignModeHandler == nil { return AnteHandlerError("sign mode handler") }x/evm/keeper/statedb_test.go (2)
Line range hint
83-92
: Consider adding edge case tests for bank-to-EVM interactions.While the basic bank transfer test is good, consider adding test cases for:
- Failed bank transfers and their impact on EVM state
- Concurrent bank and EVM transfers
- Edge cases around maximum/minimum transfer amounts
Would you like me to help generate these additional test cases?
Line range hint
8-15
: Enhance test documentation with NibiruBankKeeper context.Since this PR introduces the NibiruBankKeeper for automatic balance recording, consider updating the test documentation to explicitly mention how these tests verify the automatic state recording functionality.
// TestStateDBBalance tests the behavior of the StateDB with regards to account // balances, ensuring correct conversion between native tokens (unibi) and EVM -// tokens (wei), as well as proper balance updates during transfers. +// tokens (wei), as well as proper balance updates during transfers. It verifies +// that the NibiruBankKeeper correctly records balance changes in the StateDB +// journal automatically during both EVM and bank operations.x/evm/evmtest/erc20.go (1)
116-123
: Consider enhancing error reporting in the Assert method.The implementation effectively checks both ERC20 and bank balances. However, consider these improvements:
- Aggregate errors to show all balance mismatches at once rather than failing on the first error.
- Add documentation explaining the expected relationship between ERC20 and bank balances.
Example documentation:
+// Assert verifies that both the ERC20 and bank balances match the expected values. +// This ensures consistency between the EVM state and the Cosmos bank module state, +// which should remain synchronized during token transfers. func (bals FunTokenBalanceAssert) Assert(t *testing.T, deps TestDeps) {x/evm/precompile/funtoken_test.go (2)
Line range hint
123-137
: LGTM! Consider adding edge cases.The test setup and assertion for bank keeper consistency look good. This aligns well with the PR's objective of using NibiruBankKeeper throughout the system.
Consider adding test cases for:
- Zero amount transfers
- Maximum amount transfers
- Transfers to self
Line range hint
148-159
: Consider verifying StateDB journal entries.While the test verifies that StateDB is not nil and the response amount is correct, it would be valuable to also verify that the balance changes are properly recorded in the StateDB journal.
Consider adding assertions to verify:
- The presence of balance change entries in the StateDB journal
- The correct order of journal entries
- The ability to revert these changes through the journal
x/evm/keeper/funtoken_from_erc20.go (1)
Line range hint
125-140
: Consider adding transaction boundary documentation.The implementation is solid, but it would be helpful to document whether this function should be called within a transaction boundary, especially since it performs multiple state modifications (metadata setting and FunToken insertion).
Add a note in the function documentation:
// createFunTokenFromERC20 creates a new FunToken mapping from an existing ERC20 token. // // This function performs the following steps: // 1. Checks if the ERC20 token is already registered as a FunToken. // 2. Retrieves the metadata of the existing ERC20 token. // 3. Verifies that the corresponding bank coin denom is not already registered. // 4. Sets the bank coin denom metadata in the state. // 5. Creates and inserts the new FunToken mapping. +// +// Note: This function performs multiple state modifications and should be called +// within a transaction boundary to ensure atomicity.x/evm/keeper/gas_fees.go (2)
139-141
: LGTM! Consider adding specific test cases.The change to use
k.Bank
is consistent with the NibiruBankKeeper integration. Since this handles critical fee deductions, consider adding specific test cases to verify:
- Proper balance updates in both Bank and StateDB
- Correct error handling for insufficient funds
- StateDB journal entry creation
Would you like me to help generate comprehensive test cases for these scenarios?
Inconsistent usage of Bank vs bankKeeper across modules
The verification reveals that while the EVM module consistently uses
k.Bank
, other modules liketokenfactory
,inflation
, andoracle
are still usingk.bankKeeper
. This inconsistency needs to be addressed.
x/evm/keeper/*
: Usesk.Bank
consistently (✓)x/tokenfactory/keeper/*
: Usesk.bankKeeper
(needs update)x/inflation/keeper/*
: Usesk.bankKeeper
(needs update)x/oracle/keeper/*
: Usesk.bankKeeper
(needs update)🔗 Analysis chain
Line range hint
63-67
: LGTM! Verify consistent Bank field usage.The change to use
k.Bank
aligns with the PR's objective of using NibiruBankKeeper to automatically record ether balance changes. The error handling remains robust.Let's verify consistent usage across the codebase:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify consistent usage of Bank vs bankKeeper # Expect: All occurrences should use k.Bank instead of k.bankKeeper # Search for any remaining instances of bankKeeper rg "k\.bankKeeper" # Compare with new Bank usage rg "k\.Bank\."Length of output: 2929
x/evm/keeper/statedb.go (1)
84-96
: Consider enhancing error messages for better debugging.While the mint/burn operations are correctly implemented, the error handling could be more descriptive to aid in debugging.
Consider wrapping errors with context:
if err := bk.MintCoins(ctx, evm.ModuleName, coins); err != nil { - return err + return fmt.Errorf("failed to mint %s: %w", coins, err) } if err := bk.SendCoinsFromModuleToAccount(ctx, evm.ModuleName, addrBech32, coins); err != nil { - return err + return fmt.Errorf("failed to send minted coins to %s: %w", addrBech32, err) }Similar improvements can be applied to the burn operations.
x/evm/keeper/msg_ethereum_tx_test.go (1)
Line range hint
50-208
: Consider documenting state management strategy.The consistent change from
StateDB()
toNewStateDB()
across all test cases reflects a significant shift in state management strategy. Consider adding a comment explaining this pattern and its relationship with theNibiruBankKeeper
integration.Add a comment at the top of the test file explaining the state management strategy:
package keeper_test import ( // ... existing imports ... ) +// The test suite uses NewStateDB() to ensure each test case starts with a fresh state, +// which is crucial for proper integration with NibiruBankKeeper's automatic recording +// of ether balance changes on the StateDB journal.app/evmante/evmante_validate_basic_test.go (1)
201-201
: Add test cases for StateDB journal functionality.While the change to
NewStateDB()
aligns with the PR's objective of enhancing ether balance recording, the test suite would benefit from additional test cases that verify the automatic recording of balance changes in the StateDB journal.Would you like me to help create test cases that validate:
- Journal entries are correctly created for ether transfers
- Journal entries are properly reverted on failed transactions
- StateDB and Bank module states remain in sync
x/evm/evmtest/tx.go (1)
173-174
: Add documentation for DefaultEthCallGasLimitWhile the variable is appropriately placed and sourced from configuration, it would benefit from documentation explaining its purpose, usage, and any constraints or considerations for its value.
Add documentation above the variable:
+// DefaultEthCallGasLimit defines the default gas limit used for eth_call operations. +// This value is sourced from the server configuration and used during gas estimation +// in GenerateEthTxMsgAndSigner. var DefaultEthCallGasLimit = srvconfig.DefaultEthCallGasLimitx/evm/keeper/funtoken_from_erc20_test.go (2)
Line range hint
1-24
: Add test cases for StateDB journal entries.While the test suite comprehensively covers FunToken creation and conversion scenarios, it would be beneficial to add test cases that verify the automatic recording of balance changes in the StateDB journal, which is a key objective of this PR.
Consider adding test cases to verify:
- Journal entries are correctly recorded during balance changes
- Journal entries are properly reverted on failed transactions
- State consistency between Bank module and StateDB after commits/reversions
Would you like me to help generate these additional test cases?
Line range hint
279-357
: LGTM! Comprehensive security testing for malicious contracts.The test cases for malicious ERC20 contracts effectively verify protection against gas exhaustion attacks. This is particularly important given the integration with the new
NibiruBankKeeper
.Consider adding test cases for additional edge cases:
- Reentrant calls during token conversion
- Malicious contracts that attempt to manipulate the StateDB journal
x/evm/keeper/funtoken_from_coin_test.go (1)
479-487
: Consider using a constant for token decimals.While the addition of proper denomination metadata and ERC20 decimals verification is good, the decimal value (6) is hardcoded in multiple places. Consider extracting this into a constant to maintain consistency and make future updates easier.
+ const NIBI_TOKEN_DECIMALS = 6 DenomUnits: []*bank.DenomUnit{ { Denom: bankDenom, Exponent: 0, }, { Denom: "NIBI", - Exponent: 6, + Exponent: NIBI_TOKEN_DECIMALS, }, },Also applies to: 509-515
x/evm/statedb/statedb.go (1)
81-83
: Consider documenting integration with NibiruBankKeeperGiven that this function is part of the integration with
NibiruBankKeeper
for automatic recording of ether balance changes, it would be valuable to add documentation explaining:
- The relationship between
StateDB
andNibiruBankKeeper
- How this function enables automatic balance recording
- Thread safety considerations when accessing the shared state
Add documentation above the function:
+// FromVM retrieves the StateDB instance from an EVM object. This function is used +// by the NibiruBankKeeper to automatically record ether balance changes in the +// StateDB's journal during precompiled contract calls. The StateDB instance +// maintains the transaction context and ensures that all state changes are +// properly tracked and can be reverted if needed. +// +// Thread Safety: This function should only be called from the context of the +// current transaction as StateDB is not thread-safe. func FromVM(evmObj *vm.EVM) *StateDB {x/evm/keeper/msg_server.go (2)
515-521
: Enhance error message specificity.The error message could be more specific by including the coin denomination and amount.
- return nil, errors.Wrap(err, "failed to send coins to module account") + return nil, errors.Wrapf(err, "failed to send %s coins to module account", coin)
Line range hint
563-597
: Ensure atomicity of bank operations.Similar to the previous suggestion, the bank operations (send and burn) should be atomic to prevent coins from being stuck in the module account if the burn operation fails.
Consider wrapping the operations in a transaction:
func (k Keeper) convertCoinToEvmBornERC20(...) (*evm.MsgConvertCoinToEvmResponse, error) { erc20Addr := funTokenMapping.Erc20Addr.Address + + // Create a cached context for transaction-like behavior + cacheCtx, commit := ctx.CacheContext() if err := k.Bank.SendCoinsFromAccountToModule( - ctx, + cacheCtx, sender, evm.ModuleName, sdk.NewCoins(coin), ); err != nil { return nil, errors.Wrap(err, "error sending Bank Coins to the EVM") } actualSentAmount, err := k.ERC20().Transfer( erc20Addr, evm.EVM_MODULE_ADDRESS, recipient, coin.Amount.BigInt(), - ctx, + cacheCtx, ) if err != nil { return nil, errors.Wrap(err, "failed to transfer ERC-20 tokens") } burnCoin := sdk.NewCoin(coin.Denom, sdk.NewIntFromBigInt(actualSentAmount)) - err = k.Bank.BurnCoins(ctx, evm.ModuleName, sdk.NewCoins(burnCoin)) + err = k.Bank.BurnCoins(cacheCtx, evm.ModuleName, sdk.NewCoins(burnCoin)) if err != nil { return nil, errors.Wrap(err, "failed to burn coins") } + + // Commit changes if all operations succeed + commit()CHANGELOG.md (2)
71-74
: Consider making the changelog entry more concise and consistent.The entry for #2090 could be more concise while maintaining clarity. Consider reformatting to a single line like other entries:
-- fix(evm): Account -for (1) ERC20 transfers with tokens that return false success values instead of -throwing an error and (2) ERC20 transfers with other operations that don't bring -about the expected resulting balance for the transfer recipient. +- fix(evm): Account for ERC20 transfers with false success values and unexpected balance changes
86-95
: Consider improving formatting and conciseness of the changelog entry.The entry for #2095 spans multiple lines with inconsistent formatting. Consider making it more concise while preserving the key information:
-- fix(evm): This -change records NIBI (ether) transfers on the `StateDB` during precompiled -contract calls using the `NibiruBankKeeper`, which is struct extension of -the `bankkeeper.BaseKeeper` that is used throughout Nibiru. -The `NibiruBankKeeper` holds a reference to the current EVM `StateDB` and records -balance changes in wei as journal changes automatically. This guarantees that -commits and reversions of the `StateDB` do not misalign with the state of the -Bank module. This code change uses the `NibiruBankKeeper` on all modules that -depend on x/bank, such as the EVM and Wasm modules. +- fix(evm): Implement NibiruBankKeeper to automatically record NIBI transfers on StateDB during precompiled contract calls, ensuring state consistency between Bank module and StateDB journal
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
go.sum
is excluded by!**/*.sum
📒 Files selected for processing (44)
CHANGELOG.md
(2 hunks)app/ante/gas_wanted_test.go
(1 hunks)app/ante/handler_opts.go
(1 hunks)app/evmante/evmante_can_transfer.go
(1 hunks)app/evmante/evmante_can_transfer_test.go
(1 hunks)app/evmante/evmante_emit_event_test.go
(1 hunks)app/evmante/evmante_gas_consume_test.go
(1 hunks)app/evmante/evmante_handler.go
(1 hunks)app/evmante/evmante_handler_test.go
(1 hunks)app/evmante/evmante_increment_sender_seq_test.go
(1 hunks)app/evmante/evmante_mempool_fees_test.go
(1 hunks)app/evmante/evmante_setup_ctx_test.go
(1 hunks)app/evmante/evmante_sigverify_test.go
(1 hunks)app/evmante/evmante_validate_basic_test.go
(1 hunks)app/evmante/evmante_verify_eth_acc_test.go
(1 hunks)app/keepers.go
(4 hunks)app/keepers/all_keepers.go
(1 hunks)go.mod
(1 hunks)x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json
(1 hunks)x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol
(1 hunks)x/evm/evmmodule/genesis_test.go
(1 hunks)x/evm/evmtest/erc20.go
(1 hunks)x/evm/evmtest/eth_test.go
(1 hunks)x/evm/evmtest/smart_contract_test.go
(2 hunks)x/evm/evmtest/test_deps.go
(2 hunks)x/evm/evmtest/tx.go
(7 hunks)x/evm/keeper/bank_extension.go
(1 hunks)x/evm/keeper/erc20.go
(1 hunks)x/evm/keeper/funtoken_from_coin.go
(1 hunks)x/evm/keeper/funtoken_from_coin_test.go
(14 hunks)x/evm/keeper/funtoken_from_erc20.go
(2 hunks)x/evm/keeper/funtoken_from_erc20_test.go
(1 hunks)x/evm/keeper/gas_fees.go
(2 hunks)x/evm/keeper/grpc_query_test.go
(2 hunks)x/evm/keeper/keeper.go
(4 hunks)x/evm/keeper/msg_ethereum_tx_test.go
(4 hunks)x/evm/keeper/msg_server.go
(5 hunks)x/evm/keeper/statedb.go
(1 hunks)x/evm/keeper/statedb_test.go
(3 hunks)x/evm/precompile/funtoken.go
(4 hunks)x/evm/precompile/funtoken_test.go
(3 hunks)x/evm/precompile/wasm.go
(4 hunks)x/evm/statedb/statedb.go
(1 hunks)x/evm/statedb/statedb_test.go
(16 hunks)
🔇 Additional comments (71)
x/evm/evmtest/eth_test.go (1)
39-44
: LGTM! Clean struct-based assertion implementation.
The transition to FunTokenBalanceAssert
provides a more structured and explicit way to verify both bank and ERC20 balances.
app/evmante/evmante_handler.go (2)
16-26
: Verify decorator execution order remains correct for StateDB operations.
The order of decorators is crucial for proper transaction processing, especially with the new NibiruBankKeeper integration. The current order appears correct with setup, validation, signature verification, account verification, transfer checks, gas consumption, and sequence management.
Let's verify there are no other decorator order definitions that might conflict:
#!/bin/bash
# Description: Verify consistent decorator order across the codebase
# Test: Look for other ChainAnteDecorators calls
echo "Checking for other ante handler chains..."
rg "ChainAnteDecorators\(" app/
16-23
: Verify pointer semantics consistency across decorators.
The changes show a consistent pattern of passing options.EvmKeeper
directly to decorators without the address-of operator, suggesting EvmKeeper
is now a pointer type in handler_opts.go
. This aligns with the broader refactoring for NibiruBankKeeper integration.
Let's verify the pointer type consistency:
Also applies to: 26-26
✅ Verification successful
Pointer semantics are consistent across the codebase
The verification confirms that the pointer semantics are correctly implemented:
EvmKeeper
is defined as*evmkeeper.Keeper
inHandlerOptions
- All decorator structs consistently use
*EVMKeeper
in their fields - Constructor functions accept
*EVMKeeper
as parameter - Direct passing of
options.EvmKeeper
in the handler chain is correct as it's already a pointer
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify EvmKeeper type definition and usage consistency
# Test 1: Check EvmKeeper field type in handler options
echo "Checking EvmKeeper type in handler options..."
rg -A 1 "type.*HandlerOptions.*struct" app/ante/
# Test 2: Check decorator struct definitions
echo "Checking decorator definitions..."
rg "type.*(Setup|MempoolGasPrice|ValidateBasic|SigVerification|VerifyEthAcc|CanTransfer|GasConsume|IncrementSenderSequence|EmitEvent).*struct" app/evmante/
# Test 3: Verify no remaining address-of operations for EvmKeeper
echo "Checking for remaining address-of operations..."
rg "options\.EvmKeeper" app/evmante/
Length of output: 620
Script:
#!/bin/bash
# Let's try a different approach to verify the pointer semantics
# Check HandlerOptions definition
echo "=== Checking HandlerOptions definition ==="
rg "type.*HandlerOptions" app/ante/ -A 5
# Check decorator definitions and their EvmKeeper fields
echo -e "\n=== Checking decorator definitions ==="
rg "type.*Decorator.*struct" app/evmante/ -A 3
# Check how EvmKeeper is used in constructor functions
echo -e "\n=== Checking constructor patterns ==="
rg "^func New.*Decorator" app/evmante/ -A 3
# Check all EvmKeeper usages in the file
echo -e "\n=== Checking all EvmKeeper references ==="
rg "EvmKeeper" app/evmante/evmante_handler.go
Length of output: 4005
x/evm/evmtest/smart_contract_test.go (1)
20-20
: Verify state isolation with NewStateDB()
The switch to NewStateDB()
aligns with the broader state management improvements. However, we should verify that this change maintains test determinism and proper state isolation.
✅ Verification successful
The initial results show widespread usage of StateDB() across test files. We need to examine the actual usage patterns to determine if the change to NewStateDB() is part of a broader pattern and whether it maintains consistency with the test suite's design. This will help us verify if the change is appropriate or if it introduces inconsistencies.
Change to NewStateDB() is consistent with codebase patterns
The switch to deps.NewStateDB()
is verified to be correct and consistent with the broader codebase patterns. The evidence shows:
NewStateDB()
is widely used across test files for state management- It's the preferred method for obtaining fresh state instances in test scenarios
- The change aligns with similar usage patterns in related test files like
statedb_test.go
,funtoken_from_erc20_test.go
, and other EVM-related tests - No instances of inconsistent usage were found
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any other test files that might be affected by this state management change
# and verify consistent usage of NewStateDB vs StateDB
# Look for other test files using StateDB
rg -l "StateDB\(\)" --type go --glob "*_test.go"
# Look for potential state management patterns
ast-grep --pattern 'func TestCreate$_($_) {
$$$
StateDB()
$$$
}'
Length of output: 764
Script:
#!/bin/bash
# Let's examine the actual usage patterns of StateDB() vs NewStateDB() in test files
# to understand the consistency and potential impact
# Check for NewStateDB usage patterns
rg "NewStateDB\(\)" --type go --glob "*_test.go" -C 2
# Check specific StateDB usage in the most relevant test files
rg "StateDB\(\)" "x/evm/evmtest/smart_contract_test.go" -C 2
rg "StateDB\(\)" "x/evm/keeper/statedb_test.go" -C 2
Length of output: 14066
app/evmante/evmante_setup_ctx_test.go (2)
16-16
: LGTM! Simplified keeper initialization.
The simplified initialization of anteDec
removes unnecessary pointer wrapping, making the code more idiomatic and cleaner.
15-15
: LGTM! Verify consistent StateDB initialization pattern.
The change to deps.NewStateDB()
aligns with the PR's objective of ensuring proper StateDB reference for the NibiruBankKeeper. This ensures a fresh state for each test run.
Let's verify this initialization pattern is consistent across the codebase:
✅ Verification successful
StateDB initialization pattern is consistent across the codebase
The verification shows that all instances in the codebase use deps.NewStateDB()
consistently, with no occurrences of deps.StateDB()
. The change aligns with the established pattern across test files in various packages including x/evm
, app/ante
, and app/evmante
.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any remaining instances of StateDB() vs NewStateDB()
# to ensure consistent initialization pattern
# Search for both patterns
echo "Checking StateDB initialization patterns:"
rg -A 1 "deps\.StateDB\(\)"
rg -A 1 "deps\.NewStateDB\(\)"
Length of output: 6747
x/evm/evmtest/test_deps.go (1)
25-25
: Verify the impact of EvmKeeper pointer type change on existing tests.
The change from value to pointer type for EvmKeeper
is aligned with the PR objectives. However, we should verify that this doesn't break any existing tests that might rely on value semantics.
✅ Verification successful
Based on the search results, I can now provide a final response since I have enough information to verify the impact of the EvmKeeper pointer type change:
No issues found with EvmKeeper pointer type change
The search results show that all existing test usages of deps.EvmKeeper
are already treating it as a pointer, with operations like:
- Method calls (e.g.,
deps.EvmKeeper.CallContractWithInput()
,deps.EvmKeeper.CreateFunToken()
) - Field access (e.g.,
deps.EvmKeeper.Bank.StateDB
) - No direct assignments or copies that would be affected by value vs pointer semantics
The change from value to pointer type aligns with the existing usage patterns and doesn't impact any test behavior.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for potential test breakages due to EvmKeeper value semantics
# Test: Look for direct assignments or copies of EvmKeeper in tests
rg -g '**/*_test.go' -A 3 'EvmKeeper\s*='
# Test: Look for method calls that might assume value semantics
rg -g '**/*_test.go' -A 3 'deps\.EvmKeeper\.'
Length of output: 31369
app/ante/handler_opts.go (1)
23-23
: LGTM: Type change aligns with existing patterns
The change from evmkeeper.Keeper
to *evmkeeper.Keeper
is consistent with how other keepers are defined in the struct (e.g., IBCKeeper, DevGasKeeper). This alignment with existing patterns improves code consistency.
app/evmante/evmante_emit_event_test.go (2)
44-44
: LGTM: Clean state initialization improves test isolation.
Using NewStateDB()
ensures each test starts with a fresh state, which is crucial for accurate testing of EVM state changes and event emissions.
45-45
: LGTM: Simplified keeper reference.
The direct passing of the keeper instance is cleaner as EvmKeeper
is already a pointer type internally.
app/evmante/evmante_sigverify_test.go (2)
70-70
: LGTM! Removed redundant address-of operator.
The removal of the &
operator is correct since EvmKeeper
is likely already a pointer type in deps.App.AppKeepers.EvmKeeper
. This change maintains consistency with other decorator initializations across the codebase.
69-69
: LGTM! Verify EvmKeeper interface implementation.
The change to use NewStateDB()
is consistent with other test files and aligns with the PR's objective of supporting the NibiruBankKeeper integration.
Let's verify the EvmKeeper interface to ensure it supports the new StateDB initialization:
app/evmante/evmante_gas_consume_test.go (2)
62-62
: LGTM: Explicit StateDB initialization aligns with NibiruBankKeeper requirements.
The change from StateDB()
to NewStateDB()
correctly ensures a fresh StateDB instance for each test case, which is essential for the NibiruBankKeeper's automatic recording of ether balance changes.
64-64
: LGTM: Fixed redundant pointer indirection.
Removed unnecessary address-of operator since EvmKeeper
is already a pointer type, eliminating potential pointer-to-pointer issues.
app/evmante/evmante_increment_sender_seq_test.go (2)
70-70
: LGTM: Proper ante handler initialization.
The ante handler is correctly initialized with the required EvmKeeper
and AccountKeeper
dependencies.
69-69
: Verify state isolation with new StateDB initialization.
The change from deps.StateDB()
to deps.NewStateDB()
suggests a shift towards creating fresh state instances. Let's verify this change is consistent across test files and doesn't affect state isolation.
✅ Verification successful
Let me gather more specific information about the actual implementation and usage patterns.
Let me check the actual implementation in the test dependencies to understand the difference between these methods.
StateDB initialization change is correct and consistent
The change to deps.NewStateDB()
is correct as it's the only method available in TestDeps
for creating state databases. The method properly initializes a new state database with the current context and an empty transaction config. The previous search results showing both patterns likely include method calls and definitions, not actual usage patterns.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent StateDB initialization patterns across test files
# and verify there are no remaining uses of the old pattern.
# Test 1: Check for new StateDB initialization pattern
echo "Checking for new StateDB initialization pattern..."
rg -l "NewStateDB\(\)" "app/" "x/"
# Test 2: Check for potential old pattern usage
echo "Checking for old StateDB initialization pattern..."
rg -l "StateDB\(\)" "app/" "x/"
Length of output: 1660
Script:
#!/bin/bash
# Check the implementation and usage context of both patterns
echo "Checking StateDB() implementation..."
ast-grep --pattern 'func $_ StateDB() $_'
echo -e "\nChecking NewStateDB() implementation..."
ast-grep --pattern 'func $_ NewStateDB() $_'
echo -e "\nChecking usage context in test files..."
rg "StateDB\(\)" "app/evmante/evmante_increment_sender_seq_test.go" -B 2 -A 2
rg "NewStateDB\(\)" "app/evmante/evmante_increment_sender_seq_test.go" -B 2 -A 2
Length of output: 912
Script:
#!/bin/bash
# Check the test dependencies implementation
echo "Checking TestDeps implementation..."
rg -A 10 "type TestDeps struct" "x/evm/evmtest/"
echo -e "\nChecking StateDB and NewStateDB methods in TestDeps..."
rg "func.*TestDeps.*StateDB" "x/evm/evmtest/" -A 5
Length of output: 1202
x/evm/keeper/statedb_test.go (2)
50-50
: LGTM! Proper state verification after EVM transfer.
The use of NewStateDB()
here ensures we're reading the latest state after the transfer, which is crucial for balance verification.
24-24
: Verify state isolation with new StateDB instances.
The change from StateDB()
to NewStateDB()
aligns with the PR's objective of ensuring each operation gets a fresh state view. However, we should verify that this doesn't affect state persistence between operations.
✅ Verification successful
Based on the search results, I can now generate the final response since I have sufficient information about the StateDB usage across the codebase.
StateDB initialization change is consistent with codebase patterns
The change from StateDB()
to NewStateDB()
is correct and follows the established pattern across the codebase. The search results show that:
- All test files consistently use
deps.NewStateDB()
for state initialization - Each operation (test case, transaction, or query) creates a fresh StateDB instance
- State persistence between operations is maintained through proper commit calls
The change aligns with the codebase's design where each operation gets a fresh state view while maintaining state consistency through explicit commits.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other test files that might be affected by this StateDB initialization change
rg -l "StateDB\(\)" --type go | while read -r file; do
echo "=== $file ==="
rg -A 2 -B 2 "StateDB\(\)" "$file"
done
Length of output: 10773
app/ante/gas_wanted_test.go (1)
86-86
: LGTM! The StateDB initialization is correctly updated.
The change from StateDB()
to NewStateDB()
aligns with the global rename to better reflect that this method creates a new StateDB instance with a fresh journal.
app/evmante/evmante_mempool_fees_test.go (1)
85-85
: LGTM! Verify consistent EvmKeeper usage pattern.
The change from pointer to direct reference aligns with the broader refactoring pattern across test files.
Let's verify the consistent usage pattern:
app/evmante/evmante_verify_eth_acc_test.go (2)
68-68
: Verify EvmKeeper parameter change impact.
The removal of the &
operator for EvmKeeper
parameter suggests a change in how the keeper is handled. This could be related to the NibiruBankKeeper integration mentioned in the PR objectives.
67-67
: Verify StateDB initialization change across the codebase.
The change from deps.StateDB()
to deps.NewStateDB()
suggests a shift in how state is managed during tests. Let's verify this pattern is consistently applied.
app/keepers/all_keepers.go (2)
66-66
: LGTM! The pointer type change aligns with the PR objectives.
Converting EvmKeeper
to a pointer type is appropriate here as it enables efficient sharing of the StateDB across the system, which is necessary for the NibiruBankKeeper to track ether balance changes.
66-66
: Verify nil checks and concurrent access patterns.
Since EvmKeeper is now a pointer type, please ensure:
- Proper nil checks are in place where this keeper is used
- Concurrent access to the shared StateDB is properly synchronized
✅ Verification successful
Based on the search results, I can make the following observations:
- The EvmKeeper is used extensively throughout the codebase, primarily in test files and app initialization
- There are no explicit nil checks for EvmKeeper found in the codebase
- No direct mutex usage was found around EvmKeeper
Let me search for any concurrent access patterns or synchronization mechanisms:
Based on the search results, I can now provide a final response:
Concurrent access is properly handled, nil checks not required.
The codebase shows:
- The EvmKeeper is initialized during app setup and is never nil during runtime
- Concurrent access to state is protected through:
- Address-specific mutex locks via
AddrLocker
for EVM state operations - RPC filter mutex protection for subscription management
- Event bus synchronization for pubsub operations
- Address-specific mutex locks via
The pointer type is used for dependency injection and composition, not for optional/nullable scenarios.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for EvmKeeper usage to verify nil checks and synchronization
rg -A 3 "EvmKeeper\." --type go
# Search for potential nil checks
rg -A 3 "if.*EvmKeeper.*nil" --type go
# Look for mutex usage around EvmKeeper
ast-grep --pattern 'sync.Mutex
$$$
EvmKeeper'
Length of output: 42183
Script:
#!/bin/bash
# Look for any synchronization mechanisms around state access
rg -A 3 "sync\." --type go
# Search for any concurrent operations
rg -A 3 "go func" --type go
# Look for any state protection patterns
rg -A 3 "Lock|Unlock|RLock|RUnlock" --type go
Length of output: 34516
app/evmante/evmante_can_transfer.go (1)
Line range hint 75-89
: Verify state consistency during transfer validation.
The balance check using CanTransfer
relies on the StateDB's accuracy. With the new NibiruBankKeeper
system, please ensure:
- Balance changes are properly reflected in both StateDB and Bank module
- State reversions (in case of failed transactions) are handled consistently
- The infinite gas meter context doesn't affect balance tracking
✅ Verification successful
Based on the shell script results, I can now provide a final response since I have sufficient information about the implementation:
Balance checks and state handling are properly implemented
The codebase shows proper implementation of balance checks and state management:
- The
CanTransferDecorator
correctly uses StateDB'sGetBalance
and EVM'sCanTransfer
to validate transfers - The state is properly managed through the StateDB abstraction which maintains consistency between EVM and bank module states
- The infinite gas meter context does not affect balance tracking as it's only used for gas estimation
The balance validation in the ante handler is working as intended with proper error handling and state consistency checks.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Look for potential state consistency issues
# Expected: Proper error handling and state management
# Check for proper error handling in transfer-related code
echo "Checking transfer-related error handling:"
rg "CanTransfer|GetBalance" -A 5
# Look for state reversion handling
echo "Checking state reversion handling:"
ast-grep --pattern 'func $_(ctx $_, tx $_, simulate $_) {
$$$
stateDB := $_.NewStateDB($$$)
$$$
}'
Length of output: 32794
x/evm/keeper/funtoken_from_coin.go (1)
26-26
: Verify interface compatibility with NibiruBankKeeper.
The change from k.bankKeeper
to k.Bank
aligns with the PR's objective of using NibiruBankKeeper
. However, we should verify that the new Bank
field correctly implements all required bank keeper interfaces.
Let's verify the interface implementation:
✅ Verification successful
Let me gather more information about the GetDenomMetaData
method specifically since that's the one being used in the changed line.
Let me check one more thing to verify if NibiruBankKeeper inherits from BaseKeeper and if BaseKeeper implements GetDenomMetaData.
Interface compatibility verified successfully
The change from k.bankKeeper
to k.Bank
is safe because:
NibiruBankKeeper
embedsbankkeeper.BaseKeeper
and implements bothbankkeeper.Keeper
andbankkeeper.SendKeeper
interfacesGetDenomMetaData
is a standard method from theBaseKeeper
that's inherited- The implementation is being used consistently across the codebase in other modules like
tokenfactory
andevm
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that NibiruBankKeeper implements all required bank keeper interfaces
# Test 1: Find the bank keeper interface definition
echo "=== Bank Keeper Interface ==="
rg -A 5 "type BankKeeper interface"
# Test 2: Find the NibiruBankKeeper implementation
echo "=== NibiruBankKeeper Implementation ==="
ast-grep --pattern 'type NibiruBankKeeper struct {
$$$
}'
Length of output: 4033
Script:
#!/bin/bash
# Check the implementation of GetDenomMetaData in NibiruBankKeeper
echo "=== GetDenomMetaData Implementation ==="
ast-grep --pattern 'func ($_ *NibiruBankKeeper) GetDenomMetaData($$$) {
$$$
}'
# Check if there are any other usages of GetDenomMetaData
echo "=== GetDenomMetaData Usages ==="
rg "GetDenomMetaData" -A 2
Length of output: 1806
Script:
#!/bin/bash
# Check BaseKeeper implementation and imports
echo "=== BaseKeeper Implementation ==="
rg "BaseKeeper" -B 2 -A 2
# Check bank keeper package imports
echo "=== Bank Keeper Imports ==="
rg "bankkeeper" --type go
Length of output: 5447
app/evmante/evmante_can_transfer_test.go (1)
91-92
: LGTM! The initialization changes align with the new state management approach.
The changes reflect the PR's goal of improving state management:
- Using
NewStateDB()
ensures a fresh state for each test run, which is crucial for maintaining state consistency with the newNibiruBankKeeper
. - The decorator initialization change suggests a deliberate shift in how the keeper is handled.
Let's verify the consistency of these changes across other test files:
✅ Verification successful
The changes are consistent with the codebase patterns
The verification confirms:
- All test files consistently use
deps.NewStateDB()
for state initialization, showing proper alignment with the new state management approach. - The
CanTransferDecorator
initialization without pointer syntax matches the production usage inevmante_handler.go
, and the struct definition inevmante_can_transfer.go
shows it embeds*EVMKeeper
directly.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent usage of NewStateDB() across test files
# and similar decorator initialization patterns
echo "Checking StateDB initialization patterns:"
rg -A 1 "StateDB.*:=.*deps\." --type go
echo -e "\nChecking CanTransferDecorator initialization patterns:"
rg "CanTransferDecorator.*{.*EvmKeeper" --type go
Length of output: 451
Script:
#!/bin/bash
# Let's try a different approach with more specific patterns and proper escaping
echo "Checking StateDB initialization patterns:"
rg "stateDB\s*:=\s*(deps\.NewStateDB|deps\.StateDB)" --type go
echo -e "\nChecking CanTransferDecorator initialization patterns:"
rg "CanTransferDecorator\s*\{" --type go
# Let's also check the actual implementation to understand the intended usage
echo -e "\nChecking CanTransferDecorator definition:"
ast-grep --pattern 'type CanTransferDecorator struct { $$$ }'
Length of output: 1686
app/evmante/evmante_handler_test.go (1)
72-72
: LGTM! The change improves test isolation.
The switch to NewStateDB()
ensures a fresh state database for each test run, providing better isolation between test cases and aligning with the PR's goal of improving state management.
Let's verify that this change is consistent across other test files:
✅ Verification successful
All test files consistently use NewStateDB()
, confirming the complete migration
The verification shows that:
- No instances of the old
deps.StateDB()
pattern were found - All test files across the codebase consistently use
deps.NewStateDB()
- The change has been properly propagated across all relevant test files in:
app/evmante/
app/ante/
x/evm/
modules
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the consistent usage of NewStateDB() across test files
# Test: Search for both old and new patterns to ensure complete migration
echo "Checking for any remaining usage of StateDB():"
rg -A 2 'deps\.StateDB\(\)' --type go
echo "Verifying adoption of NewStateDB():"
rg -A 2 'deps\.NewStateDB\(\)' --type go
Length of output: 9385
x/evm/evmtest/erc20.go (1)
109-114
: Well-structured data model for balance assertions!
The FunTokenBalanceAssert
struct effectively consolidates the necessary data for balance checking, making the test code more maintainable and reducing parameter passing.
x/evm/evmmodule/genesis_test.go (1)
92-92
: LGTM! Verify keeper interface changes.
The removal of the address-of operator aligns with the broader refactoring for NibiruBankKeeper integration. The test comprehensively verifies the genesis export/import functionality.
Let's verify the keeper interface changes across the codebase:
Also applies to: 98-98
✅ Verification successful
Let me gather more information about the keeper interface changes by checking the actual method signatures and their usage.
Based on the analysis of the codebase, I can now generate the final response:
Keeper interface changes are consistent
The removal of the address-of operator in the test file is correct and consistent with the codebase. Looking at the ExportGenesis
and InitGenesis
implementations in x/evm/evmmodule/genesis.go
, the keeper is already defined as a pointer parameter:
func ExportGenesis(ctx sdk.Context, k *keeper.Keeper, ak evm.AccountKeeper) *evm.GenesisState
func InitGenesis(ctx sdk.Context, k *keeper.Keeper, accountKeeper evm.AccountKeeper, genState evm.GenesisState)
Therefore, passing the keeper without the address-of operator in the test is the right approach since deps.EvmKeeper
is already a pointer.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the consistency of ExportGenesis and InitGenesis signatures
# across the codebase to ensure all callers have been updated.
# Test 1: Check for any remaining pointer usage with ExportGenesis
echo "Checking ExportGenesis usage patterns..."
ast-grep --pattern 'ExportGenesis($$$, &$keeper, $$$)'
# Test 2: Check for any remaining pointer usage with InitGenesis
echo "Checking InitGenesis usage patterns..."
ast-grep --pattern 'InitGenesis($$$, &$keeper, $$$)'
Length of output: 289
Script:
#!/bin/bash
# Check the ExportGenesis and InitGenesis method signatures
echo "Checking ExportGenesis method signatures..."
ast-grep --pattern 'func ExportGenesis($$$) $$$'
echo -e "\nChecking InitGenesis method signatures..."
ast-grep --pattern 'func InitGenesis($$$) $$$'
echo -e "\nChecking all ExportGenesis calls..."
rg "ExportGenesis" -A 1
echo -e "\nChecking all InitGenesis calls..."
rg "InitGenesis" -A 1
Length of output: 35730
x/evm/keeper/keeper.go (3)
43-43
: LGTM! Field change aligns with PR objectives.
The change from bankKeeper
to Bank *NibiruBankKeeper
enables automatic recording of ether balance changes on the StateDB journal, which is the core objective of this PR.
66-66
: LGTM! Constructor changes maintain consistency.
The parameter and field assignment changes in NewKeeper correctly reflect the updated Bank field type and name.
Also applies to: 82-82
93-93
: Verify balance retrieval behavior remains consistent.
The change to use k.Bank.GetBalance
is aligned with the new structure. However, since this method is critical for EVM gas balance checks in the Ante Handler, we should verify that the NibiruBankKeeper's GetBalance method maintains the same behavior as the original implementation.
✅ Verification successful
Based on the search results, I can now provide a definitive response about the balance retrieval behavior:
Balance retrieval behavior is consistent and correctly implemented
The change from k.bankKeeper.GetBalance
to k.Bank.GetBalance
is safe because:
- The
NibiruBankKeeper
struct embedsbankkeeper.BaseKeeper
, inheriting the standard bank keeper implementation - The
GetBalance
method is consistently used across the codebase with the same interface signatureGetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
- The EVM gas balance retrieval specifically uses
EVMBankDenom
which is maintained consistently in both old and new implementations - Test cases in
x/evm/keeper/statedb_test.go
andx/evm/keeper/gas_fees_test.go
verify the balance retrieval behavior with the new structure
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that NibiruBankKeeper.GetBalance maintains the same interface and behavior
# as the original bankkeeper.Keeper.GetBalance
# Search for GetBalance method implementation in NibiruBankKeeper
echo "Searching for NibiruBankKeeper.GetBalance implementation:"
ast-grep --pattern 'func (k *NibiruBankKeeper) GetBalance($$$) $$$'
# Search for any test cases covering this functionality
echo -e "\nSearching for related test cases:"
rg -l "GetEvmGasBalance.*Test"
Length of output: 310
Script:
#!/bin/bash
# Let's try a broader search to understand the bank keeper implementation and its usage
# Search for NibiruBankKeeper type definition and implementation
echo "Searching for NibiruBankKeeper definition:"
rg "type NibiruBankKeeper" -A 5
# Search for GetBalance method usage in bank-related files
echo -e "\nSearching for GetBalance method usage:"
rg "GetBalance" --type go -A 2
# Search for any bank keeper interface definitions
echo -e "\nSearching for bank keeper interface definitions:"
rg "type.*BankKeeper.*interface" -A 5
# Look for test files related to bank keeper
echo -e "\nSearching for bank keeper test files:"
fd -e go -e test | rg -i "bank.*test"
Length of output: 22212
x/evm/precompile/funtoken_test.go (1)
Line range hint 137-148
: LGTM! Comprehensive balance verification.
The test properly verifies the state consistency between EVM and bank modules by checking:
- Sender's remaining ERC20 balance
- EVM module's balance
- Recipient's bank balance
x/evm/keeper/funtoken_from_erc20.go (1)
125-125
: LGTM! Consistent with the NibiruBankKeeper refactoring.
The change from k.bankKeeper
to k.Bank
aligns with the PR's objective of using the NibiruBankKeeper
throughout the codebase.
x/evm/keeper/statedb.go (3)
75-75
: LGTM: Improved address conversion using dedicated utility.
The change to use eth.EthAddrToNibiruAddr
enhances code clarity by utilizing a domain-specific function for address conversion.
76-78
: LGTM: Correct usage of BaseKeeper to avoid double-labeling.
The implementation correctly uses Bank.BaseKeeper
for balance operations during commits, which prevents double-labeling and mutation of the journal. This aligns with the PR's objectives while avoiding potential state inconsistencies.
Line range hint 75-101
: Verify integration with precompiled contract calls.
The implementation looks correct for regular balance updates. However, let's verify that the StateDB reference is properly set before precompiled contract calls, as mentioned in the PR objectives.
✅ Verification successful
Based on the gathered information from all the shell script executions, I can now provide the final response:
StateDB balance updates are properly integrated with precompile execution
The implementation in SetAccBalance
is correct and properly integrated with precompiled contracts because:
- The StateDB balance is synchronized with bank module balances through
SetBalanceWei
in the bank extension - Precompile contracts like
FunToken
handle balance operations through the bank module, which then triggers the StateDB synchronization - The balance updates maintain consistency between EVM and Cosmos states through the keeper's bank extension
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if StateDB reference is set before precompiled contract calls
# Search for precompile-related code that might use this balance update logic
rg -A 5 "func.*Precompile.*"
# Search for StateDB initialization before precompile execution
rg -B 5 "SetAccBalance.*precompile"
Length of output: 6555
Script:
#!/bin/bash
# Let's check how StateDB is used in precompile execution and balance updates
# Check for StateDB usage in precompile implementation
rg -A 5 "type precompile.*struct"
# Check for balance updates in precompile execution
rg -B 3 -A 5 "SetBalance.*evm" x/evm/precompile/
# Check for StateDB initialization in precompile execution
ast-grep --pattern 'func $_(evm *vm.EVM, $$$) {
$$$
}'
Length of output: 998
Script:
#!/bin/bash
# Let's check the precompile execution flow and StateDB integration
# Check precompile Run implementation
rg -A 10 "func.*Run.*vm\.EVM.*Contract" x/evm/precompile/
# Check how StateDB is used in the EVM keeper during precompile execution
rg -A 10 "func.*RunPrecompile" x/evm/keeper/
# Check for any direct StateDB balance updates in precompile execution
rg -B 3 -A 7 "statedb.*SetBalance|statedb.*GetBalance" x/evm/precompile/
Length of output: 181
Script:
#!/bin/bash
# Let's check the implementation details of precompile contracts
# Look for the interface or base implementation of precompiled contracts
rg -A 10 "interface.*PrecompiledContract" x/evm/
# Check for any balance-related methods in precompile implementations
rg -A 10 "func.*bankSend|func.*transfer" x/evm/precompile/
# Check for StateDB usage in EVM execution context
rg -B 3 -A 7 "StateDB.*balance|SetBalance.*StateDB" x/evm/
Length of output: 1633
x/evm/precompile/funtoken.go (2)
74-74
: LGTM: Structural changes align with NibiruBankKeeper integration
The pointer semantics for evmKeeper and removal of bankKeeper field align well with the architectural goal of using NibiruBankKeeper for bank operations through evmKeeper.Bank.
Also applies to: 79-79
54-54
: LGTM: Proper StateDB initialization
Setting the StateDB reference at the start of Run ensures proper recording of balance changes for all subsequent bank operations.
x/evm/keeper/msg_ethereum_tx_test.go (4)
90-90
: Consistent state management in error case.
The use of NewStateDB()
in the error case maintains consistency with the happy path. This is good practice for ensuring that error cases accurately reflect production behavior.
50-50
: Verify state isolation in contract creation test.
The change from StateDB()
to NewStateDB()
suggests a shift to using fresh state instances. While this aligns with the PR's objective of proper state management, we should verify that this doesn't affect test isolation.
✅ Verification successful
Based on the search results, I can now generate the final response as the verification is complete.
The change from StateDB()
to NewStateDB()
is consistent with codebase patterns
The codebase analysis shows that NewStateDB()
is consistently used across all test files for state management. This includes:
- Test setup in various EVM-related test files (
statedb_test.go
,smart_contract_test.go
) - Transaction handling in test utilities (
evmtest/tx.go
) - Ante handler tests (
app/evmante/*_test.go
)
The change aligns with the established pattern and maintains proper test isolation by creating fresh state instances. No issues found with state management or test isolation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for other test files that might be affected by this state management change
# and verify consistent usage across the test suite.
echo "Checking for similar state management patterns in test files..."
rg -l "StateDB\(\)" --type go | while read -r file; do
echo "=== $file ==="
rg "StateDB\(\)" "$file" -A 2 -B 2
done
Length of output: 10910
142-142
: Verify contract execution state isolation.
The contract execution test now uses a fresh state via NewStateDB()
. This change is particularly important here as it ensures that the contract execution starts with a clean state.
✅ Verification successful
Let me gather more information about the state isolation in contract execution tests.
Based on the analysis of the shell script results, I can now provide a final response:
State isolation is properly implemented in contract execution tests
Each test case creates a fresh state through deps.NewStateDB()
, which is implemented in TestDeps
to return a new isolated state database. The pattern is consistently used across all test files, and there are no instances of state sharing or persistence between test executions. The implementation in x/evm/evmtest/test_deps.go
confirms that each call creates a new state context.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for potential race conditions or state leakage in contract execution tests
echo "Checking for concurrent contract execution tests..."
ast-grep --pattern 'func.*Test.*Contract.*\(\) {
$$$
go func\(\) {
$$$
}\(\)
$$$
}'
Length of output: 1950
Script:
#!/bin/bash
# Check how NewStateDB is used in test files
rg "NewStateDB\(\)" --type go -B 2 -A 2
# Check for any state persistence or cleanup patterns
ast-grep --pattern 'func Test$_($_) {
$$$
stateDB := $_.NewStateDB()
$$$
}'
Length of output: 14961
208-208
: Verify transaction nonce management in transfer tests.
The simple transfer tests now use NewStateDB()
for nonce retrieval. This is consistent with other changes and aligns with the PR's goal of proper state management.
✅ Verification successful
Let me analyze the nonce management patterns more thoroughly with additional context.
This will help us understand:
- The broader context of NewStateDB() usage
- The test setup patterns to verify consistent state management
Based on the comprehensive analysis of the codebase, I can now provide a final response:
Nonce management is consistently implemented across transfer tests
The verification shows that deps.NewStateDB().GetNonce(ethAcc.EthAddr)
is used consistently throughout the codebase for nonce management:
- All test files use the same pattern for nonce retrieval
- The implementation is consistent with the test infrastructure in
evmtest
package - The state management through
NewStateDB()
is properly initialized in test setups
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify consistent nonce management across transfer-related tests
echo "Checking nonce management patterns in transfer tests..."
rg "GetNonce.*EthAddr" --type go | while read -r file; do
if [[ $file == *"_test.go" ]]; then
echo "=== $file ==="
rg "GetNonce.*EthAddr" "$file" -A 2 -B 2
fi
done
Length of output: 1950
Script:
#!/bin/bash
# Get more context around the nonce usage in test files
echo "=== Checking NewStateDB() usage patterns ==="
rg "NewStateDB\(\)" --type go -A 3 -B 3
echo -e "\n=== Checking test setup patterns ==="
ast-grep --pattern 'func Test$_($deps *evmtest.Deps) {
$$$
}'
Length of output: 20490
app/evmante/evmante_validate_basic_test.go (1)
202-202
: Let me gather more information about the type definition and usage.
#!/bin/bash
# Check the EthValidateBasicDecorator struct definition and its evmKeeper field
ast-grep --pattern 'type EthValidateBasicDecorator struct {
$$$
}'
# Check the EVMKeeper type definition
ast-grep --pattern 'type EVMKeeper struct {
$$$
}'
# Look for any other usages of EvmKeeper in decorator initialization
rg "EvmKeeper.*NewEth.*Decorator"
x/evm/precompile/wasm.go (4)
11-11
: LGTM: Required import for EVM keeper integration.
The added import enables access to the EVM keeper functionality needed for StateDB management.
75-75
: LGTM: Proper keeper integration via embedding.
The embedded EVM keeper pointer provides clean access to keeper functionality while ensuring proper state sharing.
46-50
: LGTM: Crucial StateDB reference setup for bank operations.
The StateDB reference is correctly set before any potential bank operations, ensuring proper recording of NIBI transfers in the journal. The comment effectively explains the rationale.
Let's verify that all bank operations in the file occur after this StateDB setup:
✅ Verification successful
The previous command didn't work well because:
- The ast-grep pattern was too specific
- We need to see the actual content of the file to verify the sequence of operations
These new commands will help us:
- See all Bank operations and their context
- Understand the structure of the Run method where the StateDB is set
I need to see:
- If there are any Bank operations in execute/query methods
- The complete Run method implementation to verify the StateDB setup happens before any potential Bank operations
We need to:
- Check if any of the switch case methods use Bank operations
- Look for any actual Bank method calls beyond just the StateDB assignment
StateDB reference setup is correctly placed and safe
Based on the verification results:
- The only Bank-related operation in the file is the StateDB assignment itself (
p.Bank.StateDB = startResult.StateDB
) - This assignment happens at the beginning of the Run method, before any of the switch case methods (execute, query, instantiate, executeMulti) are called
- No other Bank method calls are found in the file
This confirms that the StateDB reference is properly set before any potential Bank operations could occur in the downstream methods.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for potential bank operations before StateDB setup
ast-grep --pattern 'p.Bank.$$$' | grep -B 5 'func.*Run'
Length of output: 52
Script:
#!/bin/bash
# Let's search for all Bank operations in the wasm.go file
rg "p\.Bank\." x/evm/precompile/wasm.go -B 5 -A 5
# Also search for the Run method implementation to understand the context
ast-grep --pattern 'func (p *PrecompileWasm) Run($$$) ($$$) {
$$$
}'
Length of output: 651
Script:
#!/bin/bash
# Let's search for any Bank method calls in the execute and query methods
rg "p\.Bank\." x/evm/precompile/wasm.go -A 10 -B 10
# Also get the full Run method implementation to see the complete flow
rg "^func \(p \*PrecompileWasm\) Run" x/evm/precompile/wasm.go -A 30
Length of output: 991
Script:
#!/bin/bash
# Let's check the execute, query, instantiate, and executeMulti methods for Bank operations
rg "func \(p \*PrecompileWasm\) (execute|query|instantiate|executeMulti)" x/evm/precompile/wasm.go -A 20
# Also check for any other Bank method calls in the file
rg "p\.Bank\.[a-zA-Z]+" x/evm/precompile/wasm.go
Length of output: 195
101-101
: LGTM: Proper keeper initialization in constructor.
The EVM keeper is correctly initialized from the provided PublicKeepers.
Let's verify the keeper usage pattern across the codebase:
✅ Verification successful
LGTM: Keeper initialization is consistent with struct definition
The precompileWasm
struct embeds *evmkeeper.Keeper
as a field, and the initialization using keepers.EvmKeeper
in the constructor matches this definition. The pattern is also consistent with other precompile implementations like precompileFunToken
that use the EVM keeper.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for similar keeper initializations to ensure consistency
rg --type go "PrecompileWasm.*EvmKeeper" -B 2 -A 2
Length of output: 52
Script:
#!/bin/bash
# Let's first find all files containing PrecompileWasm to understand the usage context
rg --type go "PrecompileWasm" -l
# Then search for EvmKeeper usage patterns in the codebase
rg --type go "EvmKeeper" -B 2 -A 2
# Also check the PrecompileWasm struct definition
ast-grep --pattern 'type PrecompileWasm struct {
$$$
}'
Length of output: 58744
Script:
#!/bin/bash
# Let's check the PrecompileWasm struct definition and its usage
ast-grep --pattern 'type precompileWasm struct {
$$$
}'
# Also check for any other references to the Keeper field
rg --type go "Keeper.*\bevmkeeper" -B 2 -A 2
Length of output: 1597
x/evm/evmtest/tx.go (1)
30-30
: LGTM: Consistent usage of NewStateDB() for nonce retrieval
The change from StateDB()
to NewStateDB()
across all transaction-related functions ensures that each transaction operates on a fresh state database instance, which aligns with the PR's objective of maintaining state consistency during precompiled contract calls.
Let's verify that all StateDB usage has been updated consistently:
Also applies to: 69-69, 126-126, 151-151, 224-224
✅ Verification successful
Let me gather more specific information about the usage of StateDB()
in the relevant files to understand the context better.
Let me check one more thing to understand if there are any remaining instances of StateDB()
in the test dependencies that might need updating.
All StateDB() calls in evmtest/tx.go correctly use NewStateDB()
The verification confirms that all nonce retrievals in x/evm/evmtest/tx.go
are using deps.NewStateDB()
consistently. The TestDeps
struct only exposes NewStateDB()
method and doesn't have a StateDB()
method, which aligns with the intended changes. While there are other files in the codebase that use StateDB()
, they are test files that may have different requirements and contexts.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that there are no remaining instances of StateDB() calls
# that should have been updated to NewStateDB()
# Search for any remaining direct StateDB() calls
rg -l 'StateDB\(\)' --type go
# Search for all NewStateDB() calls to confirm the migration
rg -l 'NewStateDB\(\)' --type go
Length of output: 1442
Script:
#!/bin/bash
# Check the specific usage of StateDB() in evmtest files to understand the context
rg 'StateDB\(\)' x/evm/evmtest/tx.go -B 2 -A 2
# Check the implementation in test_deps.go to understand the relationship
rg 'StateDB|NewStateDB' x/evm/evmtest/test_deps.go -B 2 -A 2
Length of output: 1189
Script:
#!/bin/bash
# Search for StateDB method definition in TestDeps
ast-grep --pattern 'func ($_ TestDeps) StateDB() $_'
# Check for any other StateDB() usage in test_deps.go
rg 'func.*StateDB' x/evm/evmtest/test_deps.go
Length of output: 155
x/evm/keeper/funtoken_from_erc20_test.go (1)
28-28
: Verify state isolation with new StateDB instance.
The change from StateDB()
to NewStateDB()
for nonce retrieval suggests improved state isolation. However, we should verify that this doesn't affect the test's ability to detect potential issues with nonce management.
x/evm/keeper/erc20.go (1)
183-185
: LGTM! Improved code formatting.
The multi-line formatting of the CallContractWithInput
invocation enhances readability while maintaining the same functionality.
x/evm/embeds/artifacts/contracts/TestNativeSendThenPrecompileSend.sol/TestNativeSendThenPrecompileSend.json (2)
Line range hint 4-45
: Contract provides good test coverage for NibiruBankKeeper changes.
The contract's ABI and implementation provide comprehensive test coverage for the PR changes:
- Tests native token transfers and their StateDB journal entries
- Tests precompile integration with the bank keeper
- Verifies state consistency through amount validation
Let's verify test coverage:
✅ Verification successful
Let me gather more information about the test implementation to verify the coverage claims:
Review comment verification successful
The contract and test implementation confirm comprehensive coverage of NibiruBankKeeper changes:
- Contract implements native token transfer using
send()
followed by precompile'sbankSend()
- Test suite properly sets up dependencies, funds the contract, and executes the test scenario
- Amount validation is enforced through require statements in both native and precompile transfers
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify test coverage for the changes
# Test 1: Look for related test files
echo "Looking for Go test files that use this contract..."
rg -t go "TestNativeSendThenPrecompileSend"
# Test 2: Check for similar test patterns
echo "Looking for similar test patterns..."
rg -l "nativeSendThenPrecompileSend|bankSend"
Length of output: 1749
Script:
#!/bin/bash
# Check the test implementation details
echo "=== Test Implementation Details ==="
rg -A 20 "func.*TestNativeSendThenPrecompileSend" x/evm/keeper/funtoken_from_coin_test.go
# Check the actual contract implementation
echo -e "\n=== Contract Implementation ==="
cat x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol
Length of output: 2076
46-47
: Verify bytecode changes and contract functionality.
The bytecode changes indicate recompilation of the contract. The contract's functionality aligns with the PR objectives by:
- Testing native token transfers using low-level calls
- Making precompile calls to test bank transfers
- Validating transfer amounts and state consistency
Let's verify the contract's source and compilation settings:
✅ Verification successful
Bytecode changes are valid and match source implementation
The bytecode changes in TestNativeSendThenPrecompileSend.json are verified to be correct based on:
- Source code shows the contract implements:
- Native token sends using low-level
send()
- Precompile calls to
bankSend()
- Amount validation with error messages matching bytecode
- Native token sends using low-level
- Compilation settings in hardhat.config.js confirm Solidity 0.8.24
- Test implementation validates the contract's functionality for:
- Correct handling of native and precompile sends
- State consistency checks
- Amount validation
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify contract source and compilation settings
# Test 1: Find the contract source file
echo "Looking for contract source file..."
fd -t f "TestNativeSendThenPrecompileSend.sol"
# Test 2: Check for hardhat config to verify compiler settings
echo "Looking for hardhat config..."
fd -t f "hardhat.config"
# Test 3: Search for related test files
echo "Looking for related test files..."
rg -l "TestNativeSendThenPrecompileSend"
Length of output: 689
Script:
#!/bin/bash
# Let's examine the contract source and compilation settings
# Check contract source
echo "=== Contract Source ==="
cat x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol
# Check hardhat config for compiler settings
echo -e "\n=== Hardhat Config ==="
cat x/evm/embeds/hardhat.config.js
# Check test implementation
echo -e "\n=== Test Implementation ==="
cat x/evm/keeper/funtoken_from_coin_test.go
Length of output: 17711
go.mod (1)
248-248
: LGTM! Dependency updates align with PR objectives.
The update to v0.47.11-nibiru.2
of the Cosmos SDK fork and switch to the NibiruChain's go-ethereum fork properly support:
- The CacheMultiStore Copy() functionality needed for state management
- Custom StateDB journal implementations for the NibiruBankKeeper
Let's verify the integration points:
✅ Verification successful
Let me gather more information to verify the integration points.
Based on the gathered information, I can now generate the final response:
Dependency update is correctly integrated with codebase
The verification confirms proper integration between the Cosmos SDK fork and the codebase:
- CacheMultiStore Copy() is utilized in StateDB (x/evm/statedb/statedb.go:583)
- NibiruBankKeeper is implemented with StateDB journal integration (x/evm/keeper/bank_extension.go:18-23)
- Journal system properly tracks and reverts state changes (x/evm/statedb/journal.go)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the integration between Cosmos SDK and go-ethereum forks
# Test 1: Check for CacheMultiStore Copy() implementation
echo "Checking CacheMultiStore Copy() implementation..."
rg -p "func.*Copy.*CacheMultiStore"
# Test 2: Check for StateDB journal integration points
echo "Checking StateDB journal integration..."
rg -p "func.*journal.*StateDB"
Length of output: 355
Script:
#!/bin/bash
# Let's check for CacheMultiStore usage and StateDB implementations more broadly
# Check for CacheMultiStore usage patterns
echo "Checking CacheMultiStore usage..."
rg -p "CacheMultiStore" -A 3
# Check for StateDB and journal related code
echo "Checking StateDB and journal implementations..."
rg -p "type.*StateDB" -A 5
rg -p "journal" -A 3 x/evm/
# Check for bank keeper integration
echo "Checking bank keeper integration..."
rg -p "type.*BankKeeper" -A 5
Length of output: 16136
x/evm/keeper/funtoken_from_coin_test.go (2)
28-28
: LGTM! Improved test setup and initialization.
The changes enhance the test setup by using a fresh state DB instance, adopting a more comprehensive type system with evm.FunToken
, and improving readability through better variable naming.
Also applies to: 175-175, 289-290
327-387
: LGTM! Enhanced test assertions for better state verification.
The new assertion blocks using FunTokenBalanceAssert
provide comprehensive verification of both bank and ERC20 balances across multiple accounts. This structured approach helps prevent race conditions and ensures state consistency, which directly aligns with the PR's objective of improving state management.
x/evm/statedb/statedb_test.go (3)
85-85
: LGTM! Consistent StateDB initialization across test cases.
The changes systematically update all test cases to use deps.NewStateDB()
, maintaining test isolation while preserving the existing test logic and assertions.
Also applies to: 138-138, 171-171, 204-204, 257-257, 267-267, 300-300, 311-311, 367-367, 409-409, 427-427, 502-502, 579-579, 598-598
Line range hint 1-633
: Verify test coverage for NibiruBankKeeper integration.
While the StateDB initialization changes are consistent, we should ensure that the test suite adequately covers the new NibiruBankKeeper
functionality for recording ether balance changes.
Let's check for related test coverage:
#!/bin/bash
# Description: Verify test coverage for NibiruBankKeeper integration
# Test 1: Check for NibiruBankKeeper tests
echo "Checking for NibiruBankKeeper tests..."
rg -l "NibiruBankKeeper.*Test|Test.*NibiruBankKeeper"
# Test 2: Check for balance recording tests
echo "Checking for balance recording tests..."
ast-grep --pattern 'func Test$$$Balance$$$'
85-85
: Verify the StateDB initialization changes.
The switch from deps.StateDB()
to deps.NewStateDB()
and the removal of the address-of operator for EvmKeeper
suggest significant changes in how the StateDB is initialized. These changes might be related to the integration of NibiruBankKeeper
for recording ether balance changes.
Let's verify the changes in the initialization logic:
Also applies to: 524-524
✅ Verification successful
The StateDB initialization changes are safe and correct.
The changes from deps.StateDB()
to deps.NewStateDB()
and the removal of the address-of operator for EvmKeeper
are consistent with the codebase:
- The
StateDB
is designed to be used as a fresh instance for each transaction/test, as evidenced by the implementation instatedb.go
which maintains transaction-specific state and journals. - The
New
function instatedb.go
acceptskeeper Keeper
directly, not a pointer, confirming that the removal of&
is correct. - The changes align with proper state isolation in tests, ensuring each test case starts with a clean state.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the changes in StateDB initialization and EvmKeeper usage
# Test 1: Check the old and new StateDB initialization methods
echo "Checking StateDB initialization methods..."
rg -A 5 "func.*StateDB|func.*NewStateDB"
# Test 2: Check EvmKeeper usage patterns
echo "Checking EvmKeeper usage patterns..."
rg "statedb\.New.*EvmKeeper"
Length of output: 372
Script:
#!/bin/bash
# Let's try a more focused search approach
# Check for StateDB initialization patterns in the test file
echo "Checking StateDB initialization in test file..."
rg -A 5 "StateDB" x/evm/statedb/statedb_test.go
# Check the actual StateDB implementation
echo "Checking StateDB implementation..."
rg -A 5 "StateDB" x/evm/statedb/statedb.go
# Look for EvmKeeper usage in statedb package
echo "Checking EvmKeeper usage..."
rg "EvmKeeper" x/evm/statedb/
Length of output: 20786
x/evm/statedb/statedb.go (1)
81-83
:
Add safety check for type assertion
The current implementation could panic if evmObj.StateDB
is nil or not of type *StateDB
. Since this is a critical path in EVM execution, we should handle these cases gracefully.
Consider using a safe type assertion:
func FromVM(evmObj *vm.EVM) *StateDB {
- return evmObj.StateDB.(*StateDB)
+ if evmObj == nil || evmObj.StateDB == nil {
+ return nil
+ }
+ stateDB, ok := evmObj.StateDB.(*StateDB)
+ if !ok {
+ return nil
+ }
+ return stateDB
}
Let's verify the usage patterns of this function:
x/evm/keeper/msg_server.go (1)
205-208
: LGTM! Documentation improvements enhance code clarity.
The enhanced documentation provides valuable insights into the function's behavior, including different callers, prechecks, and preprocessing steps.
x/evm/keeper/grpc_query_test.go (2)
407-407
: LGTM: Consistent usage of NewStateDB().
The change maintains consistency with the previous update, ensuring proper state database initialization.
333-333
: LGTM: Using NewStateDB() for state initialization.
The change from StateDB()
to NewStateDB()
aligns with the PR's objective of ensuring proper state management during EVM operations.
Let's verify similar changes across other test files:
x/evm/embeds/contracts/TestNativeSendThenPrecompileSend.sol (1)
23-27
: LGTM!
The implementation of the bankSend
call is correct, and the parameters are appropriately passed.
x/evm/keeper/bank_extension.go (2)
93-100
: Approved: Custom function findEtherBalanceChangeFromCoins
is appropriate
The implementation of findEtherBalanceChangeFromCoins
correctly iterates through the coins to identify ether balance changes. This approach avoids potential issues with unsorted coins and matches the performance considerations discussed previously.
80-91
: Ensure StateDB
is properly initialized before syncing accounts
In the SyncStateDBWithAccount
method, the check for bk.StateDB == nil
prevents operations when the StateDB
is uninitialized. Ensure that StateDB
is correctly set before invoking bank operations that might require state synchronization.
app/keepers.go (4)
372-382
: LGTM!
The initialization of EvmKeeper
with nibiruBankKeeper
aligns with the updated architecture and ensures proper integration of the EVM module.
639-639
: LGTM!
The update to initialize the EVM module with app.EvmKeeper
is appropriate and maintains consistency across the application.
614-614
: Verify that NibiruBankKeeper
satisfies the bank.Keeper
interface
Please ensure that NibiruBankKeeper
implements all the necessary methods required by bank.NewAppModule
. This verification is crucial to avoid interface compliance issues at runtime.
Run the following script to confirm that NibiruBankKeeper
implements the required methods of bank.Keeper
:
#!/bin/bash
# Description: Compare methods of `NibiruBankKeeper` with the `bank.Keeper` interface
# List methods defined in `NibiruBankKeeper`
rg -A 1 -B 1 'func \(\*NibiruBankKeeper\)'
# List methods in the `bank.Keeper` interface
rg -A 1 -B 1 'type Keeper interface {' $(fd --extension go)
# Compare the two lists for discrepancies
266-276
: Ensure that StateDB
in NibiruBankKeeper
is properly initialized before use
StateDB
is set to nil
during the initialization of NibiruBankKeeper
. Please verify that StateDB
is correctly assigned before any operations that depend on it to prevent potential nil
pointer dereference errors.
Run the following script to check where StateDB
is assigned in the codebase:
✅ Verification successful
Let's search for the definition and initialization patterns of StateDB to understand how it's being handled.
Let's verify how the StateDB initialization flow works between the EVM keeper and bank keeper to understand if the nil StateDB is an expected initial state.
Based on the code findings so far, I can generate a final response as we have sufficient context about the StateDB initialization pattern:
Setting StateDB
to nil
in NibiruBankKeeper
initialization is the expected behavior
The StateDB
field is designed to be nil
by default and is only set during Ethereum transaction processing. This is confirmed by:
- The defensive check in
SyncStateDBWithAccount
:if bk.StateDB == nil { return }
- The EVM keeper sets the bank keeper's
StateDB
during transaction processing:evmKeeper.Bank.StateDB = stateDB
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Search for assignments to `NibiruBankKeeper.StateDB`
rg -A 2 -B 2 'NibiruBankKeeper\.StateDB\s*='
Length of output: 16694
Script:
#!/bin/bash
# Search for NibiruBankKeeper StateDB assignments and usages
rg -A 2 -B 2 'StateDB.*=' x/evm/keeper/bank_extension.go
# Search for NibiruBankKeeper struct and its methods
ast-grep --pattern 'type NibiruBankKeeper struct {
$$$
}'
# Search for methods that might initialize StateDB
ast-grep --pattern 'func ($_ *NibiruBankKeeper) $_($$$) {
$$$
}'
Length of output: 1413
Script:
#!/bin/bash
# Search for where StateDB is initialized in the EVM keeper
rg -A 5 -B 5 'func NewKeeper|InitGenesis|BeginBlock' x/evm/keeper/keeper.go
# Search for where the EVM keeper is initialized and connected to the bank keeper
rg -A 5 -B 5 'NewKeeper.*evm' app/keepers.go
Length of output: 446
// NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before | ||
// any operation that has the potential to use Bank send methods. This will | ||
// guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are | ||
// recorded if wei (NIBI) is transferred. | ||
p.evmKeeper.Bank.StateDB = start.StateDB | ||
err = p.evmKeeper.Bank.MintCoins(ctx, evm.ModuleName, sdk.NewCoins(coinToSend)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider consolidating duplicate StateDB assignments
The code contains duplicate StateDB assignments with identical comments. Since the StateDB is already set at line 154, the second assignment at line 168 appears redundant.
Consider consolidating the code as follows:
// NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before
// any operation that has the potential to use Bank send methods. This will
// guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are
// recorded if wei (NIBI) is transferred.
p.evmKeeper.Bank.StateDB = start.StateDB
err = p.evmKeeper.Bank.MintCoins(ctx, evm.ModuleName, sdk.NewCoins(coinToSend))
if err != nil {
return nil, fmt.Errorf("mint failed for module \"%s\" (%s): contract caller %s: %w",
evm.ModuleName, evm.EVM_MODULE_ADDRESS.Hex(), caller.Hex(), err,
)
}
-// NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before
-// any operation that has the potential to use Bank send methods. This will
-// guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are
-// recorded if wei (NIBI) is transferred.
-p.evmKeeper.Bank.StateDB = start.StateDB
err = p.evmKeeper.Bank.SendCoinsFromModuleToAccount(
ctx,
evm.ModuleName,
toAddr,
sdk.NewCoins(coinToSend),
)
Also applies to: 163-173
if err := k.Bank.SendCoinsFromAccountToModule( | ||
ctx, from, evm.ModuleName, fee); err != nil { | ||
return fmt.Errorf("unable to pay the \"create_fun_token_fee\": %w", err) | ||
} | ||
if err := k.bankKeeper.BurnCoins(ctx, evm.ModuleName, fee); err != nil { | ||
if err := k.Bank.BurnCoins(ctx, evm.ModuleName, fee); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider wrapping operations in a transaction for atomicity.
The function performs two bank operations (send and burn) that should be atomic. If the burn operation fails, the sent coins would be stuck in the module account.
Consider wrapping both operations in a transaction:
func (k Keeper) deductCreateFunTokenFee(ctx sdk.Context, msg *evm.MsgCreateFunToken) error {
fee := k.FeeForCreateFunToken(ctx)
from := sdk.MustAccAddressFromBech32(msg.Sender)
+ // Create a cached context for transaction-like behavior
+ cacheCtx, commit := ctx.CacheContext()
+
if err := k.Bank.SendCoinsFromAccountToModule(
- ctx, from, evm.ModuleName, fee); err != nil {
+ cacheCtx, from, evm.ModuleName, fee); err != nil {
return fmt.Errorf("unable to pay the \"create_fun_token_fee\": %w", err)
}
- if err := k.Bank.BurnCoins(ctx, evm.ModuleName, fee); err != nil {
+ if err := k.Bank.BurnCoins(cacheCtx, evm.ModuleName, fee); err != nil {
return fmt.Errorf("failed to burn the \"create_fun_token_fee\" after payment: %w", err)
}
+
+ // Commit changes if both operations succeed
+ commit()
return nil
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if err := k.Bank.SendCoinsFromAccountToModule( | |
ctx, from, evm.ModuleName, fee); err != nil { | |
return fmt.Errorf("unable to pay the \"create_fun_token_fee\": %w", err) | |
} | |
if err := k.bankKeeper.BurnCoins(ctx, evm.ModuleName, fee); err != nil { | |
if err := k.Bank.BurnCoins(ctx, evm.ModuleName, fee); err != nil { | |
func (k Keeper) deductCreateFunTokenFee(ctx sdk.Context, msg *evm.MsgCreateFunToken) error { | |
fee := k.FeeForCreateFunToken(ctx) | |
from := sdk.MustAccAddressFromBech32(msg.Sender) | |
// Create a cached context for transaction-like behavior | |
cacheCtx, commit := ctx.CacheContext() | |
if err := k.Bank.SendCoinsFromAccountToModule( | |
cacheCtx, from, evm.ModuleName, fee); err != nil { | |
return fmt.Errorf("unable to pay the \"create_fun_token_fee\": %w", err) | |
} | |
if err := k.Bank.BurnCoins(cacheCtx, evm.ModuleName, fee); err != nil { | |
return fmt.Errorf("failed to burn the \"create_fun_token_fee\" after payment: %w", err) | |
} | |
// Commit changes if both operations succeed | |
commit() | |
return nil | |
} |
// any operation that has the potential to use Bank send methods. This will | ||
// guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are | ||
// recorded if wei (NIBI) is transferred. | ||
p.evmKeeper.Bank.StateDB = start.StateDB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't we already set p.evmKeeper.Bank.StateDB
in the Run()
method, prior to calling bankSend
? I think it's better to keep it in the Run()
method because that executes prior to any specific method call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It gets messed up by the ERC20 tranfers and stuff
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual StateDB
object might get mutated by the ERC-20 transfers, but the p.evmKeeper.Bank.StateDB
field is actually a pointer with a value e.g. 0x12345678
, which is the same as what's held in start.StateDB
.
So in effect, the statement here is saying p.evmKeeper.Bank.StateDB = 0x12345678
, and the StateDB's memory location should remain stable before and after precompile execution.
It's not a big deal though, since the assignment is very cheap to do (it's just writing a 64-bit address).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It ends up creating a new reference to the *statedb.StateDB entirely. You'll find that if you remove these reassignments, it actually regresses and reintroduces the security vulnerability, failing our unit tests.
This test is the meaningful one: TestNativeSendThenPrecompileSend
This issue arises from both ERC20().Transfer
and ERC20().Burn
calling ApplyEvmMsg with commit=true. This results in calling
stateDB := k.NewStateDB(ctx, txConfig)
and creates a fresh pointer that differs from the parent StateDB that the precompile uses. Sadly, editing the child StateDB's journal doesn't affect the parent.
And yes, adding the pointer assignment is also inexpensive
// any operation that has the potential to use Bank send methods. This will | ||
// guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are | ||
// recorded if wei (NIBI) is transferred. | ||
p.evmKeeper.Bank.StateDB = start.StateDB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise, p.evmKeeper.Bank.StateDB
should already be set, so there shouldn't be a need to set it again.
// any operation that has the potential to use Bank send methods. This will | ||
// guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are | ||
// recorded if wei (NIBI) is transferred. | ||
p.evmKeeper.Bank.StateDB = start.StateDB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual StateDB
object might get mutated by the ERC-20 transfers, but the p.evmKeeper.Bank.StateDB
field is actually a pointer with a value e.g. 0x12345678
, which is the same as what's held in start.StateDB
.
So in effect, the statement here is saying p.evmKeeper.Bank.StateDB = 0x12345678
, and the StateDB's memory location should remain stable before and after precompile execution.
It's not a big deal though, since the assignment is very cheap to do (it's just writing a 64-bit address).
There was a problem hiding this 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 (3)
CHANGELOG.md (1)
71-74
: Consider improving the changelog entry formatting.The entry content is split across multiple lines with inconsistent wrapping. Consider reformatting it into a single line or using consistent indentation for better readability, similar to other entries in the file.
-for (1) ERC20 transfers with tokens that return false success values instead of -throwing an error and (2) ERC20 transfers with other operations that don't bring -about the expected resulting balance for the transfer recipient. +for (1) ERC20 transfers with tokens that return false success values instead of throwing an error and (2) ERC20 transfers with other operations that don't bring about the expected resulting balance for the transfer recipient.x/evm/evmtest/erc20.go (2)
107-113
: Add comments to exported structFunTokenBalanceAssert
and its fields.Consider adding GoDoc comments to the
FunTokenBalanceAssert
struct and its exported fields to improve code readability and maintainability.
115-125
: Use a pointer receiver for theAssert
method.The
Assert
method currently has a value receiver, which copies the entireFunTokenBalanceAssert
struct each time it's called. Since the struct contains pointer fields and does not modify the receiver, using a pointer receiver can improve performance by avoiding unnecessary copies.Apply this diff to change the receiver to a pointer:
-func (bals FunTokenBalanceAssert) Assert(t *testing.T, deps TestDeps) { +func (bals *FunTokenBalanceAssert) Assert(t *testing.T, deps TestDeps) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
go.sum
is excluded by!**/*.sum
📒 Files selected for processing (5)
CHANGELOG.md
(2 hunks)app/keepers.go
(4 hunks)app/keepers/all_keepers.go
(1 hunks)go.mod
(1 hunks)x/evm/evmtest/erc20.go
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- app/keepers/all_keepers.go
- go.mod
🔇 Additional comments (8)
app/keepers.go (5)
273-282
: LGTM: NibiruBankKeeper initialization is correct.
The initialization properly wraps the bank keeper's base functionality while allowing for StateDB integration. The initial nil StateDB is appropriate as it will be set during EVM operations.
379-389
: LGTM: EvmKeeper initialization with NibiruBankKeeper.
The integration with NibiruBankKeeper is correct and aligns with the PR objectives of automatically recording ether balance changes.
637-637
: LGTM: Bank module initialization is consistent.
The module initialization correctly uses the enhanced NibiruBankKeeper while maintaining compatibility with the module interface.
663-663
: LGTM: EVM module initialization completes the integration.
The module initialization properly uses the EvmKeeper with its enhanced NibiruBankKeeper integration.
273-282
: Verify complete integration of NibiruBankKeeper.
Let's ensure all modules that perform bank operations are properly integrated with the new NibiruBankKeeper.
Also applies to: 379-389
✅ Verification successful
Based on the search results, I can now generate a final response since I have comprehensive information about the BankKeeper usage across the codebase.
NibiruBankKeeper integration appears complete and properly implemented
The integration is verified to be complete based on the following evidence:
- The
NibiruBankKeeper
is correctly initialized and assigned toapp.BankKeeper
- All modules using bank operations (oracle, tokenfactory, inflation, devgas, evm) interact through the standard BankKeeper interface
- The EVM module's precompiles (wasm, funtoken) already include proper comments acknowledging the NibiruBankKeeper's StateDB requirements
- The
bank_extension.go
implements all necessary bank operations with proper StateDB handling
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Find all potential bank keeper usages that might need updating
# Test: Search for BankKeeper type usage
echo "Searching for BankKeeper type usage..."
rg -A 2 "BankKeeper\s+[^*].*"
# Test: Search for direct bank keeper method calls
echo "Searching for bank keeper method calls..."
rg "\.SendCoins|\.SendCoinsFromModuleToAccount|\.SendCoinsFromAccountToModule"
Length of output: 8927
CHANGELOG.md (1)
86-94
: LGTM! Clear and well-structured changelog entry.
The entry properly documents the changes from PR #2095, explaining what was changed, how it was implemented, and the rationale behind the change. It follows the changelog format guidelines and provides sufficient detail for understanding the impact.
x/evm/evmtest/erc20.go (2)
24-24
: Refactor approved for AssertERC20BalanceEqual
function.
The function now delegates to AssertERC20BalanceEqualWithDescription
, enhancing code reusability.
96-98
: Refactor approved for AssertBankBalanceEqual
function.
The function now calls AssertBankBalanceEqualWithDescription
, promoting consistency and reducing code duplication.
bech32Addr := eth.EthAddrToNibiruAddr(account) | ||
actualBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, bech32Addr, denom).Amount.BigInt() | ||
var errSuffix string | ||
if description == "" { | ||
errSuffix = description | ||
} else { | ||
errSuffix = ": " + description | ||
} | ||
assert.Equalf(t, expectedBalance.String(), actualBalance.String(), | ||
"expected %s, got %s", expectedBalance, actualBalance, errSuffix) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix formatting in AssertBankBalanceEqualWithDescription
.
Similar to the previous function, the assert.Equalf
call has a format string expecting two arguments but receives three. Simplify errSuffix
handling and correct the format string to include the error suffix.
Apply this diff to correct the formatting:
func AssertBankBalanceEqualWithDescription(
t *testing.T,
deps TestDeps,
denom string,
account gethcommon.Address,
expectedBalance *big.Int,
description string,
) {
bech32Addr := eth.EthAddrToNibiruAddr(account)
actualBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, bech32Addr, denom).Amount.BigInt()
- var errSuffix string
- if description == "" {
- errSuffix = description
- } else {
- errSuffix = ": " + description
- }
+ errSuffix := ""
+ if description != "" {
+ errSuffix = ": " + description
+ }
assert.Equalf(t, expectedBalance.String(), actualBalance.String(),
- "expected %s, got %s", expectedBalance, actualBalance, errSuffix)
+ "expected %s, got %s%s", expectedBalance, actualBalance, errSuffix)
}
📝 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.
bech32Addr := eth.EthAddrToNibiruAddr(account) | |
actualBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, bech32Addr, denom).Amount.BigInt() | |
var errSuffix string | |
if description == "" { | |
errSuffix = description | |
} else { | |
errSuffix = ": " + description | |
} | |
assert.Equalf(t, expectedBalance.String(), actualBalance.String(), | |
"expected %s, got %s", expectedBalance, actualBalance, errSuffix) | |
} | |
bech32Addr := eth.EthAddrToNibiruAddr(account) | |
actualBalance := deps.App.BankKeeper.GetBalance(deps.Ctx, bech32Addr, denom).Amount.BigInt() | |
errSuffix := "" | |
if description != "" { | |
errSuffix = ": " + description | |
} | |
assert.Equalf(t, expectedBalance.String(), actualBalance.String(), | |
"expected %s, got %s%s", expectedBalance, actualBalance, errSuffix) | |
} |
actualBalance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20, account, deps.Ctx) | ||
var errSuffix string | ||
if description == "" { | ||
errSuffix = description | ||
} else { | ||
errSuffix = ": " + description | ||
} | ||
assert.NoError(t, err, errSuffix) | ||
assert.Equalf(t, expectedBalance.String(), actualBalance.String(), | ||
"expected %s, got %s", expectedBalance, actualBalance, | ||
errSuffix, | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix formatting in AssertERC20BalanceEqualWithDescription
.
The assert.Equalf
function is called with a format string that expects two arguments, but three arguments are provided, which can lead to formatting errors. Additionally, the handling of errSuffix
can be simplified.
Apply this diff to correct the formatting and simplify the code:
func AssertERC20BalanceEqualWithDescription(
t *testing.T,
deps TestDeps,
erc20, account gethcommon.Address,
expectedBalance *big.Int,
description string,
) {
actualBalance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20, account, deps.Ctx)
- var errSuffix string
- if description == "" {
- errSuffix = description
- } else {
- errSuffix = ": " + description
- }
+ errSuffix := ""
+ if description != "" {
+ errSuffix = ": " + description
+ }
assert.NoError(t, err, errSuffix)
assert.Equalf(t, expectedBalance.String(), actualBalance.String(),
- "expected %s, got %s", expectedBalance, actualBalance,
- errSuffix,
+ "expected %s, got %s%s", expectedBalance, actualBalance, errSuffix,
)
}
📝 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.
actualBalance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20, account, deps.Ctx) | |
var errSuffix string | |
if description == "" { | |
errSuffix = description | |
} else { | |
errSuffix = ": " + description | |
} | |
assert.NoError(t, err, errSuffix) | |
assert.Equalf(t, expectedBalance.String(), actualBalance.String(), | |
"expected %s, got %s", expectedBalance, actualBalance, | |
errSuffix, | |
) | |
} | |
actualBalance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20, account, deps.Ctx) | |
errSuffix := "" | |
if description != "" { | |
errSuffix = ": " + description | |
} | |
assert.NoError(t, err, errSuffix) | |
assert.Equalf(t, expectedBalance.String(), actualBalance.String(), | |
"expected %s, got %s%s", expectedBalance, actualBalance, errSuffix, | |
) | |
} |
Purpose / Abstract
fix(evm): This change records NIBI (ether) transfers on the
StateDB
duringprecompiled contract calls using the
NibiruBankKeeper
, which is a structextension of the
bankkeeper.BaseKeeper
that is used throughout Nibiru. TheNibiruBankKeeper
holds a reference to the current EVMStateDB
and recordsbalance changes in wei as journal changes automatically.
This guarantees that commits and reversions of the
StateDB
do not misalignwith the state of the Bank module. This code change uses the
NibiruBankKeeper
on all modules that depend on x/bank, such as the EVM and Wasm modules.
Each "Send*" method from the bank keeper has an override function that keeps the
the keeper consistent with the Bank when ether is transferred.
Note however that because calls of
ApplyEvmMsg
initialize new*statedb.StateDB
instances even if the calls are for queries, we need to makesure that
NibiruBankKeeper
references the currnet precompile run'sStateDB
before any potential use of the bank keeper.
Cosmos-SDK Diff
See the git diff between the updated Cosmos-SDK dependency
(NibiruChain/cosmos-sdk tag v0.47.11-nibiru.2)
.
This adds deep copy for the multistore and removes an interface assertion that
makes it possible to plug in the
NibiruBankKeeper
as the bank keeper acrossevery module.
Related
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Refactor
Tests
These updates enhance the functionality and reliability of the Nibiru EVM, preparing for an upcoming audit.