Skip to main content

Overview

Address: 0x0000000000000000000000000000000000000002 Introduced: Frontier The SHA256 precompile implements the SHA-256 cryptographic hash function, producing a 32-byte hash of arbitrary input data. SHA-256 is part of the SHA-2 family standardized by NIST and is widely used in Bitcoin and other systems. This precompile enables Ethereum contracts to verify Bitcoin SPV proofs, validate SHA-256 based signatures, and interact with systems that use SHA-256 hashing.

Gas Cost

Formula: 60 + 12 * ceil(input_length / 32)
  • Base cost: 60 gas
  • Per-word cost: 12 gas per 32-byte word
  • Partial words round up
Examples:
  • 0 bytes: 60 gas
  • 32 bytes: 72 gas (60 + 12*1)
  • 33 bytes: 84 gas (60 + 12*2)
  • 64 bytes: 84 gas (60 + 12*2)

Input Format

Accepts arbitrary-length byte array. No restrictions on input size.

Output Format

Offset | Length | Description
-------|--------|-------------
0      | 32     | SHA-256 hash of input
Total output length: 32 bytes (256 bits)

Usage Example

import { execute, PrecompileAddress } from '@tevm/voltaire/precompiles';
import { Hardfork } from '@tevm/voltaire/primitives/Hardfork';

// Hash some data
const input = new TextEncoder().encode("Hello, Ethereum!");

// Calculate required gas
const words = Math.ceil(input.length / 32);
const gasNeeded = 60n + 12n * BigInt(words);

// Execute precompile
const result = execute(
  PrecompileAddress.SHA256,
  input,
  gasNeeded,
  Hardfork.CANCUN
);

if (result.success) {
  console.log('SHA-256 hash:', result.output);
  console.log('Gas used:', result.gasUsed);
} else {
  console.error('Error:', result.error);
}

Error Conditions

  • Out of gas (insufficient for 60 + 12 * ceil(len/32))

Use Cases

  • Bitcoin SPV proofs: Verify Bitcoin block headers and transactions in Ethereum contracts
  • Cross-chain bridges: Validate proofs from SHA-256 based blockchains
  • Legacy system integration: Interface with systems using SHA-256 hashing
  • Document verification: Hash and verify document integrity
  • Merkle trees: Build SHA-256 based Merkle trees for data verification

Implementation Details

  • Zig: Uses hardware-accelerated SHA-256 implementation from crypto module
  • TypeScript: Wraps SHA256.hash from crypto module
  • Integration: Standalone, no dependencies on other primitives
  • Performance: Optimized for throughput with SIMD instructions where available

Test Vectors

import * as Hex from '@tevm/voltaire/primitives/Hex';
import { Bytes32 } from '@tevm/voltaire/primitives/Bytes32';

// Test 1: Empty input
const input1 = new Uint8Array(0);
// Expected: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
const expected1 = Bytes32('0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');

// Test 2: "abc"
const input2 = new TextEncoder().encode("abc");
// Expected: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
const expected2 = Hash('0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');

// Test 3: Large input (1000 bytes of zeros)
const input3 = Hex('0x' + '00'.repeat(1000));
// Gas: 60 + 12 * ceil(1000/32) = 60 + 12*32 = 444

Bitcoin Integration

Bitcoin uses double SHA-256 for block hashes. To verify Bitcoin blocks in Ethereum:
// Bitcoin block hash = SHA256(SHA256(header))
const firstHash = executeSHA256(blockHeader);
const blockHash = executeSHA256(firstHash.output);

Performance Considerations

SHA-256 is more expensive than Keccak256 on Ethereum (60 vs 30 base gas). Use Keccak256 for Ethereum-native hashing when possible. Gas costs favor larger batches:
  • Per-byte cost: ~0.375 gas/byte
  • Prefer hashing larger inputs over multiple small ones

References

Specifications