Bitcoin
$5,566.72
-7.16
Ethereum
$173.21
-1.47
Litecoin
$41.08
-1.16
DigitalCash
$131.45
-5.79
Monero
$88.15
-1.86
Nxt
$0.05
0
Ethereum Classic
$7.21
-0.26
Dogecoin
$0.00
-0

What is Ethereum Gas: A Comprehensive Guide

The crazy world of constant innovation and Dapp development that we are living in right now wouldn’t have been possible without the advent of Ethereum. Everyone took notice when Ethereum first came to fore. For the first time ever, we had a decentralized platform which could rent out computational power to developers to create their own dapps. In order to power up these dapps, fuel was needed, which was promptly called “Ethereum Gas”. So, in order to understand the significance of Dapps, let’s go back in time and introduce ourselves to one of the most brilliant people alive right now.

Nick Szabo and Smart Contracts

If you are new to cryptocurrency then chances are that you have not even heard of Nick Szabo’s name. However, the fact is, if you were to create a Mount Rushmore of cryptocurrency greats, then you simply can’t omit his name from the list. The man is a living legend and has pretty much created the basis of a multi-billion dollar industry (ICOs).

This is mainly in part because of his two path-breaking papers.

Bit Gold laid the foundation of Bitcoin. In fact, because of this paper, many in the community expect him to be Satoshi Nakamoto. In the paper, Szabo points out the third-party dependency of modern financial systems and identifies them to be security plot holes. He says, “It would be very nice if there were a protocol whereby unforgeable costly bits could be created online with minimal dependence on trusted third parties, and then securely stored, transferred, and assayed with similar minimal trust. Bit gold.”

However, today’s topic is about the second paper that he worked on.

The paper was named “Smart Contracts: Building Blocks for Digital Free Markets” wherein in he describes and coins “smart contracts”. Contracts are an integral part of the fabric that makes modern society. A smart contract is an idea of establishing an agreement between two complete strangers in a trustless way and to make sure that the contract is honored via self-executing code. Two people can get into a contractual agreement without the need for a third party.

In fact, the way he explained how smart contracts are going to work, is via his famous vending machine example.

Yup that’s right…the humble vending machine.

Smart Contracts, as with vending machines, works on the IFTTT logic aka the IF-THIS-THEN-THAT logic. In simpler terms, the contract will execute newer instructions and codes if and only if the older code have been executed.

Let’s see how this works in a vending machine. Each and every step that you take acts like a trigger for the next step to execute itself. It is kinda like the domino effect. Suppose you need to take some food from the machine, this is what you will need to do.

Step 1: You give the vending machine some money.
Step 2: You punch in the button corresponding to the item that you want.
Step 3: The item comes out and you collect it.

Ok, so if you review all these steps, then there is one thing that you are going to notice. Really think about it. Will any of the steps work if the previous one hasn’t been executed yet? Each and every one of those steps is directly related to the previous step.

Oh and there is one more thing that you need to think about.

In the entirety of your interaction with the vending machine, there were only two parties involved, you and the machine. There was no need to have a third party involvement and this is one of the most critical features of smart contracts. Only you and the person that you need to directly involve yourself with need to be part of the interaction. There is absolutely no need to have third parties involved.

Alright, so we know how smart contracts are supposed to ideally work. However, before we could put it into practice, another important innovation was needed. This innovation happened when an unknown programmer released a seemingly innocuous whitepaper.

Satoshi Nakamoto and The Bitcoin Era

On November 2008, an unknown programmer with the pseudonym, Satoshi Nakamoto, released a whitepaper titled, “Bitcoin: A Peer-to-Peer Electronic Cash System”. This was path-breaking in every sense of the term. For the first time ever, we had a truly decentralized cryptocurrency which didn’t require any third party, like a bank. You, and only you, had full control over your currency(achieved via public key cryptography) and you can send it to whoever you want, provided, they also had a wallet address.

The key behind this wondrous new currency was the blockchain technology.

A blockchain is a time-stamped series of immutable record of data that is managed by a cluster of computers not owned by any single entity. Each of these blocks of data (i.e. block) are secured and bound to each other using cryptographic principles (i.e. chain). Ok, so what does that mean in simple terms?

Imagine a universal ledger that anyone can download and write into. Anybody who has a copy of that ledger can:

  • Check the records that have been logged into the ledger.
  • Check the time at which those records were logged.
  • Cannot tamper with any of the previously made entries because the ledger is immutable. This property of “immutability” is one of the most important features of the blockchain and it gains it through cryptographic hash functions.

That is what Bitcoin gave to us, the first proper implementation of a technology which can act as an immutable and transparent ledger. This innovation gives us a system which is completely incorruptible and free from human corruption since each and every transaction made into the blockchain can be checked.

Vitalik Buterin and Ethereum

Bitcoin, in every sense of the word, disrupted the world’s financial system.

However, people weren’t convinced that the blockchain technology was limited to mere currency. One of those people who wanted to explore the other areas of blockchain application was Bitcoin Magazine co-founder, Vitalik Buterin. In late 2013, Buterin presented a paper which had outlined what was going to go on to become Ethereum. He raised the point that Bitcoin was in need of a scripting language which could be used to create decentralized applications. His proposal was shut down.

Buterin then moved on to create a different platform called Ethereum. Eventually, proper development of Ethereum began in early 2014 through a Swiss company, Ethereum Switzerland GmbH (EthSuisse). Ethereum held its ICO between 20th July- 2nd September 2014 and raised ~$18.4 million.

Ethereum is planning to be the ultimate software platform of the future. A supercomputer where developers all over the world can code and develop their own decentralized applications (Dapps).

And this is where we finally come back to smart contracts. Ethereum broke the mould and opened the doors to second generation blockchain technologies. However, what are the requirements of a great Dapp platform? Let’s looking into that.

Requirements of a Dapp Platform

