Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 18 additions & 20 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
29 changes: 17 additions & 12 deletions crates/agentkeys-chain/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion docs/chain-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
2 changes: 1 addition & 1 deletion docs/research/ai-hardware-companion-office-hours.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`).
Expand Down
2 changes: 1 addition & 1 deletion docs/spec/deployed-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions docs/v2-stage2-heima-deploy-and-test.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<omni>` |
| `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 |
Expand Down
2 changes: 1 addition & 1 deletion docs/wiki/heima-setup-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -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?

Expand Down
Loading