Builder pages and faucet: Devnet 3 chain id 4464 since the class v5 floor (8 October 2026, 13:27 BST reading)

- the faucet reads eth_chainId from its node on every send and in its status (a fixed id signed refused transactions once the floor crossed); FAUCET_CHAIN_ID is gone from the env; the faucet now reads node1-dn3's EVM, the node the public RPC fronts
- /build, /faucet, docs/build/first-contract.md, rpc.md and faucet.md: 4464 with the floor note, "read it, never fix it"
- a second walkthrough PASS on the 4464 chain from build-2 through the public RPC and faucet: Counter at block 29878, 12 s end to end

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-08 12:38:51 +00:00
parent 1513244d55
commit e15464ac58
10 changed files with 53 additions and 45 deletions

6
docs/build/build.md vendored
View file

@ -16,13 +16,13 @@ This file is the source of [igneum.network/build](https://igneum.network/build).
| | Devnet 3 | Testnet | Mainnet |
|---|---|---|---|
| Chain id | 4463 (`0x116f`) | 4462 (`0x116e`) | 4461 (`0x116d`) |
| Chain id | 4464 (`0x1170`) since its class v5 floor on 8 October 2026; 4463 below it | 4462 (`0x116e`) | 4461 (`0x116d`) |
| Network id | `igneum-devnet-3` | `igneum-testnet-1` | not started |
| RPC | `https://rpc.devnet.igneum.network` (a node you run serves `http://127.0.0.1:26790`) | `https://rpc.testnet.igneum.network` (answers; nothing mines there yet, so a transaction waits) | none |
| Coins | no value, resets without notice | no value, resets with notice | not started |
| Symbol, decimals | IGN, 18 | IGN, 18 | IGN, 18 |
Devnet 3 is where you build today. It is a developer network: it resets without notice and its coins have no value. Its public RPC takes the read methods, `eth_sendRawTransaction` and a wRPC websocket at `/ws`, at 20 requests a second per address. The public testnet exists, its RPC answers, and no blocks are being produced on it until it opens. Mainnet has no date. Devnet 3 answers chain id 4463 until its class v5 floor, then 4464.
Devnet 3 is where you build today. It is a developer network: it resets without notice and its coins have no value. Its public RPC takes the read methods, `eth_sendRawTransaction` and a wRPC websocket at `/ws`, at 20 requests a second per address. The public testnet exists, its RPC answers, and no blocks are being produced on it until it opens. Mainnet has no date. Devnet 3 answered 4463 until its class v5 floor at DAA 68,400 on 8 October 2026 and 4464 from it; read it with `eth_chainId` rather than fixing it, since a transaction signed for the wrong id is refused.
## Endpoints and tools
@ -58,7 +58,7 @@ cast send 0xDEPLOYED "increment()" --rpc-url $RPC --private-key $PK
cast call 0xDEPLOYED "number()(uint256)" --rpc-url $RPC
```
The call answers `1`. Paste the transaction hash into [the explorer](/explorer). Hardhat, ethers and viem work the same way: chain id 4463, the RPC above.
The call answers `1`. Paste the transaction hash into [the explorer](/explorer). Hardhat, ethers and viem work the same way: chain id 4464, the RPC above.
## The RPC the node serves

View file

@ -5,7 +5,7 @@
## What it is
- A small Node service on a build box, `infra/build-server/faucet/faucet.mjs`, behind Caddy at `faucet.igneum.network`. The page on igneum.network posts to it.
- It signs a plain transfer with its own key and sends it to the Devnet 3 node on the same box by address (`FAUCET_RPC`), never chosen by chain id: Devnet 3 answers the same chain id as the shared devnet.
- It signs a plain transfer with its own key and sends it to the Devnet 3 node on the same box by address (`FAUCET_RPC`), never chosen by chain id. The chain id it signs with is read from that node on every send: Devnet 3 moved from 4463 to 4464 at its class v5 floor on 8 October 2026.
- The key lives only in the service's environment file on that box. It is not in the repository and not on the site.
## The rules, as the code enforces them

View file

@ -10,7 +10,7 @@ With Foundry. Tested end to end on Devnet 3 from a build box on 8 October 2026;
```
export RPC=https://rpc.devnet.igneum.network
cast chain-id --rpc-url $RPC # 4463
cast chain-id --rpc-url $RPC # 4464 (4463 before the class v5 floor of 8 October 2026)
```
## 1. A key, for the devnet only
@ -89,3 +89,9 @@ PASS 10:17:23Z: Devnet 3 chain id 4463, faucet drip 0x8620e9d894484e824e4ac33002
```
Through the public endpoints, `https://rpc.devnet.igneum.network` and `https://faucet.igneum.network`, from the box: the first faucet drip and the first reader-path deploy on Devnet 3.
After the class v5 floor moved the chain id to 4464 the same afternoon, from a second box:
```
PASS 12:38:39Z: Devnet 3 chain id 4464, faucet drip 0xa54fdb7e964dab095aaccaab36ea548fc3fa8727acb809b593c2d4d1359c233f, deployed Counter at 0x7de503a4F39feEBCE8c4ABbAcC04282EE75120Fe (tx 0x6ccdbb4f6393fcf09e58ba2f4de1af98c547eeab6f02d93eacfebae883200dc6), increment then setNumber(41) read back 41, receipt status 1 (success), block 29878, 12 s end to end, Foundry 1.8.5
```

4
docs/build/rpc.md vendored
View file

@ -9,9 +9,9 @@ Transport: HTTP POST, JSON-RPC 2.0, one request per call, no batches tested. The
| Method | Note |
|---|---|
| `web3_clientVersion` | `igneumd/<version>/execution-layer-v3` |
| `net_version` | the chain id as a decimal string, `"4463"` |
| `net_version` | the chain id as a decimal string, `"4464"` (`"4463"` before the class v5 floor) |
| `net_listening`, `net_peerCount` | |
| `eth_chainId` | `0x116f` (4463) on Devnet 3; `0x1170` after its class v5 floor |
| `eth_chainId` | `0x1170` (4464) on Devnet 3 since its class v5 floor at DAA 68,400 on 8 October 2026; `0x116f` (4463) below it. Read it, never fix it |
| `eth_blockNumber` | the executed chain tip |
| `eth_syncing` | `false` when the executor is at the tip |
| `eth_mining` | `false` from the RPC's point of view: mining is the miner's, not the node's |

View file

@ -7,7 +7,8 @@
// append-only JSONL file next to the service (FAUCET_STATE, default ./grants.jsonl); the window is read from it at start.
// Environment (EnvironmentFile=/srv/faucet/env on the box, mode 600; the key is nowhere else): FAUCET_KEY (0x + 64 hex),
// FAUCET_RPC (the Devnet 3 node by address, never chosen by chain id: Devnet 3 answers the same id as the shared devnet),
// FAUCET_CHAIN_ID (4463), FAUCET_PORT (8790), FAUCET_ORIGIN (the page's origin for CORS, https://igneum.network).
// FAUCET_PORT (8790), FAUCET_ORIGIN (the page's origin for CORS, https://igneum.network). The chain id is READ FROM THE NODE on
// every send (eth_chainId): Devnet 3 moved from 4463 to 4464 at its class v5 floor on 8 October 2026 and a fixed id signs refused transactions.
// Signing: site/lib/eth.mjs, copied next to this file by faucet.sh (zero dependencies).
// node faucet.mjs the service
// node faucet.mjs --self-test the limiter and the handler against a fake node: known-failed cases first
@ -58,7 +59,7 @@ const ignOf = wei => (Number(BigInt(wei) / 10n ** 12n) / 1e6).toFixed(6);
export function createHandler({ env = process.env, rpc, lim, record = () => {}, now = () => Date.now() } = {}) {
const key = env.FAUCET_KEY || '', rpcUrl = env.FAUCET_RPC || '';
const chainId = Number(env.FAUCET_CHAIN_ID || 4463);
const chainIdOf = async () => Number(BigInt(await rpc('eth_chainId')));
const origin = env.FAUCET_ORIGIN || 'https://igneum.network';
if (AMOUNT_IGN > HARD_CAP_IGN) throw new Error(`AMOUNT_IGN ${AMOUNT_IGN} is over the ${HARD_CAP_IGN} IGN cap`);
if (!/^0x[0-9a-fA-F]{64}$/.test(key) || !rpcUrl) throw new Error('FAUCET_KEY (0x + 64 hex) and FAUCET_RPC are required');
@ -83,8 +84,8 @@ export function createHandler({ env = process.env, rpc, lim, record = () => {},
if (req.method === 'OPTIONS') { res.writeHead(204); return res.end(); }
if (path !== '/api/faucet' && path !== '/api/faucet/') return json(res, 404, { ok: false, error: 'not found' });
if (req.method === 'GET') {
let balance = null;
try { balance = ignOf(await rpc('eth_getBalance', [from, 'latest'])); } catch { /* the node is the status */ }
let balance = null, chainId = null;
try { balance = ignOf(await rpc('eth_getBalance', [from, 'latest'])); chainId = await chainIdOf(); } catch { /* the node is the status */ }
return json(res, 200, { ok: true, network: 'igneum-devnet-3', chainId, amount: String(AMOUNT_IGN), window_hours: WINDOW_HOURS, daily_max: DAILY_MAX, address: from, balance_ign: balance, sends_24h: lim.count(), funded: balance !== null && Number(balance) >= AMOUNT_IGN });
}
if (req.method !== 'POST') { res.setHeader('Allow', 'GET, POST, OPTIONS'); return json(res, 405, { ok: false, error: 'method not allowed' }); }
@ -98,11 +99,12 @@ export function createHandler({ env = process.env, rpc, lim, record = () => {},
const row = { t: now(), address: to, ip, tx: null };
lim.add(row); // reserved before the send, so two asks in the same second cannot both pass
const result = chain.then(async () => {
const [nonceHex, block, tipHex, balHex] = await Promise.all([
const [nonceHex, block, tipHex, balHex, chainId] = await Promise.all([
rpc('eth_getTransactionCount', [from, 'pending']),
rpc('eth_getBlockByNumber', ['latest', false]),
rpc('eth_maxPriorityFeePerGas').catch(() => '0x3b9aca00'),
rpc('eth_getBalance', [from, 'latest']),
chainIdOf(),
]);
const value = toWei(AMOUNT_IGN);
if (BigInt(balHex) < value * 2n) throw Object.assign(new Error('The faucet is empty right now. It is being refilled; try again in an hour.'), { status: 503 });
@ -111,12 +113,12 @@ export function createHandler({ env = process.env, rpc, lim, record = () => {},
try { gas = BigInt(await rpc('eth_estimateGas', [{ from, to, value: '0x' + value.toString(16) }])); } catch { /* the plain-transfer default */ }
const tx = { chainId, nonce: BigInt(nonceHex), maxPriorityFeePerGas: tip, maxFeePerGas: baseFee * 2n + tip, gas, to, value, data: '0x' };
const signed = signTransaction(tx, key);
return rpc('eth_sendRawTransaction', [signed.raw]);
return { hash: await rpc('eth_sendRawTransaction', [signed.raw]), chainId };
});
chain = result.catch(() => {});
try {
const hash = await result;
row.tx = hash; record(row);
const { hash, chainId } = await result;
row.tx = hash; row.chainId = chainId; record(row);
return json(res, 200, { ok: true, tx: hash, amount: String(AMOUNT_IGN), chainId, to });
} catch (e) {
lim.drop(row);
@ -129,7 +131,7 @@ if (process.argv.includes('--self-test')) {
// known-failed first: a fake node that answers every read and refuses every send must leave the limiter empty and answer 502
let t = 1_000_000; const now = () => t;
const fakeNode = (sendOk = true) => async (m, p) => ({
eth_getTransactionCount: '0x1', eth_getBlockByNumber: { baseFeePerGas: '0x174876e800' }, eth_maxPriorityFeePerGas: '0x3b9aca00',
eth_chainId: '0x1170', eth_getTransactionCount: '0x1', eth_getBlockByNumber: { baseFeePerGas: '0x174876e800' }, eth_maxPriorityFeePerGas: '0x3b9aca00',
eth_getBalance: '0x' + (10n ** 21n).toString(16), eth_estimateGas: '0x5208',
eth_sendRawTransaction: sendOk ? '0x' + 'ab'.repeat(32) : (() => { throw new Error('refused'); })(),
})[m];
@ -139,25 +141,25 @@ if (process.argv.includes('--self-test')) {
const res = { h: {}, setHeader(k, v) { this.h[k] = v; }, writeHead(s, hh) { this.status = s; Object.assign(this.h, hh || {}); }, end(b) { resolve({ status: this.status, body: b ? JSON.parse(b) : null }); } };
h(req, res);
});
const env = { FAUCET_KEY: '0x' + '11'.repeat(32), FAUCET_RPC: 'http://fake', FAUCET_CHAIN_ID: '4463' };
const env = { FAUCET_KEY: '0x' + '11'.repeat(32), FAUCET_RPC: 'http://fake' };
const A = '0x' + 'a1'.repeat(20), B = '0x' + 'b2'.repeat(20);
let fails = 0; const expect = (c, msg) => { if (!c) { console.error('self-test failed: ' + msg); fails++; } };
{ const lim = limiter(now); const h = createHandler({ env, rpc: fakeNode(false), lim, now }); const r = await call(h, 'POST', { address: A }); expect(r.status === 502 && lim.count() === 0, `a refused send must answer 502 and reserve nothing (got ${r.status}, ${lim.count()})`); }
{ const lim = limiter(now); const h = createHandler({ env, rpc: fakeNode(), lim, now }); const r = await call(h, 'POST', { address: 'not-an-address' }); expect(r.status === 400, 'a bad address must answer 400'); }
{ const lim = limiter(now); const recorded = []; const h = createHandler({ env, rpc: fakeNode(), lim, record: r => recorded.push(r), now });
const r1 = await call(h, 'POST', { address: A }); expect(r1.status === 200 && r1.body.ok && r1.body.tx.startsWith('0x'), 'the first ask sends');
const r1 = await call(h, 'POST', { address: A }); expect(r1.status === 200 && r1.body.ok && r1.body.tx.startsWith('0x') && r1.body.chainId === 4464, 'the first ask sends with the chain id read from the node');
expect(recorded.length === 1 && recorded[0].tx === r1.body.tx, 'the send is recorded with its hash');
const r2 = await call(h, 'POST', { address: A }); expect(r2.status === 429 && /address/.test(r2.body.error), 'the same address inside the window is refused');
const r3 = await call(h, 'POST', { address: B }); expect(r3.status === 429 && /connection/.test(r3.body.error), 'the same connection inside the window is refused');
const r4 = await call(h, 'POST', { address: B }, '2.2.2.2'); expect(r4.status === 200, 'another address from another connection sends');
t += WINDOW_MS + 1; const r5 = await call(h, 'POST', { address: A }); expect(r5.status === 200, 'after the window the address sends again');
const s = await call(h, 'GET'); expect(s.status === 200 && s.body.network === 'igneum-devnet-3' && s.body.sends_24h === 1 && s.body.funded === true, `the status carries the network and the window count (got ${JSON.stringify(s.body)})`);
const s = await call(h, 'GET'); expect(s.status === 200 && s.body.network === 'igneum-devnet-3' && s.body.chainId === 4464 && s.body.sends_24h === 1 && s.body.funded === true, `the status carries the network and the window count (got ${JSON.stringify(s.body)})`);
for (let i = 0; i < DAILY_MAX - 1; i++) lim.add({ t: now(), address: '0x' + String(i).padStart(40, '0'), ip: 'x' + i, tx: '0x' });
const r6 = await call(h, 'POST', { address: '0x' + 'c3'.repeat(20) }, '3.3.3.3'); expect(r6.status === 429 && /today/.test(r6.body.error), 'the daily total refuses the next ask'); }
{ let threw = false; try { createHandler({ env: { ...env, FAUCET_KEY: 'bad' }, rpc: fakeNode(), now }); } catch { threw = true; } expect(threw, 'a bad key must refuse to start'); }
expect(AMOUNT_IGN <= HARD_CAP_IGN, 'the amount is under the cap');
if (fails) process.exit(1);
console.log(`self-test passed: a refused send reserves nothing (502), a bad address 400, the same address and the same connection are refused inside ${WINDOW_HOURS} h (429), another pair sends, the window expires, the status counts, the ${DAILY_MAX}-a-day total refuses, a bad key refuses to start, ${AMOUNT_IGN} IGN is under the ${HARD_CAP_IGN} IGN cap`);
console.log(`self-test passed: a refused send reserves nothing (502), a bad address 400, the same address and the same connection are refused inside ${WINDOW_HOURS} h (429), another pair sends, the window expires, the status counts, the ${DAILY_MAX}-a-day total refuses, a bad key refuses to start, the chain id comes from the node, ${AMOUNT_IGN} IGN is under the ${HARD_CAP_IGN} IGN cap`);
process.exit(0);
}

View file

@ -6,7 +6,7 @@
# infra/build-server/faucet/faucet.sh status the unit, the loopback status (balance, sends in the window), the Caddy host
# infra/build-server/faucet/faucet.sh self-test node faucet.mjs --self-test on the box
# /srv/faucet/env (mode 600, the build user's) is written by hand on the box and never by this script: FAUCET_KEY, FAUCET_RPC
# (the Devnet 3 node by address), FAUCET_CHAIN_ID, FAUCET_PORT, FAUCET_ORIGIN. The key is nowhere else.
# (the Devnet 3 node by address; the chain id is read from it), FAUCET_PORT, FAUCET_ORIGIN. The key is nowhere else.
set -euo pipefail
HERE=$(cd "$(dirname "$0")" && pwd); ROOT=$(cd "$HERE/../../.." && pwd)
KEY="${IGNEUM_BUILD_KEY:-$HOME/.ssh/igneum_ed25519}"; HOST=$(head -1 "${IGNEUM_BUILD_HOST_FILE:-$HOME/.config/igneum/build-server}" | tr -d '[:space:]')
@ -37,7 +37,7 @@ case "$mode" in
if [ "$GO" = 0 ]; then
say "DRY: scp faucet.mjs, site/lib/eth.mjs -> $HOST:/srv/faucet/; igneum-faucet.service -> root@$IP:/etc/systemd/system/; append to /etc/caddy/Caddyfile unless $FAUCET_HOST is there:"; caddy_block; say "DRY: systemctl daemon-reload, enable --now igneum-faucet; curl 127.0.0.1:$PORT/api/faucet"; exit 0
fi
"${SSHB[@]}" 'test -s /srv/faucet/env' || { say "/srv/faucet/env is missing on the box: write it by hand first (FAUCET_KEY, FAUCET_RPC, FAUCET_CHAIN_ID, FAUCET_PORT, FAUCET_ORIGIN)"; exit 1; }
"${SSHB[@]}" 'test -s /srv/faucet/env' || { say "/srv/faucet/env is missing on the box: write it by hand first (FAUCET_KEY, FAUCET_RPC, FAUCET_PORT, FAUCET_ORIGIN)"; exit 1; }
scp -q -i "$KEY" "$HERE/faucet.mjs" "$ROOT/site/lib/eth.mjs" "$HOST:/srv/faucet/"
"${SSHB[@]}" 'cd /srv/faucet && node faucet.mjs --self-test' || { say "the self-test failed on the box; nothing started"; exit 1; }
scp -q -i "$KEY" "$HERE/igneum-faucet.service" "root@$IP:/etc/systemd/system/igneum-faucet.service"

View file

@ -245,8 +245,8 @@ table{min-width:560px}
<p><strong>The EVM you already know.</strong> Solidity deploys unchanged. Standard JSON-RPC, EIP-1559 transactions, the chain id in the signature, <code>cancun</code> as the EVM version. Gas has two dimensions on Igneum, execution and proving, and the node folds the second into the price it quotes, so <code>eth_estimateGas</code> and <code>eth_gasPrice</code> work as they do on Ethereum.</p>
</section>
<section class="doc-section"><h2 id="networks">Networks</h2>
<div class="tbl"><table><thead><tr><th></th><th>Devnet 3</th><th>Testnet</th><th>Mainnet</th></tr></thead><tbody><tr><td>Chain id</td><td>4463 (<code>0x116f</code>)</td><td>4462 (<code>0x116e</code>)</td><td>4461 (<code>0x116d</code>)</td></tr><tr><td>Network id</td><td><code>igneum-devnet-3</code></td><td><code>igneum-testnet-1</code></td><td>not started</td></tr><tr><td>RPC</td><td><code>https://rpc.devnet.igneum.network</code> (a node you run serves <code>http://127.0.0.1:26790</code>)</td><td><code>https://rpc.testnet.igneum.network</code> (answers; nothing mines there yet, so a transaction waits)</td><td>none</td></tr><tr><td>Coins</td><td>no value, resets without notice</td><td>no value, resets with notice</td><td>not started</td></tr><tr><td>Symbol, decimals</td><td>IGN, 18</td><td>IGN, 18</td><td>IGN, 18</td></tr></tbody></table></div>
<p>Devnet 3 is where you build today. It is a developer network: it resets without notice and its coins have no value. Its public RPC takes the read methods, <code>eth_sendRawTransaction</code> and a wRPC websocket at <code>/ws</code>, at 20 requests a second per address. The public testnet exists, its RPC answers, and no blocks are being produced on it until it opens. Mainnet has no date. Devnet 3 answers chain id 4463 until its class v5 floor, then 4464.</p>
<div class="tbl"><table><thead><tr><th></th><th>Devnet 3</th><th>Testnet</th><th>Mainnet</th></tr></thead><tbody><tr><td>Chain id</td><td>4464 (<code>0x1170</code>) since its class v5 floor on 8 October 2026; 4463 below it</td><td>4462 (<code>0x116e</code>)</td><td>4461 (<code>0x116d</code>)</td></tr><tr><td>Network id</td><td><code>igneum-devnet-3</code></td><td><code>igneum-testnet-1</code></td><td>not started</td></tr><tr><td>RPC</td><td><code>https://rpc.devnet.igneum.network</code> (a node you run serves <code>http://127.0.0.1:26790</code>)</td><td><code>https://rpc.testnet.igneum.network</code> (answers; nothing mines there yet, so a transaction waits)</td><td>none</td></tr><tr><td>Coins</td><td>no value, resets without notice</td><td>no value, resets with notice</td><td>not started</td></tr><tr><td>Symbol, decimals</td><td>IGN, 18</td><td>IGN, 18</td><td>IGN, 18</td></tr></tbody></table></div>
<p>Devnet 3 is where you build today. It is a developer network: it resets without notice and its coins have no value. Its public RPC takes the read methods, <code>eth_sendRawTransaction</code> and a wRPC websocket at <code>/ws</code>, at 20 requests a second per address. The public testnet exists, its RPC answers, and no blocks are being produced on it until it opens. Mainnet has no date. Devnet 3 answered 4463 until its class v5 floor at DAA 68,400 on 8 October 2026 and 4464 from it; read it with <code>eth_chainId</code> rather than fixing it, since a transaction signed for the wrong id is refused.</p>
</section>
<section class="doc-section"><h2 id="endpoints-and-tools">Endpoints and tools</h2>
<ul><li><strong>Wallet.</strong> Any Ethereum wallet. <a href="/metamask">Add Igneum to MetaMask</a> with one click, or the <a href="/wallet">Igneum wallet</a>.</li><li><strong>Faucet.</strong> <a href="/faucet">10 IGN of Devnet 3 coin</a> per address per day. No account.</li><li><strong>Explorer.</strong> <a href="/explorer">The explorer</a> shows blocks, the DAG, miners and addresses. The EVM views, transactions and contracts, are being built and link from the same page as they land.</li><li><strong>Swap.</strong> <a href="/swap">The swap</a>: test tokens on Devnet 3, every swap in a proven block.</li><li><strong>Source.</strong> <a href="https://git.igneum.network/igneum-network/igneum" rel="noopener">git.igneum.network/igneum-network/igneum</a>: the node, the miner, the site, and these pages under <code>docs/build/</code>.</li></ul>
@ -264,7 +264,7 @@ forge create src/Counter.sol:Counter --rpc-url $RPC --private-key $PK --broadcas
<p><code>forge create</code> prints <code>Deployed to: 0x...</code>. Call it:</p>
<pre>cast send 0xDEPLOYED "increment()" --rpc-url $RPC --private-key $PK
cast call 0xDEPLOYED "number()(uint256)" --rpc-url $RPC</pre>
<p>The call answers <code>1</code>. Paste the transaction hash into <a href="/explorer">the explorer</a>. Hardhat, ethers and viem work the same way: chain id 4463, the RPC above.</p>
<p>The call answers <code>1</code>. Paste the transaction hash into <a href="/explorer">the explorer</a>. Hardhat, ethers and viem work the same way: chain id 4464, the RPC above.</p>
</section>
<section class="doc-section"><h2 id="the-rpc-the-node-serves">The RPC the node serves</h2>
<p>Read from a Devnet 3 node, not from a spec. <code>web3_clientVersion</code> answers <code>igneumd/2.1.0/execution-layer-v3</code>. The full list, served and not served, with the probe that produced it: <a href="https://git.igneum.network/igneum-network/igneum/src/branch/master/docs/build/rpc.md" rel="noopener">docs/build/rpc.md</a>.</p>

View file

@ -230,7 +230,7 @@ dt{color:var(--ash)}dd{margin:0;font-family:var(--f-mono);font-size:14px;overflo
<div class="eyebrow"><span class="line"></span>Devnet 3 faucet</div>
<h1>10 IGN a day, <span class="accent">for building.</span></h1>
<p>Paste an address. The faucet sends 10 IGN of Devnet 3 coin and shows you the transaction hash. Once per address per day, once per connection per day. No account, no sign-in, nothing to install.</p>
<p class="notice" id="faucet-state">Devnet 3, chain id 4463. The coins have no value and the chain resets without notice. <span id="faucet-balance"></span></p>
<p class="notice" id="faucet-state">Devnet 3, chain id 4464 since its class v5 floor. The coins have no value and the chain resets without notice. <span id="faucet-balance"></span></p>
</div>
<div class="grid">
<section class="card" aria-labelledby="ask">
@ -252,7 +252,7 @@ dt{color:var(--ash)}dd{margin:0;font-family:var(--f-mono);font-size:14px;overflo
<div class="rule"><span class="num">04</span><div><b>What is stored</b><span>The address, the connection's IP, the transaction hash and the time, on the box that runs the faucet, for 24 hours of rate limiting. Nothing else.</span></div></div>
</div>
<dl>
<dt>Chain id</dt><dd>4463 (Devnet 3)</dd>
<dt>Chain id</dt><dd>4464 (Devnet 3; 4463 before 8 October 2026)</dd>
<dt>RPC</dt><dd>https://rpc.devnet.igneum.network</dd>
<dt>Wallet set-up</dt><dd><a href="/metamask">MetaMask: chain id, RPC, one click</a></dd>
<dt>Then</dt><dd><a href="/build">Deploy a contract in five minutes</a></dd>

View file

@ -273,12 +273,12 @@
<article class="record"><div class="record-top"><time datetime="2026-10-05">5 Oct 2026</time><span class="badge">log</span></div><h3>Live devnet: real transactions, the first non-empty shard proven and…</h3><p>Live devnet: real transactions, the first non-empty shard proven and paid, and the exporter's block structure fixed</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-05">5 Oct 2026</time><span class="badge">log</span></div><h3>The program id split</h3><p>The program id split: why the Apple M5 Max rejected the RTX 5090 Windows rig's proofs, and the verifier at 114 s</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-05">5 Oct 2026</time><span class="badge">log</span></div><h3>Live devnet: the first shards proven, verified and paid</h3></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Economy simulation: mining versus proving under stress</h3><p>Sim/economy: mining versus proving under stress, agent-based</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Difficulty rule attacked seven ways</h3><p>Difficulty rule under attack: pool hopping, pulsed rental, timestamp stretching, short-lane oscillation, epoch games, polluted window, block flood</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Timestamp attack on the difficulty rule fixed</h3><p>Difficulty rule: timestamp attack fixed , simulator regression, 3-node forger test</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Devnet v4: nine branches merged into one node</h3><p>Devnet-v4 integration: nine branches merged, 3-node test network on the merged node, Windows cross-build</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Generator v2 adopted: every hash does 128 distinct reads</h3><p>Generator version 2 adopted: exact load count, fresh-source loads, program acceptance; every vector re-cut, three workers re-checked, 20,000-program census, devnet-v4 binaries rebuilt</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>First GPU proof of an Igneum block: 1.4 s on an RTX 5090</h3><p>Proving v0 on the RTX 5090: first GPU proof of an Igneum block</p></article></div>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Devnet v4 live: generator v2, two-thirds floor, fresh chain</h3><p>Devnet v4 cut-over: generator v2, 2/3 floor, three nodes and a seed on a fresh chain</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>One-click Windows workers</h3><p>One-click Windows workers: what the Apple M5 Max could measure</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>First live hourly swap: no pause on Mac, NVIDIA or AMD</h3><p>First hourly program swap on the live devnet: compile-ahead, no pause, two cards</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine</h3></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>First live finality lock: 77.4% of weight, 17 voters</h3><p>First finality lock on the live devnet: checkpoint 242 at 77.4% of all weight, two hours after genesis</p></article>
<article class="record"><div class="record-top"><time datetime="2026-10-04">4 Oct 2026</time><span class="badge">log</span></div><h3>The gfx1036 worker fault and what the Apple M5 Max could and could…</h3><p>The gfx1036 worker fault and what the Apple M5 Max could and could not reproduce</p></article></div>
<p class="empty-state" data-filter-empty="log" hidden>Nothing in the log matches that.</p>
<p class="note">Every entry is a dated heading of <a href="/bench">the engineering log</a>, where the commands and the hardware are. The phases and their gates are the litepaper’s <a href="/litepaper#roadmap">roadmap</a>.</p>
<div class="onward"><a href="/bench" class="btn">The engineering log</a><a href="/evidence" class="btn">Every claim and its status</a><a href="/live" class="btn">The live devnet</a></div>

View file

@ -222,33 +222,33 @@
},
{
"date": "2026-10-04",
"text": "Sim/economy: mining versus proving under stress, agent-based",
"short": "Economy simulation: mining versus proving under stress"
"text": "Devnet v4 cut-over: generator v2, 2/3 floor, three nodes and a seed on a fresh chain",
"short": "Devnet v4 live: generator v2, two-thirds floor, fresh chain"
},
{
"date": "2026-10-04",
"text": "Difficulty rule under attack: pool hopping, pulsed rental, timestamp stretching, short-lane oscillation, epoch games, polluted window, block flood",
"short": "Difficulty rule attacked seven ways"
"text": "One-click Windows workers: what the Apple M5 Max could measure",
"short": "One-click Windows workers"
},
{
"date": "2026-10-04",
"text": "Difficulty rule: timestamp attack fixed , simulator regression, 3-node forger test",
"short": "Timestamp attack on the difficulty rule fixed"
"text": "First hourly program swap on the live devnet: compile-ahead, no pause, two cards",
"short": "First live hourly swap: no pause on Mac, NVIDIA or AMD"
},
{
"date": "2026-10-04",
"text": "Devnet-v4 integration: nine branches merged, 3-node test network on the merged node, Windows cross-build",
"short": "Devnet v4: nine branches merged into one node"
"text": "Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine",
"short": "Proving: devnet v4 shards on the Apple M5 Max CPU, loaded machine"
},
{
"date": "2026-10-04",
"text": "Generator version 2 adopted: exact load count, fresh-source loads, program acceptance; every vector re-cut, three workers re-checked, 20,000-program census, devnet-v4 binaries rebuilt",
"short": "Generator v2 adopted: every hash does 128 distinct reads"
"text": "First finality lock on the live devnet: checkpoint 242 at 77.4% of all weight, two hours after genesis",
"short": "First live finality lock: 77.4% of weight, 17 voters"
},
{
"date": "2026-10-04",
"text": "Proving v0 on the RTX 5090: first GPU proof of an Igneum block",
"short": "First GPU proof of an Igneum block: 1.4 s on an RTX 5090"
"text": "The gfx1036 worker fault and what the Apple M5 Max could and could not reproduce",
"short": "The gfx1036 worker fault and what the Apple M5 Max could and could…"
}
]
}