diff --git a/CLAUDE.md b/CLAUDE.md index 408c7183..7c13e50d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -226,37 +226,35 @@ On every session start: 4. `jj describe -m "harness: stage N complete"` 5. `jj new` (start fresh change for next stage) -## Heima EVM compatibility level — pin to `london` in foundry.toml +## Heima EVM compatibility level — keep `evm_version = "london"` in foundry.toml (but NOT because Heima is "London") -Heima's Frontier EVM (the parachain's `pallet_evm` + `pallet_ethereum` stack) is at **London** EVM level. Pre-Merge. Verified live 2026-05-19 against `https://rpc.heima-parachain.heima.network` block header: +**Two separate things — do not conflate them (the earlier revision of this section did):** -| Field | Present? | Implication | -|---|---|---| -| `baseFeePerGas: 0x5d21dba00` | ✅ | EIP-1559 active → ≥ London | -| `difficulty: 0x0`, `mixHash: null`, `prevRandao: absent` | ❌ | Pre-Paris (Merge introduced these) → < Paris | -| `withdrawalsRoot: null` | ❌ | Pre-Shanghai | -| `blobGasUsed`, `excessBlobGas: null` | ❌ | Pre-Cancun | +1. **EVM *execution* level (which opcodes the chain runs) = Cancun.** Heima's Frontier `stable2412` `pallet_evm` returns `&CANCUN_CONFIG` from `frame/evm/src/lib.rs::config()` (the `// London` doc-comment one line up is stale upstream). **Verified on-chain** (local `heima-node --dev`, 2026-06-01) by deploying + *executing* contracts that use post-London opcodes: + - `PUSH0` (Shanghai, `0x5f`): a Shanghai-compiled `set(42)` ran; `x()` returned `42`. + - `TSTORE`/`TLOAD` (EIP-1153, **Cancun-only**): `rt(99)` returned `99`. + So **Heima does NOT reject PUSH0 or other ≤Cancun opcodes.** The previous claim ("london avoids PUSH0 which Heima would reject") was wrong. -**Practical consequence**: any Foundry project that deploys to Heima MUST set `evm_version = "london"` in `foundry.toml`. With `paris` or higher, `forge script ... --broadcast` errors with: +2. **Foundry `forge script` simulator's block-header validation — this is the real reason for the pin, and it is unrelated to (1).** Heima is a Substrate/Aura parachain via Frontier, so its block header has **no `prevrandao`/`mixHash`/`withdrawalsRoot`/`blobGasUsed`** fields — those are Ethereum-PoS-consensus header fields, NOT opcode-capability signals. `forge script ... --broadcast` runs a local simulation that validates the fetched header against the target EVM revision *before broadcasting*; with `evm_version = paris` or higher it requires `prevrandao` and errors: -``` -EVM error; header validation error: `prevrandao` not set -``` + ``` + EVM error; header validation error: `prevrandao` not set + ``` -…because forge's simulator validates the chain's block header against its target EVM version before broadcasting, and a Paris-or-higher simulator requires `prevrandao` in the header. + **Verified 2026-06-01**: running the real `DeployAgentKeysV1.s.sol` against the dev chain with `FOUNDRY_EVM_VERSION=cancun` reproduced this error; with `london` it deploys. (Note: `forge create --broadcast` with `cancun` does NOT hit this — it's specific to `forge script`'s simulator. Our deploy path uses `forge script`, so the pin stays.) -`london` also avoids the Shanghai-era PUSH0 opcode (which Heima would reject during EVM execution). +**Practical consequence (unchanged): keep `evm_version = "london"` in `crates/agentkeys-chain/foundry.toml`** so `forge script` broadcasts don't trip header validation. But understand it's a **simulator-header workaround, not an EVM-capability ceiling** — our contracts *may* use ≤Cancun features (PUSH0, transient storage) at runtime if ever needed; only the broadcast simulator cares about the header. -Verify the live EVM version of Heima any time with: +**Why the earlier "London" conclusion was wrong:** it introspected the block header (`baseFeePerGas` present, `mixHash`/`withdrawalsRoot`/`blobGasUsed` absent) and inferred the EVM level from header *format*. Header format reflects the consensus/block-structure layer; opcode support is set independently by Frontier's `config()`. The header check is the right way to predict the **forge-script-simulator** behavior, but the wrong way to determine the **opcode execution level**. + +Determine the real opcode level any time by *executing* a probe on a dev chain (authoritative), not by reading the header: ```bash -curl -sS -H 'Content-Type: application/json' \ - -d '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false],"id":1}' \ - https://rpc.heima-parachain.heima.network | jq '{baseFeePerGas: .result.baseFeePerGas, mixHash: .result.mixHash, withdrawalsRoot: .result.withdrawalsRoot, blobGasUsed: .result.blobGasUsed}' +# spin a dev chain, fund an EVM acct, then: +# deploy a TSTORE/TLOAD contract (Cancun-only) and call it — if it returns its input, EVM >= Cancun. +# (header introspection only tells you what forge-script's simulator will accept, not what the EVM runs.) ``` -If any of `mixHash`/`withdrawalsRoot`/`blobGasUsed` becomes non-null in the future (Heima upgrade), bump `evm_version` accordingly in `crates/agentkeys-chain/foundry.toml` AND re-read the verification check above. - ## Deployed contract registry Live v2 stage-1 contract addresses on each chain are kept in [`docs/spec/deployed-contracts.md`](docs/spec/deployed-contracts.md). The same addresses are also written to `scripts/operator-workstation.env` (via `env_set` in `scripts/heima-bring-up.sh` step 6) for shell-script consumption — those env-file entries are the operational source of truth and `deployed-contracts.md` is the human-readable canonical record (deployer, deploy date, block, explorer links, ABI summary). diff --git a/crates/agentkeys-chain/foundry.toml b/crates/agentkeys-chain/foundry.toml index 81c14a0b..22061411 100644 --- a/crates/agentkeys-chain/foundry.toml +++ b/crates/agentkeys-chain/foundry.toml @@ -4,19 +4,24 @@ out = "out" libs = ["lib"] script = "script" test = "test" -# Heima uses Frontier (EVM-compatible). Frontier's block headers do NOT -# include the `prevrandao` field (Paris+ EVMs require it). Forge's -# simulator validates block headers against its target EVM version -# before broadcasting; with evm_version=paris it errors out on Heima -# mainnet with: -# "EVM error; header validation error: `prevrandao` not set" -# Drop to london (pre-Merge, pre-prevrandao). Our contracts don't use -# any post-london features, so this is a no-op semantically; it's -# purely about the validator's expectations. +# Pin = a `forge script` SIMULATOR workaround, NOT an EVM-capability ceiling. +# +# Heima's EVM *execution* level is actually Cancun (Frontier stable2412's +# pallet_evm config() returns CANCUN_CONFIG). Verified on-chain 2026-06-01: +# PUSH0 (Shanghai) and TSTORE/TLOAD (EIP-1153, Cancun-only) both deploy AND +# execute on a heima-node dev chain. So the chain does NOT reject post-london +# opcodes — the old "london avoids PUSH0 which Heima would reject" note was wrong. # -# Also avoids the Shanghai-era PUSH0 opcode (which london doesn't emit -# either) — keeps the bytecode forwards-compatible with older -# Frontier nodes. +# Why pin london anyway: Heima is a Substrate/Aura parachain via Frontier, so +# its block header has no `prevrandao` field (a PoS-consensus header field, not +# an opcode signal). `forge script ... --broadcast` validates the fetched header +# against the target EVM revision before broadcasting; with evm_version=paris+ +# it errors: +# "EVM error; header validation error: `prevrandao` not set" +# Verified 2026-06-01: DeployAgentKeysV1.s.sol with FOUNDRY_EVM_VERSION=cancun +# reproduces the error; with london it deploys. (forge CREATE --broadcast does +# NOT hit this; our deploy path is forge SCRIPT, so the pin stays.) +# Full diagnosis: CLAUDE.md "Heima EVM compatibility level". evm_version = "london" solc_version = "0.8.20" optimizer = true diff --git a/docs/chain-setup.md b/docs/chain-setup.md index 60982d61..ba0a15b9 100644 --- a/docs/chain-setup.md +++ b/docs/chain-setup.md @@ -95,7 +95,7 @@ The JSON shape is documented in [`docs/arch.md`](arch.md) §22a. Add a new chain ## EVM version pin (Heima-specific) -Heima Frontier runs at London EVM level (pre-Merge). [`crates/agentkeys-chain/foundry.toml`](../crates/agentkeys-chain/foundry.toml) pins `evm_version = "london"` so Foundry's simulator doesn't reject `prevrandao`-less block headers. **Don't change this** without re-verifying against a live Heima block header — see [CLAUDE.md "Heima EVM compatibility level"](../CLAUDE.md) for the verification recipe. +Heima's EVM *execution* level is **Cancun** (Frontier `stable2412` `pallet_evm` `config()` returns `CANCUN_CONFIG`; PUSH0 + TSTORE/TLOAD verified executing on a dev chain 2026-06-01). We still pin `evm_version = "london"` in [`crates/agentkeys-chain/foundry.toml`](../crates/agentkeys-chain/foundry.toml), but **only** because `forge script ... --broadcast` validates Heima's `prevrandao`-less Substrate/Aura block header against the target revision and rejects `paris`+ — it is a simulator workaround, not an opcode ceiling. **Don't change the pin** for the `forge script` deploy path — see [CLAUDE.md "Heima EVM compatibility level"](../CLAUDE.md) for the full diagnosis and the (header-introspection-is-misleading) caveat. Other EVM targets (Ethereum, Base, etc.) are post-Merge and accept `paris` / `shanghai` / `cancun`. For those, override per-deploy: diff --git a/docs/research/ai-hardware-companion-office-hours.md b/docs/research/ai-hardware-companion-office-hours.md index 5b0946ba..3bda48fd 100644 --- a/docs/research/ai-hardware-companion-office-hours.md +++ b/docs/research/ai-hardware-companion-office-hours.md @@ -63,7 +63,7 @@ Skip in v1: ACP/AMP payment rails, MCP marketplace, full LLM resale tier (only s ## Constraints - **Existing AgentKeys infrastructure**: Stage 7+ shipped (broker, OIDC issuer, credential/memory/audit workers, ERC-7730 EIP-712 signing, Heima EVM live). Don't rebuild what exists. -- **Heima EVM**: pinned to `london` per `foundry.toml`. Any on-chain audit anchor must use Heima testnet or Substrate-style cheap anchoring. +- **Heima EVM**: `foundry.toml` pins `evm_version = "london"` as a `forge script` header-validation workaround, but Heima's actual EVM execution level is **Cancun** (see CLAUDE.md "Heima EVM compatibility level"). Any on-chain audit anchor must use Heima testnet or Substrate-style cheap anchoring. - **AWS profile mapping**: `agentkeys-admin` defaults to us-west-2 but operational region is us-east-1. Region-explicit calls only. - **No raw `git`**: all version control via `jj`. - **Idempotency**: every remote-setup script must short-circuit on re-run (per `CLAUDE.md`). diff --git a/docs/spec/deployed-contracts.md b/docs/spec/deployed-contracts.md index e4dd6007..c7f7688d 100644 --- a/docs/spec/deployed-contracts.md +++ b/docs/spec/deployed-contracts.md @@ -54,7 +54,7 @@ Future stage-2/3 work: agentkeys-specific indexing on top of Litentry's fork of - Deployer wallet (EVM): `0xdE644936D5B7d5d42032fd08bbA42Fbbfd6663Bc` - Deployer wallet (Substrate SS58 prefix 31): `47NGSq6JE5ZSnymGNa4nFVjWbsuhTfoSKN2jtpk28mUyC1M3` *(see [funding the EVM side via the Substrate twin](../../scripts/evm-to-substrate-address.mjs))* - Deploy date: 2026-05-19 -- Compiler: Solc 0.8.20, `evm_version = "london"` (matches Heima's Frontier EVM level — see CLAUDE.md "Heima EVM compatibility level") +- Compiler: Solc 0.8.20, `evm_version = "london"` (a `forge script` header-validation workaround, NOT Heima's EVM level — Heima's execution level is actually Cancun; see CLAUDE.md "Heima EVM compatibility level") - Forge: 1.6.0 - Deploy script: [`crates/agentkeys-chain/script/DeployAgentKeysV1.s.sol`](../../crates/agentkeys-chain/script/DeployAgentKeysV1.s.sol) diff --git a/docs/v2-stage2-heima-deploy-and-test.md b/docs/v2-stage2-heima-deploy-and-test.md index 13fd7fd6..b463d2ff 100644 --- a/docs/v2-stage2-heima-deploy-and-test.md +++ b/docs/v2-stage2-heima-deploy-and-test.md @@ -67,7 +67,7 @@ cd - ## 2. Deploy the stage-2 contract set to Heima Mainnet -Heima EVM is at London level (no EIP-7212 P-256 precompile — see [CLAUDE.md](../CLAUDE.md)), so we deploy `P256Verifier` ourselves. The deploy script writes all 6 addresses to stdout in the same stable format the stage-1 bring-up parses. +Heima has no EIP-7212 / RIP-7212 P-256 precompile (`0x100`) registered in its Frontier precompile set, so we deploy the pure-Solidity `P256Verifier` ourselves. (This is independent of EVM version — Heima's EVM execution level is actually **Cancun**, not London; see [CLAUDE.md "Heima EVM compatibility level"](../CLAUDE.md). The `evm_version = "london"` pin is a `forge script` header-validation workaround, not an opcode limit.) The deploy script writes all 6 addresses to stdout in the same stable format the stage-1 bring-up parses. ```bash export AGENTKEYS_CHAIN=heima @@ -251,7 +251,7 @@ All five are tracked under [#90](https://github.com/litentry/agentKeys/issues/90 | Symptom | Diagnosis | Fix | |---|---|---| | `forge test` errors `Stack too deep` | `via_ir` not enabled | Already set in [`foundry.toml`](../crates/agentkeys-chain/foundry.toml) — re-pull, the via_ir = true line should be present | -| Forge broadcast errors `prevrandao not set` | Foundry default `evm_version=paris` rejects Heima's London header | Pass `--evm-version london` to forge script | +| Forge broadcast errors `prevrandao not set` | `forge script`'s simulator validates Heima's Substrate/Aura header (no `prevrandao` field) against the target revision; `paris`+ requires it | Pass `--evm-version london` to forge script (header workaround — Heima's EVM execution level is actually Cancun, this is not an opcode limit) | | `agentkeys k11 enroll --rp-id companion.localhost` fails with "no credential available" in browser | macOS / Safari may not resolve `*.localhost` automatically | Add `127.0.0.1 companion.localhost` to `/etc/hosts`, then retry | | Companion daemon starts but `/v1/companion/whoami` returns 500 | `--companion-operator-omni` not passed | Re-run with `--companion-operator-omni 0x` | | `cast call recoveryThreshold` returns `Error: ... reverted` | You're calling the OLD SidecarRegistry (PR #87 address) | Make sure `SIDECAR_REGISTRY_ADDRESS_HEIMA` in operator-workstation.env points to the NEW instance from §2 | diff --git a/docs/wiki/heima-setup-faq.md b/docs/wiki/heima-setup-faq.md index 5adb0f08..e6c129ef 100644 --- a/docs/wiki/heima-setup-faq.md +++ b/docs/wiki/heima-setup-faq.md @@ -91,7 +91,7 @@ Then re-run the orchestrator from the failing step. ## Q. `forge script` errors with "header validation error: `prevrandao` not set" -Heima Frontier is at London EVM level (pre-Merge). [`crates/agentkeys-chain/foundry.toml`](https://github.com/litentry/agentKeys/blob/main/crates/agentkeys-chain/foundry.toml) must pin `evm_version = "london"`. If you bumped it for unrelated reasons, revert. The full diagnosis is in CLAUDE.md "Heima EVM compatibility level". +`forge script`'s simulator validates the chain's block header against the target EVM revision before broadcasting. Heima is a Substrate/Aura parachain via Frontier, so its header has no `prevrandao` field, and a `paris`+ simulator rejects it. Keep `evm_version = "london"` pinned in [`crates/agentkeys-chain/foundry.toml`](https://github.com/litentry/agentKeys/blob/main/crates/agentkeys-chain/foundry.toml) for the `forge script` deploy path; if you bumped it for unrelated reasons, revert. Note this is a *header-validation* workaround only — Heima's actual EVM execution level is **Cancun** (PUSH0 + transient storage run on-chain), not London. The full diagnosis is in CLAUDE.md "Heima EVM compatibility level". ## Q. Anvil contract addresses are different every run — is that wrong?