Skip to content

Commit

Permalink
fix: audit (#59)
Browse files Browse the repository at this point in the history
* return non nil empty values

* add missing log fields at marshal receipt

* put base_fee and gas price at context creation
  • Loading branch information
beer-1 authored Sep 19, 2024
1 parent 6a5d3ac commit dfcc4e0
Show file tree
Hide file tree
Showing 22 changed files with 586 additions and 98 deletions.
2 changes: 2 additions & 0 deletions app/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
opchildtypes "github.com/initia-labs/OPinit/x/opchild/types"
"github.com/initia-labs/initia/app/ante/accnum"
"github.com/initia-labs/initia/app/ante/sigverify"
evmante "github.com/initia-labs/minievm/x/evm/ante"
evmkeeper "github.com/initia-labs/minievm/x/evm/keeper"

"github.com/skip-mev/block-sdk/v2/block"
Expand Down Expand Up @@ -85,6 +86,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
accnum.NewAccountNumberDecorator(options.AccountKeeper),
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
evmante.NewGasPricesDecorator(),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
Expand Down
15 changes: 15 additions & 0 deletions app/ibc-hooks/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ func _createTestInput(
banktypes.RegisterQueryServer(queryRouter, &bankKeeper)

communityPoolKeeper := &MockCommunityPoolKeeper{}
gasPriceKeeper := &MockGasPriceKeeper{GasPrices: map[string]math.LegacyDec{}}
evmKeeper := evmkeeper.NewKeeper(
ac,
appCodec,
Expand All @@ -311,6 +312,7 @@ func _createTestInput(
accountKeeper,
bankKeeper,
communityPoolKeeper,
gasPriceKeeper,
msgRouter,
queryRouter,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Expand Down Expand Up @@ -424,3 +426,16 @@ func (m mockIBCMiddleware) OnRecvPacket(ctx sdk.Context, packet channeltypes.Pac
func (m mockIBCMiddleware) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error {
return nil
}

type MockGasPriceKeeper struct {
GasPrices map[string]math.LegacyDec
}

func (k *MockGasPriceKeeper) GasPrice(ctx context.Context, denom string) (math.LegacyDec, error) {
gasPrice, ok := k.GasPrices[denom]
if !ok {
return math.LegacyZeroDec(), nil
}

return gasPrice, nil
}
36 changes: 36 additions & 0 deletions app/keepers/gas_price.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package keepers

import (
"context"
"errors"

"cosmossdk.io/collections"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
)

type opchildKeeperForGasPriceKeeper interface {
MinGasPrices(ctx context.Context) (sdk.DecCoins, error)
}

type GasPriceKeeper struct {
opck opchildKeeperForGasPriceKeeper
}

func newGasPriceKeeper(opck opchildKeeperForGasPriceKeeper) GasPriceKeeper {
return GasPriceKeeper{
opck: opck,
}
}

func (k GasPriceKeeper) GasPrice(ctx context.Context, denom string) (math.LegacyDec, error) {
gasPrices, err := k.opck.MinGasPrices(ctx)
if err != nil && errors.Is(err, collections.ErrNotFound) {
// allow this case due to init_genesis ordering
return math.LegacyZeroDec(), nil
} else if err != nil {
return math.LegacyZeroDec(), err
}

return gasPrices.AmountOf(denom), nil
}
2 changes: 2 additions & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ func NewAppKeeper(
// EVMKeeper Configuration //
//////////////////////////////

gasPriceKeeper := newGasPriceKeeper(appKeepers.OPChildKeeper)
*appKeepers.EVMKeeper = *evmkeeper.NewKeeper(
ac,
appCodec,
Expand All @@ -556,6 +557,7 @@ func NewAppKeeper(
accountKeeper,
bankKeeper,
communityPoolKeeper,
gasPriceKeeper,
bApp.MsgServiceRouter(),
bApp.GRPCQueryRouter(),
authorityAddr,
Expand Down
7 changes: 3 additions & 4 deletions indexer/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func (e *EVMIndexerImpl) ListenCommit(ctx context.Context, res abci.ResponseComm
func (e *EVMIndexerImpl) ListenFinalizeBlock(ctx context.Context, req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock) error {
sdkCtx := sdk.UnwrapSDKContext(ctx)

// compute base fee from the opChild gas prices
baseFee, err := e.baseFee(sdkCtx)
// load base fee from evm keeper
baseFee, err := e.evmKeeper.BaseFee(sdkCtx)
if err != nil {
e.logger.Error("failed to get base fee", "err", err)
return err
Expand Down Expand Up @@ -123,7 +123,7 @@ func (e *EVMIndexerImpl) ListenFinalizeBlock(ctx context.Context, req abci.Reque
GasUsed: blockGasMeter.GasConsumedToLimit(),
Number: big.NewInt(blockHeight),
Time: uint64(sdkCtx.BlockTime().Unix()),
BaseFee: baseFee.ToInt(),
BaseFee: baseFee,

// empty values
Root: coretypes.EmptyRootHash,
Expand Down Expand Up @@ -167,7 +167,6 @@ func (e *EVMIndexerImpl) ListenFinalizeBlock(ctx context.Context, req abci.Reque
return err
}

// emit log events
if len(e.logsChans) > 0 {
for idx, log := range receipt.Logs {
// fill in missing fields before emitting
Expand Down
46 changes: 0 additions & 46 deletions indexer/utils.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package indexer

import (
"context"
"encoding/json"
"fmt"

collcodec "cosmossdk.io/collections/codec"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/gogoproto/proto"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
coretypes "github.com/ethereum/go-ethereum/core/types"

"github.com/initia-labs/minievm/x/evm/types"
Expand Down Expand Up @@ -105,46 +102,3 @@ func (c collJsonVal[T]) Stringify(value T) string {
func (c collJsonVal[T]) ValueType() string {
return "jsonvalue"
}

// calculate BaseFee
func (e *EVMIndexerImpl) feeDenom(ctx context.Context) (string, error) {
params, err := e.evmKeeper.Params.Get(ctx)
if err != nil {
return "", err
}

return params.FeeDenom, nil
}

func (e *EVMIndexerImpl) feeDenomWithDecimals(ctx context.Context) (string, uint8, error) {
feeDenom, err := e.feeDenom(ctx)
if err != nil {
return "", 0, err
}

decimals, err := e.evmKeeper.ERC20Keeper().GetDecimals(ctx, feeDenom)
if err != nil {
return "", 0, err
}

return feeDenom, decimals, nil
}

func (e *EVMIndexerImpl) baseFee(ctx context.Context) (*hexutil.Big, error) {
params, err := e.opChildKeeper.GetParams(ctx)
if err != nil {
return nil, err
}

feeDenom, decimals, err := e.feeDenomWithDecimals(ctx)
if err != nil {
return nil, err
}

// multiply by 1e9 to prevent decimal drops
gasPrice := params.MinGasPrices.AmountOf(feeDenom).
MulTruncate(math.LegacyNewDec(1e9)).
TruncateInt().BigInt()

return (*hexutil.Big)(types.ToEthersUint(decimals+9, gasPrice)), nil
}
14 changes: 14 additions & 0 deletions jsonrpc/backend/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,20 @@ func (b *JSONRPCBackend) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc

// marshalReceipt marshals a transaction receipt into a JSON object.
func marshalReceipt(receipt *coretypes.Receipt, tx *rpctypes.RPCTransaction) map[string]interface{} {
for idx, log := range receipt.Logs {
log.Index = uint(idx)
if tx.BlockHash != nil {
log.BlockHash = *tx.BlockHash
}
if tx.BlockNumber != nil {
log.BlockNumber = tx.BlockNumber.ToInt().Uint64()
}
log.TxHash = tx.Hash
if tx.TransactionIndex != nil {
log.TxIndex = uint(*tx.TransactionIndex)
}
}

fields := map[string]interface{}{
"blockHash": tx.BlockHash,
"blockNumber": hexutil.Uint64(tx.BlockNumber.ToInt().Uint64()),
Expand Down
15 changes: 15 additions & 0 deletions x/bank/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ func _createTestInput(
banktypes.RegisterQueryServer(queryRouter, &bankKeeper)

communityPoolKeeper := &MockCommunityPoolKeeper{}
gasPriceKeeper := &MockGasPriceKeeper{GasPrices: map[string]math.LegacyDec{}}
evmKeeper := evmkeeper.NewKeeper(
ac,
appCodec,
Expand All @@ -303,6 +304,7 @@ func _createTestInput(
accountKeeper,
bankKeeper,
communityPoolKeeper,
gasPriceKeeper,
msgRouter,
queryRouter,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Expand Down Expand Up @@ -341,3 +343,16 @@ func (k *MockCommunityPoolKeeper) FundCommunityPool(ctx context.Context, amount

return nil
}

type MockGasPriceKeeper struct {
GasPrices map[string]math.LegacyDec
}

func (k *MockGasPriceKeeper) GasPrice(ctx context.Context, denom string) (math.LegacyDec, error) {
gasPrice, ok := k.GasPrices[denom]
if !ok {
return math.LegacyZeroDec(), nil
}

return gasPrice, nil
}
132 changes: 132 additions & 0 deletions x/evm/ante/ante_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package ante_test

import (
"context"
"testing"

"github.com/stretchr/testify/suite"

tmproto "github.com/cometbft/cometbft/proto/tendermint/types"

"cosmossdk.io/log"
dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/server"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsign "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli"

minitiaapp "github.com/initia-labs/minievm/app"
evmconfig "github.com/initia-labs/minievm/x/evm/config"
evmtypes "github.com/initia-labs/minievm/x/evm/types"
)

// AnteTestSuite is a test suite to be used with ante handler tests.
type AnteTestSuite struct {
suite.Suite

app *minitiaapp.MinitiaApp
ctx sdk.Context
clientCtx client.Context
txBuilder client.TxBuilder
}

// returns context and app with params set on account keeper
func (suite *AnteTestSuite) createTestApp(tempDir string) (*minitiaapp.MinitiaApp, sdk.Context) {
appOptions := make(simtestutil.AppOptionsMap, 0)
appOptions[flags.FlagHome] = tempDir
appOptions[server.FlagInvCheckPeriod] = simcli.FlagPeriodValue

app := minitiaapp.NewMinitiaApp(
log.NewNopLogger(), dbm.NewMemDB(), dbm.NewMemDB(), dbm.NewMemDB(), nil, true, evmconfig.DefaultEVMConfig(), appOptions,
)
ctx := app.BaseApp.NewUncachedContext(false, tmproto.Header{})
err := app.AccountKeeper.Params.Set(ctx, authtypes.DefaultParams())
suite.NoError(err)

err = app.EVMKeeper.Params.Set(ctx, evmtypes.DefaultParams())
suite.NoError(err)

return app, ctx
}

// SetupTest setups a new test, with new app, context, and anteHandler.
func (suite *AnteTestSuite) SetupTest() {
tempDir := suite.T().TempDir()
suite.app, suite.ctx = suite.createTestApp(tempDir)
suite.ctx = suite.ctx.WithBlockHeight(1)

// Set up TxConfig.
encodingConfig := minitiaapp.MakeEncodingConfig()

// We're using TestMsg encoding in some tests, so register it here.
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
testdata.RegisterInterfaces(encodingConfig.InterfaceRegistry)

suite.clientCtx = client.Context{}.
WithTxConfig(encodingConfig.TxConfig)
}

// CreateTestTx is a helper function to create a tx given multiple inputs.
func (suite *AnteTestSuite) CreateTestTx(privs []cryptotypes.PrivKey, accNums []uint64, accSeqs []uint64, chainID string) (authsign.Tx, error) {
defaultSignMode, err := authsign.APISignModeToInternal(suite.clientCtx.TxConfig.SignModeHandler().DefaultMode())
suite.NoError(err)

// First round: we gather all the signer infos. We use the "set empty
// signature" hack to do that.
var sigsV2 []signing.SignatureV2
for i, priv := range privs {

sigV2 := signing.SignatureV2{
PubKey: priv.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: defaultSignMode,
Signature: nil,
},
Sequence: accSeqs[i],
}

sigsV2 = append(sigsV2, sigV2)
}
err = suite.txBuilder.SetSignatures(sigsV2...)
if err != nil {
return nil, err
}

// Second round: all signer infos are set, so each signer can sign.
sigsV2 = []signing.SignatureV2{}
for i, priv := range privs {
signerData := authsign.SignerData{
Address: sdk.AccAddress(priv.PubKey().Address()).String(),
ChainID: chainID,
AccountNumber: accNums[i],
Sequence: accSeqs[i],
PubKey: priv.PubKey(),
}
sigV2, err := tx.SignWithPrivKey(
context.TODO(), defaultSignMode, signerData,
suite.txBuilder, priv, suite.clientCtx.TxConfig, accSeqs[i])
if err != nil {
return nil, err
}

sigsV2 = append(sigsV2, sigV2)
}
err = suite.txBuilder.SetSignatures(sigsV2...)
if err != nil {
return nil, err
}

return suite.txBuilder.GetTx(), nil
}

func TestAnteTestSuite(t *testing.T) {
suite.Run(t, new(AnteTestSuite))
}
8 changes: 8 additions & 0 deletions x/evm/ante/context_keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ante

// private type creates an interface key for Context that cannot be accessed by any other package
type contextKey int

const (
ContextKeyGasPrices contextKey = iota
)
Loading

0 comments on commit dfcc4e0

Please sign in to comment.