There is a reason why there is a mad dash to produce the best and the most effective Dapp platform out there. Every blockchain developer worth their salt knows that Dapps are the future. If the future is indeed going to be decentralized, then Dapps are going to be the front and center of it.

So, what are the requirements that high-functioning Dapps require from their platforms? Let’s take a look.

#1 Scalability

If a Dapp is planning to introduce an industry disrupting service and be a hit with many people, then it would require the smart contract platform to provide the necessary features. This is the reason why the smart contract platform should be scalable enough to accommodate for these Dapps.

#2 Negligible Latency

Have you ever taken part in an online multiplayer game?

If you have, then tell us the worst thing that you experience while playing it. That’s right…LAG.

Nothing’s worse than having a bad lag to ruin your gaming experience right then and there. Now imagine if instead of a game, it was a Dapp, and let’s say its a medical service related Dapp which requires quick communication.

Can you see why it can be important for a Dapp platform to have near negligible latency?

#3 Free to Use

This is another important note to take care of. If you are building a dapp on a platform then you must make sure that the platform is free to use.

Why?

Well, do you really want your users to pay for the platform just to gain the benefits of your Dapp?

#4 Provides Seamless Upgradation

One of the biggest things that most Dapp developers will need is a platform that will allow them to upgrade or counterattack bugs with ease. Think about it, if a developer has to deal with a bug, then how problematic will it be if it somehow freezes up the entire platform as a result?

#5 Parallel Performance

An ideal platform should allow Dapps to parallelize their tasks and distribute workload in an efficient and speedy manner. As we have already talked about, scalability and low latency are both important traits, and one way to achieve them is by having a platform that helps in parallelizing your tasks.

#6 Sequential Performance

Having said that, not all functions of a Dapp should be parallelized. Think of a simple transaction. There are a lot of functions there that need to be executed in a sequence. Eg. Alice can’t send her coins to Bob unless Alice has properly verified her identity. This is why Dapp platforms should also provide optimal sequential performance capability.

Ethereum Virtual Machine – Dapp Platform

Alright so we know what is required for an ideal Dapp platform and Ethereum provides us just that via the Ethereum virtual machine. The smart contracts that run on the EVM need to have the following properties to execute themselves properly:

  • Determinism
  • Isolated
  • Terminable

Determinism

We have already talked about determinism before (while discussing hash functions.) A program is deemed deterministic IF it gives the same output to the same input every single time. Having said that, there may be moments when the program acts in an indeterministic manner:

  • If the program calls an indeterministic function in the middle of execution
  • The data source that the program is using is indeterministic in nature
  • When a program calls another program aka dynamic calling.

The simplest examples of determinism are classical mathematical operations.

For example, assuming the same base, 3*4 will always be 12, regardless of how many times you do the operation. Similarly, when you run a smart contract, no matter how many times you execute it, it will give you the same result. This is extremely important for contracts which are dealing with huge amounts of money, they need to execute with a high degree of predictability.

So, having said that, what the circumstances which could lead a contract to at in an un-deterministic manner. Turns out, that there are three ways that it can happen:

  • If the contract itself calls an undeterminisitc function.
  • If the data that the contract acquires during runtime is undeterministic. Since the data is undeterministic, the contract also becomes undeterministic. Consider a program, which acquires the list of the top 10 goalscorers of the week from the English Premier League. Since that list is constantly changing, it will be undeterministic.
  • Finally, whenever a contract executes dynamic calling, it is undeterministic. The dynamic call happens when a contract calls another contract. Since the target is only determined during execution, it becomes undeterministic.

Isolated

In Ethereum, anyone and everyone can create a smart contract, however, this freedom comes with a price. Since there is no barrier to entry, anyone can knowingly, or unknowingly, upload a bug or virus with these contracts. This is why it is necessary to have a mechanism that isolates these smart contracts in a sandbox that keeps the entire ecosystem safe from the infected smart contract.

Terminable

Smart contracts must take the necessary steps to terminate executing in a given time limit. In other words, there must be a way to externally “kill” the contract when necessary. The steps that can be taken to ensure this are:

  • Turing Incompleteness: A Turing incomplete contract is incapable of making jumps and/or loops. This ensures that the contract can’t enter an endless loop.
  • Step/Fee meter: A contract can keep track of the number of steps that it has taken to make sure they don’t exceed a particular step limit. Or, they can also use a fee meter. In a fee meter, a prepaid fee is paid to execute the contract, and each step of the program takes a particular amount of fee to execute. Once the fee has been utilized, the contract stops executing. Every instruction execution requires a particular amount of fee. If the fee spent exceeds the pre-paid fee then the contract is terminated. Ethereum’s gas actually follows this principle.
  • Timer: The contract has a pre-determined timer and it executes for the duration of the timer. Once the time-limit exceeds, the contract stops executing.

Keeping all this in mind, Ethereum gives their developers the Ethereum Virtual Machine (EVM) which presents an ecosystem for the users to create their smart contract. The language that is used to code these contracts is called “Solidity” which is a Turing Complete program.

Now, remember, we said earlier that “Turing Incompleteness” is one of the ways that contracts can assure that they are terminable So, what is it that Ethereum uses to make sure that their contracts terminate? They use a Fee meter called “Gas”, and that’s what we are going to get into next.

Now that we have seen these features, it is important to know how they are executed. Usually, the smart contracts are run using one of the two systems:

  • Virtual Machines: Ethereum uses this.
  • Docker: Hyperledger Fabric uses this.

Let’s compare these two and determine which makes for a better ecosystem. For simplicity’s sake, we are going to compare Ethereum (Virtual Machine) to Fabric (Docker).

