If a contract call predictably requires 41043 of gas to be processed as estimated by
estimateGas, how come I need to specify gasLimit of ~70000 to be processed?
I believe in some cases cumulativeGasUsed is not accurate due to spending gas / refunding gas. If at any point the contract gets above the gasLimit, it will fail with an Out of Gas exception. If a refund is issued later in the contract, it will bring the cumulative gas down even though it rises above what you think is the "gas limit" during the execution of the contract.
Contract had data in storage
Each time a user sent a transaction to the contract, the contract would clear the oldest item in storage out
However, since the contract only refunds at the end of the transaction, all funds were stuck in the contract due to being out of gas.
So before a user sends a transaction, let's say the gas is 100,000. After the user sends the transaction, the gas is 100,000. During the contract, at a certain point, it "needs" 200,000. And the second it hits that limit, it's out of gas and done.
In etherdice's case, it was actually worse because he was hitting the global limit of 3141592 that was around prior to homestead.
You can specify the gas exactly and it should go through just fine. The only gotcha is that if the contract state changes that you're executing against, and it would require more gas than provided by even a single unit, you'll lose all the provided gas and the transaction will be rolled back.
Here are general tips, followed by a synthesis of the other answers and comments to explain this particular situation.
estimateGas, as its name implies, is not always 100% accurate
gas refunds are only provided at the end of the transaction: one must provide enough gas during the entire transaction, otherwise an Out of Gas exception will cause all gas to be forfeited
rule of thumb in contract and transaction debugging is: when in doubt, increase the gas
Conclusion appears to be:
- OP was performing a few storage writes (where value is overwritten)
- The few storage writes actually lead to a gas refund
- OP was using a stable branch of Geth
- Stable branch of Geth has a bug that underestimated the gas since Geth normalized it to include gas refunds, instead of reporting the maximum gas consumed during the transaction
- Thus the transaction was running Out of Gas and needed a higher gas limit to be processed
Geth v1.4 or the
develop branch has the fix for estimateGas. Note, although
estimateGas is practical to use, it will still not be correct for all possible scenarios.