Ethereum Gas


On the ethereum blockchain, gas refers to the necessary cost to perform a transaction on the network and in turn this cost will be rewarded to the miner. Miners can set minimum gas price so transaction with gas price below the limit will not be propagated and included in the pending block.
Block Gas Limit
Blocks also have total gas limits to prevent runaway computation/keep the network decentralized. Up to time, it is 10,000,000 gas.
Gas Limit

Normal transfer eth to EOA address always require 21,000 gas limit (intrinsic gas), but gas limit interact with contract might be higher. Therefore, you can use tool below to estimate it.

ETH wastage can be happen when gas limit is too low thus cause the transaction fail.

Q: Could i specify exact gas limit according to previous gas used?
A: If contract call Tx trigger Refund Gas mechanism, then eventually you will trigger out-of-gas error.

Q: Which opcodes trigger refund?
A: SELFDESTRUCT refunds 24,000 and SSTORE[x] = 0 (deletion) refunds 15,000 gas.

Q: How to calculate refunded gas in the Tx?
A: In this example (vmtrace). Refunded gas = (Gas limit - Last executed gas) - Gas used = (60,000 - 18,791) - 26,209 = 15,000. Please also note that vm trace always start with gas after less intrinsic gas.

Q: How to calculate intrinsic gas?
A: Always start with 21,000 gas as initial intrinsic gas. However Tx with payload (data in data field) will subject to more intrinsic gas where payload data with 0 byte cost extra 4 gas while non 0 byte cost extra 16 gas.
In this example . There are one 0 byte and six non 0 bytes, therefore intrinsic gas would be 21000 + (1 * 4) + (6 * 16) = 21,100.
Gas Used
The actual gas amount used by this transaction.
Gas Price
The price of gas (unit in wei) in this transaction.
Transaction Fees
Tx Fees = Gas used * gas price. Remaining ETH will be refunded to initiator's account.

Estimate Gas Limit


eth_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".

eth_estimateGas as the name implied, it is estimation and not always accurate. So it is advised to specify a higher gasLimit than estimateGas.
<?php 

include_once "../libraries/vendor/autoload.php";
include_once("eth_utils.php");

define("GWEI_TO_WEI",'1000000000');
define("ETH_TO_WEI",'1000000000000000000');

$hosts = ["https://mainnet.infura.io"=>"https://mainnet.infura.io","https://ropsten.infura.io"=>"https://ropsten.infura.io", "https://cloudflare-eth.com"=>"https://cloudflare-eth.com", "https://evm-dataseed1.meerscan.io"=>"https://evm-dataseed1.meerscan.io"];


include_once("html_iframe_header.php");
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
	try {
		
		if (!in_array($_POST['host'], array_keys($hosts))) {
			throw new Exception("Please provide valid host.");
		}
		
		$url = $_POST['host'] . "/" . $_POST['path'];
		
		$gasPrice = "0x".bcdechex(bcmul($_POST['gas_price'],GWEI_TO_WEI, 18));
		$gasLimit = "0x".bcdechex($_POST['gas_limit']);
		$to = $_POST['to'];
		$from = $_POST['from'];
		$data = $_POST['data'];
		$value = "0x".bcdechex(bcmul($_POST['value'],ETH_TO_WEI, 18));
		
		$ch = curl_init();
		$requestId = time();
		
		$params = [];
		$params['jsonrpc']= "2.0";
		$params['method'] = 'eth_estimateGas';
		$params['params'] = [["from"=>$from, "to"=>$to, "gas"=>$gasLimit, "gasPrice"=>$gasPrice,"value"=>$value, "data"=>$data]];
		$params['id'] = $requestId;
		
		curl_setopt($ch, CURLOPT_URL,$url);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS,$req = json_encode($params));
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);

		$resp = curl_exec($ch);
		
		if ($resp === false) {
			throw new Exception("curl_exec return false");
		}
		
		if (strlen($err = @curl_error($ch)) > 0) {
			$errno = @curl_errno($ch);
			throw new Exception( "{$err} ({$errno})" );
		}
		
		$result = json_decode($resp,true); 
		if ($result['id'] != $requestId) {
			throw new Exception("Invalid request id.");
		}
		$result = $result['result'];
		
		curl_close ($ch);
		
		?>
		<div class="alert alert-success">
			<h6 class="mt-3">Host</h6>
			<textarea class="form-control" rows="1" readonly><?php echo $url;?></textarea>
			
			<h6 class="mt-3">JSON-RPC Request</h6>
			<textarea class="form-control" rows="5" readonly><?php echo $req;?></textarea>
			
			<h6 class="mt-3">JSON-RPC Response</h6>
			<textarea class="form-control" rows="1" readonly><?php echo $resp;?></textarea>
			
			<small>
				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.
			</small>
			
			<h6 class="mt-3">Result</h6>
			Gas limit is <?php echo hexdec($result);?>.
			
		</div>
		<?php
	} catch (Exception $e) {
		$errmsg .= "Problem found. " . $e->getMessage();
	}
} 

