> ## Documentation Index
> Fetch the complete documentation index at: https://docs.quantumapi.io/llms.txt
> Use this file to discover all available pages before exploring further.

# QVM vs EVM

> What's the same and what's different between Quantum Chain's QVM and Ethereum's EVM, and how to migrate.

## 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.

<Tip>
  If you only deploy contracts and route transactions through Qustody, the signing primitive is handled for you. The migration is largely a no-op.
</Tip>

## 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 namespaces** — `eth_*`, `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

| Area                                          | EVM (Ethereum)               | QVM (Quantum Chain)                                                                                                          |
| --------------------------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Transaction signature algorithm               | secp256k1 ECDSA              | Post-quantum signature scheme                                                                                                |
| Signature size                                | 65 bytes (`v`, `r`, `s`)     | \~3 293 bytes                                                                                                                |
| Public key in transaction                     | Recovered from the signature | Carried alongside the signature, \~1 952 bytes                                                                               |
| Transaction RLP tail                          | `…, v, r, s`                 | `…, signature, publicKey`                                                                                                    |
| Sender recovery                               | `ecrecover(digest, v, r, s)` | Read the `publicKey` field, hash it: `Keccak256(publicKey)[12:32]`                                                           |
| Precompile `0x01` (`ecrecover`)               | secp256k1 recovery           | **Removed**                                                                                                                  |
| Precompile `0x0b`                             | N/A                          | **New** — verifies a post-quantum signature given `(digest, publicKey, signature)`                                           |
| HD wallets (BIP-32 / BIP-44)                  | Supported                    | **Not 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) | Supported                    | **Not supported** — they only sign secp256k1. Use Qustody, Clef, or a quantum-aware wallet.                                  |
| EIP-712 typed-data signing                    | Standard                     | Same digest construction; verifying contracts must call `0x0b` instead of `ecrecover`.                                       |
| EIP-1271 contract signatures                  | Standard                     | Same interface; the inner verification must call `0x0b`.                                                                     |
| Cross-chain bridges using `ecrecover`         | Work as designed             | **Will fail** without contract changes.                                                                                      |
| Account abstraction (EIP-4337)                | Works                        | Works, but `validateUserOp` must call `0x0b` instead of `ecrecover`.                                                         |

## Migration checklist

<Steps>
  <Step title="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.

    ```bash theme={null}
    rg -n 'ecrecover|ECDSA\.recover' contracts/
    ```
  </Step>

  <Step title="Replace ecrecover with the 0x0b precompile">
    See the [drop-in helper](#drop-in-ecrecover-replacement) 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.
  </Step>

  <Step title="Update key generation">
    Use the project's `keygenerator` binary or the equivalent SDK function (see [Accounts and keys](/quantum-chain/accounts-and-keys)). Do not feed Ethereum mnemonics into BIP-32 derivation — the resulting bytes are not valid Quantum Chain keys.
  </Step>

  <Step title="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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="Smoke-test on devnet">
    Spin up the [development network](/guides/configure-a-development-network) and replay your contract suite end-to-end before promoting to mainnet.
  </Step>
</Steps>

## 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.

```solidity theme={null}
// 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:

```solidity theme={null}
// 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

<Warning>
  **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)`.
</Warning>

<Warning>
  **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.
</Warning>

<Note>
  **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.
</Note>

## Related

<CardGroup cols={2}>
  <Card title="Quantum Chain overview" icon="circle-info" href="/quantum-chain/overview">
    Network properties, components, and high-level architecture.
  </Card>

  <Card title="Accounts and keys" icon="key" href="/quantum-chain/accounts-and-keys">
    Generate and manage post-quantum keypairs.
  </Card>

  <Card title="Signing transactions" icon="pen-nib" href="/quantum-chain/signing-transactions">
    Three signing models: local keystore, Clef, Qustody.
  </Card>

  <Card title="Quantum safety" icon="shield-halved" href="/concepts/quantum-safety">
    Why post-quantum cryptography, and what it protects.
  </Card>
</CardGroup>
