Skip to content

Ethereum Anchoring

PrimeStamp supports direct Ethereum anchoring by embedding document hashes in transaction calldata or through a dedicated timestamping smart contract. Ethereum provides strong decentralization guarantees and is the most widely used smart contract platform.

How It Works

PrimeStamp offers two anchoring modes on Ethereum:

Calldata Embedding

The simplest approach sends a self-transfer (zero-value transaction) with the document hash embedded in the calldata field. The transaction data is prefixed with PRIMESTAMP: followed by the raw hash bytes:

calldata = b"PRIMESTAMP:" + document_hash

This approach requires no smart contract deployment and works immediately on any EVM-compatible chain.

Smart Contract

For organizations that need structured on-chain records, PrimeStamp supports calling a custom timestamping contract. The contract stores hashes and emits events that can be indexed by off-chain services:

function timestamp(bytes32 hash) external {
    // Store hash with block timestamp
}

Trust Weight

Ethereum anchors carry a trust weight of 4:

  • Large proof-of-stake validator set (~1 million validators)
  • Second-largest blockchain by market capitalization
  • Extensive tooling and block explorer support for verification
  • ~12 block confirmation provides strong finality

Configuration

from primestamp.anchors.adapters import EthereumAnchorAdapter

adapter = EthereumAnchorAdapter(
    rpc_url="https://mainnet.infura.io/v3/YOUR_PROJECT_ID",
    private_key="0xYOUR_PRIVATE_KEY",
    contract_address=None,  # None = calldata mode, or set contract address
    chain_id=1,             # 1 = Mainnet, 5 = Goerli, 11155111 = Sepolia
    gas_price_gwei=None,    # None = auto-detect from network
)

Required Dependencies

pip install "primestamp[anchors]"
# or directly:
pip install web3

Submitting a Hash

import hashlib

document = b"Quarterly financial report Q4 2025"
document_hash = hashlib.sha3_256(document).digest()

result = await adapter.submit(document_hash)

if result.success:
    print(f"TX hash: {result.tx_hash}")
    print(f"Status: {result.status}")      # SUBMITTED
    print(f"From: {result.proof_data['from']}")
else:
    print(f"Error: {result.error}")

Checking Confirmation

Ethereum uses 12 block confirmations as the standard threshold for finality:

status = await adapter.get_status(tx_hash)

if status.status == AnchorStatus.CONFIRMED:
    print(f"Block: {status.block_height}")
    print(f"Timestamp: {status.timestamp}")
    print(f"Gas used: {status.proof_data['gas_used']}")
    print(f"Confirmations: {status.proof_data['confirmations']}")

Verification

Verification checks that the document hash appears in the calldata of the specified transaction and that the transaction has sufficient confirmations:

is_valid = await adapter.verify(document_hash, proof)
# Checks:
# 1. Transaction exists on-chain
# 2. document_hash is present in tx.input (calldata)
# 3. Transaction has >= 12 confirmations

Gas Costs

The cost of an Ethereum anchor depends on the gas price at submission time:

Component Gas Units Notes
Base transaction 21,000 Minimum for any transaction
Calldata (zero bytes) 4 per byte Cheaper than non-zero
Calldata (non-zero bytes) 16 per byte Hash bytes are typically non-zero
Total (calldata mode) ~21,500 21,000 base + ~500 for 32-byte hash + prefix
Total (contract mode) ~50,000 Includes SSTORE and event emission

At typical gas prices:

Gas Price Calldata Cost Contract Cost
10 gwei ~$0.50 ~$1.20
30 gwei ~$1.50 ~$3.50
100 gwei ~$5.00 ~$12.00

For cost-sensitive applications, consider using an L2 chain like Polygon or Arbitrum for day-to-day stamping and reserving Ethereum mainnet for high-value documents.

Confirmation Timing

Phase Duration
Transaction broadcast 1-5 seconds
First confirmation (1 block) ~12 seconds
Standard confirmation (12 blocks) ~2.5 minutes
Conservative confirmation (32 blocks) ~6.5 minutes

Using with Presets

The archival and maximum presets include Ethereum anchoring:

from primestamp import StampEngine, KeyPair

engine = StampEngine(key_pair=KeyPair.generate())
stamp = engine.create_stamp(content, preset="archival")
# Anchors to: Bitcoin + Ethereum + RFC 3161

CLI Usage

# Stamp with Ethereum anchoring
primestamp stamp document.pdf --anchor ethereum

# Check transaction status
primestamp verify document.pdf --check-anchors

# Estimate gas cost before stamping
primestamp stamp --estimate-cost --anchor ethereum

Testnet Usage

For development and testing, use Sepolia:

adapter = EthereumAnchorAdapter(
    rpc_url="https://sepolia.infura.io/v3/YOUR_PROJECT_ID",
    private_key="0xTEST_PRIVATE_KEY",
    chain_id=11155111,  # Sepolia
)

Sepolia ETH can be obtained from public faucets for free.