Virtual Machine Docker
Deterministic The contracts have no un-deterministic functions and the data is limited to on-chain information only. However, it executes dynamic calls which can be un-deterministic in nature. Thankfully the data accessible is deterministic Because of the design of the docker, the system is reliant on users to create contracts which are deterministic. That is not really the best of solutions.
Terminable Ethereum uses the “Fee-meter” for termination. Every step in the contracts costs “gas” and once the gas cost exceeds the pre-paid fee, the contract is killed. Fabric uses the timer. However, since the timer can change from node to node because each node has its own computational power there is a risk to the consensus process.
Isolated Has good isolation properties. Is namespace-reliant and not capable of proper isolation

 

So, as can be seen, Virtual Machines provide better Deterministic, terminable and isolated environment for the Smart contracts. However, dockers have one distinct advantage. They provide coding language flexibility while in a Virtual Machine (VM) like Ethereum, one needs to learn a whole new language (solidity) to create smart contracts.

The EVM is the virtual machine in which all the smart contracts function in Ethereum. It is a simple yet powerful Turing Complete 256-bit virtual machine. Turing Complete means that given the resources and memory, any program executed in the EVM can solve any problem.

Alright, so now that you know what smart contracts are what Ethereum gas can do, let’s understand what it actually is.

What is Ethereum Gas?

Gas is the lifeblood of the Ethereum ecosystem. It is the unit that measures the amount of computational effort that it takes to execute certain operations. Every single thing in Ethereum, be it a transaction, smart contract, or even an ICO takes a certain amount of gas. In fact, gas is what is used to calculate the amount of ether you will need to pay to the network to execute an operation.

Let’s look at an analogy to better understand how gas works. Suppose you need to fill up gas before you go to work, what are you going to do?

  • Go to the gas station and specify how much gas you want to fill up in your car.
  • Fill up the tank with the specified amount of gas.
  • Pay the amount of money you owe.

In the analogy, the car is the operation that you want to execute, like a transaction or smart contrast. The gas station is an Ethereum miner, the gas is Ethereum gas, and the money that you pay is the miner fee. The smallest unit of gas measurement is “wei”.

So, as you may have inferred by now, to get an operation done in Ethereum, the person initiating the transaction or the smart contract must specify a gas limit before they submit it to the miners. If a gas limit has not been specified, the miners will not execute the operation. Now when submitting a gas limit, the following two cases will occur:

  • The gas limit is too low
  • The gas limit is too high

If the gas limit is too low, the miners will immediately stop all operations. However, the contract initiator must pay for the number of computations that have taken place till then.

If the gas limit is too high, the contract will be executed and the leftover gas will be refunded immediately.

So, in theory, it should make sense to always submit contracts or transactions with a bloated gas limit right? Unfortunately, it doesn’t work like that in reality. Miners in Ethereum are limited by a 6,700,000 gas limit per block, and each and every transaction in Ethereum has a gas limit of 21,000. So, now consider the following two transaction scenarios that a miner may face:

  • Executing a simple transaction with a gas limit of 48,000.
  • Executing two simple transactions with gas limits of 21,000 each.

Obviously, the miner will choose the second scenario because it makes more sense to them economically.

How Ethereum Gas Works

To better understand how gas works in Ethereum, let’s use an analogy. Suppose you are going on a road trip. Before you do so you go through these steps:

  • You go to the gas station and tell them exactly how much gas you want to fill up in your car
  • The gas station attendant fills up your car with the amount of gas
  • Once your car has been filled up, you pay the amount of money that you owe them for your car.

Now, let’s draw parallels with Ethereum.

  • Driving the car is the operation that you want to execute, like executing a function of a smart contract.
  • The gas is well….gas.
  • The gas station is your miner.
  • The money that you paid them is the miner fees.

So, for any operations that users need to execute in ethereum, they have to fill up their contracts with gas for the following operations:

  • The general execution of the smart contract.
  • Secondly, intrinsic gas, i.e. the gas needed to cover the data.

Why Do We Need The Gas System?

So, now that you have the bases covered, the real question is, why do we need the gas system? Well, there are two main reasons:

  • Halting property
  • Incentivization

Halting Property

Like we have mentioned before, a smart contract needs to have some sort of feature which will let them stop execution. Remember that the contracts are coded using solidity, which is a Turing complete language. A Turing complete language is basically a language which can complete any operation, provided it has enough computational resources. This is the reason why smart contracts need to have an in-built computation halting mechanism in place.

The gas system does exactly that.

Each and every step in the smart contract requires a particular amount of gas for execution. Once the gas completely runs out, the contract stops working.

Incentivization

Like any proof-of-work peer-to-peer system, Ethereum is heavily dependent on the hashrate of their miners. More the miners, more the hashrate, more secure and fast the system.

So, seeing how critical miners are to the system, how exactly can you attract more and more of them into the ecosystem? Well, there are two ways that miners can make money in the Ethereum ecosystem:

  • By mining the blocks (obviously)
  • By taking over the responsibility of putting transactions inside the blocks that they have mined.

We are pretty sure that you know how the former point works. In this guide, we are going look at the second point.

The miners are responsible for putting transactions inside their blocks. In order to do so, they must use their computational power to validate smart contracts. The gas system allows them to charge a certain fee for doing so. This fee is known as the miner’s fee and helps in giving them the required amount of incentivization to take an active part in the ecosystem.

The reason gas is important is that it helps to ensure an appropriate fee is being paid by transactions submitted to the network. By requiring that a transaction pay for each operation it performs (or causes a contract to perform), we ensure that network doesn’t become bogged down with performing a lot of intensive work that isn’t valuable to anyone. This is a different strategy than the Bitcoin transaction fee, which is based only on the size in kilobytes of a transaction. Since Ethereum allows arbitrarily complex computer code to be run, a short length of code can actually result in a lot of computational work being done. So it’s important to measure the work done directly instead of just choosing a fee based on the length of a transaction or contract.

