Description
On a POST /api/v1/contracts/call request with "estimate": true, the web3 module returns
HTTP 500 (Internal Server Error) when both of the following are true:
from is an ECDSA (secp256k1) account, and
value is greater than 0.
The same request returns HTTP 200 when value is omitted, or when from is an ED25519 account.
Expected: the request returns an HTTP 200 gas estimate (as it does for the ED25519 sender and the
no-value cases).
Observed on mirror node v0.156.0 (web3 module), deployed via solo against consensus node
v0.73.0.
Steps to reproduce
-
Deploy a local network with solo (consensus node v0.73.0, mirror node v0.156.0):
cat > /tmp/mirror-node-values.yaml <<'EOF'
web3:
env:
HIERO_MIRROR_WEB3_OPCODE_TRACER_ENABLED: "true"
HIERO_MIRROR_WEB3_EVM_NETWORK: "OTHER"
EOF
cat > /tmp/falcon-local.yml <<EOF
network:
--release-tag: "v0.73.0"
--node-aliases: "node1"
setup:
--release-tag: "v0.73.0"
--node-aliases: "node1"
consensusNode:
--node-aliases: "node1"
mirrorNode:
--enable-ingress: true
--pinger: true
--mirror-node-version: "v0.156.0"
--values-file: "/tmp/mirror-node-values.yaml"
EOF
npx @hashgraph/solo@0.78.0 one-shot falcon deploy \
--values-file /tmp/falcon-local.yml \
--dev --deploy-explorer=false --deploy-relay=false
The deploy output prints funded accounts. Note one 0.0.100x account address (these are
ECDSA / hex private key), e.g. 0.0.1003.
-
Port-forward the web3 module:
kubectl port-forward -n one-shot svc/mirror-1-web3 8545:80
-
Send the gas-estimation call with an ECDSA from and value > 0 (replace EC with the
account from step 1):
EC=0x05fba803be258049a27b820088bab1cad2058871
URL=http://127.0.0.1:8545/api/v1/contracts/call
curl -s -w '\nHTTP %{http_code}\n' -X POST "$URL" -H 'Content-Type: application/json' \
-d "{\"from\":\"$EC\",\"to\":\"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\"value\":5000000000,\"estimate\":true}"
Result: HTTP 500, body {"_status":{"messages":[{"message":"Internal Server Error","detail":"","data":""}]}}.
-
For comparison, the same call without value returns HTTP 200:
curl -s -w '\nHTTP %{http_code}\n' -X POST "$URL" -H 'Content-Type: application/json' \
-d "{\"from\":\"$EC\",\"to\":\"0x742d35Cc6634C0532925a3b844Bc454e4438f44e\",\"estimate\":true}"
-
And the same call with an ED25519 from (treasury 0.0.2) and value > 0 returns HTTP 200:
curl -s -w '\nHTTP %{http_code}\n' -X POST "$URL" -H 'Content-Type: application/json' \
-d '{"from":"0x0000000000000000000000000000000000000002","to":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e","value":5000000000,"estimate":true}'
Observed results
from key type |
value |
HTTP status |
| ECDSA |
none / 0 |
200 |
| ECDSA |
> 0 |
500 |
| ED25519 (treasury 0.2) |
> 0 |
200 |
Additional context
When the 500 occurs, the mirror-1-web3 pod logs the following:
kubectl logs -n one-shot deploy/mirror-1-web3
2026-06-16T20:36:17.556Z ERROR tomcat-handler-185 o.h.m.w.c.GenericControllerAdvice Generic error: jakarta.servlet.ServletException: Handler dispatch failed: java.lang.Error: Structure.getFieldOrder() on class org.hyperledger.besu.nativelib.secp256k1.LibSecp256k1$secp256k1_pubkey returns names ([data]) which do not match declared field names ([])
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:978)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:866)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1000)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:653)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:874)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:723)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:128)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
at org.hiero.mirror.web3.config.MetricsFilter.doFilterInternal(MetricsFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
at org.hiero.mirror.web3.config.LoggingFilter.doFilterInternal(LoggingFilter.java:48)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:199)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
at org.springframework.web.filter.ForwardedHeaderFilter.doFilterInternal(ForwardedHeaderFilter.java:174)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:165)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:77)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:113)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:83)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:72)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:1272)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1801)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at java.base@25.0.2/java.lang.Thread.runWith(Thread.java:1487)
at java.base@25.0.2/java.lang.VirtualThread.run(VirtualThread.java:456)
at java.base@25.0.2/java.lang.VirtualThread$VThreadContinuation$1.run(VirtualThread.java:248)
Caused by: java.lang.Error: Structure.getFieldOrder() on class org.hyperledger.besu.nativelib.secp256k1.LibSecp256k1$secp256k1_pubkey returns names ([data]) which do not match declared field names ([])
at com.sun.jna.Structure.getFields(Structure.java:1158)
at com.sun.jna.Structure.deriveLayout(Structure.java:1337)
at com.sun.jna.Structure.calculateSize(Structure.java:1234)
at com.sun.jna.Structure.calculateSize(Structure.java:1180)
at com.sun.jna.Structure.allocateMemory(Structure.java:430)
at com.sun.jna.Structure.<init>(Structure.java:220)
at com.sun.jna.Structure.<init>(Structure.java:208)
at com.sun.jna.Structure.<init>(Structure.java:195)
at com.sun.jna.Structure.<init>(Structure.java:187)
at org.hyperledger.besu.nativelib.secp256k1.LibSecp256k1$secp256k1_pubkey.<init>(LibSecp256k1.java:106)
at com.hedera.node.app.hapi.utils.EthSigsUtils.recoverAddressFromPubKey(EthSigsUtils.java:47)
at com.hedera.node.app.hapi.utils.EthSigsUtils.recoverAddressFromPubKey(EthSigsUtils.java:63)
at com.hedera.node.app.service.token.AliasUtils.recoverAddressFromPubKey(AliasUtils.java:124)
at com.hedera.node.app.service.token.AliasUtils.extractEvmAddress(AliasUtils.java:75)
at com.hedera.node.app.service.token.impl.handlers.CryptoCreateHandler.preHandle(CryptoCreateHandler.java:200)
at com.hedera.node.app.workflows.dispatcher.TransactionDispatcher.dispatchPreHandle(TransactionDispatcher.java:103)
at com.hedera.node.app.workflows.handle.dispatch.ChildDispatchFactory.preHandleChild(ChildDispatchFactory.java:378)
at com.hedera.node.app.workflows.handle.dispatch.ChildDispatchFactory.createChildDispatch(ChildDispatchFactory.java:186)
at com.hedera.node.app.workflows.handle.DispatchHandleContext.dispatch(DispatchHandleContext.java:495)
at com.hedera.node.app.service.contract.impl.exec.scope.HandleHederaNativeOperations.createHollowAccount(HandleHederaNativeOperations.java:139)
at com.hedera.node.app.service.contract.impl.state.DispatchingEvmFrameState.tryLazyCreation(DispatchingEvmFrameState.java:502)
at com.hedera.node.app.service.contract.impl.state.ProxyWorldUpdater.tryLazyCreation(ProxyWorldUpdater.java:236)
at com.hedera.node.app.service.contract.impl.exec.processors.CustomMessageCallProcessor.doTransferValueOrHalt(CustomMessageCallProcessor.java:309)
at com.hedera.node.app.service.contract.impl.exec.processors.CustomMessageCallProcessor.start(CustomMessageCallProcessor.java:152)
at org.hyperledger.besu.evm.processor.AbstractMessageProcessor.process(AbstractMessageProcessor.java:191)
at com.hedera.node.app.service.contract.impl.exec.FrameRunner.runToCompletion(FrameRunner.java:143)
at com.hedera.node.app.service.contract.impl.exec.FrameRunner.runToCompletion(FrameRunner.java:91)
at com.hedera.node.app.service.contract.impl.exec.TransactionProcessor.processTransactionWithParties(TransactionProcessor.java:151)
at com.hedera.node.app.service.contract.impl.exec.TransactionProcessor.processTransaction(TransactionProcessor.java:122)
at com.hedera.node.app.service.contract.impl.exec.ContextTransactionProcessor.call(ContextTransactionProcessor.java:185)
at com.hedera.node.app.service.contract.impl.handlers.ContractCallHandler.handle(ContractCallHandler.java:62)
at com.hedera.node.app.workflows.dispatcher.TransactionDispatcher.dispatchHandle(TransactionDispatcher.java:221)
at com.hedera.node.app.workflows.handle.DispatchProcessor.tryHandle(DispatchProcessor.java:167)
at com.hedera.node.app.workflows.handle.DispatchProcessor.processDispatch(DispatchProcessor.java:139)
at com.hedera.node.app.workflows.handle.DispatchProcessor.processDispatch(DispatchProcessor.java:118)
at com.hedera.node.app.workflows.standalone.TransactionExecutors.lambda$newExecutor$1(TransactionExecutors.java:227)
at com.hedera.node.app.workflows.standalone.TransactionExecutors$DefaultTracerBinding.runWhere(TransactionExecutors.java:338)
at com.hedera.node.app.workflows.standalone.TransactionExecutors.lambda$newExecutor$0(TransactionExecutors.java:226)
at org.hiero.mirror.web3.service.TransactionExecutionService.execute(TransactionExecutionService.java:92)
at org.hiero.mirror.web3.service.ContractCallService.doProcessCall(ContractCallService.java:115)
at org.hiero.mirror.web3.service.ContractCallService.callContract(ContractCallService.java:106)
at org.hiero.mirror.web3.service.ContractExecutionService.estimateGas(ContractExecutionService.java:96)
at org.hiero.mirror.web3.service.ContractExecutionService.lambda$processCallWithGas$0(ContractExecutionService.java:66)
at org.hiero.mirror.web3.common.ContractCallContext.lambda$run$0(ContractCallContext.java:80)
at java.base@25.0.2/jdk.internal.vm.ScopedValueContainer.callWithoutScope(ScopedValueContainer.java:162)
at java.base@25.0.2/jdk.internal.vm.ScopedValueContainer.call(ScopedValueContainer.java:147)
at java.base@25.0.2/java.lang.ScopedValue$Carrier.runWith(ScopedValue.java:62)
at java.base@25.0.2/java.lang.ScopedValue$Carrier.call(ScopedValue.java:419)
at org.hiero.mirror.web3.common.ContractCallContext.run(ContractCallContext.java:80)
at org.hiero.mirror.web3.service.ContractExecutionService.processCallWithGas(ContractExecutionService.java:56)
at org.hiero.mirror.web3.service.ContractExecutionService.processCall(ContractExecutionService.java:49)
at org.hiero.mirror.web3.controller.ContractController.call(ContractController.java:44)
at java.base@25.0.2/java.lang.reflect.Method.invoke(Method.java:565)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:252)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:184)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:934)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:853)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:86)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
... 45 common frames omitted
2026-06-16T20:36:17.560Z WARN tomcat-handler-185 o.h.m.w.c.LoggingFilter [::1] POST /api/v1/contracts/call in 9 ms : 500 Handler dispatch failed: java.lang.Error: Structure.getFieldOrder() on class org.hyperledger.besu.nativelib.secp256k1.LibSecp256k1$secp256k1_pubkey returns names ([data]) which do not match declared field names ([]) - {"nonce":"0x1","value":5000000000,"from":"0x7d55e4b98d6478b8c8379e1bd6d8b767a19b0616","to":"0xe4ac0763398050e5d2b868672f0fe624888580ba","estimate":true}
The same HTTP 500 and the same log line were observed in two environments:
- GitHub Actions CI runner (Linux, x86_64).
- Local solo deployment (macOS, arm64).
Hedera network
other (local solo network)
Version
mirror node v0.156.0 (web3 module); consensus node v0.73.0; solo v0.78.0
Operating system
Linux (CI runner) and macOS (local)
Description
On a
POST /api/v1/contracts/callrequest with"estimate": true, the web3 module returnsHTTP 500 (
Internal Server Error) when both of the following are true:fromis an ECDSA (secp256k1) account, andvalueis greater than 0.The same request returns HTTP 200 when
valueis omitted, or whenfromis an ED25519 account.Expected: the request returns an HTTP 200 gas estimate (as it does for the ED25519 sender and the
no-value cases).
Observed on mirror node
v0.156.0(web3 module), deployed via solo against consensus nodev0.73.0.Steps to reproduce
Deploy a local network with solo (consensus node
v0.73.0, mirror nodev0.156.0):The deploy output prints funded accounts. Note one
0.0.100xaccount address (these areECDSA / hex private key), e.g.
0.0.1003.Port-forward the web3 module:
Send the gas-estimation call with an ECDSA
fromandvalue > 0(replaceECwith theaccount from step 1):
Result: HTTP 500, body
{"_status":{"messages":[{"message":"Internal Server Error","detail":"","data":""}]}}.For comparison, the same call without
valuereturns HTTP 200:And the same call with an ED25519
from(treasury0.0.2) andvalue > 0returns HTTP 200:Observed results
fromkey typevalueAdditional context
When the 500 occurs, the
mirror-1-web3pod logs the following:The same HTTP 500 and the same log line were observed in two environments:
Hedera network
other (local solo network)
Version
mirror node v0.156.0 (web3 module); consensus node v0.73.0; solo v0.78.0
Operating system
Linux (CI runner) and macOS (local)