Open mehcode opened 4 years ago
The value returned by a COST_ANSWER for ContractCallLocal is an estimate, notably it uses a default size for the (predicted) returned data. If the actual size of returned data is much larger, then the estimated fee will be smaller than the required, and you'll get the INSUFFICIENT error.
Our tests using https://github.com/hashgraph/hedera-services/tree/master/test-clients passed with a complete match of the cost returned in the ContractCallLocalQuery
COST_ANSWER
response. By complete match, I mean the ANSWER_ONLY
query went through just fine with the exact returned cost from COST_ANSWER
, or we received INSUFFICIENT_TX_FEE
even when we deduct only 1 tinyBar from the returned cost. The tests were done both locally and against our current testnet.
@mehcode, could you please provide us a sample of ContractCallLocalQuery
, both with COST_ANSWER
and ANSWER_ONLY
ResponseType
that caused the mismatch, especially the Transaction
as the payment
in the QueryHeader
? Thank you!
The value returned by a COST_ANSWER for ContractCallLocal is an estimate, notably it uses a default size for the (predicted) returned data. If the actual size of returned data is much larger, then the estimated fee will be smaller than the required, and you'll get the INSUFFICIENT error.
That is why the .net sdk had to add a feature to add "extra bytes returned gas" to a query contract call, this is to cover the unestimatable bytes fee. This is not a great workaround.
I also can't help but notice this was opened 8 days ago. TESTNET was failing all over the place with COST_ANSWER back then (including contract queries), unfortunately, by being reset, the edge case that caused whatever the problem has disappeared. Could it have been a caching problem with a gRPC service not being rebooted during upgrade (previewnet mirror node had a similar problem lately that was cleared up by recycling the gRPC service)
Summary of the defect
COST_ANSWER for ContractCallLocal does not match the actual fee and using its value directly results in INSUFFICIENT_TX_FEE.
How to reproduce (if possible)
Execute COST_ANSWER for a very simple ContractCallLocal. Then use that amount in a payment transaction for a ANSWER_ONLY ContractCallLocal without changing any other variables.
You can use the
CreateStatefulContractExample
example in the Java SDK but you'll need to remove our workaround for this issue inContractCallQuery#getCostAsync
.Additional Context
The Java, Go, and JavaScript have historically always multiplied the cost from COST_ANSWER by 1.1, before using it in a payment transaction. Doing this, the problem goes away. But it seems like this problem has gotten worse as of the latest 0.7 testnet as the .Net SDK has also reported finding this.
My guess is whatever is happening is now also affecting the relatively simple queries and low gas costs that are normally used in SDK testing.