So if gas is basically a transaction fee, how do you pay it? This is where it gets a little tricky. Although gas is a unit that things can be measured in, there isn’t any actual token for gas. That is, you can’t own 1000 gas. Instead, gas exists only inside of the Ethereum virtual machine as a count of how much work is being performed. When it comes to actually paying for the gas, the transaction fee is charged as a certain number of ether, the built-in token on the Ethereum network and the token with which miners are rewarded for producing blocks.

This might seem odd at first. Why don’t operations just have a cost measured in ether directly? The answer is that ether, like bitcoins, have a market price that can change rapidly! But the cost of computation doesn’t go up or down just because the price of ether changes. So it’s helpful to separate out the price of computation from the price of the ether token, so that the cost of an operation doesn’t have to be changed every time the market moves.

The terminology here gets a little messy. Operations in the EVM have gas cost, but gas itself also has a gas price measured in terms of ether. Every transaction specifies the gas price it is willing to pay in ether for each unit of gas, allowing the market to decide the relationship between the price of ether and the cost of computing operations (as measured in gas). It’s the combination of the two, total gas used multiplied by gas price paid, that results in the total fee paid by a transaction.

As tricky as it is, it’s important to understand this distinction, because it results in one of the most confusing things about Ethereum transactions to the initial learner: there is a difference between your transaction running out of gas and your transaction not having a high enough fee. If the gas price I set in my transaction is too low, no one will even bother to run my transaction in the first place. It will simply not be included in the blockchain by miners. But if I provide an acceptable gas price, and then my transaction results in so much computational work that the combined gas costs go past the amount I attached as a fee, that gas counts as “spent” and I don’t get it back. The miner will stop processing the transaction, revert any changes it made, but still include it in the blockchain as a “failed transaction”, collecting the fees for it. This may seem harsh, but when you realise that the real work for the miner was in performing the computation, you can see that they will never get those resources back either. So it’s only fair that you pay them for the work they did, even though your badly designed transaction ran out of gas.

Providing too big of a fee is also different than providing too much ether. If you set a very high gas price, you will end up paying lots of ether for only a few operations, just like setting a super high transaction fee in bitcoin. You’ll definitely be prioritised to the front of the line, but your money is gone. If you provided a normal gas price, however, and just attached more ether than was needed to pay for the gas that your transaction consumed, the excess amount will be refunded back to you. Miners only charge you for the work that they actually do. You can think of the gas price as the hourly wage for the miner, and the gas cost as their timesheet of work performed.”

So, how do we measure gas? Gas is simply measured in units of gas. A transaction sent to the Ethereum network costs some discrete amount of gas (e.g. 100 gas) depending on how many EVM instructions need to be executed.

So, How Does Gas Convert into Ether?

Alright, so the next step is to convert this gas into Ether. There is no fixed rate of conversion of course.

The sender of the transaction can specify whatever gas price they want, think of how transaction fees work in bitcoin, that’s pretty much what that is here. The miners can choose whatever transaction they want to verify. Logically speaking, they would usually choose the transaction with the highest gas price.

The average gas price is typically on the order of about 20 Gwei (or 0.00000002 ETH) but can increase during times of high network traffic as there are more transactions competing to be included in the next block.

The following chart shows you the average Ethereum gas price chart.

Gas Usage For Users vs Developers

Your experience and interaction with gas will differ based on the role that you are fulfilling. Basically, whether you are a user or a developer.

A User’s Relationship with Gas

If you are a user and are interacting with a smart contract, then you will need to specify a gas amount. This, in turn, will take two components into consideration:

  • Gas Limit
  • Gas Price

Gas Limit

Gas Limit is the total gallons of gas to put in the tank of your smart contract. This amount only affects the smart contract execution itself and must be sufficient for all of the resources required by the smart contract. If you didn’t put in the necessary gas limit, then you will get an Out of Gas exception. You don’t really need to guess how much you have to put in. There are tools like MetaMask which will attempt to make their best guess at this value and is more or less right on a non-congested ethereum network. All the unused gas will be refunded back to you (more on this later).

Gas Price

The second thing that you, as a user, need to keep in mind is Gas Price. This amount is typically denoted in gwei(10⁹ wei) and does not affect the execution of transaction or smart contract interaction, but rather the speed at which the transaction gets added to a block.

If you think about our car and fuel analogy above, gas price is…well…the price of the fuel that you pay.

If you pay a higher gas price, your transaction will get added to a block more quickly, thus speeding up the processing of your transaction. With our gas station example, think of paying “higher gas price” as you paying for the gas that you want to fill into your car and a little extra that you pay to the gas station attendant on the side to make sure that they give your car a higher preference.

So, in terms of Ethereum, if 20 gwei is the average price to pay and you give 50 gwei instead, you will be bumped to the head of the line, Similarly, if you pay just 5 gwei, then you will have to wait several minutes before anyone puts your transaction inside the blockchain.

The gas price is a powerful feature to have at your disposal depending on the type of dApp you are trying to write. Places like https://ethgasstation.info can help you to understand the current network load and corresponding wait times related to gas price.

A Developer’s Relationship with Gas

If you are a developer, then you don’t really need to care about Gas Price at all. All that you should be concerned with is your smart contract’s Gas Limits. The gas limit needs to fall within reasonable limits to make sure that you are not compromising on user experience.

Let’s take an example.

If you are creating a smart contract to handle custody of a million dollars worth of eth, you may not be concerned with a $5 gas limit. However, if you were doing a social platform with $5 gas limits for every post you would bankrupt your users very quickly. You need to design your smart contracts to fit with your use case as processing power and storage come at a high premium in ethereum right now.

What is Ethereum Gas Limit?

Before we go any further, it is important to know the concept of gas limit.

Like we have said before, in order to get an operation done in Ethereum, the sender of the transaction must specify a gas limit before they submit it to the network. The gas limit is the maximum amount of gas the sender is willing to pay for this transaction.

There are some points that must be considered before you specify a gas limit:

  • Different operation are going to have different gas costs
  • The miners will stop executing the moment the gas runs out.
  • If there is any gas left over, it will be immediately refunded to the operation generator.