if ($errmsg) {
?>
    <div class="alert alert-danger">
        <strong>Error!</strong> <?php echo $errmsg?>
    </div>
<?php
}

?>
<form id='this_form' action='?action=submit' method='post'>
	<div class="form-group">
		<label for="host">Host To Receive RPC:</label>
		
		<div class="input-group mb-3">
			<select id="host" name="host" class="form-control" >
			<?php
			foreach($hosts as $k=>$v) {
				echo "<option value='{$k}'".($k == $_POST['host'] ? " selected": "").">{$v}</option>";
			}
			?>
			</select>
			<div class="input-group-append">
				<span class="input-group-text">
					/
				</span>
			</div>
			
			<input class="form-control" type='text' name='path' id='path' value='<?php echo $_POST['path']?>' placeholder="Put extra path or blank if it does not.">
			
		</div>
	</div>
	
	<div class="form-group">
        <label for="from">From Address:</label>
        <input class="form-control" type='text' name='from' id='from' value='<?php echo $_POST['from']?>'>
    </div>
	
    <div class="form-group">
        <label for="to">To Address:</label>
        <input class="form-control" type='text' name='to' id='to' value='<?php echo $_POST['to']?>'>
    </div>
	
	<div class="form-group">
		<label for="gas_price">Gas Price:</label>
		
		<div class="input-group mb-3">
			<input class="form-control" type='text' name='gas_price' id='gas_price' value='<?php echo $_POST['gas_price']?>'>
			<div class="input-group-append">
			  <span class="input-group-text">GWEI</span>
			</div>
		</div>
	</div>
	
	 <div class="form-group">
        <label for="gas_limit">Gas Limit:</label>
        <input class="form-control" type='text' name='gas_limit' id='gas_limit' value='<?php echo $_POST['gas_limit'] ?? "60000"?>'>
    </div>
	
	<div class="form-group">
        <label for="data">Data (Hex):</label>
        <input class="form-control" type='text' name='data' id='data' value='<?php echo $_POST['data']?>'>
    </div>
	
	 <div class="form-group">
		<label for="value">ETH Value:</label>
		
		<div class="input-group mb-3">
			<input class="form-control" type='text' name='value' id='value' value='<?php echo $_POST['value']?>'>
			<div class="input-group-append">
			  <span class="input-group-text">ETH</span>
			</div>
		</div>
	</div>
	
		
    <input type='submit' class="btn btn-success btn-block"/>
</form>
<?php
include_once("html_iframe_footer.php");








Tutorials
About Us
Contents have been open source in GITHUB. Please give me a ⭐ if you found this helpful :)
Community
Problem? Raise me a new issue.
Support Us
Buy me a coffee. so i can spend more nights for this :)

BTCSCHOOLS would like to present you with more pratical but little theory throughout our tutorials. Pages' content are constantly keep reviewed to avoid mistakes, but we cannot warrant correctness of all contents. While using this site, you agree to accept our terms of use, cookie & privacy policy. Copyright 2019 by BTCSCHOOLS. All Rights Reserved.