A smart contract development business have its costs come from the transactions of smart contracts; the gas consumption has a direct impact on the company’s costs structure. Writing contracts in an energy-saving way are essential. This article will analyze some of the factors that affect gas consumption in smart contracts. Outlining what is the most expensive instruction and uses it with caution. Gas consumption can refer to the following two tables:

The gas used in Table 1 is the consumed gas. If it is displayed as FORMULA, it means it is not a fixed value, and please refer to the description on the right. Since we usually use Solidity to develop, we may not be able to correspond to the instructions in Table 1 above directly. In this case, we can refer to Table 2 and find some extra instructions. The following is a list of behaviors and instructions that consume more gas:

Create Contract

Corresponding to CREATE and CODECOPY two instructions. Creating another empty contract in the contract consumes 42,901 gas (64,173 gas total). If the direct deployment of a blank contract, a total of 68,653 gas. If you include implementation, there may be hundreds of thousands or even millions of gas. It should be the most expensive of all the instructions. Gas consumption can be significant if multiple contract instances are created. Avoid using contract as a data storage:

Bad

1
2
3
4
5
6
7
8
9
contract User {
uint256 public amount;
bool public isAdmin;

function User(uint256 _amount, bool _isAdmin) {
amount = _amount;
isAdmin = _isAdmin;
}
}

Good

1
2
3
4
contract MyContract {
mapping(address => uint256) amount;
mapping(address => bool) isAdmin;
}

or

1
2
3
4
5
6
7
8
contract MyContract {
struct {
uint256 amount;
bool isAdmin;
}

mapping(address => User) users;
}

Storage

Corresponds to the SSTORE instruction. It takes 20,000 gas to store new data. It takes 5000 gas to modify the data. One exception is to change a variable that is not zero to zero. We will discuss this later. Avoid duplicate writes, try to write at the end as much as possible.:

Bad

1
2
3
4
5
6
uint256 public count;
// ...
for (uint256 i = 0; i < 10; ++i) {
// ...
++count;
}

Good

1
2
3
4
for (uint256 i = 0; i < 10; ++i) {
// ...
}
count += 10;

Transaction Input Data

The basic gas for the transaction is 21,000. The input data is 68 gas per byte, and 4 gas if the byte is 0x00. For example, gas is 68 * 4 = 272 if data is 0x0dbe671f; It’s 68 * 1 + 4 * 3= 80 if 0x0000001f. Since all the parameters are 32 bytes, the gas consumption is minimal when the parameter is zero. It will be 32 * 4 = 128. The maximum value is as follows:

1
2
n: The number of bytes of the parameter
n * 68 + ( 32 - n ) * 4

For example, the maximum gas consumption of bytes32 is 2,176. address is 20 bytes so that it is 1,408.

Transfer

call, send and transfer functions correspond to the CALL instruction. The basic consumption is 7,400 gas. In fact, consumption will be nearly 7,600. It is noteworthy that if the transfer to a never seen address, will be an extra 25,000 gas.

No extra consumption

1
2
3
function withdraw(uint256 amount) {
msg.sender.transfer(amount);
}

There may be extra consumption

1
2
3
function withdrawTo(uint256 amount, address receiver) {
receiver.transfer(amount);
}

ecrecover

Corresponding to the CALL instruction. This function will consume 3700 gas.

Call an External Contract

Calling an external contract executes the EXTCODESIZE and CALL instructions. The basic consumption of 1400 gas. It is not recommended to split multiple contracts unless necessary. Multiple inheritances can be used to manage the code.

Event

Corresponds to the LOG1 instruction. An event with no parameters is 750 gas. Each additional parameter theoretically will increase by 256 gas, but in fact, it will be more.

Hash

There are several built-in hash functions in smart contracts that you can use: keccak256, sha256 and ripemd160. The more parameters, the more gas consumed. Gas consumption: ripemd160 > sha256 > keccak256. So if there is no other purpose, it is recommended to use keccak256.

Other sections have less impact but can still be optimized. We’ll discuss them later. Last but not least, maybe some people do not know, remember to turn on the compiler optimization options.

Further Reading

Next Post: Solidity Gas Optimizations - Function Name