Alright, now let’s see how this will look at runtime. Let’s look at a simple addition operation:

  • Storing 10 in a variable. Let’s say this operation costs 45 gas.
  • Adding two variables, let’s say this costs 10 gas.
  • Storing the result which again costs 45 gas.

Let’s imagine that you create this addition contract and specify a 110 gas limit.

The total gas used by the miner to run the computation is (45+10+45) = 100 gas.

The fee that is owed to the miner, assuming 1 gas costs 20 Gwei, is (100 * 20 Gwei) = 0.000002 ETH.

Now, how much gas is left over?

110 – 100 = 10 gas.

The 10 unused gas is returned back to you (10 * 20 Gwei) = 0.0000002 ETH.

So, now that you have an idea as to how this works, let’s consider the following two scenarios:

  • The specified gas limit is too low.
  • The specified gas limit is too high.

Scenario #1: The Gas Limit is too low

If an operation runs out of gas, then it is reverted back to its original state like nothing actually happened. Having said that, the contract initiator needs to pay the miners fees for their computational costs and, even if it is not executed, the operation still gets added to the blockchain.

This will be clear the moment we go back to our road trip analogy.

Suppose you need to have 35 liters of gas in your car, but you only put in 30 liters. Since you haven’t filled up enough gas in your car, you will not be able to reach your destination. However, you will still need to pay for the 30 liters that your car has consumed right? Burning up fuel is an irreversible process after all.

So, how will this work in the context of our smart contract? Let’s bring up our smart contract and see how it works:

  • First, we want to store a number in a variable which will let’s say, cost 45 units of gas
  • You add the number with itself, which costs 10 gas
  • Then you store the result again, which will cost 45 gas.

So, overall, you need 100 gas. What happens if you just set a gas limit of only 90 gas?

In this scenario, the miner will do 90 gas worth of computation and then charge the sender fees for the 90 gas which turns out to be (90 * 20 Gwei) = 0.0000018 ETH.

Also, the contract reverts back to its original state and the transaction is included in the blockchain.

Scenario #2: The Gas Limit is too high

Now, let’s look at the second scenario. What happens if the gas limit is too high?

After all, this makes sense right? Whatever gas is leftover, it gets refunded to the sender, right? Of course, that sounds like the way to go. However, in reality, it doesn’t really work like that.

Miners are limited by the block gas limit, which is around 6,700,000 gas. A basic transaction (simple transfer of ETH) has at least a gas requirement of 21,000 gas. Miners can only include transactions which add up to be less than or equal to the block gas limit.

Alright, now let’s do a thought experiment.

  • On one hand, we had transaction A, which is a simple transaction but has a gas limit of 42000 units of gas
  • On the other hand, we had two transactions B and C which are again simple transactions but have specified gas limits of 21000 units of gas.

 

If you are a miner, which transaction will be more profitable for you?

The first transaction, i.e. transaction A, will force you to refund a huge amount of unused gas.

Secondly, the transactions B and C will allow you to refund little to nothing back.

The second point makes more sense to them economically right?

This is precisely why having a bloated gas limit is not a sensible way to go. It is more reasonable to set a gas limit which is just a little higher than the required amount of gas for your transaction.

The following is the average gas limit chart.

High and Low Gas vs High and Low Fee

So, till now it must be clear to you that gas and ether are not one and the same. “Gas” is the name for a special unit used in Ethereum. It measures how much “work” an action or set of actions takes to perform: for example, to calculate one Keccak256 cryptographic hash it will take 30 gas each time a hash is calculated, plus a cost of 6 more gas for every 256 bits of data being hashed. Like we have mentioned several times before, Gas is the amount of computational power required while ether is the currency used to pay for that gas.

When the gas runs out, the miners will stop working on it because they won’t be able to earn more money. So, to establish the relationship between Fees and Gas:

  • Gas is the way that fees are calculated
  • The fees are paid in ether, and it is different from the gas
  • The gas cost is the amount of work that goes into something, like the number of hours of labour, whereas the gas price is like the hourly wage you pay for the work to be done. The combination of the two determines your total transaction fee.
  • If your gas price is too low, no one will process your transaction
  • If your gas price is fine but the gas cost of your transaction runs “over budget” the transaction fails but still goes into the blockchain, and you don’t get the money back for the work that the laborers did.

Basically, this makes sure that nothing runs forever, and that people will be careful about the code that they run. It keeps both miners and users safe from bad code.

Now with the knowledge of everything we have obtained so far, let’s go through certain gas and fees scenario or, as we like to call them, the “LOW-HIGH” scenario.

If an operation has LOW gas, then the miners won’t even pick it up because it doesn’t have enough gas to finish computation.

If an operation has LOW fees, then it might have just enough gas to cover it but still, the miners won’t be chomping at the bits to pick it up because an operation with low fees isn’t economically appealing for them.

If an operation has HIGH gas, then it means that the operation is bloated with a high gas limit and hence the miners will not pick it up.

If an operation has HIGH fees, then the miners know that they will make a lot of money from it and will be picking it up instantly.

The currently recommended gas prices for different types of transaction speeds, according to ethgasstation are:

Alright, with everything we know so far, let’s summarize whatever we have learnt to put the Fuel vs Fee debate to rest.

Fuel (Gas) Fee (Ether)
General Every single operation that you do in the EVM costs a certain amount of gas. The creator of the contract declares a certain amount of gas that is allocated to the contract beforehand Every single transaction in Ethereum has a user-specified gas price
Start of the Transaction The contract creator has to allocate enough gas to the contract to run the it The contract creator will have to lock up enough ether in the contract to compensate for the allotted gas
Consumption per Operation The gas that has been allocated will reduce as and when a single operation is executed It will be deferred until an unsuccessful or successful transaction
Unsuccessful Transaction The transaction is unsuccessful the moment the contract runs out of gas. In the case, the contract goes back to its original state automatically The entire ether that has been locked up is paid to the miner
Successful Transaction The transaction is executed and there is still some gas leftover The miners get paid the equivalent amount of ether for the gas that executes the contract

 

