0

My friend asked me how does geth estimates gas limits and gas prices. How does it do this?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
maczniak
  • 1,082
  • 1
  • 8
  • 13
  • This is definitely a programming question to me, since my app relies on how geth is estimating gas and I need to know if it accounts for sudden spikes in gas cost – xref Aug 23 '19 at 15:32

2 Answers2

7

If you send transactions without gas limits or gas prices via RPC API, geth uses Estimate() or SuggestPrice() instead. Remix uses these, too. These behaviors are of geth v1.8.23. Different versions may work differently.

EstimateGas

input: block number (default: "pending"), 'gas limit' of the transaction (default: gas limit of the given block number)

EstimateGas tries to find a minimal gas to run this transaction on the given block number. It do a binary search between 21000 and 'gas limit'. For example, if 'gas limit' is 79000, it tries to run this transaction with the gas limit, 50000 = (21000 + 79000) / 2. If it failed, it tries with 64500 = (50000 + 79000) / 2, and so on. If it failed with 'gas limit', it returns 0 and error message, "gas required exceeds allowance or always failing transaction".

NOTE: Even if a transaction fails due to non-gas issues, it consider a failure as insufficient gas. Then it will return 0 with an error message in the end.

source: geth /internal/ethapi/api.go

Suggest(Gas)Price

input: number of blocks to search (default: 20, --gpoblocks), price percentile (default: 60, --gpopercentile), fallback result (default: 1 GWei, --gasprice)

SuggestPrice queries gas prices of 'number of recent blocks' from "latest" block in parallel. If it cannot get answers over half of 'number of blocks' due to any reasons, it will query more blocks up to five times 'number of blocks'.

A gas price of a block means a minimum gas price within transactions in that block. Transactions that a miner sent are excluded.

SuggestPrice sorts gas prices of blocks, then picks up the given percentile among prices (0 for the smallest price and 100 for the largest price). It caches this result, and returns a cached result immediately for the same "latest" (mined) block.

If all tries are failed, it returns a last result. If there is no last results, it returns a 'fallback result'. And SuggestPrice cannot return over 500 GWei.

source: geth /eth/gasprice/gasprice.go

maczniak
  • 1,082
  • 1
  • 8
  • 13
  • why do the binary search? I thought just run the tx with a full gas limit x, and after the execution, we may find out how much gas will be used, then make a buffer and multiply the gas cost by two or three is ok? – Jerrylk Jan 10 '22 at 06:11
  • @Jerrylk I am not sure. IMHO, if logic depends on `GAS` (remaining gas) or `GASLIMIT` opcodes, different results may occur. – maczniak Jan 20 '22 at 10:37
1

Agree with @maczniak's answer but one more to add. The reason why geth uses binary search here is that gas actually consumed in one tx does not necessarily equal to the gas required to make the tx success. For example for the following contract, calling SetField will actually consume much less gas than it's required i.e. 100000+

contract FunkyGasPattern {
    string public field;

    function SetField(string value) {
        // This check will screw gas estimation! Good, good!
        if (msg.gas < 100000) {
            throw;
        }
        field = value;
    }
}

ref https://github.com/ethereum/go-ethereum/pull/3587

zhangzhimin
  • 141
  • 1
  • 10