Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(evm): ensure only one copy of StateDB when executing Ethereum txs #2165

Merged
merged 35 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3b0387a
cleanup
k-yang Jan 13, 2025
d64647e
cleanup
k-yang Jan 13, 2025
8507e06
partial refactor
k-yang Jan 13, 2025
bd6e0d5
fix: compilation errors
k-yang Jan 14, 2025
f44ce1e
refactor: remove CallContract completely
k-yang Jan 14, 2025
837a6a0
refactor: mintOrUnescrowERC20
k-yang Jan 14, 2025
ae354d6
refactor: use simpler evmObj creation pattern
k-yang Jan 14, 2025
e9ab63d
fix: empty gas price in gethcore Message
k-yang Jan 14, 2025
84e4bf6
fix: contract address collision error
k-yang Jan 15, 2025
4cb566c
fix: TestPrecompileSelfCallRevert
k-yang Jan 15, 2025
3b420a3
fix: unnecessary stateDB creation
k-yang Jan 15, 2025
aec26d0
fix: ensure stateDB singleton
k-yang Jan 16, 2025
1962805
fix: balance check
k-yang Jan 16, 2025
4f9d897
fix: balance transfer check had wrong direction
k-yang Jan 16, 2025
6d082cc
fix: deploy contract args
k-yang Jan 16, 2025
4d92d5b
fix: use a new StateDB before CallContractWithInput
k-yang Jan 16, 2025
edf959e
Merge branch 'main' into refactor/evm/call-contract
k-yang Jan 16, 2025
e94abc7
Update CHANGELOG.md
k-yang Jan 16, 2025
e95f809
fix: clear StateDB between txs
k-yang Jan 16, 2025
396afb4
Update account_info_test.go
k-yang Jan 16, 2025
39fdac9
Update account_info_test.go
k-yang Jan 16, 2025
8445c92
Update app/evmante/evmante_can_transfer.go
k-yang Jan 16, 2025
b4f3ac8
fix base fee wei
k-yang Jan 16, 2025
ff27306
refactor: funtoken tests
k-yang Jan 16, 2025
0d26abc
refactor: simplify NewEVM() object creation in tests
k-yang Jan 17, 2025
ab913ba
fix: stateDB should not commit on ERC20 calls
k-yang Jan 17, 2025
ecfd2fe
fix: commit after minting funtokens
k-yang Jan 17, 2025
4117272
fix: erc20 burn was committing when it shouldn't be
k-yang Jan 17, 2025
997a946
fix: linter
k-yang Jan 17, 2025
cfc3bbe
Merge branch 'main' into refactor/evm/call-contract
k-yang Jan 17, 2025
b775d16
Merge branch 'main' into refactor/evm/call-contract
Unique-Divine Jan 17, 2025
a8dd8a6
Merge branch 'refactor/evm/call-contract' of https://github.com/Nibir…
Unique-Divine Jan 17, 2025
eb47f0a
refactor: TestCreateFunTokenFromCoin
k-yang Jan 17, 2025
138dd63
refactor: make a trivial change to use fresh cache in CI
Unique-Divine Jan 17, 2025
d35274a
test(gosdk): larger timeouts before next broadcast
Unique-Divine Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ needed to include double quotes around the hexadecimal string.
- [#2162](https://github.com/NibiruChain/nibiru/pull/2162) - test(testutil): try retrying for 'panic: pebbledb: closed'
- [#2167](https://github.com/NibiruChain/nibiru/pull/2167) - refactor(evm): removed blockGasUsed transient variable
- [#2168](https://github.com/NibiruChain/nibiru/pull/2168) - chore(evm-solidity): Move unrelated docs, gen-embeds, and add Solidity docs
- [#2165](https://github.com/NibiruChain/nibiru/pull/2165) - fix(evm): use Singleton StateDB pattern for EVM txs

#### Nibiru EVM | Before Audit 2 - 2024-12-06

Expand Down Expand Up @@ -346,7 +347,6 @@ Nibiru v1.3.0 adds interchain accounts.

- [#1859](https://github.com/NibiruChain/nibiru/pull/1859) - refactor(oracle): add oracle slashing events


---

[LEGACY CHANGELOG](./LEGACY-CHANGELOG.md)
48 changes: 18 additions & 30 deletions app/evmante/evmante_can_transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import (
"cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
gethcommon "github.com/ethereum/go-ethereum/common"
gethcore "github.com/ethereum/go-ethereum/core/types"

"github.com/NibiruChain/nibiru/v2/eth"
"github.com/NibiruChain/nibiru/v2/x/evm"
"github.com/NibiruChain/nibiru/v2/x/evm/statedb"
)

// CanTransferDecorator checks if the sender is allowed to transfer funds according to the EVM block
Expand All @@ -25,7 +24,6 @@ type CanTransferDecorator struct {
func (ctd CanTransferDecorator) AnteHandle(
ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler,
) (sdk.Context, error) {
params := ctd.GetParams(ctx)
ethCfg := evm.EthereumConfig(ctd.EVMKeeper.EthChainID(ctx))
signer := gethcore.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()))

Expand All @@ -40,7 +38,7 @@ func (ctd CanTransferDecorator) AnteHandle(

baseFeeWeiPerGas := evm.NativeToWei(ctd.EVMKeeper.BaseFeeMicronibiPerGas(ctx))

coreMsg, err := msgEthTx.AsMessage(signer, baseFeeWeiPerGas)
evmMsg, err := msgEthTx.AsMessage(signer, baseFeeWeiPerGas)
if err != nil {
return ctx, errors.Wrapf(
err,
Expand All @@ -59,37 +57,27 @@ func (ctd CanTransferDecorator) AnteHandle(
return ctx, errors.Wrapf(
sdkerrors.ErrInsufficientFee,
"gas fee cap (wei) less than block base fee (wei); (%s < %s)",
coreMsg.GasFeeCap(), baseFeeWeiPerGas,
evmMsg.GasFeeCap(), baseFeeWeiPerGas,
)
}

cfg := &statedb.EVMConfig{
ChainConfig: ethCfg,
Params: params,
// Note that we use an empty coinbase here because the field is not
// used during this Ante Handler.
BlockCoinbase: gethcommon.Address{},
BaseFeeWei: baseFeeWeiPerGas,
}

stateDB := ctd.NewStateDB(
Copy link
Member Author

Choose a reason for hiding this comment

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

Creating a new StateDB here uses the anteCtx, which gets tossed when the tx runs. That means whenever StateDB commits, it's committing to a out of scope ctx.

It's better to just read the bank balances directly via the Cosmos ctx (which is what core.CanTransfer does anyways).

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

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

if evmMsg.Value().Sign() > 0 {
nibiruAddr := eth.EthAddrToNibiruAddr(evmMsg.From())
balanceNative := ctd.Bank.GetBalance(ctx, nibiruAddr, evm.EVMBankDenom).Amount.BigInt()
balanceWei := evm.NativeToWei(balanceNative)

if balanceWei.Cmp(evmMsg.Value()) < 0 {
return ctx, errors.Wrapf(
sdkerrors.ErrInsufficientFunds,
"failed to transfer %s wei ( balance=%s )from address %s using the EVM block context transfer function",
evmMsg.Value(),
balanceWei,
evmMsg.From(),
)
}
}
}

Expand Down
6 changes: 1 addition & 5 deletions app/evmante/evmante_can_transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ import (
func (s *TestSuite) TestCanTransferDecorator() {
testCases := []struct {
name string
txSetup func(deps *evmtest.TestDeps) sdk.FeeTx
ctxSetup func(deps *evmtest.TestDeps)
beforeTxSetup func(deps *evmtest.TestDeps, sdb *statedb.StateDB)
txSetup func(deps *evmtest.TestDeps) sdk.FeeTx
wantErr string
}{
{
Expand Down Expand Up @@ -92,9 +91,6 @@ func (s *TestSuite) TestCanTransferDecorator() {
anteDec := evmante.CanTransferDecorator{deps.App.AppKeepers.EvmKeeper}
tx := tc.txSetup(&deps)

if tc.ctxSetup != nil {
tc.ctxSetup(&deps)
}
if tc.beforeTxSetup != nil {
tc.beforeTxSetup(&deps, stateDB)
err := stateDB.Commit()
Expand Down
6 changes: 3 additions & 3 deletions eth/rpc/backend/backend_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (s *BackendSuite) SetupSuite() {

// Send Transfer TX and use the results in the tests
s.Require().NoError(err)
transferTxHash = s.SendNibiViaEthTransfer(recipient, amountToSend, true)
transferTxHash = s.SendNibiViaEthTransfer(recipient, amountToSend, true /*waitForNextBlock*/)
blockNumber, blockHash, _ := WaitForReceipt(s, transferTxHash)
s.Require().NotNil(blockNumber)
s.Require().NotNil(blockHash)
Expand Down Expand Up @@ -151,7 +151,7 @@ func (s *BackendSuite) DeployTestContract(waitForNextBlock bool) (gethcommon.Has
&gethcore.LegacyTx{
Nonce: uint64(nonce),
Data: bytecodeForCall,
Gas: 1500_000,
Gas: 1_500_000,
GasPrice: big.NewInt(1),
},
waitForNextBlock,
Expand All @@ -177,7 +177,7 @@ func SendTransaction(s *BackendSuite, tx *gethcore.LegacyTx, waitForNextBlock bo

// WaitForReceipt waits for a transaction to be included in a block, returns block number, block hash and receipt
func WaitForReceipt(s *BackendSuite, txHash gethcommon.Hash) (*big.Int, *gethcommon.Hash, *backend.TransactionReceipt) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
Copy link
Member Author

Choose a reason for hiding this comment

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

I increased the wait time because a 5 second timeout was causing issues when I stepped through the code with a debugger (which takes longer than 5 seconds).

defer cancel()

for {
Expand Down
4 changes: 0 additions & 4 deletions eth/rpc/backend/gas_used_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,6 @@ func (s *BackendSuite) TestGasUsedFunTokens() {
s.Require().NotNil(blockNumber2)
s.Require().NotNil(blockNumber3)

// TXs should have been included in the same block
s.Require().Equal(blockNumber1, blockNumber2)
Copy link
Member Author

Choose a reason for hiding this comment

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

Unnecessary to have the txs in the same block.

s.Require().Equal(blockNumber2, blockNumber3)

// 1 and 3 should pass and 2 should fail
s.Require().Equal(gethcore.ReceiptStatusSuccessful, receipt1.Status)
s.Require().Equal(gethcore.ReceiptStatusFailed, receipt2.Status)
Expand Down
2 changes: 1 addition & 1 deletion x/common/testutil/testnetwork/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ func (n *Network) LatestHeight() (int64, error) {
// committed after a given block. If that height is not reached within a timeout,
// an error is returned. Regardless, the latest height queried is returned.
func (n *Network) WaitForHeight(h int64) (int64, error) {
return n.WaitForHeightWithTimeout(h, 40*time.Second)
return n.WaitForHeightWithTimeout(h, 5*time.Minute)
Copy link
Member Author

Choose a reason for hiding this comment

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

Same issue with the debugger timing out.

}

// WaitForHeightWithTimeout is the same as WaitForHeight except the caller can
Expand Down
21 changes: 11 additions & 10 deletions x/evm/evmmodule/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ type Suite struct {

// TestKeeperSuite: Runs all the tests in the suite.
func TestKeeperSuite(t *testing.T) {
s := new(Suite)
suite.Run(t, s)
suite.Run(t, new(Suite))
}

// TestExportInitGenesis
Expand All @@ -48,21 +47,23 @@ func (s *Suite) TestExportInitGenesis() {
deployResp, err := evmtest.DeployContract(&deps, erc20Contract)
s.Require().NoError(err)
erc20Addr := deployResp.ContractAddr

evmObj, _ := deps.NewEVM()
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 17, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle error returned by deps.NewEVM()

The error returned by deps.NewEVM() is being ignored. It's important to check and handle this error to ensure that evmObj is initialized correctly.

Apply this diff to handle the error:

-	evmObj, _ := deps.NewEVM()
+	evmObj, err := deps.NewEVM()
+	s.Require().NoError(err)
📝 Committable suggestion

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

Suggested change
evmObj, _ := deps.NewEVM()
evmObj, err := deps.NewEVM()
s.Require().NoError(err)

Copy link
Member Author

Choose a reason for hiding this comment

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

deps.NewEVM() does not return an error

Copy link
Contributor

Choose a reason for hiding this comment

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

@k-yang You are correct. Looking at the source code, deps.NewEVM() returns (*vm.EVM, *statedb.StateDB) without an error value. I apologize for my mistake in the review comment.

🔗 Analysis chain

@k-yang You are correct. I apologize for my mistake. The deps.NewEVM() method indeed returns only *vm.EVM without an error value.


🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the NewEVM method definition in test dependencies
ast-grep --pattern 'func $_(deps TestDeps) NewEVM() $ret'

Length of output: 59


Script:

#!/bin/bash
# Search for NewEVM method definition with context
rg "NewEVM" -A 5 -B 2

Length of output: 39790


✏️ Learnings added
Learnt from: k-yang
PR: NibiruChain/nibiru#2165
File: x/evm/evmmodule/genesis_test.go:51-51
Timestamp: 2025-01-17T17:32:27.201Z
Learning: The `NewEVM()` method in TestDeps returns `(*vm.EVM, *statedb.StateDB)` without an error value. The second return value is often discarded when only the EVM object is needed.

Learnt from: k-yang
PR: NibiruChain/nibiru#2165
File: x/evm/evmmodule/genesis_test.go:51-51
Timestamp: 2025-01-17T17:32:27.201Z
Learning: The `NewEVM()` method in TestDeps returns only `*vm.EVM` without an error value.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

totalSupply, err := deps.EvmKeeper.ERC20().LoadERC20BigInt(
deps.Ctx, erc20Contract.ABI, erc20Addr, "totalSupply",
deps.Ctx, evmObj, erc20Contract.ABI, erc20Addr, "totalSupply",
)
s.Require().NoError(err)

// Transfer ERC-20 tokens to user A
_, _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserA, amountToSendA, deps.Ctx)
_, _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserA, amountToSendA, deps.Ctx, evmObj)
s.Require().NoError(err)

// Transfer ERC-20 tokens to user B
_, _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserB, amountToSendB, deps.Ctx)
_, _, err = deps.EvmKeeper.ERC20().Transfer(erc20Addr, fromUser, toUserB, amountToSendB, deps.Ctx, evmObj)
s.Require().NoError(err)

// Create fungible token from bank coin
funToken := evmtest.CreateFunTokenForBankCoin(&deps, "unibi", &s.Suite)
funToken := evmtest.CreateFunTokenForBankCoin(deps, "unibi", &s.Suite)
s.Require().NoError(err)
funTokenAddr := funToken.Erc20Addr.Address

Expand Down Expand Up @@ -98,15 +99,15 @@ func (s *Suite) TestExportInitGenesis() {
evmmodule.InitGenesis(deps.Ctx, deps.EvmKeeper, deps.App.AccountKeeper, *evmGenesisState)

// Verify erc20 balances for users A, B and sender
balance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20Addr, toUserA, deps.Ctx)
balance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20Addr, toUserA, deps.Ctx, evmObj)
s.Require().NoError(err)
s.Require().Equal(amountToSendA, balance)

balance, err = deps.EvmKeeper.ERC20().BalanceOf(erc20Addr, toUserB, deps.Ctx)
balance, err = deps.EvmKeeper.ERC20().BalanceOf(erc20Addr, toUserB, deps.Ctx, evmObj)
s.Require().NoError(err)
s.Require().Equal(amountToSendB, balance)

balance, err = deps.EvmKeeper.ERC20().BalanceOf(erc20Addr, fromUser, deps.Ctx)
balance, err = deps.EvmKeeper.ERC20().BalanceOf(erc20Addr, fromUser, deps.Ctx, evmObj)
s.Require().NoError(err)
s.Require().Equal(
new(big.Int).Sub(totalSupply, big.NewInt(amountToSendA.Int64()+amountToSendB.Int64())),
Expand All @@ -122,7 +123,7 @@ func (s *Suite) TestExportInitGenesis() {
s.Require().True(funTokens[0].IsMadeFromCoin)

// Check that fungible token balance of user C is correct
balance, err = deps.EvmKeeper.ERC20().BalanceOf(funTokenAddr, toUserC, deps.Ctx)
balance, err = deps.EvmKeeper.ERC20().BalanceOf(funTokenAddr, toUserC, deps.Ctx, evmObj)
s.Require().NoError(err)
s.Require().Equal(amountToSendC, balance)
}
97 changes: 39 additions & 58 deletions x/evm/evmtest/erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
gethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"

Expand All @@ -15,19 +16,52 @@ import (
"github.com/NibiruChain/nibiru/v2/x/evm"
)

func AssertERC20BalanceEqual(
func AssertERC20BalanceEqualWithDescription(
t *testing.T,
deps TestDeps,
evmObj *vm.EVM,
erc20, account gethcommon.Address,
expectedBalance *big.Int,
description string,
) {
AssertERC20BalanceEqualWithDescription(t, deps, erc20, account, expectedBalance, "")
actualBalance, err := deps.EvmKeeper.ERC20().BalanceOf(erc20, account, deps.Ctx, evmObj)
var errSuffix string
if description == "" {
errSuffix = description
} else {
errSuffix = ": " + description
}
k-yang marked this conversation as resolved.
Show resolved Hide resolved
assert.NoError(t, err, errSuffix)
assert.Equalf(t, expectedBalance.String(), actualBalance.String(),
"expected %s, got %s: %s", expectedBalance, actualBalance, errSuffix,
)
}

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
}
assert.Equalf(t, expectedBalance.String(), actualBalance.String(),
"expected %s, got %s: %s", expectedBalance, actualBalance, errSuffix,
)
}

// CreateFunTokenForBankCoin: Uses the "TestDeps.Sender" account to create a
// "FunToken" mapping for a new coin
func CreateFunTokenForBankCoin(
deps *TestDeps, bankDenom string, s *suite.Suite,
deps TestDeps, bankDenom string, s *suite.Suite,
) (funtoken evm.FunToken) {
if deps.App.BankKeeper.HasDenomMetaData(deps.Ctx, bankDenom) {
s.Failf("setting bank.DenomMetadata would overwrite existing denom \"%s\"", bankDenom)
Expand Down Expand Up @@ -86,18 +120,6 @@ func CreateFunTokenForBankCoin(
return funtoken
}

func AssertBankBalanceEqual(
t *testing.T,
deps TestDeps,
denom string,
account gethcommon.Address,
expectedBalance *big.Int,
) {
AssertBankBalanceEqualWithDescription(
t, deps, denom, account, expectedBalance, "",
)
}

// BigPow multiplies "amount" by 10 to the "pow10Exp".
func BigPow(amount *big.Int, pow10Exp uint8) (powAmount *big.Int) {
pow10 := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(pow10Exp)), nil)
Expand All @@ -112,9 +134,9 @@ type FunTokenBalanceAssert struct {
Description string
}

func (bals FunTokenBalanceAssert) Assert(t *testing.T, deps TestDeps) {
func (bals FunTokenBalanceAssert) Assert(t *testing.T, deps TestDeps, evmObj *vm.EVM) {
AssertERC20BalanceEqualWithDescription(
t, deps, bals.FunToken.Erc20Addr.Address, bals.Account, bals.BalanceERC20,
t, deps, evmObj, bals.FunToken.Erc20Addr.Address, bals.Account, bals.BalanceERC20,
bals.Description,
)
AssertBankBalanceEqualWithDescription(
Expand All @@ -123,47 +145,6 @@ func (bals FunTokenBalanceAssert) Assert(t *testing.T, deps TestDeps) {
)
}

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
}
assert.NoError(t, err, errSuffix)
assert.Equalf(t, expectedBalance.String(), actualBalance.String(),
"expected %s, got %s", expectedBalance, actualBalance,
errSuffix,
)
}

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
}
assert.Equalf(t, expectedBalance.String(), actualBalance.String(),
"expected %s, got %s", expectedBalance, actualBalance, errSuffix)
}

const (
// FunTokenGasLimitSendToEvm consists of gas for 3 calls:
// 1. transfer erc20 from sender to module
Expand Down
Loading
Loading