Gas Refund Scenarios

When it comes to solidity, there are two ways that can get gas refund back:

  • SUICIDE: This kills the smart contract and gets you back 24000 gas in return
  • SSTORE: Storage deletion, which gets you back 15000 gas.

So, if your contract is using up 14,000 gas and deletes a storage then you should get back (15000-14000) 1000 gas refunded to you right?

It isn’t that simple.

If that was the case, then miners will lose all incentive. After all, the miners shouldn’t pay you to do your computations right? So, how do you avoid scenarios like these?

Turns out…all that they needed to do was to put in a condition, and it goes something like this. Once a refund has been accumulated, it cannot exceed half the gas used up during the computation.

Let’s take an example to see how this will work.

We are going to use a smart contract which consumes 14000 gas and the gas limit that we have set for this contract is 20000 gas.

This smart contract also includes an SSTORAGE command.

So, how will this contract work out and how much gas can you get back as the contract creator?

Well, the gas limit is 20000 and the contract consumes 14000, which means that you are getting back 20000-14000 = 6000 units of unused gas.

Now, remember that the SSTORAGE command has also been used, so theoretically they should get back 15,000 gas as well. So, the user i.e. you, should get back 6000 + 15000 = 21000 gas! That’s more than the gas limit that you set in the first place! That is pretty absurd.

But, because of the condition that we have stated earlier, the amount of gas that has been used in the contract is 14,000 and since 15,000 > 14,000/2, the REFUND generated will be 14,000/2= 7000.

So, instead of 21000 gas, you get back 6000 + 7000 = 13000 units of gas instead.

If this seems a little confusing, let’s take another example of clarify it.

Suppose we have a contract which uses up 90,000 gas and it includes a SUICIDE function.

A SUICIDE function should give you 24,000 gas back which is < 90,000/2.

So, in this situation, since the condition is met, you will get back a gas refund of 24,000 + unused gas.

Solidity and Gas In Programming

For anyone who wants to learn how to make DAPPs (Decentralized Applications) or get into the ICO game, learning Solidity is an absolute must. Solidity was developed by Gavin Wood, Christian Reitwiessner, Alex Beregszaszi, Yoichi Hirai and several former Ethereum core contributors to enable writing smart contracts on blockchain platforms such as Ethereum.

Solidity is meant to be a purposefully slimmed down, loosely-typed language with a syntax very similar to JavaScript. You can check out the Solidity Docs right here.

Using Solidity you will be coding smart contracts which are going to be executed in the Ethereum Virtual Machine aka EVM. Ethereum developers mention a set amount of gas which is assigned to their contracts. Each line of the contract requires some amount of gas to execute. The gas limit should be enough for the contract to execute completely.

Having said that, let’s begin coding.

Remix – IDE

We are going to execute our codes on Remix. Click here to go on the Remix website. Remix is an in-browser environment where you can execute your smart contracts on a test blockchain. This was created by the Ethereum Foundation themselves so that you can start developing contracts, as and when you please.

#1 Hello World

//section 1

pragma solidity ^0.4.19;

contract myfirstcontract {

    string public greeting;

   address public owner;

event GreetingChanged(string oldGreeting, string newGreeting);

 

//section 2  

   function myfirstcontract(string _greeting) {

 

       greeting = _greeting;

       owner = msg.sender;

     }

//section 3  

   function setGreeting(string _greeting) {

       require(owner == msg.sender);

       GreetingChanged(greeting, _greeting);

       greeting = _greeting;

   }

}

Analyzing The Above Code

So, we have divided the smart contract into three sections. Let’s look at each of the section and see what’s going on in there.

Section 1

//section 1

pragma solidity ^0.4.19;

