Skip to content

Commit

Permalink
Merge branch 'main' into expertdicer/erc20-metadata-handling
Browse files Browse the repository at this point in the history
  • Loading branch information
expertdicer committed Jan 18, 2025
2 parents 39ae66d + 13c71a7 commit b4e2574
Show file tree
Hide file tree
Showing 38 changed files with 1,814 additions and 1,733 deletions.
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(
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)
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)
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
4 changes: 3 additions & 1 deletion eth/rpc/backend/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,9 @@ func ShouldIgnoreGasUsed(res *abci.ResponseDeliverTx) bool {
}

// GetLogsFromBlockResults returns the list of event logs from the tendermint block result response
func GetLogsFromBlockResults(blockRes *tmrpctypes.ResultBlockResults) ([][]*gethcore.Log, error) {
func GetLogsFromBlockResults(
blockRes *tmrpctypes.ResultBlockResults,
) ([][]*gethcore.Log, error) {
blockLogs := [][]*gethcore.Log{}
for _, txResult := range blockRes.TxsResults {
logs, err := AllTxLogsFromEvents(txResult.Events)
Expand Down
19 changes: 10 additions & 9 deletions gosdk/gosdk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,26 @@ func (s *TestSuite) ConnectGrpc() {
s.grpcConn = grpcConn
}

func (s *TestSuite) DoTestNewQueryClient() {
_, err := gosdk.NewQuerier(s.grpcConn)
s.NoError(err)
}

func (s *TestSuite) TestNewNibiruSdk() {
rpcEndpt := s.val.RPCAddress
nibiruSdk, err := gosdk.NewNibiruSdk(s.cfg.ChainID, s.grpcConn, rpcEndpt)
s.NoError(err)
s.nibiruSdk = &nibiruSdk

s.nibiruSdk.Keyring = s.val.ClientCtx.Keyring

s.Run("DoTestBroadcastMsgs", func() { s.DoTestBroadcastMsgs() })
s.Run("DoTestBroadcastMsgs", func() {
s.DoTestBroadcastMsgs()
})
s.Run("DoTestBroadcastMsgsGrpc", func() {
s.NoError(s.network.WaitForNextBlock())
for t := 0; t < 4; t++ {
s.NoError(s.network.WaitForNextBlock())
}
s.DoTestBroadcastMsgsGrpc()
})
s.Run("DoTestNewQueryClient", s.DoTestNewQueryClient)
s.Run("DoTestNewQueryClient", func() {
_, err := gosdk.NewQuerier(s.grpcConn)
s.NoError(err)
})
}

// FIXME: Q: What is the node home for a local validator?
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)
}

// 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()
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)
}
Loading

0 comments on commit b4e2574

Please sign in to comment.