diff --git a/CHANGELOG.md b/CHANGELOG.md index 23dcb15d1..88fa93ee9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,9 +63,9 @@ committed as expected, fixes the `StateDB.Commit` to follow its guidelines more closely, and solves for a critical state inconsistency producible from the FunToken.sol precompiled contract. It also aligns the precompiles to use consistent setup and dynamic gas calculations, addressing the following tickets. - - https://github.com/NibiruChain/nibiru/issues/2083 - - https://github.com/code-423n4/2024-10-nibiru-zenith/issues/43 - - https://github.com/code-423n4/2024-10-nibiru-zenith/issues/47 + - + - + - - [#2088](https://github.com/NibiruChain/nibiru/pull/2088) - refactor(evm): remove outdated comment and improper error message text - [#2089](https://github.com/NibiruChain/nibiru/pull/2089) - better handling of gas consumption within erc20 contract execution - [#2091](https://github.com/NibiruChain/nibiru/pull/2091) - feat(evm): add fun token creation fee validation @@ -163,6 +163,7 @@ about the expected resulting balance for the transfer recipient. - [#2060](https://github.com/NibiruChain/nibiru/pull/2060) - fix(evm-precompiles): add assertNumArgs validation - [#2056](https://github.com/NibiruChain/nibiru/pull/2056) - feat(evm): add oracle precompile - [#2065](https://github.com/NibiruChain/nibiru/pull/2065) - refactor(evm)!: Refactor out dead code from the evm.Params +- [#2100](https://github.com/NibiruChain/nibiru/pull/2100) - refactor: cleanup statedb and precompile sections ### State Machine Breaking (Other) diff --git a/app/server/config/server_config.go b/app/server/config/server_config.go index b72638ed2..f393983a9 100644 --- a/app/server/config/server_config.go +++ b/app/server/config/server_config.go @@ -174,7 +174,7 @@ type TLSConfig struct { // AppConfig helps to override default appConfig template and configs. // return "", nil if no custom configuration is required for the application. -func AppConfig(denom string) (string, interface{}) { +func AppConfig(denom string) (string, any) { // Optionally allow the chain developer to overwrite the SDK's default // server config. customAppConfig := DefaultConfig() diff --git a/cmd/nibid/cmd/base64.go b/cmd/nibid/cmd/base64.go index 5f235d3ea..ba5685aff 100644 --- a/cmd/nibid/cmd/base64.go +++ b/cmd/nibid/cmd/base64.go @@ -33,7 +33,7 @@ func GetBuildWasmMsg() *cobra.Command { Value string `json:"value,omitempty"` } - js, err := json.Marshal(map[string]interface{}{ + js, err := json.Marshal(map[string]any{ "stargate": stargateMessage{ TypeURL: anyMsg.TypeUrl, Value: base64.StdEncoding.EncodeToString(anyMsg.Value), diff --git a/cmd/nibid/cmd/decode_base64.go b/cmd/nibid/cmd/decode_base64.go index 3de3706f2..8625070c3 100644 --- a/cmd/nibid/cmd/decode_base64.go +++ b/cmd/nibid/cmd/decode_base64.go @@ -27,7 +27,7 @@ import ( // from the provided JSON data. // - err error: An error object, which is nil if the operation is successful. func YieldStargateMsgs(jsonBz []byte) (sgMsgs []wasmvm.StargateMsg, err error) { - var data interface{} + var data any if err := json.Unmarshal(jsonBz, &data); err != nil { return sgMsgs, err } @@ -50,7 +50,7 @@ func YieldStargateMsgs(jsonBz []byte) (sgMsgs []wasmvm.StargateMsg, err error) { // encoded base 64 string. func parseStargateMsgs(jsonData any, msgs *[]wasmvm.StargateMsg) { switch v := jsonData.(type) { - case map[string]interface{}: + case map[string]any: if typeURL, ok := v["type_url"].(string); ok { if value, ok := v["value"].(string); ok { *msgs = append(*msgs, wasmvm.StargateMsg{ @@ -62,7 +62,7 @@ func parseStargateMsgs(jsonData any, msgs *[]wasmvm.StargateMsg) { for _, value := range v { parseStargateMsgs(value, msgs) } - case []interface{}: + case []any: for _, value := range v { parseStargateMsgs(value, msgs) } @@ -93,7 +93,7 @@ func DecodeBase64StargateMsgs( ) (newSgMsgs []StargateMsgDecoded, err error) { codec := clientCtx.Codec - var data interface{} + var data any if err := json.Unmarshal(jsonBz, &data); err != nil { return newSgMsgs, fmt.Errorf( "failed to decode stargate msgs due to invalid JSON: %w", err) diff --git a/eth/eip712/eip712_legacy.go b/eth/eip712/eip712_legacy.go index c1d0b1b30..b50f10e5f 100644 --- a/eth/eip712/eip712_legacy.go +++ b/eth/eip712/eip712_legacy.go @@ -38,7 +38,7 @@ func LegacyWrapTxToTypedData( data []byte, feeDelegation *FeeDelegationOptions, ) (apitypes.TypedData, error) { - txData := make(map[string]interface{}) + txData := make(map[string]any) if err := json.Unmarshal(data, &txData); err != nil { return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, "failed to JSON unmarshal data") @@ -58,7 +58,7 @@ func LegacyWrapTxToTypedData( } if feeDelegation != nil { - feeInfo, ok := txData["fee"].(map[string]interface{}) + feeInfo, ok := txData["fee"].(map[string]any) if !ok { return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrInvalidType, "cannot parse fee from tx data") } @@ -139,7 +139,7 @@ func extractMsgTypes(cdc codectypes.AnyUnpacker, msgTypeName string, msg sdk.Msg return rootTypes, nil } -func walkFields(cdc codectypes.AnyUnpacker, typeMap apitypes.Types, rootType string, in interface{}) (err error) { +func walkFields(cdc codectypes.AnyUnpacker, typeMap apitypes.Types, rootType string, in any) (err error) { defer doRecover(&err) t := reflect.TypeOf(in) @@ -161,8 +161,8 @@ func walkFields(cdc codectypes.AnyUnpacker, typeMap apitypes.Types, rootType str } type CosmosAnyWrapper struct { - Type string `json:"type"` - Value interface{} `json:"value"` + Type string `json:"type"` + Value any `json:"value"` } // legacyTraverseFields: Recursively inspects the fields of a given diff --git a/eth/eip712/encoding_legacy.go b/eth/eip712/encoding_legacy.go index 805eb48dd..23f943eaf 100644 --- a/eth/eip712/encoding_legacy.go +++ b/eth/eip712/encoding_legacy.go @@ -17,8 +17,8 @@ import ( ) type aminoMessage struct { - Type string `json:"type"` - Value interface{} `json:"value"` + Type string `json:"type"` + Value any `json:"value"` } // LegacyGetEIP712BytesForMsg returns the EIP-712 object bytes for the given SignDoc bytes by decoding the bytes into diff --git a/eth/eip712/message.go b/eth/eip712/message.go index 6a8577c22..176d90b56 100644 --- a/eth/eip712/message.go +++ b/eth/eip712/message.go @@ -14,7 +14,7 @@ import ( type eip712MessagePayload struct { payload gjson.Result numPayloadMsgs int - message map[string]interface{} + message map[string]any } const ( @@ -34,7 +34,7 @@ func createEIP712MessagePayload(data []byte) (eip712MessagePayload, error) { return eip712MessagePayload{}, errorsmod.Wrap(err, "failed to flatten payload JSON messages") } - message, ok := payload.Value().(map[string]interface{}) + message, ok := payload.Value().(map[string]any) if !ok { return eip712MessagePayload{}, errorsmod.Wrap(errortypes.ErrInvalidType, "failed to parse JSON as map") } diff --git a/eth/rpc/backend/blocks.go b/eth/rpc/backend/blocks.go index a64e73e2a..7bc5f4b97 100644 --- a/eth/rpc/backend/blocks.go +++ b/eth/rpc/backend/blocks.go @@ -57,7 +57,7 @@ func (b *Backend) BlockNumber() (hexutil.Uint64, error) { // GetBlockByNumber returns the JSON-RPC compatible Ethereum block identified by // block number. Depending on fullTx it either returns the full transaction // objects or if false only the hashes of the transactions. -func (b *Backend) GetBlockByNumber(blockNum rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { +func (b *Backend) GetBlockByNumber(blockNum rpc.BlockNumber, fullTx bool) (map[string]any, error) { resBlock, err := b.TendermintBlockByNumber(blockNum) if err != nil { return nil, nil @@ -85,7 +85,7 @@ func (b *Backend) GetBlockByNumber(blockNum rpc.BlockNumber, fullTx bool) (map[s // GetBlockByHash returns the JSON-RPC compatible Ethereum block identified by // hash. -func (b *Backend) GetBlockByHash(hash gethcommon.Hash, fullTx bool) (map[string]interface{}, error) { +func (b *Backend) GetBlockByHash(hash gethcommon.Hash, fullTx bool) (map[string]any, error) { resBlock, err := b.TendermintBlockByHash(hash) if err != nil { return nil, err @@ -348,8 +348,8 @@ func (b *Backend) RPCBlockFromTendermintBlock( resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults, fullTx bool, -) (map[string]interface{}, error) { - ethRPCTxs := []interface{}{} +) (map[string]any, error) { + ethRPCTxs := []any{} block := resBlock.Block baseFeeWei, err := b.BaseFeeWei(blockRes) diff --git a/eth/rpc/backend/node_info.go b/eth/rpc/backend/node_info.go index 402578dd5..e95488b2a 100644 --- a/eth/rpc/backend/node_info.go +++ b/eth/rpc/backend/node_info.go @@ -39,7 +39,7 @@ func (b *Backend) Accounts() ([]gethcommon.Address, error) { // - highestBlock: block number of the highest block header this node has received from peers // - pulledStates: number of state entries processed until now // - knownStates: number of known state entries that still need to be pulled -func (b *Backend) Syncing() (interface{}, error) { +func (b *Backend) Syncing() (any, error) { status, err := b.clientCtx.Client.Status(b.ctx) if err != nil { return false, err @@ -49,7 +49,7 @@ func (b *Backend) Syncing() (interface{}, error) { return false, nil } - return map[string]interface{}{ + return map[string]any{ "startingBlock": hexutil.Uint64(status.SyncInfo.EarliestBlockHeight), "currentBlock": hexutil.Uint64(status.SyncInfo.LatestBlockHeight), // "highestBlock": nil, // NA diff --git a/eth/rpc/backend/tracing.go b/eth/rpc/backend/tracing.go index 4a20557cd..94bb8fbba 100644 --- a/eth/rpc/backend/tracing.go +++ b/eth/rpc/backend/tracing.go @@ -18,7 +18,7 @@ import ( // TraceTransaction returns the structured logs created during the execution of EVM // and returns them as a JSON object. -func (b *Backend) TraceTransaction(hash gethcommon.Hash, config *evm.TraceConfig) (interface{}, error) { +func (b *Backend) TraceTransaction(hash gethcommon.Hash, config *evm.TraceConfig) (any, error) { // Get transaction by hash transaction, err := b.GetTxByEthHash(hash) if err != nil { @@ -124,7 +124,7 @@ func (b *Backend) TraceTransaction(hash gethcommon.Hash, config *evm.TraceConfig // Response format is unknown due to custom tracer config param // More information can be found here https://geth.ethereum.org/docs/dapp/tracing-filtered - var decodedResult interface{} + var decodedResult any err = json.Unmarshal(traceResult.Data, &decodedResult) if err != nil { return nil, err @@ -219,7 +219,7 @@ func (b *Backend) TraceCall( txArgs evm.JsonTxArgs, contextBlock rpc.BlockNumber, config *evm.TraceConfig, -) (interface{}, error) { +) (any, error) { blk, err := b.TendermintBlockByNumber(contextBlock) if err != nil { b.logger.Debug("block not found", "contextBlock", contextBlock) @@ -253,7 +253,7 @@ func (b *Backend) TraceCall( if err != nil { return nil, err } - var decodedResult interface{} + var decodedResult any err = json.Unmarshal(traceResult.Data, &decodedResult) if err != nil { return nil, err diff --git a/eth/rpc/backend/utils.go b/eth/rpc/backend/utils.go index 23ce2f410..bb689bcce 100644 --- a/eth/rpc/backend/utils.go +++ b/eth/rpc/backend/utils.go @@ -109,7 +109,7 @@ func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height i // See eth_feeHistory method for more details of the return format. func (b *Backend) retrieveEVMTxFeesFromBlock( tendermintBlock *tmrpctypes.ResultBlock, - ethBlock *map[string]interface{}, + ethBlock *map[string]any, rewardPercentiles []float64, tendermintBlockResult *tmrpctypes.ResultBlockResults, targetOneFeeHistory *rpc.OneFeeHistory, diff --git a/eth/rpc/rpc.go b/eth/rpc/rpc.go index de5a97991..c6c0891de 100644 --- a/eth/rpc/rpc.go +++ b/eth/rpc/rpc.go @@ -114,9 +114,9 @@ func BlockMaxGasFromConsensusParams( // transactions. func FormatBlock( header tmtypes.Header, size int, gasLimit int64, - gasUsed *big.Int, transactions []interface{}, bloom gethcore.Bloom, + gasUsed *big.Int, transactions []any, bloom gethcore.Bloom, validatorAddr gethcommon.Address, baseFee *big.Int, -) map[string]interface{} { +) map[string]any { var transactionsRoot gethcommon.Hash if len(transactions) == 0 { transactionsRoot = gethcore.EmptyRootHash @@ -124,7 +124,7 @@ func FormatBlock( transactionsRoot = gethcommon.BytesToHash(header.DataHash) } - result := map[string]interface{}{ + result := map[string]any{ "number": hexutil.Uint64(header.Height), "hash": hexutil.Bytes(header.Hash()), "parentHash": gethcommon.BytesToHash(header.LastBlockID.Hash.Bytes()), diff --git a/eth/rpc/rpcapi/debugapi/api.go b/eth/rpc/rpcapi/debugapi/api.go index c70673273..7ce3fa345 100644 --- a/eth/rpc/rpcapi/debugapi/api.go +++ b/eth/rpc/rpcapi/debugapi/api.go @@ -65,7 +65,7 @@ func NewImplDebugAPI( // TraceTransaction returns the structured logs created during the execution of EVM // and returns them as a JSON object. -func (a *DebugAPI) TraceTransaction(hash common.Hash, config *evm.TraceConfig) (interface{}, error) { +func (a *DebugAPI) TraceTransaction(hash common.Hash, config *evm.TraceConfig) (any, error) { a.logger.Debug("debug_traceTransaction", "hash", hash) return a.backend.TraceTransaction(hash, config) } @@ -115,7 +115,7 @@ func (a *DebugAPI) TraceCall( args evm.JsonTxArgs, blockNrOrHash rpc.BlockNumberOrHash, config *evm.TraceConfig, -) (interface{}, error) { +) (any, error) { a.logger.Debug("debug_traceCall", args.String(), "block number or hash", blockNrOrHash) // Get Tendermint Block diff --git a/eth/rpc/rpcapi/eth_api.go b/eth/rpc/rpcapi/eth_api.go index 62590347f..3ada30358 100644 --- a/eth/rpc/rpcapi/eth_api.go +++ b/eth/rpc/rpcapi/eth_api.go @@ -30,8 +30,8 @@ type IEthAPI interface { // // Retrieves information from a particular block in the blockchain. BlockNumber() (hexutil.Uint64, error) - GetBlockByNumber(ethBlockNum rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) - GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) + GetBlockByNumber(ethBlockNum rpc.BlockNumber, fullTx bool) (map[string]any, error) + GetBlockByHash(hash common.Hash, fullTx bool) (map[string]any, error) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint GetBlockTransactionCountByNumber(blockNum rpc.BlockNumber) *hexutil.Uint @@ -97,15 +97,15 @@ type IEthAPI interface { // and replaced by a canonical block instead. GetUncleByBlockHashAndIndex( hash common.Hash, idx hexutil.Uint, - ) map[string]interface{} + ) map[string]any GetUncleByBlockNumberAndIndex( number, idx hexutil.Uint, - ) map[string]interface{} + ) map[string]any GetUncleCountByBlockHash(hash common.Hash) hexutil.Uint GetUncleCountByBlockNumber(blockNum rpc.BlockNumber) hexutil.Uint // Other - Syncing() (interface{}, error) + Syncing() (any, error) GetTransactionLogs(txHash common.Hash) ([]*gethcore.Log, error) FillTransaction( args evm.JsonTxArgs, @@ -144,13 +144,13 @@ func (e *EthAPI) BlockNumber() (hexutil.Uint64, error) { } // GetBlockByNumber returns the block identified by number. -func (e *EthAPI) GetBlockByNumber(ethBlockNum rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { +func (e *EthAPI) GetBlockByNumber(ethBlockNum rpc.BlockNumber, fullTx bool) (map[string]any, error) { e.logger.Debug("eth_getBlockByNumber", "number", ethBlockNum, "full", fullTx) return e.backend.GetBlockByNumber(ethBlockNum, fullTx) } // GetBlockByHash returns the block identified by hash. -func (e *EthAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { +func (e *EthAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]any, error) { e.logger.Debug("eth_getBlockByHash", "hash", hash.Hex(), "full", fullTx) return e.backend.GetBlockByHash(hash, fullTx) } @@ -359,7 +359,7 @@ func (e *EthAPI) ChainId() (*hexutil.Big, error) { //nolint // Always returns nil. func (e *EthAPI) GetUncleByBlockHashAndIndex( _ common.Hash, _ hexutil.Uint, -) map[string]interface{} { +) map[string]any { return nil } @@ -367,7 +367,7 @@ func (e *EthAPI) GetUncleByBlockHashAndIndex( // index. Always returns nil. func (e *EthAPI) GetUncleByBlockNumberAndIndex( _, _ hexutil.Uint, -) map[string]interface{} { +) map[string]any { return nil } @@ -396,7 +396,7 @@ func (e *EthAPI) GetUncleCountByBlockNumber(_ rpc.BlockNumber) hexutil.Uint { // - highestBlock: block number of the highest block header this node has received from peers // - pulledStates: number of state entries processed until now // - knownStates: number of known state entries that still need to be pulled -func (e *EthAPI) Syncing() (interface{}, error) { +func (e *EthAPI) Syncing() (any, error) { e.logger.Debug("eth_syncing") return e.backend.Syncing() } diff --git a/eth/rpc/rpcapi/eth_filters_api.go b/eth/rpc/rpcapi/eth_filters_api.go index 782014bb5..eca8dd27c 100644 --- a/eth/rpc/rpcapi/eth_filters_api.go +++ b/eth/rpc/rpcapi/eth_filters_api.go @@ -621,7 +621,7 @@ func (api *FiltersAPI) GetFilterLogs(ctx context.Context, id gethrpc.ID) ([]*get // // This function implements the "eth_getFilterChanges" JSON-RPC service method. // https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges -func (api *FiltersAPI) GetFilterChanges(id gethrpc.ID) (interface{}, error) { +func (api *FiltersAPI) GetFilterChanges(id gethrpc.ID) (any, error) { api.logger.Debug("eth_getFilterChanges") api.filtersMu.Lock() defer api.filtersMu.Unlock() diff --git a/eth/rpc/rpcapi/websockets.go b/eth/rpc/rpcapi/websockets.go index 68fb7eb9e..530dd39d7 100644 --- a/eth/rpc/rpcapi/websockets.go +++ b/eth/rpc/rpcapi/websockets.go @@ -41,9 +41,9 @@ type WebsocketsServer interface { } type SubscriptionResponseJSON struct { - Jsonrpc string `json:"jsonrpc"` - Result interface{} `json:"result"` - ID float64 `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Result any `json:"result"` + ID float64 `json:"id"` } type SubscriptionNotification struct { @@ -53,8 +53,8 @@ type SubscriptionNotification struct { } type SubscriptionResult struct { - Subscription gethrpc.ID `json:"subscription"` - Result interface{} `json:"result"` + Subscription gethrpc.ID `json:"subscription"` + Result any `json:"result"` } type ErrorResponseJSON struct { @@ -157,7 +157,7 @@ type wsConn struct { mux *sync.Mutex } -func (w *wsConn) WriteJSON(v interface{}) error { +func (w *wsConn) WriteJSON(v any) error { w.mux.Lock() defer w.mux.Unlock() @@ -203,7 +203,7 @@ func (s *websocketsServer) readLoop(wsConn *wsConn) { continue } - var msg map[string]interface{} + var msg map[string]any if err = json.Unmarshal(mb, &msg); err != nil { s.sendErrResponse(wsConn, err.Error()) continue @@ -299,8 +299,8 @@ func (s *websocketsServer) readLoop(wsConn *wsConn) { } // tcpGetAndSendResponse sends error response to client if params is invalid -func (s *websocketsServer) getParamsAndCheckValid(msg map[string]interface{}, wsConn *wsConn) ([]interface{}, bool) { - params, ok := msg["params"].([]interface{}) +func (s *websocketsServer) getParamsAndCheckValid(msg map[string]any, wsConn *wsConn) ([]any, bool) { + params, ok := msg["params"].([]any) if !ok { s.sendErrResponse(wsConn, "invalid parameters") return nil, false @@ -336,7 +336,7 @@ func (s *websocketsServer) tcpGetAndSendResponse(wsConn *wsConn, mb []byte) erro return errors.Wrap(err, "could not read body from response") } - var wsSend interface{} + var wsSend any err = json.Unmarshal(body, &wsSend) if err != nil { return errors.Wrap(err, "failed to unmarshal rest-server response") @@ -362,7 +362,7 @@ func newPubSubAPI(clientCtx client.Context, logger log.Logger, tmWSClient *rpccl } } -func (api *pubSubAPI) subscribe(wsConn *wsConn, subID gethrpc.ID, params []interface{}) (pubsub.UnsubscribeFunc, error) { +func (api *pubSubAPI) subscribe(wsConn *wsConn, subID gethrpc.ID, params []any) (pubsub.UnsubscribeFunc, error) { method, ok := params[0].(string) if !ok { return nil, errors.New("invalid parameters") @@ -462,11 +462,11 @@ func try(fn func(), l log.Logger, desc string) { fn() } -func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra interface{}) (pubsub.UnsubscribeFunc, error) { +func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra any) (pubsub.UnsubscribeFunc, error) { crit := filters.FilterCriteria{} if extra != nil { - params, ok := extra.(map[string]interface{}) + params, ok := extra.(map[string]any) if !ok { err := errors.New("invalid criteria") api.logger.Debug("invalid criteria", "type", fmt.Sprintf("%T", extra)) @@ -475,7 +475,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra inte if params["address"] != nil { address, isString := params["address"].(string) - addresses, isSlice := params["address"].([]interface{}) + addresses, isSlice := params["address"].([]any) if !isString && !isSlice { err := errors.New("invalid addresses; must be address or array of addresses") api.logger.Debug("invalid addresses", "type", fmt.Sprintf("%T", params["address"])) @@ -502,7 +502,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra inte } if params["topics"] != nil { - topics, ok := params["topics"].([]interface{}) + topics, ok := params["topics"].([]any) if !ok { err := errors.Errorf("invalid topics: %s", topics) api.logger.Error("invalid topics", "type", fmt.Sprintf("%T", topics)) @@ -511,7 +511,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra inte crit.Topics = make([][]common.Hash, len(topics)) - addCritTopic := func(topicIdx int, topic interface{}) error { + addCritTopic := func(topicIdx int, topic any) error { tstr, ok := topic.(string) if !ok { err := errors.Errorf("invalid topic: %s", topic) @@ -538,7 +538,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID gethrpc.ID, extra inte } // in case we actually have a list of subtopics - subtopicsList, ok := subtopics.([]interface{}) + subtopicsList, ok := subtopics.([]any) if !ok { err := errors.New("invalid subtopics") api.logger.Error("invalid subtopic", "type", fmt.Sprintf("%T", subtopics)) diff --git a/x/common/testutil/nullify.go b/x/common/testutil/nullify.go index 202b59e6f..96fc340f6 100644 --- a/x/common/testutil/nullify.go +++ b/x/common/testutil/nullify.go @@ -16,7 +16,7 @@ var ( // Fill analyze all struct fields and slices with // reflection and initialize the nil and empty slices, // structs, and pointers. -func Fill(x interface{}) interface{} { +func Fill(x any) any { v := reflect.Indirect(reflect.ValueOf(x)) switch v.Kind() { case reflect.Slice: diff --git a/x/common/testutil/testnetwork/logger.go b/x/common/testutil/testnetwork/logger.go index dfdf56d97..7b1206a94 100644 --- a/x/common/testutil/testnetwork/logger.go +++ b/x/common/testutil/testnetwork/logger.go @@ -11,8 +11,8 @@ import ( // Typically, a `testing.T` struct is used as the logger for both the "Network" // and corresponding "Validators". type Logger interface { - Log(args ...interface{}) - Logf(format string, args ...interface{}) + Log(args ...any) + Logf(format string, args ...any) } var _ Logger = (*testing.T)(nil) diff --git a/x/devgas/v1/types/params.go b/x/devgas/v1/types/params.go index 433aa4d43..532436c73 100644 --- a/x/devgas/v1/types/params.go +++ b/x/devgas/v1/types/params.go @@ -28,7 +28,7 @@ func DefaultParams() ModuleParams { } } -func validateBool(i interface{}) error { +func validateBool(i any) error { _, ok := i.(bool) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -37,7 +37,7 @@ func validateBool(i interface{}) error { return nil } -func validateShares(i interface{}) error { +func validateShares(i any) error { v, ok := i.(sdk.Dec) if !ok { @@ -59,7 +59,7 @@ func validateShares(i interface{}) error { return nil } -func validateArray(i interface{}) error { +func validateArray(i any) error { _, ok := i.([]string) if !ok { return fmt.Errorf("invalid parameter type: %T", i) diff --git a/x/epochs/types/identifier.go b/x/epochs/types/identifier.go index 3dd3012cb..714b9dd66 100644 --- a/x/epochs/types/identifier.go +++ b/x/epochs/types/identifier.go @@ -20,7 +20,7 @@ const ( // ValidateEpochIdentifierInterface performs a stateless // validation of the epoch ID interface. -func ValidateEpochIdentifierInterface(i interface{}) error { +func ValidateEpochIdentifierInterface(i any) error { v, ok := i.(string) if !ok { return fmt.Errorf("invalid parameter type: %T", i) diff --git a/x/evm/errors.go b/x/evm/errors.go index 9fc6722ac..87d5c747b 100644 --- a/x/evm/errors.go +++ b/x/evm/errors.go @@ -106,6 +106,6 @@ func (e *RevertError) ErrorCode() int { } // ErrorData returns the hex encoded revert reason. -func (e *RevertError) ErrorData() interface{} { +func (e *RevertError) ErrorData() any { return e.reason } diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index 9cc9290e9..4e13254a9 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -736,7 +736,7 @@ func (k *Keeper) TraceEthTxMsg( traceConfig *evm.TraceConfig, commitMessage bool, tracerJSONConfig json.RawMessage, -) (*interface{}, uint, error) { +) (*any, uint, error) { // Assemble the structured logger or the JavaScript tracer var ( tracer tracers.Tracer @@ -805,7 +805,7 @@ func (k *Keeper) TraceEthTxMsg( return nil, 0, grpcstatus.Error(grpccodes.Internal, err.Error()) } - var result interface{} + var result any result, err = tracer.GetResult() if err != nil { return nil, 0, grpcstatus.Error(grpccodes.Internal, err.Error()) diff --git a/x/evm/params.go b/x/evm/params.go index 66d31e035..e0211d0bb 100644 --- a/x/evm/params.go +++ b/x/evm/params.go @@ -35,7 +35,7 @@ func DefaultParams() Params { } // validateChannels checks if channels ids are valid -func validateChannels(i interface{}) error { +func validateChannels(i any) error { channels, ok := i.([]string) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -76,7 +76,7 @@ func (p Params) IsEVMChannel(channel string) bool { return slices.Contains(p.EVMChannels, channel) } -func validateEIPs(i interface{}) error { +func validateEIPs(i any) error { eips, ok := i.([]int64) if !ok { return fmt.Errorf("invalid EIP slice type: %T", i) diff --git a/x/evm/precompile/.gitignore b/x/evm/precompile/.gitignore deleted file mode 100644 index e8c12ff4f..000000000 --- a/x/evm/precompile/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -node_modules -.env - -# Hardhat files -/cache -/artifacts - -# TypeChain files -/typechain -/typechain-types - -# solidity-coverage files -/coverage -/coverage.json - -# Hardhat Ignition default folder for deployments against a local node -ignition/deployments/chain-31337 diff --git a/x/evm/precompile/errors.go b/x/evm/precompile/errors.go index a95989b71..438ffa750 100644 --- a/x/evm/precompile/errors.go +++ b/x/evm/precompile/errors.go @@ -1,7 +1,6 @@ package precompile import ( - "errors" "fmt" "reflect" @@ -9,6 +8,13 @@ import ( "github.com/ethereum/go-ethereum/core/vm" ) +func assertNotReadonlyTx(readOnly bool, method *gethabi.Method) error { + if readOnly { + return fmt.Errorf("method %s cannot be called in a read-only context (e.g. staticcall)", method.Name) + } + return nil +} + // ErrPrecompileRun is error function intended for use in a `defer` pattern, // which modifies the input error in the event that its value becomes non-nil. // This creates a concise way to prepend extra information to the original error. @@ -34,14 +40,6 @@ func ErrMethodCalled(method *gethabi.Method, wrapped error) error { return fmt.Errorf("%s method called: %w", method.Name, wrapped) } -// Check required for transactions but not needed for queries -func assertNotReadonlyTx(readOnly bool, isTx bool) error { - if readOnly && isTx { - return errors.New("cannot write state from staticcall (a read-only call)") - } - return nil -} - // assertContractQuery checks if a contract call is a valid query operation. This // function verifies that no funds (wei) are being sent with the query, as query // operations should be read-only and not involve any value transfer. diff --git a/x/evm/precompile/funtoken.go b/x/evm/precompile/funtoken.go index e9ccaee82..1d50d99ab 100644 --- a/x/evm/precompile/funtoken.go +++ b/x/evm/precompile/funtoken.go @@ -3,7 +3,6 @@ package precompile import ( "fmt" "math/big" - "sync" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -32,21 +31,19 @@ func (p precompileFunToken) Address() gethcommon.Address { return PrecompileAddr_FunToken } -func (p precompileFunToken) ABI() *gethabi.ABI { - return embeds.SmartContract_FunToken.ABI -} - // RequiredGas calculates the cost of calling the precompile in gas units. func (p precompileFunToken) RequiredGas(input []byte) (gasCost uint64) { - return RequiredGas(input, p.ABI()) + return requiredGas(input, p.ABI()) +} + +func (p precompileFunToken) ABI() *gethabi.ABI { + return embeds.SmartContract_FunToken.ABI } const ( FunTokenMethod_BankSend PrecompileMethod = "bankSend" ) -type PrecompileMethod string - // Run runs the precompiled contract func (p precompileFunToken) Run( evm *vm.EVM, contract *vm.Contract, readonly bool, @@ -54,7 +51,7 @@ func (p precompileFunToken) Run( defer func() { err = ErrPrecompileRun(err, p) }() - start, err := OnRunStart(evm, contract, p.ABI()) + start, err := OnRunStart(evm, contract.Input, p.ABI()) if err != nil { return nil, err } @@ -87,8 +84,6 @@ type precompileFunToken struct { evmKeeper evmkeeper.Keeper } -var executionGuard sync.Mutex - // bankSend: Implements "IFunToken.bankSend" // // The "args" populate the following function signature in Solidity: @@ -105,15 +100,10 @@ func (p precompileFunToken) bankSend( caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - ctx, method, args := start.Ctx, start.Method, start.Args - if e := assertNotReadonlyTx(readOnly, true); e != nil { - err = e - return - } - if !executionGuard.TryLock() { - return nil, fmt.Errorf("bankSend is already in progress") + ctx, method, args := start.CacheCtx, start.Method, start.Args + if err := assertNotReadonlyTx(readOnly, method); err != nil { + return nil, err } - defer executionGuard.Unlock() erc20, amount, to, err := p.decomposeBankSendArgs(args) if err != nil { diff --git a/x/evm/precompile/oracle.go b/x/evm/precompile/oracle.go index fb0b2981b..f59b93822 100644 --- a/x/evm/precompile/oracle.go +++ b/x/evm/precompile/oracle.go @@ -24,7 +24,11 @@ func (p precompileOracle) Address() gethcommon.Address { } func (p precompileOracle) RequiredGas(input []byte) (gasPrice uint64) { - return RequiredGas(input, embeds.SmartContract_Oracle.ABI) + return requiredGas(input, p.ABI()) +} + +func (p precompileOracle) ABI() *gethabi.ABI { + return embeds.SmartContract_Oracle.ABI } const ( @@ -38,21 +42,19 @@ func (p precompileOracle) Run( defer func() { err = ErrPrecompileRun(err, p) }() - res, err := OnRunStart(evm, contract, embeds.SmartContract_Oracle.ABI) + startResult, err := OnRunStart(evm, contract.Input, p.ABI()) if err != nil { return nil, err } - method, args, ctx := res.Method, res.Args, res.Ctx + method, args, ctx := startResult.Method, startResult.Args, startResult.CacheCtx switch PrecompileMethod(method.Name) { case OracleMethod_queryExchangeRate: - bz, err = p.queryExchangeRate(ctx, method, args, readonly) + return p.queryExchangeRate(ctx, method, args) default: err = fmt.Errorf("invalid method called with name \"%s\"", method.Name) return } - - return } func PrecompileOracle(keepers keepers.PublicKeepers) vm.PrecompiledContract { @@ -68,10 +70,9 @@ type precompileOracle struct { func (p precompileOracle) queryExchangeRate( ctx sdk.Context, method *gethabi.Method, - args []interface{}, - readOnly bool, + args []any, ) (bz []byte, err error) { - pair, err := p.decomposeQueryExchangeRateArgs(args) + pair, err := p.parseQueryExchangeRateArgs(args) if err != nil { return nil, err } @@ -88,7 +89,7 @@ func (p precompileOracle) queryExchangeRate( return method.Outputs.Pack(price.String()) } -func (p precompileOracle) decomposeQueryExchangeRateArgs(args []any) ( +func (p precompileOracle) parseQueryExchangeRateArgs(args []any) ( pair string, err error, ) { diff --git a/x/evm/precompile/precompile.go b/x/evm/precompile/precompile.go index 40d0c74b4..234a27f4b 100644 --- a/x/evm/precompile/precompile.go +++ b/x/evm/precompile/precompile.go @@ -85,15 +85,15 @@ func methodById(abi *gethabi.ABI, sigdata []byte) (*gethabi.Method, error) { return nil, fmt.Errorf("no method with id: %#x", sigdata[:4]) } -func DecomposeInput( +func decomposeInput( abi *gethabi.ABI, input []byte, -) (method *gethabi.Method, args []interface{}, err error) { +) (method *gethabi.Method, args []any, err error) { // ABI method IDs are exactly 4 bytes according to "gethabi.ABI.MethodByID". if len(input) < 4 { - readableBz := collections.HumanizeBytes(input) - err = fmt.Errorf("input \"%s\" too short to extract method ID (less than 4 bytes)", readableBz) + err = fmt.Errorf("input \"%s\" too short to extract method ID (less than 4 bytes)", collections.HumanizeBytes(input)) return } + method, err = methodById(abi, input[:4]) if err != nil { err = fmt.Errorf("unable to parse ABI method by its 4-byte ID: %w", err) @@ -109,8 +109,8 @@ func DecomposeInput( return method, args, nil } -func RequiredGas(input []byte, abi *gethabi.ABI) uint64 { - method, _, err := DecomposeInput(abi, input) +func requiredGas(input []byte, abi *gethabi.ABI) uint64 { + method, err := methodById(abi, input[:4]) if err != nil { // It's appropriate to return a reasonable default here // because the error from DecomposeInput will be handled automatically by @@ -122,26 +122,27 @@ func RequiredGas(input []byte, abi *gethabi.ABI) uint64 { // Map access could panic. We know that it won't panic because all methods // are in the map, which is verified by unit tests. - methodIsTx := precompileMethodIsTxMap[PrecompileMethod(method.Name)] var costPerByte, costFlat uint64 - if methodIsTx { + if isMutation[PrecompileMethod(method.Name)] { costPerByte, costFlat = gasCfg.WriteCostPerByte, gasCfg.WriteCostFlat } else { costPerByte, costFlat = gasCfg.ReadCostPerByte, gasCfg.ReadCostFlat } - argsBzLen := uint64(len(input[4:])) - return (costPerByte * argsBzLen) + costFlat + // Calculate the total gas required based on the input size and flat cost + return (costPerByte * uint64(len(input[4:]))) + costFlat } +type PrecompileMethod string + type OnRunStartResult struct { // Args contains the decoded (ABI unpacked) arguments passed to the contract // as input. Args []any - // Ctx is a cached SDK context that allows isolated state + // CacheCtx is a cached SDK context that allows isolated state // operations to occur that can be reverted by the EVM's [statedb.StateDB]. - Ctx sdk.Context + CacheCtx sdk.Context // Method is the ABI method for the precompiled contract call. Method *gethabi.Method @@ -178,9 +179,9 @@ type OnRunStartResult struct { // } // ``` func OnRunStart( - evm *vm.EVM, contract *vm.Contract, abi *gethabi.ABI, + evm *vm.EVM, contractInput []byte, abi *gethabi.ABI, ) (res OnRunStartResult, err error) { - method, args, err := DecomposeInput(abi, contract.Input) + method, args, err := decomposeInput(abi, contractInput) if err != nil { return res, err } @@ -194,8 +195,8 @@ func OnRunStart( // journalEntry captures the state before precompile execution to enable // proper state reversal if the call fails or if [statedb.JournalChange] // is reverted in general. - cacheCtx, journalEntry := stateDB.CacheCtxForPrecompile(contract.Address()) - if err = stateDB.SavePrecompileCalledJournalChange(contract.Address(), journalEntry); err != nil { + cacheCtx, journalEntry := stateDB.CacheCtxForPrecompile() + if err = stateDB.SavePrecompileCalledJournalChange(journalEntry); err != nil { return res, err } if err = stateDB.CommitCacheCtx(); err != nil { @@ -203,14 +204,14 @@ func OnRunStart( } return OnRunStartResult{ - Args: args, - Ctx: cacheCtx, - Method: method, - StateDB: stateDB, + Args: args, + CacheCtx: cacheCtx, + Method: method, + StateDB: stateDB, }, nil } -var precompileMethodIsTxMap map[PrecompileMethod]bool = map[PrecompileMethod]bool{ +var isMutation map[PrecompileMethod]bool = map[PrecompileMethod]bool{ WasmMethod_execute: true, WasmMethod_instantiate: true, WasmMethod_executeMulti: true, diff --git a/x/evm/precompile/test/export.go b/x/evm/precompile/test/export.go index 28670e3e0..24700ce85 100644 --- a/x/evm/precompile/test/export.go +++ b/x/evm/precompile/test/export.go @@ -8,20 +8,17 @@ import ( "path" "strings" - serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" - wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasm "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/ethereum/go-ethereum/core/vm" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/stretchr/testify/suite" "github.com/NibiruChain/nibiru/v2/app" + serverconfig "github.com/NibiruChain/nibiru/v2/app/server/config" "github.com/NibiruChain/nibiru/v2/x/evm/embeds" "github.com/NibiruChain/nibiru/v2/x/evm/evmtest" "github.com/NibiruChain/nibiru/v2/x/evm/precompile" - "github.com/NibiruChain/nibiru/v2/x/evm/statedb" ) // SetupWasmContracts stores all Wasm bytecode and has the "deps.Sender" @@ -31,68 +28,52 @@ func SetupWasmContracts(deps *evmtest.TestDeps, s *suite.Suite) ( ) { wasmCodes := DeployWasmBytecode(s, deps.Ctx, deps.Sender.NibiruAddr, deps.App) - otherArgs := []struct { - InstMsg []byte - Label string + instantiateArgs := []struct { + InstantiateMsg []byte + Label string }{ { - InstMsg: []byte("{}"), - Label: "https://github.com/NibiruChain/nibiru-wasm/blob/main/contracts/nibi-stargate/src/contract.rs", + InstantiateMsg: []byte("{}"), + Label: "https://github.com/NibiruChain/nibiru-wasm/blob/main/contracts/nibi-stargate/src/contract.rs", }, { - InstMsg: []byte(`{"count": 0}`), - Label: "https://github.com/NibiruChain/nibiru-wasm/tree/ec3ab9f09587a11fbdfbd4021c7617eca3912044/contracts/00-hello-world-counter", + InstantiateMsg: []byte(`{"count": 0}`), + Label: "https://github.com/NibiruChain/nibiru-wasm/tree/ec3ab9f09587a11fbdfbd4021c7617eca3912044/contracts/00-hello-world-counter", }, } - for wasmCodeIdx, wasmCode := range wasmCodes { + for i, wasmCode := range wasmCodes { s.T().Logf("Instantiate using Wasm precompile: %s", wasmCode.binPath) codeId := wasmCode.codeId m := wasm.MsgInstantiateContract{ Admin: "", CodeID: codeId, - Label: otherArgs[wasmCodeIdx].Label, - Msg: otherArgs[wasmCodeIdx].InstMsg, - Funds: []sdk.Coin{}, + Label: instantiateArgs[i].Label, + Msg: instantiateArgs[i].InstantiateMsg, } msgArgsBz, err := json.Marshal(m.Msg) s.NoError(err) - var funds []precompile.WasmBankCoin - fundsJson, err := m.Funds.MarshalJSON() - s.NoErrorf(err, "fundsJson: %s", fundsJson) - err = json.Unmarshal(fundsJson, &funds) - s.Require().NoError(err) - - callArgs := []any{m.Admin, m.CodeID, msgArgsBz, m.Label, funds} + callArgs := []any{m.Admin, m.CodeID, msgArgsBz, m.Label, []precompile.WasmBankCoin{}} input, err := embeds.SmartContract_Wasm.ABI.Pack( string(precompile.WasmMethod_instantiate), callArgs..., ) s.Require().NoError(err) - ethTxResp, evmObj, err := deps.EvmKeeper.CallContractWithInput( + ethTxResp, _, err := deps.EvmKeeper.CallContractWithInput( deps.Ctx, deps.Sender.EthAddr, &precompile.PrecompileAddr_Wasm, true, input, ) s.Require().NoError(err) s.Require().NotEmpty(ethTxResp.Ret) - // Finalize transaction - err = evmObj.StateDB.(*statedb.StateDB).Commit() - s.Require().NoError(err) - s.T().Log("Parse the response contract addr and response bytes") - var contractAddrStr string - var data []byte - err = embeds.SmartContract_Wasm.ABI.UnpackIntoInterface( - &[]any{&contractAddrStr, &data}, - string(precompile.WasmMethod_instantiate), - ethTxResp.Ret, - ) + vals, err := embeds.SmartContract_Wasm.ABI.Unpack(string(precompile.WasmMethod_instantiate), ethTxResp.Ret) s.Require().NoError(err) - contractAddr, err := sdk.AccAddressFromBech32(contractAddrStr) + + contractAddr, err := sdk.AccAddressFromBech32(vals[0].(string)) s.NoError(err) contracts = append(contracts, contractAddr) } @@ -118,7 +99,7 @@ func DeployWasmBytecode( rootPathBz, err := exec.Command("go", "list", "-m", "-f", "{{.Dir}}").Output() s.Require().NoError(err) rootPath := strings.Trim(string(rootPathBz), "\n") - for _, pathToWasmBin := range []string{ + for _, wasmFile := range []string{ // nibi_stargate.wasm is a compiled version of: // https://github.com/NibiruChain/nibiru-wasm/blob/main/contracts/nibi-stargate/src/contract.rs "x/tokenfactory/fixture/nibi_stargate.wasm", @@ -129,11 +110,11 @@ func DeployWasmBytecode( // Add other wasm bytecode here if needed... } { - pathToWasmBin = path.Join(string(rootPath), pathToWasmBin) - wasmBytecode, err := os.ReadFile(pathToWasmBin) + binPath := path.Join(rootPath, wasmFile) + wasmBytecode, err := os.ReadFile(binPath) s.Require().NoErrorf( err, - "rootPath %s, pathToWasmBin %s", rootPath, pathToWasmBin, + "path %s, pathToWasmBin %s", binPath, ) // The "Create" fn is private on the nibiru.WasmKeeper. By placing it as the @@ -150,7 +131,7 @@ func DeployWasmBytecode( codeIds = append(codeIds, struct { codeId uint64 binPath string - }{codeId, pathToWasmBin}) + }{codeId, binPath}) } return codeIds diff --git a/x/evm/precompile/wasm.go b/x/evm/precompile/wasm.go index f19511cb9..cddfc488e 100644 --- a/x/evm/precompile/wasm.go +++ b/x/evm/precompile/wasm.go @@ -37,27 +37,26 @@ func (p precompileWasm) Run( defer func() { err = ErrPrecompileRun(err, p) }() - start, err := OnRunStart(evm, contract, p.ABI()) + startResult, err := OnRunStart(evm, contract.Input, p.ABI()) if err != nil { return nil, err } - method := start.Method - switch PrecompileMethod(method.Name) { + switch PrecompileMethod(startResult.Method.Name) { case WasmMethod_execute: - bz, err = p.execute(start, contract.CallerAddress, readonly) + bz, err = p.execute(startResult, contract.CallerAddress, readonly) case WasmMethod_query: - bz, err = p.query(start, contract) + bz, err = p.query(startResult, contract) case WasmMethod_instantiate: - bz, err = p.instantiate(start, contract.CallerAddress, readonly) + bz, err = p.instantiate(startResult, contract.CallerAddress, readonly) case WasmMethod_executeMulti: - bz, err = p.executeMulti(start, contract.CallerAddress, readonly) + bz, err = p.executeMulti(startResult, contract.CallerAddress, readonly) case WasmMethod_queryRaw: - bz, err = p.queryRaw(start, contract) + bz, err = p.queryRaw(startResult, contract) default: // Note that this code path should be impossible to reach since // "DecomposeInput" parses methods directly from the ABI. - err = fmt.Errorf("invalid method called with name \"%s\"", method.Name) + err = fmt.Errorf("invalid method called with name \"%s\"", startResult.Method.Name) return } if err != nil { @@ -74,13 +73,13 @@ func (p precompileWasm) Address() gethcommon.Address { return PrecompileAddr_Wasm } -func (p precompileWasm) ABI() *gethabi.ABI { - return embeds.SmartContract_Wasm.ABI -} - // RequiredGas calculates the cost of calling the precompile in gas units. func (p precompileWasm) RequiredGas(input []byte) (gasCost uint64) { - return RequiredGas(input, p.ABI()) + return requiredGas(input, p.ABI()) +} + +func (p precompileWasm) ABI() *gethabi.ABI { + return embeds.SmartContract_Wasm.ABI } // Wasm: A struct embedding keepers for read and write operations in Wasm, such @@ -123,23 +122,22 @@ func (p precompileWasm) execute( caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) } }() - - if err := assertNotReadonlyTx(readOnly, true); err != nil { - return bz, err + if err := assertNotReadonlyTx(readOnly, method); err != nil { + return nil, err } - wasmContract, msgArgs, funds, err := p.parseExecuteArgs(args) + + wasmContract, msgArgsBz, funds, err := p.parseExecuteArgs(args) if err != nil { err = ErrInvalidArgs(err) return } - callerBech32 := eth.EthAddrToNibiruAddr(caller) - data, err := p.Wasm.Execute(ctx, wasmContract, callerBech32, msgArgs, funds) + data, err := p.Wasm.Execute(ctx, wasmContract, eth.EthAddrToNibiruAddr(caller), msgArgsBz, funds) if err != nil { return } @@ -162,7 +160,7 @@ func (p precompileWasm) query( start OnRunStartResult, contract *vm.Contract, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) @@ -171,6 +169,7 @@ func (p precompileWasm) query( if err := assertContractQuery(contract); err != nil { return bz, err } + wasmContract, req, err := p.parseQueryArgs(args) if err != nil { err = ErrInvalidArgs(err) @@ -207,14 +206,14 @@ func (p precompileWasm) instantiate( caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) } }() - if err := assertNotReadonlyTx(readOnly, true); err != nil { - return bz, err + if err := assertNotReadonlyTx(readOnly, method); err != nil { + return nil, err } callerBech32 := eth.EthAddrToNibiruAddr(caller) @@ -258,14 +257,14 @@ func (p precompileWasm) executeMulti( caller gethcommon.Address, readOnly bool, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) } }() - if err := assertNotReadonlyTx(readOnly, true); err != nil { - return bz, err + if err := assertNotReadonlyTx(readOnly, method); err != nil { + return nil, err } wasmExecMsgs, err := p.parseExecuteMultiArgs(args) @@ -327,7 +326,7 @@ func (p precompileWasm) queryRaw( start OnRunStartResult, contract *vm.Contract, ) (bz []byte, err error) { - method, args, ctx := start.Method, start.Args, start.Ctx + method, args, ctx := start.Method, start.Args, start.CacheCtx defer func() { if err != nil { err = ErrMethodCalled(method, err) diff --git a/x/evm/precompile/wasm_parse.go b/x/evm/precompile/wasm_parse.go index 80d950622..97a532753 100644 --- a/x/evm/precompile/wasm_parse.go +++ b/x/evm/precompile/wasm_parse.go @@ -16,51 +16,38 @@ type WasmBankCoin struct { Amount *big.Int `json:"amount"` } -func parseSdkCoins(unparsed []struct { - Denom string `json:"denom"` - Amount *big.Int `json:"amount"` -}, -) sdk.Coins { - parsed := sdk.Coins{} - for _, coin := range unparsed { - parsed = append( - parsed, - // Favor the sdk.Coin constructor over sdk.NewCoin because sdk.NewCoin - // is not panic-safe. Validation will be handled when the coin is used - // as an argument during the execution of a transaction. - sdk.Coin{ - Denom: coin.Denom, - Amount: sdk.NewIntFromBigInt(coin.Amount), - }, - ) - } - return parsed -} - // Parses [sdk.Coins] from a "BankCoin[]" solidity argument: // // ```solidity // BankCoin[] memory funds // ``` func parseFundsArg(arg any) (funds sdk.Coins, err error) { - bankCoinsUnparsed, ok := arg.([]struct { + if arg == nil { + return funds, nil + } + + raw, ok := arg.([]struct { Denom string `json:"denom"` Amount *big.Int `json:"amount"` }) - switch { - case arg == nil: - bankCoinsUnparsed = []struct { - Denom string `json:"denom"` - Amount *big.Int `json:"amount"` - }{} - case !ok: - err = ErrArgTypeValidation("BankCoin[] funds", arg) - return - case ok: - // Type assertion succeeded + + if !ok { + return funds, ErrArgTypeValidation("BankCoin[] funds", arg) } - funds = parseSdkCoins(bankCoinsUnparsed) - return + + for _, coin := range raw { + funds = append( + funds, + // Favor the sdk.Coin constructor over sdk.NewCoin because sdk.NewCoin + // is not panic-safe. Validation will be handled when the coin is used + // as an argument during the execution of a transaction. + sdk.Coin{ + Denom: coin.Denom, + Amount: sdk.NewIntFromBigInt(coin.Amount), + }, + ) + } + return funds, nil } // Parses [sdk.AccAddress] from a "string" solidity argument: @@ -148,6 +135,7 @@ func (p precompileWasm) parseExecuteArgs(args []any) ( return } + // contract address argIdx := 0 contractAddrStr, ok := args[argIdx].(string) if !ok { @@ -162,6 +150,7 @@ func (p precompileWasm) parseExecuteArgs(args []any) ( return } + // msg args argIdx++ msgArgs, ok = args[argIdx].([]byte) if !ok { @@ -174,6 +163,7 @@ func (p precompileWasm) parseExecuteArgs(args []any) ( return } + // funds argIdx++ funds, e := parseFundsArg(args[argIdx]) if e != nil { @@ -202,7 +192,11 @@ func (p precompileWasm) parseQueryArgs(args []any) ( } argsIdx++ - reqBz := args[argsIdx].([]byte) + reqBz, ok := args[argsIdx].([]byte) + if !ok { + err = ErrArgTypeValidation("bytes req", args[argsIdx]) + return + } req = wasm.RawContractMessage(reqBz) if e := req.ValidateBasic(); e != nil { err = e diff --git a/x/evm/statedb/journal_test.go b/x/evm/statedb/journal_test.go index 6390b640f..c1c74110c 100644 --- a/x/evm/statedb/journal_test.go +++ b/x/evm/statedb/journal_test.go @@ -31,13 +31,12 @@ func (s *Suite) TestComplexJournalChanges() { )) s.T().Log("Set up helloworldcounter.wasm") - - wasmContract := test.SetupWasmContracts(&deps, &s.Suite)[1] - fmt.Printf("wasmContract: %s\n", wasmContract) + helloWorldCounterWasm := test.SetupWasmContracts(&deps, &s.Suite)[1] + fmt.Printf("wasmContract: %s\n", helloWorldCounterWasm) s.T().Log("Assert before transition") test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 0, + &s.Suite, deps, helloWorldCounterWasm, 0, ) deployArgs := []any{"name", "SYMBOL", uint8(18)} @@ -129,11 +128,11 @@ func (s *Suite) TestComplexJournalChanges() { s.T().Log("commitEvmTx=true, expect 0 dirty journal entries") commitEvmTx := true evmObj = test.IncrementWasmCounterWithExecuteMulti( - &s.Suite, &deps, wasmContract, 7, commitEvmTx, + &s.Suite, &deps, helloWorldCounterWasm, 7, commitEvmTx, ) // assertions after run test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7, + &s.Suite, deps, helloWorldCounterWasm, 7, ) stateDB, ok := evmObj.StateDB.(*statedb.StateDB) s.Require().True(ok, "error retrieving StateDB from the EVM") @@ -145,7 +144,7 @@ func (s *Suite) TestComplexJournalChanges() { s.T().Log("commitEvmTx=false, expect dirty journal entries") commitEvmTx = false evmObj = test.IncrementWasmCounterWithExecuteMulti( - &s.Suite, &deps, wasmContract, 5, commitEvmTx, + &s.Suite, &deps, helloWorldCounterWasm, 5, commitEvmTx, ) stateDB, ok = evmObj.StateDB.(*statedb.StateDB) s.Require().True(ok, "error retrieving StateDB from the EVM") @@ -158,7 +157,7 @@ func (s *Suite) TestComplexJournalChanges() { s.T().Log("Expect no change since the StateDB has not been committed") test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7, // 7 = 7 + 0 + &s.Suite, deps, helloWorldCounterWasm, 7, // 7 = 7 + 0 ) s.T().Log("Expect change to persist on the StateDB cacheCtx") @@ -166,14 +165,14 @@ func (s *Suite) TestComplexJournalChanges() { s.NotNil(cacheCtx) deps.Ctx = *cacheCtx test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 12, // 12 = 7 + 5 + &s.Suite, deps, helloWorldCounterWasm, 12, // 12 = 7 + 5 ) // NOTE: that the [StateDB.Commit] fn has not been called yet. We're still // mid-transaction. s.T().Log("EVM revert operation should bring about the old state") err = test.IncrementWasmCounterWithExecuteMultiViaVMCall( - &s.Suite, &deps, wasmContract, 50, commitEvmTx, evmObj, + &s.Suite, &deps, helloWorldCounterWasm, 50, commitEvmTx, evmObj, ) stateDBPtr := evmObj.StateDB.(*statedb.StateDB) s.Require().Equal(stateDB, stateDBPtr) @@ -185,7 +184,7 @@ snapshots and see the prior states.`)) cacheCtx = stateDB.GetCacheContext() deps.Ctx = *cacheCtx test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7+5+50, + &s.Suite, deps, helloWorldCounterWasm, 7+5+50, ) errFn := common.TryCatch(func() { @@ -201,7 +200,7 @@ snapshots and see the prior states.`)) s.NotNil(cacheCtx) deps.Ctx = *cacheCtx test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7+5, + &s.Suite, deps, helloWorldCounterWasm, 7+5, ) stateDB.RevertToSnapshot(0) @@ -209,13 +208,13 @@ snapshots and see the prior states.`)) s.NotNil(cacheCtx) deps.Ctx = *cacheCtx test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7, // state before precompile called + &s.Suite, deps, helloWorldCounterWasm, 7, // state before precompile called ) err = stateDB.Commit() deps.Ctx = stateDB.GetEvmTxContext() test.AssertWasmCounterState( - &s.Suite, deps, wasmContract, 7, // state before precompile called + &s.Suite, deps, helloWorldCounterWasm, 7, // state before precompile called ) }) } diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index a411660f9..4e93b127a 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -569,7 +569,7 @@ func (s *StateDB) commitCtx(ctx sdk.Context) error { return nil } -func (s *StateDB) CacheCtxForPrecompile(precompileAddr common.Address) ( +func (s *StateDB) CacheCtxForPrecompile() ( sdk.Context, PrecompileCalled, ) { if s.writeToCommitCtxFromCacheCtx == nil { @@ -590,15 +590,14 @@ func (s *StateDB) CacheCtxForPrecompile(precompileAddr common.Address) ( // // See [PrecompileCalled] for more info. func (s *StateDB) SavePrecompileCalledJournalChange( - precompileAddr common.Address, journalChange PrecompileCalled, ) error { s.Journal.append(journalChange) s.multistoreCacheCount++ if s.multistoreCacheCount > maxMultistoreCacheCount { return fmt.Errorf( - "exceeded maximum number Nibiru-specific precompiled contract calls in one transaction (%d). Called address %s", - maxMultistoreCacheCount, precompileAddr.Hex(), + "exceeded maximum number Nibiru-specific precompiled contract calls in one transaction (%d).", + maxMultistoreCacheCount, ) } return nil diff --git a/x/evm/vmtracer.go b/x/evm/vmtracer.go index 2a20f2b01..2078bdfe7 100644 --- a/x/evm/vmtracer.go +++ b/x/evm/vmtracer.go @@ -51,8 +51,8 @@ func NewTracer(tracer string, msg core.Message, cfg *params.ChainConfig, height // TxTraceResult is the result of a single transaction trace during a block trace. type TxTraceResult struct { - Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer - Error string `json:"error,omitempty"` // Trace failure produced by the tracer + Result any `json:"result,omitempty"` // Trace results produced by the tracer + Error string `json:"error,omitempty"` // Trace failure produced by the tracer } var _ vm.EVMLogger = &NoOpTracer{} diff --git a/x/inflation/types/params.go b/x/inflation/types/params.go index 1ca46623b..6b95bbb7c 100644 --- a/x/inflation/types/params.go +++ b/x/inflation/types/params.go @@ -71,7 +71,7 @@ func DefaultParams() Params { } } -func validatePolynomialFactors(i interface{}) error { +func validatePolynomialFactors(i any) error { v, ok := i.([]sdk.Dec) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -83,7 +83,7 @@ func validatePolynomialFactors(i interface{}) error { return nil } -func validateInflationDistribution(i interface{}) error { +func validateInflationDistribution(i any) error { v, ok := i.(InflationDistribution) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -109,7 +109,7 @@ func validateInflationDistribution(i interface{}) error { return nil } -func validateBool(i interface{}) error { +func validateBool(i any) error { _, ok := i.(bool) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -118,7 +118,7 @@ func validateBool(i interface{}) error { return nil } -func validateUint64(i interface{}) error { +func validateUint64(i any) error { _, ok := i.(uint64) if !ok { return fmt.Errorf("invalid genesis state type: %T", i) @@ -126,7 +126,7 @@ func validateUint64(i interface{}) error { return nil } -func validateEpochsPerPeriod(i interface{}) error { +func validateEpochsPerPeriod(i any) error { val, ok := i.(uint64) if !ok { return fmt.Errorf("invalid parameter type: %T", i) @@ -139,7 +139,7 @@ func validateEpochsPerPeriod(i interface{}) error { return nil } -func validatePeriodsPerYear(i interface{}) error { +func validatePeriodsPerYear(i any) error { val, ok := i.(uint64) if !ok { return fmt.Errorf("invalid parameter type: %T", i) diff --git a/x/oracle/types/hash.go b/x/oracle/types/hash.go index b9d816ecc..a828a6414 100644 --- a/x/oracle/types/hash.go +++ b/x/oracle/types/hash.go @@ -99,7 +99,7 @@ func (h AggregateVoteHash) MarshalJSON() ([]byte, error) { } // MarshalYAML marshals to YAML using Bech32. -func (h AggregateVoteHash) MarshalYAML() (interface{}, error) { +func (h AggregateVoteHash) MarshalYAML() (any, error) { return h.String(), nil } diff --git a/x/tokenfactory/types/codec.go b/x/tokenfactory/types/codec.go index e0e639c0d..c20e55ad4 100644 --- a/x/tokenfactory/types/codec.go +++ b/x/tokenfactory/types/codec.go @@ -58,7 +58,7 @@ func TX_MSG_TYPE_URLS() []string { // Amino JSON serialization and EIP-712 compatibility. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { for _, ele := range []struct { - MsgType interface{} + MsgType any Name string }{ {&MsgCreateDenom{}, "nibiru/tokenfactory/create-denom"},