Skip to main content

TL;DR

The Quantum Virtual Machine (QVM) is the execution layer of Quantum Chain. It runs the same bytecode, opcodes, and gas accounting as upstream Ethereum, but the cryptographic primitives that authorize transactions and recover senders are post-quantum. Most contracts and tooling work unchanged. Anything that relied on ecrecover or secp256k1-derived addresses needs migration.
If you only deploy contracts and route transactions through Qustody, the signing primitive is handled for you. The migration is largely a no-op.

What’s identical

  • Bytecode and opcodes — Berlin, London hard fork sets. Solidity and Vyper produce the same artifacts.
  • Gas table — gas costs per opcode are unchanged.
  • Address format — 20 bytes, derived as Keccak256(publicKey)[12:32]. The formula is the same; only the public key shape changes.
  • Toolchain — Hardhat, Foundry, ethers.js, viem, web3.py compile and ABI-encode the same way. Read calls and contract interactions work without modification.
  • Block, receipt, log, and event schemas — identical.
  • JSON-RPC namespaceseth_*, net_*, web3_*, debug_*, txpool_*, plus the qc_* alias.
  • Transaction envelopes — legacy, EIP-2930, and EIP-1559 are all supported.
  • Standard precompiles at addresses 0x02 through 0x0a: SHA-256, RIPEMD-160, identity, modexp, BN-256 add/mul/pairing, blake2f.
  • Consensus — Clique Proof-of-Authority on mainnet today.

What’s different

AreaEVM (Ethereum)QVM (Quantum Chain)
Transaction signature algorithmsecp256k1 ECDSAPost-quantum signature scheme
Signature size65 bytes (v, r, s)~3 293 bytes
Public key in transactionRecovered from the signatureCarried alongside the signature, ~1 952 bytes
Transaction RLP tail…, v, r, s…, signature, publicKey
Sender recoveryecrecover(digest, v, r, s)Read the publicKey field, hash it: Keccak256(publicKey)[12:32]
Precompile 0x01 (ecrecover)secp256k1 recoveryRemoved
Precompile 0x0bN/ANew — verifies a post-quantum signature given (digest, publicKey, signature)
HD wallets (BIP-32 / BIP-44)SupportedNot applicable — post-quantum keys do not fit the BIP-32 derivation algebra. Use the project’s mnemonic-to-keypair tool.
Hardware wallets (Ledger ETH app, Trezor ETH)SupportedNot supported — they only sign secp256k1. Use Qustody, Clef, or a quantum-aware wallet.
EIP-712 typed-data signingStandardSame digest construction; verifying contracts must call 0x0b instead of ecrecover.
EIP-1271 contract signaturesStandardSame interface; the inner verification must call 0x0b.
Cross-chain bridges using ecrecoverWork as designedWill fail without contract changes.
Account abstraction (EIP-4337)WorksWorks, but validateUserOp must call 0x0b instead of ecrecover.

Migration checklist

1

Audit your contracts

Search your codebase for ecrecover and any library that calls it: OpenZeppelin’s ECDSA.sol, EIP-712 verification helpers, multisig wallets, meta-transaction relayers, EIP-2612 permit code, EIP-4337 account-abstraction validators. Each call site needs to be replaced with a call to the 0x0b precompile.
rg -n 'ecrecover|ECDSA\.recover' contracts/
2

Replace ecrecover with the 0x0b precompile

See the drop-in helper below. Update every verification path to pass (digest, publicKey, signature) instead of (digest, v, r, s). Off-chain code must learn to send the publicKey alongside the signature.
3

Update key generation

Use the project’s keygenerator binary or the equivalent SDK function (see Accounts and keys). Do not feed Ethereum mnemonics into BIP-32 derivation — the resulting bytes are not valid Quantum Chain keys.
4

Update wallet integrations

Standard MetaMask, Ledger ETH app, and Trezor ETH paths produce ECDSA keys and will not work. Integrate via Qustody, Clef, or a custom wallet that supports the post-quantum scheme.
5

Re-test EIP-712 / EIP-1271 flows

Anything that verifies a user signature on-chain — permit, meta-transactions, multisig, account abstraction — must be re-pointed at the 0x0b precompile.
6

Re-budget gas

Transaction-level signature verification is more expensive than ECDSA, and the post-quantum signature is larger, so calldata costs are higher. Calls to the 0x0b precompile have a fixed gas cost defined in the genesis config. Re-run gas snapshots before mainnet migration.
7

Update RPC clients

ethers.js, viem, and web3.py work for read calls and contract interactions. They cannot produce a valid Quantum Chain signature on their own — defer signing to Qustody, Clef, or a quantum-aware library.
8

Smoke-test on devnet

Spin up the development network and replay your contract suite end-to-end before promoting to mainnet.

Drop-in ecrecover replacement

Solidity helper that calls the 0x0b precompile and returns the recovered address, mirroring the shape of the old ecrecover. Sizes are illustrative; check the genesis config for the canonical values used on your network.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

library QuantumSig {
    address constant PQ_VERIFY = address(0x0b);

    /// @notice Verify a post-quantum signature and return the signer address.
    /// @param digest    The 32-byte Keccak-256 digest that was signed.
    /// @param publicKey The signer's post-quantum public key.
    /// @param signature The post-quantum signature over `digest`.
    /// @return signer   The 20-byte address derived from `publicKey`, or 0x0 on failure.
    function recover(
        bytes32 digest,
        bytes calldata publicKey,
        bytes calldata signature
    ) internal view returns (address signer) {
        bytes memory input = abi.encodePacked(digest, publicKey, signature);
        (bool ok, bytes memory out) = PQ_VERIFY.staticcall(input);
        if (!ok || out.length != 32) {
            return address(0);
        }
        // The precompile returns Keccak256(publicKey) padded to 32 bytes;
        // the address is the low 20 bytes.
        signer = address(uint160(uint256(bytes32(out))));
    }
}
Usage replacing a classic ecrecover call:
// Before (EVM):
// address signer = ecrecover(digest, v, r, s);

// After (QVM):
address signer = QuantumSig.recover(digest, publicKey, signature);
require(signer == expected, "bad signature");

Where this matters most

Multisig contracts (Gnosis Safe and similar) that verify owner signatures via ecrecover will accept zero valid signatures on QVM. They need a fork that points at 0x0b and accepts (publicKey, signature) pairs in place of (v, r, s).
Cross-chain bridges that prove a signed message came from a specific Ethereum address will not validate post-quantum signatures. Either deploy a QVM-aware verifier on the destination chain or proxy the signing through a service that produces both signature types.
EIP-2612 permit workflows must be updated. The off-chain code that produces the signature and the on-chain permit() function that verifies it both depend on ecrecover. Expect to fork your token contracts.

Quantum Chain overview

Network properties, components, and high-level architecture.

Accounts and keys

Generate and manage post-quantum keypairs.

Signing transactions

Three signing models: local keystore, Clef, Qustody.

Quantum safety

Why post-quantum cryptography, and what it protects.