contract myfirstcontract {   

   string public greeting;

   address public owner; 

   event GreetingChanged(string oldGreeting, string newGreeting);

“pragma solidity ^0.4.19” shows that we are using the 0.4.19 version of the solidity. The “^” also makes sure that our program will execute on higher versions as well.

“contract myfirstcontract” declares our contract which we have named “myfirstcontract”.

After that, we are declaring a string called “greeting” which we will use to save our message. This string is a “public” string. We are also declaring a public variable named “owner” of type address to save the address of the owner of the contract.

The advantage of using a “public” variable is that it automatically gets a “getter” function assigned to them. A getter function helps access the value of a variable while a “setter” function allows you to modify the value.

After that, we have an event called “GreetingChanged”. This event makes sure that anytime there occurs any change in greeting, the change is broadcasted.

Section 2

//section 2  

   function myfirstcontract(string _greeting) {

       greeting = _greeting;

       owner = msg.sender;

   }

In this section, we are going to declare a constructor. The constructor, as you may have noticed, shares the same name as the contract. The job of the constructor is to initialize the variables during runtime. The constructor takes “_greeting” as a parameter and uses that to initialize “greeting”. At the same time, the address of the person who is sending the parameter is saved in the owner. Since the constructor executes only at the beginning of the runtime, the person whose address gets saved is the contract creator.

Section 3

//section 3  

  function setGreeting(string _greeting) {

       require(owner == msg.sender);

       GreetingChanged(greeting, _greeting);

       greeting = _greeting;

   }

In the third section, we have the setter function, which will help us modify the values kept in the variables. As a parameter, this function takes in the new greeting, in case a modification is required.

So, what is happening inside the function?

We want to introduce some access control to the program. This is why we are checking whether the one making the modification is the owner of the contract or not. As we will see later, if someone else tries to do a modification, the compiler will throw an exception and return an error.

So, if that condition is met, the GreetingChanged event is triggered and the value of “greeting” gets updated with “_greeting”.

Alright, so now let’s compile the program. Save your program and choose “myfirstcontract” here:

After that, click on “Deploy” to execute the contract. The moment you do that, notice what happens in the log.

You see that message?

It shows the execution was successful. Also, do you see that down arrow key next to the Debug button? Click on it and it will open up the details of the transactions:

Status: Shows that the transaction has succeeded

Transaction Hash: The unique hash of the transaction. It shows the transaction ID.

Contract Address: The address of the smart contract. Whenever a contract is successfully deployed, it gets assigned an address which sorta acts like the contracts ID.

From: The address of the owner of the contract that we have chosen

To: Shows that the constructor has generated the variables.

Gas: The upper limit of the gas that we have set beforehand

Transaction Cost: How much gas it cost to send the contract to the blockchain.

Execution Cost: How much gas it cost to execute the contract.

Hash: The hash of the transaction.

Input: This is the compiled solidity code that is actually read by the Ethereum Virtual Machine.

Decoded Input: The input given to the contract which is passed via the parameters.

Logs: Shows any events that the contract may have generated.

Value: Since the contract was given no Ether tokens by us, it shows 0 wei.

Ok, now we want you to focus on the right side of your screen. Do you see this?

Next, to the “Account” field you will see that the address has a little less than 100 Ether tokens. This shows that this much Ether was used to deploy the contract.

Click the tab under Deployed Contracts and it will reveal this:

In this:

  • “greeting” and “owner” are getter functions which have been created by default because of the variables were declared as “public”.
  • The “setGreeting” is a setter function where you can input the data.

Since “setGreeting” takes in a string parameter, you must input the data in double quotes. Quite like this:

Once you enter the data, press the “setGreeting” button:

There are two fields that we want you to focus on:

Decoded Input: Shows the input string that we have given.

Logs: Creates an event which shows that the value of “greeting” has changed.

Alright, now let’s click on the “greeting” button on the getter function:

It instantly gives you the value of the greeting variable.

When you check the logs you will see the following:

See the “decoded output” field and you will see “Hello World” there.

Similarly, just click on the “owner” button:

It shows the value of the address of the owner. Now when you check the logs:

The decoded output shows the address of the owner of the contract.

Now, let’s do something. Let’s choose some other address in the Account field:

When you change the address, try to get to enter a new string in the setter function, you will get the following message in the log:

This error comes because this fails the access control we put into our code. Remember this line of code:

require(owner == msg.sender);

This makes sure that no other address apart from the owner can change the data in the contract.

Criticism of Ethereum Gas. Is it Justified?

Even though the gas system has gotten praise for presenting a smoothly running mechanism which incentivizes the miners pretty positively, it has come under criticism lately for being a tad too expensive for developers and smart contract creators.

Regarding this, Danny Ryan did some interesting studies in his Hackernoon article.

Consider the following scenario:

When two numbers are added a million times in Ethereum it costs ~$26.55 in fees.

Danny Ryan compared that to a standard AWS system. He said that he can add two numbers a million times using python in 0.04 seconds, which going by the $0.0059 hourly Amazon EC2 rate costs $0.000000066.

This means that computation in Ethereum is 400 million times more expensive!

Based on his studies, this is the conclusion he made:

“To be fair, adding two numbers together 1 million times is a bit contrived. A well written contract would likely move such computational complexity off-chain and deal more with updating state in the contract. Storing vast amounts of data to the blockchain is also not an ordinary task. Depending on the task, a user would likely store a cryptographic reference (a hash) of the data on-chain and keep the rest of the data off-chain.

That said, we as developers need to be aware of these costs, and design dApps accordingly. We need to find the balance between on-chain and off-chain complexity, while still leveraging the decentralized capabilities of the blockchain.”

How To Cut Gas Costs For Dapps

As you can imagine, with skyrocketing gas costs, a huge priority for Dapps currently is gas cost cutting. Developers are using the following five methods to cut cost:

  • Bit-compaction
  • Batching
  • Separating writes to storage structs
  • uint256 and direct memory access
  • Assembly optimization

These techniques have been taken from this article by Zhichao Li.

Bit-compaction

Bit-compaction format for external function parameters helps cut gas costs because it minimizes the amount of input data sent to the Ethereum blockchain. Please note that it introduces certain small extra gas costs to unpack the data. However, the savings usually weigh out the extra costs.

Take the following code snippet for example:

pragma solidity ^0.4.21;
contract bitCompaction {
function oldExam(uint64 a, uint64 b, uint64 c, uint64 d) public {
}
function newExam(uint256 packed) public {
}
}
Its corresponding assembly code shows that the oldExam function incurs 4 `CALLDATALOAD` operations once it is called, and each `CALLDATALOAD` operation triggers one memory allocation operation in Ethereum, while the newExam function incurs only 1 instead. Note that the assembly code is too large for us to present here, but one can easily generate it by performing (for example) `solc — asm — optimize — optimize-runs 200 bitCompaction.sol`.

In the experiment, we have the following call data for each function:

oldExam call data: ([]uint8) (len=132 cap=132) {
00000000 3e f2 62 fd 00 00 00 00 00 00 00 00 00 00 00 00
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000020 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000040 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000060 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000080 00 00 00 01
}
newExam call data: ([]uint8) (len=36 cap=36) {
00000000 83 ba 6e 5a 00 00 00 00 00 00 00 01 00 00 00 00
00000010 00 00 00 01 00 00 00 00 00 00 00 01 00 00 00 00
00000020 00 00 00 01
}
As we can see, those uint64 parameters in the oldExam function are first converted to uint256 ones once being called. Gas costs for the above two are 22235 and 21816 respectively, meaning the newExam function saves 419 gas costs. The more scattered the parameters are, the more savings you cut by adopting the bit compaction method.

Batching

Batching cuts gas cost because it reduces common data processing. Take the following code snippet for example:

Old: func once(uint256 header, uint256 val…) x N
New: func batch(uint256 header, uint256[] val… x N)

Executing the old function N times processes the common `header` field N times, as well as calling the function N times. However, by batching, the function is called only one time and the common `header` field is processed only one time. Therefore, it saves gas costs by reducing `CALLDATALOAD`, memory allocation, and function call operations. The larger the N, the larger the savings by adopting the batching mechanism. The batching gas cost effectiveness of DEx.top is already published here.

Separating Writes to Storage struct

Separating writes to struct object that is defined in storage, cuts gas cost in many cases. Take the following code snippet for example:

pragma solidity ^0.4.21;
contract structWrite {
struct Object {
uint64 v1;
uint64 v2;
uint64 v3;
uint64 v4;
}
Object obj;
function StructWrite() public {
obj.v1 = 1;
obj.v2 = 1;
obj.v3 = 1;
obj.v4 = 1;
}
function oldExam(uint64 a, uint64 b) public {
uint a0; uint a1; uint a2; uint a3; uint a4; uint a5; uint a6;
uint b0; uint b1; uint b2; uint b3; uint b4; uint b5;
obj.v1 = a + b;
obj.v2 = a – b;
obj.v3 = a * b;
obj.v4 = a / (b + 1);
}
function setObject(uint64 v1, uint64 v2, uint64 v3, uint64 v4) private {
obj.v1 = v1;
obj.v2 = v2;
obj.v3 = v3;
obj.v4 = v4;
}
function newExam(uint64 a, uint64 b) public {
uint a0; uint a1; uint a2; uint a3; uint a4;
uint b0; uint b1; uint b2; uint b3;
setObject(a + b, a – b, a * b, a / (b + 1));
}
}
Once the optimize option is turned on, for the above example, SOLC compiles storage struct writes in such a way that the oldExam function would incur 1 EVM `SSTORE` operation (`SSTORE` is the most gas costly operation) for each of the struct field in Object since the current implementation of SOLC could not optimize the `SSTORE` operations when there is not enough stack space (there is stack space for only 16 local variables).

However, with the new approach, it has ample stack space such that the current compiler can optimize the struct accesses by performing, in total, only 1 `SSTORE` operation after merging writes to the struct. This can be easily verified against by looking at the corresponding assembly code. This is restricted to the current implementation of SOLC, and is subject to change in the future.

For the above example, the gas costs are 58140 and 27318 respectively, indicating a gas cost saving of 30822 for the newExam function. When the stack space is not enough, the more fields the struct has, the more gas cut you achieve if the new approach is leveraged.

uint256 and Direct Memory Access

Calculation unit in SOLC is uint256. Hence other types (e.g., uint8) require type conversions before calculations are applied. This incurs extra gas costs. Moreover, direct memory access is more GC-efficient than direct storage access, and more GC-efficient than struct pointer based access. These smaller tricks can be represented as:

uint8 data; => uint256 data;
uint256 val = storageData; => uint256 memoryData = storageData;
(N Times) uint256 val = memoryData;
uint64 val = obj.v1; => uint64 val = val1;

Assembly Optimization

When compiling your SOLC code, make sure to perform GC experiments with the SOLC `optimize — runs` option to figure out the best GC-efficient assembly code to run in EVM.

Optimization Gas Usage For Contracts

Let’s look at some factors that one should keep in mind for the optimal usage of gas consumption.

Contract Size

The first thing that you should keep an eye out for is the size of the smart contract. There are no two ways about it, the overall size of your smart contract is definitely going to play a part in the overall cost of your interaction with it. In order to make this interaction more optimal, you should be able to break the contract up into smaller separate contracts, which will decrease user’s gas costs when interacting.

Think about it like this.

If you have a Dapp which deals with fresh fruits and baking, then common sense dictates that you make a single contract which shares the common parts. However, what happens if the global fresh fruit market goes down and there is a lack of fruits everywhere? Does it make sense for users who simply want baked goods to pay for the fruits as well? In this case, it makes sense to break down the contract into a fresh contract and baking contract.

Global Variables(Storage)

Global variables are stored or persisted in a contract’s state on the blockchain. This is perhaps the most expensive operation in terms of gas for a transaction. It is therefore imperative to have the minimum memory footprint for your stored global variables. This is a good programming practice in all languages, but it is especially crucial in a constrained environment such as the ethereum blockchain. An instance of this would be using the expensive type string when you could use a uint to denote something.

string STATUS = ‘unknown status’; //This is really expensive
uint STATUS = 0; //This is a lot cheaper

Note: It is important to realize that a uint == uint256. Also, for whatever reason, a uint256 takes less gas to store than a uint8. So, if you are trying to optimize data types as you should, just realize this caveat.

Remove as much duplication within structs as you can. If you have member variables within structs that are storing the same value, remove the duplicates if you can without sacrificing security.

struct Game {
uint256 betAmount;
uint outcome;
uint status;
JediBet originator;
JediBet taker;
}

JediBet orig; // There is no reason to have these global vars
JediBet take; // when they are already in the Game struct

Tuning a Contract

We will now take a look at our Bet.sol contract in Remix. Open up Remix in your browser, create a new contract, and paste in the code from here. Put your cursor on line 142— at the generateBetOutcome method and take a look in the upper right hand corner of the editor. You will see a gas pump icon and an estimate for the gas as shown here.


This tool is invaluable for a quick look at your estimated gas for a method invocation, but it is just an estimate. For private methods such as this, you don’t have the luxury of calling it and seeing the gas usage from the debug logs.

If you want to see a closer estimate of how much the execution will cost, you can make it public and call it directly from remix. Note that this is nowhere near the Remix IDE’s estimated cost, but it could differ based on the state of the contract at the time of execution.

Conclusion

So there you have it. Everything that you need to know about the importance of gas in the Ethereum ecosystem.It really is the lifeblood of the whole ecosystem, and we are not exaggerating. Let us know what you think,

Leave A Reply

Your email address will not be published.