Compatibility, measured
A GPU-secured network for Ethereum-compatible applications and verifiable computation. Compatibility is a product deliverable here, not a sentence: every row below is a test that ran against the devnet from the repository (tools/reference-apps/compat/run.mjs), with its evidence, and a row that could not run says so and why. Devnet, no value.
Last run: 2026-10-08 16:24 UTC on igneum-devnet-4 (chain id 4465). 2 passed, 0 failed, 18 untested. Sender 0x27C433aE…, contracts compiled with solc 0.8.28+commit.7893614a.Emscripten.clang.
+Last run: 2026-10-08 16:34 UTC on igneum-devnet-4 (chain id 4465). 20 passed, 0 failed, 0 untested. Sender 0x27C433aE…, contracts compiled with solc 0.8.28+commit.7893614a.Emscripten.clang.
Three boundaries hold for everything on this page: proven execution is not finality; EVM compatibility is not Ethereum security; ZK is not privacy. The four words included, executed, proven and finalised are defined on /receipt.
Representative contracts
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| an ERC-20 deploys (CREATE address as Ethereum computes it, code at the address) | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| ERC-20 transfer: balances move, the Transfer log decodes, eth_call reads the new balance | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| ERC-20 approve then transferFrom by a spender (the sender approves itself as spender): allowance consumed, logs decode | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| a probe contract deploys (counter, block context reader, revert, out-of-gas loop, CREATE2) | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| a counter increments twice and reads 2 (state persists across chain blocks) | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| an ERC-20 deploys (CREATE address as Ethereum computes it, code at the address) | passed | at 0xb2495fd85f54d73d7a13059a8e61956b67ad7aed, block 739, gas 436751 of 639078 estimated | tx 0x8fd280cb…a5b9, address 0xb2495fd85f54d73d7a13059a8e61956b67ad7aed, block 739, gasUsed 436751, estimated 639078 |
| ERC-20 transfer: balances move, the Transfer log decodes, eth_call reads the new balance | passed | 5 CTT to 0x00000000, log decoded, balance read | tx 0xe787770a…25fb, block 742 |
| ERC-20 approve then transferFrom by a spender (the sender approves itself as spender): allowance consumed, logs decode | passed | allowance 3 then 1 after transferFrom of 2 | approve 0xfc7a3a64…5d24, transferFrom 0x6c0a22dc…ef22 |
| a probe contract deploys (counter, block context reader, revert, out-of-gas loop, CREATE2) | passed | at 0x3efc60794d574627eb5cb4eca77d96735dac4c42 | tx 0x551c2403…8e15, address 0x3efc60794d574627eb5cb4eca77d96735dac4c42, block 751 |
| a counter increments twice and reads 2 (state persists across chain blocks) | passed | count 2 after blocks 753 and 755 | first 0xfaf85576…75a1, second 0x97ca4151…19c8 |
Wallet fee estimation
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| eth_gasPrice, eth_maxPriorityFeePerGas and eth_feeHistory answer in Ethereum's shapes | passed | gasPrice 10101 gwei, priority 1 gwei, feeHistory 5 base fees | gasPrice 0x92fd2845200, maxPriorityFeePerGas 0x3b9aca00 |
| a plain transfer: eth_estimateGas against the receipt's gasUsed (the quote folds proving gas; both above Ethereum's 21,000) | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| a contract call: eth_estimateGas against gasUsed (a wallet that quotes from the node is covered) | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| the documented difference: a transfer sent with a local 21,000 gas limit (Ethereum's intrinsic cost) instead of the node's quote | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| eth_gasPrice, eth_maxPriorityFeePerGas and eth_feeHistory answer in Ethereum's shapes | passed | gasPrice 196.130804856 gwei, priority 1 gwei, feeHistory 5 base fees | gasPrice 0x2daa4e9478, maxPriorityFeePerGas 0x3b9aca00 |
| a plain transfer: eth_estimateGas against the receipt's gasUsed (the quote folds proving gas; both above Ethereum's 21,000) | passed | estimated 59650, used 21000 (35% of the estimate); Ethereum's figure is 21,000 | tx 0x99c4dc1a…cad0, estimated 59650, gasUsed 21000, ethereum 21000 |
| a contract call: eth_estimateGas against gasUsed (a wallet that quotes from the node is covered) | passed | estimated 134366, used 26371 | tx 0xeb8bafa3…bee4, estimated 134366, gasUsed 26371 |
| the documented difference: a transfer sent with a local 21,000 gas limit (Ethereum's intrinsic cost) instead of the node's quote | passed | the node accepted it and it succeeded with gasUsed 21000: a wallet with a hard-coded 21,000 works | sent true, hash 0x538fdf72…b121, status success, gasUsed 21000 |
Indexing
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| eth_getLogs by address, by topic and by block range returns the receipts' logs with consistent logIndex and transactionIndex | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| eth_getBlockByNumber with full transactions, eth_getBlockReceipts and eth_getTransactionByHash agree on indices and hashes | untested | no block with two or more transactions in the last 600 chain blocks (the chain is young and nothing sends yet); reruns when the chain carries transactions |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| eth_getLogs by address, by topic and by block range returns the receipts' logs with consistent logIndex and transactionIndex | passed | 4 logs by address, 3 Transfer logs by topic, each found in its receipt | byAddress 4, byTopic 3, fromBlock 739 |
| eth_getBlockByNumber with full transactions, eth_getBlockReceipts and eth_getTransactionByHash agree on indices and hashes | passed | block 742: 1 transactions, indices 0 to 0 continuous | block 742, count 1 |
Failed transactions
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| a revert with a reason: eth_call returns the reason, the sent transaction has status 0, gas is charged, the nonce advances | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| an out-of-gas call: status 0 and the whole limit charged | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| a revert with a reason: eth_call returns the reason, the sent transaction has status 0, gas is charged, the nonce advances | passed | eth_call answers code 3 "execution reverted" with Error(string) data decoding to "compat says no"; the sent transaction: status 0, gasUsed 22292 of 200000, nonce 23 to 24 | tx 0xfcdf8d24…6a1e, gasUsed 22292, block 762, call_error_code 3, call_error_message execution reverted, revert_data 0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e636f6d7061742073617973206e6f000000000000000000000000000000000000 |
| an out-of-gas call: status 0 and the whole limit charged | passed | status 0, gasUsed 150000 of the 150000 limit | tx 0xb3986b45…a1f6, gasUsed 150000, limit 150000 |
Receipts
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| a receipt carries every Ethereum field, logsBloom recomputes from its logs, contractAddress is set on creation | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| the block's receipts rebuild its receipts trie root (Ethereum's layout, the node's encoding) equal to the header's receiptsRoot | untested | no block with two or more transactions in the last 600 chain blocks (the chain is young and nothing sends yet); reruns when the chain carries transactions |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| a receipt carries every Ethereum field, logsBloom recomputes from its logs, contractAddress is set on creation | passed | 15 fields, bloom recomputed over 1 log(s), contractAddress 0xb2495fd8 | tx 0x8fd280cb…a5b9 |
| the block's receipts rebuild its receipts trie root (Ethereum's layout, the node's encoding) equal to the header's receiptsRoot | passed | block 742, 1 receipts, root 0xa28061003c4c | block 742, receipts 1, receiptsRoot 0xa2806100…ac55 |
Application assumptions
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| block.number, timestamp, chainid, basefee and blockhash(number-1) read from a contract match the block the call executed in | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) | |
| CREATE2 lands at the address Ethereum computes (keccak(0xff, deployer, salt, keccak(initcode))) | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| block.number, timestamp, chainid, basefee and blockhash(number-1) read from a contract match the block the call executed in | passed | block 768: number, timestamp, chainid 4465, basefee, blockhash(n-1) = parentHash, msg.sender and tx.origin all match | tx 0x3c1d2dff…4fcd, block 768 |
| CREATE2 lands at the address Ethereum computes (keccak(0xff, deployer, salt, keccak(initcode))) | passed | child at 0xE63036B0fEC0d01321Ef4DA62C084d1Ec2eA47be | tx 0x11cd9873…a80c, address 0xE63036B0fEC0d01321Ef4DA62C084d1Ec2eA47be |
Differences: block context
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| block.coinbase is the miner of the DAG block that first included the transaction, not one miner per chain block (measured: coinbase against the block's igneum.mergeset) | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| block.coinbase is the miner of the DAG block that first included the transaction, not one miner per chain block (measured: coinbase against the block's igneum.mergeset) | passed | coinbase 0xc119093F = the including block's miner 0xc119093f; the chain block merged 2 block(s) with 1 distinct miner(s), chain block miner 0xc119093f | tx 0x3c1d2dff…4fcd, coinbase 0xc119093F38E3764Fdd86ea9635b7f616DEC6C3A6, includingMiner 0xc119093f38e3764fdd86ea9635b7f616dec6c3a6, chainBlockMiner 0xc119093f38e3764fdd86ea9635b7f616dec6c3a6 |
Differences: randomness
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| block.prevrandao: its value is derived from the chain's epoch seed (not Ethereum's beacon RANDAO); measured across consecutive blocks, and from a contract when a sender is funded | passed | blocks 377 to 380: 1 distinct epoch seed(s), 4 distinct mixHash value(s) in the headers; the source is the chain's epoch seed, which holds for an epoch, so prevrandao is not fresh per block and must not seed a lottery |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| block.prevrandao: its value is derived from the chain's epoch seed (not Ethereum's beacon RANDAO); measured across consecutive blocks, and from a contract when a sender is funded | passed | blocks 767 to 770: 1 distinct epoch seed(s), 4 distinct mixHash value(s) in the headers; the source is the chain's epoch seed, which holds for an epoch, so prevrandao is not fresh per block and must not seed a lottery; a contract reading it twice in one call got the same value, and at block 768 it read 0x9cf17fa10c95… |
Differences: two-dimensional fees
-| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| a receipt carries pgasUsed, provingBaseFeePerGas, burnedProvingFee and burnedExecutionBaseFee; effectiveGasPrice covers both dimensions | untested | no funded sender on this devnet tonight (the faucet refused this connection; ask again tomorrow) |
| Row | Verdict | What was measured | Evidence |
|---|---|---|---|
| a receipt carries pgasUsed, provingBaseFeePerGas, burnedProvingFee and burnedExecutionBaseFee; effectiveGasPrice covers both dimensions | passed | gasUsed 51375, pgasUsed 1968, proving base fee 10000 gwei per pgas; paid 5188875000000000 wei, of which proving burn 19680000000000000, execution burn 5137500000000000, tip 41100000000000 (parts sum differs from gasUsed × effectiveGasPrice) | tx 0xe787770a…25fb, gasUsed 51375, pgasUsed 1968, effectiveGasPrice 0x178411b200, parts_equal_paid false |
What the differences mean for an application
- Block context:
block.coinbaseis the miner of the DAG block that first included the transaction, so one chain block can carry transactions with different coinbases; code that pays or trustsblock.coinbaseas "the block producer" sees several producers per block. - Randomness:
block.prevrandaoderives from the chain's epoch seed and holds for an epoch, so it is not fresh per block and must not seed a lottery or a commitment; use an application-level randomness source. - Two-dimensional fees: every transaction pays execution gas and proving gas; the node folds the second into the gas it quotes, so a wallet that quotes from the node (eth_estimateGas, eth_gasPrice, eth_feeHistory) is covered and a wallet with Ethereum's constants (21,000 for a transfer) is not; the receipt carries the split under
igneum(pgasUsed, provingBaseFeePerGas, burnedProvingFee, burnedExecutionBaseFee, minerTip).
${esc(res.balance_wei)} wei at chain block ${res.block}, under checkpoint ${res.checkpoint} (locked ${esc(ago(Number(proof.headers[proof.headers.length - 1].timestamp)))}). Verified here in ${res.ms} ms, ${res.headers} headers checked.
${esc(res.reason)}
${esc(res.reason)}
Data served by ${esc(API)} (a read service in front of a devnet node). Nothing it answered was taken on trust: the certificate, every header hash and parent link, the coinbase inclusion, the segment record's signature and the account proof were recomputed in this tab. What is trusted: that the aggregator's statement is the true execution result (every node checks it natively before paying the record; the SP1 proof behind it is verified by nodes, not in this tab yet), and the voter list with weights, which came from the node (spec 10.1).
`; + + `Data served by ${esc(API)} (a read service in front of a Devnet 3 node). Nothing it answered was taken on trust: the certificate, every header hash and parent link, the coinbase inclusion, the segment record's signature and the account proof were recomputed in this tab. What is trusted: that the aggregator's statement is the true execution result (every node checks it natively before paying the record; the SP1 proof behind it is verified by nodes, not in this tab yet), and the voter list with weights, which came from the node (spec 10.1).
`; setStatus(res.verified ? 'verified' : 'refused', res.verified ? 'ok' : 'bad'); return res; } @@ -76,24 +76,28 @@ export async function runReceipt(tx) { await new Promise(resolve => setTimeout(resolve, 20)); const bad = clone(receipt); bad.raw_tx_hex = flipHex(bad.raw_tx_hex, 40); const neg = verifyReceipt(bad, deps); - const res = verifyReceipt(receipt, deps); + const res = verifyPaymentReceipt(receipt, deps); + if (res.payment) { receipt.kind = 'payment receipt'; receipt.authenticates = 'inclusion of the signed transaction in a finalised block and its successful execution outcome (status and logs) through the proven segment\'s receipts commitment'; } + let negPay = null; + if (res.payment) { const b2 = clone(receipt); const r0 = b2.segment.receipts[Number(b2.segment.receipt_position)]; r0.status = '0x0'; negPay = verifyPaymentReceipt(b2, deps); } window.__igneumReceipt = { receipt, neg, res }; const t = res.tx || {}; const when = new Date(Number(res.block_time || 0)).toISOString().replace('T', ' ').slice(0, 19) + ' UTC'; const top = res.verified - ? `Outcome authenticated: ${esc(res.outcome.asset)}, ${esc(formatIgn(res.outcome.amount_wei))} IGN to ${esc(res.outcome.recipient || 'contract creation')}, executed with status success, through the receipts commitment of the proven segment ending at chain block ${esc(String(receipt.execution.chain_block))}.
` : `This is the inclusion receipt. ${esc(res.payment_unavailable || receipt.payment_unavailable || 'the outcome is not authenticated')}${res.receipt_status === 'failed' ? ' The authenticated status is FAILED: no transfer took place.' : ''}
`}${esc(res.reason)}
${esc(res.reason)}
The file carries the raw transaction, the including block's header and merkle path, every header up to the certified checkpoint, the certificate and the voter table. Anyone re-verifies it offline with the one-file verifier: node verify-receipt.js receipt.json (verify-receipt.js, plain JavaScript, no npm, no network). A tampered file fails there the same way the copy above failed here.
${esc(String(err.message || err))}
${esc(String(err.message || err))}
Igneum reference apps: the negative cases, in this tab (devnet, no value)
-Each row runs site/lc/core.js on live devnet data from . A tampered case must read refused; the genuine case must read verified. The same cases run under Node in tools/reference-apps/light-service/verify.test.mjs. Parameters: ?api= (the read service), ?address= (the balance to prove; default: the miner of the latest block), ?tx= (a transaction; default: one in a recent block).
Igneum reference apps: the negative cases, in this tab (Devnet 3, no value)
+Each row runs site/lc/core.js on live Devnet 3 data from . A tampered case must read refused; the genuine case must read verified. The same cases run under Node in tools/reference-apps/light-service/verify.test.mjs. Parameters: ?api= (the read service), ?address= (the balance to prove; default: the miner of the latest block), ?tx= (a transaction; default: one in a recent block).
Receipt
| case | result | ms | reason |