[Ethereum] Gas cost of a sha256 hash

gashash

I'm confused about the cost of the sha256 function, because my understanding of the cost from the yellow paper ( https://ethereum.github.io/yellowpaper/paper.pdf (Appendix E. Precompiled Contracts) ) doesn't match my experiments of executing the sha256 hash function in Remix.

Here's my understanding of how much sha256 should cost for a 'word' (a 256-bit input):

From the yellow paper:

We define Ξ_{SHA256} as a precompiled contract implementing the SHA2-256 hash function. Its gas usage is dependent on the input data size, a factor rounded up to the nearest number of words.

The gas requirement (g_r) is stated as:

g_r = 60 + ( 12 * ( |I_d| / 32􏰛) )

(where I've edited the notation to look nicer in markdown without latex).

Elsewhere in the paper, it defines I_d as:

I_d, the byte array that is the input data to this execution; if the execution agent is a transaction, this would be the transaction data.

So my interpretation of gas cost for a word of 256-bits (32-bytes) is:

g_r = 60 + ( 12 * 32 / 32 ) = 60 + 12 = 72 gas

However:

I've explored the gas costs of the following simple function in Remix:

function hash() public pure returns (uint256 a) {
    a = 1234;
    a = uint256(sha256(abi.encodePacked(a)));
}

This has a transaction cost of 22789 gas of which the execution cost is 1517 gas.

Now, some of this will be extraneous storage costs to store a on the stack (and other stuff).

'Commenting out' the hashing line (// a = uint256(sha256(abi.encodePacked(a)));), for a very rough comparison, gives a transaction cost of 21486 gas of which the execution cost is 214 gas.

So a very approx. experimental cost of sha256 appears to be 1517 - 214 = 1303 gas. I'm surprised at how high this cost is (given my understanding that sha256 should be just 72 gas).

Any help would be appreciated in understanding the actual cost of sha256 🙂

Best Answer

The Yellow paper only stablishes costs for opcodes of the EVM at a low level. The solidity compiler have to generate extra code to accomodate to the source code written at a high level.

Some of the details the compiler hides from user

  • abi.encodePacked converts its parameters to a byte sequence in memory. It has to allocate memory and copy its parameters there.
  • sha256 is a precompiled contract. It has to make the call to the precompiled contract, check the result and copy the output. Making a contract call is 700 gas.

Another thing to consider is that the compiler by default generates unoptimized code and it can have many redundancies.

Related Topic