# Differences between EVM chains

* Transaction signing is incompatible
  * QTUM is based on Bitcoin and therefore requires Bitcoin transaction signing
    * EVM transactions are done with special opcodes in Bitcoin output scripts (OP\_CALL/OP\_CREATE)
  * Use [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) to sign transactions for use in eth\_sendRawTransaction
    * Currently, the library only supports sending 1 tx per block due to Bitcoin inputs being re-used so test your code to redo transactions if they are rejected with eth\_sendRawTransaction
      * This will be fixed in a future version
* Solidity
  * msg.value is denoted in satoshis, not wei, your dapp needs to handle this correctly
  * eth\_sign
    * uses a different message prefix than Ethereum: "\u0015Qtum Signed Message:\n" (equal to "\x15Qtum Signed Message:\n")
      * you will need to update your contracts to use this prefix
    * ecrecover won't recover a QTUM address from eth\_sign, you will need to implement [QIP6 - btc\_ecrecover](https://blog.qtum.org/qip-6-87e7a9743e14) in your contracts
      * [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) properly signs messages
* Sending coins with the creation of a contract will cause a loss of coins
  * This is a Qtum intentional deisgn decision and will not change
  * Janus will prevent this with eth\_sendTransaction but will permit it with eth\_sendRawTransaction
  * [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) will reject creating such a transaction
* Contract address generation differs from EVM chains
  * on EVM chains, the contract address is generated via a hash of the deployer address + the nonce
  * QTUM has no concept of a nonce because it is built on Bitcoin
    * instead the contract address is generated via a hash of the transaction which will always be different because the Bitcoin inputs will be different
    * so, if your app depends on a consistent contract address between deployments on different chains you need to pay special attention to this
    * For contract address generation code, see [generateContractAddress](https://github.com/earlgreytech/qtum-ethers/blob/main/src/lib/helpers/utils.ts)
* Account address generation differs from EVM chains
  * You really only need to worry about this if you need to use the same account address on different chains
  * [eth\_accounts](https://github.com/qtumproject/janus/blob/master/pkg/transformer/eth_accounts.go) and [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) will abstract this away from you
  * For account address generation code, see [computeAddress](https://github.com/earlgreytech/qtum-ethers/blob/main/src/lib/helpers/utils.ts)
* Block hash is computed differently from EVM chains
  * If you are generating the blockhash from the block header, it will be wrong
    * we plan to add a compatiblity layer in Janus to transparently serve the correct block when requesting an Ethereum block hash
      * this will eventually require hooking up Janus to a database to keep a map of hash(block header) => QTUM block hash
* Remix
  * Debug calls are not supported so you will not be able to do any debugging in Remix
  * You can use Remix with Janus or [(Alpha) QTUM Metamask fork](https://github.com/earlgreytech/metamask-extension/releases)
* It is possible for a QTUM transaction to have more than one EVM transaction in it
  * this is because QTUM does EVM transactions inside Bitcoin outputs which there can be multiple of
  * Janus and [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) will not generate such a transaction
  * Janus will try and work around such a transaction when requesting information about the transaction
    * but it is not possible to map to the EVM model perfectly so there will always be some data missing for these transactions
* QTUM is proof of stake and requires coins to be mature (older than 2000 blocks) to be used in a transaction
  * this includes staking rewards, gas refunds and block rewards on your local regtest environment
    * a gas refund is an output generated by the miner for every EVM transaction in the same block as the EVM transaction takes place in for unused gas
  * Janus will try to use mature coins first and will fall back to immature coins if there are no mature coins left
    * this can result in transactions being rejected
  * [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) will not use immature coins for transactions, but if you end up using high gas limits for your transactions you could quickly run out of usable coins
    * if there are no mature coins, the transaction will fail locally
* Bitcoin input scripts
  * Bitcoin has many different types of scripts
    * For a detailed primer on this topic see [A breakdown of Bitcoin "standard" script types (crazy long)](https://www.reddit.com/r/Bitcoin/comments/jmiko9/a_breakdown_of_bitcoin_standard_script_types/)
  * [eth\_sendTransaction](https://github.com/qtumproject/janus/blob/master/pkg/transformer/eth_sendTransaction.go) delegates transaction signing to QTUM so most input scripts should be supported
  * [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) deals with signing transactions locally and only supports Pay to public key hash (P2PKH) scripts, other script types will be ignored and not selected.
    * This can result in your spendable balance being lower than your actual balance.
    * Support for Pay to public key (P2PK) input scripts is on the roadmap
* [eth\_estimateGas](https://github.com/qtumproject/janus/blob/master/pkg/transformer/eth_estimateGas.go)
  * Gas estimation on QTUM is not perfect, so a buffer of 10% is added in Janus
  * Gas will be refunded in the block that your transaction is mined
    * Keep in mind that to re-use this gas refund, you must wait 2000 blocks
* [eth\_sendTransaction](https://github.com/qtumproject/janus/blob/master/pkg/transformer/eth_sendTransaction.go)
  * When trying to send all your QTUM Balance in a transaction, in EVM you would do value = total - (gas limit \* gas price)
  * Since QTUM uses Bitcoin transactions, the cost of a transaction differs based on how many bytes are in the transaction
    * This means if you have many inputs in a transaction, it will cost more to send
  * There is no easy way to send your entire QTUM balance in a single transaction with Janus
    * However, [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) supports this via value = total - (gas limit \* gas price)
    * Adding this to Janus is on the roadmap
* Since QTUM runs on Bitcoin, QTUM has the concept of [dust](https://en.bitcoinwiki.org/wiki/Cryptocurrency_dust)
  * Janus delegates transaction signing to QTUM so QTUM will handle dealing with dust
  * [(Beta) QTUM ethers-js library](https://github.com/earlgreytech/qtum-ethers) currently uses dust, but at some point will prevent spending dust by default with a semver change
* On a transfer of Qtum to a Qtum address, there is no receipt generated for such a transfer
* When converting from WEI -> QTUM, precision is lost due to QTUM's smallest demonination being 1 satoshi.
  * 1 satoshi = 0.00000001 QTUM = 10000000000 wei
* QTUM's minimum gas price is 40 satoshi
  * When specifying a gas price in wei lower than that, the minimum gas price will be used (40 satoshi)
  * With the minimum fee per byte being 4 satoshi
* QTUM will reject transactions with very large fees (to prevent accidents)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.qtum.info/qtum-documentation/web3/differences-between-evm-chains.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
