Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6b01e2e
test: mutation-harden LibOpConditions coverage
thedavidmeister Jun 15, 2026
44fab0c
[3b-attempt] test: one contract per file (fix pre-existing static vio…
thedavidmeister Jun 15, 2026
1cb2b12
Merge remote-tracking branch 'origin/main' into 2026-06-15-libop-cove…
thedavidmeister Jun 19, 2026
40e88cf
merge(main): resolve conflicts [merge-update]
thedavidmeister Jun 19, 2026
655a02b
Merge remote-tracking branch 'origin/main' into 2026-06-15-libop-cove…
thedavidmeister Jul 5, 2026
a87eafc
Remove submodule-era residue from .soldeerignore
thedavidmeister Aug 15, 2026
55fa2cc
merge(main): resolve one-contract-per-file collision with #549
Aug 18, 2026
9352cb1
Bump rain-solmem 0.1.3 -> 0.1.26 and the dep chain pinning it
Aug 22, 2026
341c99f
Regenerate ABI artifacts; trim CLAUDE.md under the agent-context cap
Aug 22, 2026
1fad1fd
Merge pull request #560 from rainlanguage/bump-solmem-0.1.26
thedavidmeister Aug 22, 2026
ea7dac6
Migrate to the tag-driven release standard, in-repo
Aug 23, 2026
785103a
Declare the measured dependency reach set, not the copied one
Aug 23, 2026
e536078
Merge pull request #563 from rainlanguage/2026-08-23-tag-release-migr…
thedavidmeister Aug 23, 2026
4503ef3
Expose the deploy reusable's legacy and verify inputs
Aug 23, 2026
d1ad78e
Describe HyperEVM's fee-history behaviour as measured
Aug 23, 2026
20bad4f
Drop the legacy input: HyperEVM does not need type-0
Aug 23, 2026
072df38
Merge pull request #564 from rainlanguage/2026-08-23-deploy-workflow-…
thedavidmeister Aug 23, 2026
6177baa
Cut release 0.1.9: freeze candidate pins as src/generated/0_1_9/
Aug 25, 2026
0cec49c
Drop the Build Environment section
Aug 25, 2026
c298c94
Merge pull request #568 from rainlanguage/2026-08-25-release-sol-v0.1.9
thedavidmeister Aug 25, 2026
201f6bd
Merge pull request #569 from rainlanguage/2026-08-25-drop-stale-build…
thedavidmeister Aug 25, 2026
8ed598e
Rename the Git is clean job id to git-clean
Aug 27, 2026
068e38e
Merge pull request #572 from rainlanguage/571-git-clean-job-id
thedavidmeister Aug 27, 2026
dac6552
Bump rain-solmem 0.1.26 -> 0.1.28 and the dep chain pinning it
Sep 6, 2026
86be118
Merge pull request #573 from rainlanguage/2026-09-06-bump-solmem-0.1.28
thedavidmeister Sep 6, 2026
e8e510f
Move the deployed contracts' logic into BaseRainlang* abstracts
Sep 6, 2026
5692a3f
Refresh the committed ABI copies for the thinned concretes
Sep 6, 2026
10a1af0
Make the test concretes' bindings virtual so tests can subclass them
Sep 6, 2026
93f2825
Slim to the library half: the deploy half moves to rainlang.deploy
Sep 6, 2026
5675aa7
Merge pull request #575 from rainlanguage/2026-09-06-base-rainlang-ab…
thedavidmeister Sep 7, 2026
a60b17d
Merge remote-tracking branch 'origin/main' into 2026-09-06-slim-to-li…
Sep 7, 2026
51056ff
Keep the frozen 0_1_9 record: snapshots are append-only org-wide
Sep 7, 2026
9ea0d2b
Exclude slither's unimplemented-functions detector
Sep 7, 2026
8ffb22e
Drop the crates ignore from .prettierignore: no crates here
Sep 7, 2026
801055a
Merge pull request #576 from rainlanguage/2026-09-06-slim-to-library
thedavidmeister Sep 7, 2026
06ffe3c
Merge pull request #554 from rainlanguage/553-soldeerignore-submodule…
thedavidmeister Sep 7, 2026
8956238
Spell the pinned forge-std and rain-sol-codegen versions in every import
Sep 7, 2026
2a2a1f4
Merge pull request #577 from rainlanguage/2026-09-07-spell-pinned-ver…
thedavidmeister Sep 7, 2026
6c9198f
Merge branch 'pr-536' into review-536
Sep 7, 2026
1addc75
Spell rain-solmem 0.1.28 in the new imports
Sep 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 0 additions & 3 deletions .cargo/config.toml

This file was deleted.

1,573 changes: 0 additions & 1,573 deletions .gas-snapshot

This file was deleted.

10 changes: 0 additions & 10 deletions .github/workflows/copy-artifacts.yaml

This file was deleted.

13 changes: 13 additions & 0 deletions .github/workflows/git-clean.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Git is clean
on: [push]
jobs:
git-clean:
# Shared reusable (rainix#201): rebuild the committed artifacts from
# committed sources — `script/Build.sol`, `forge build`, CopyArtifacts,
# `forge fmt` — then `git diff --exit-code`. This is what makes the
# committed `src/generated/` record current at PR time rather than only at
# tag time. Includes the Cachix substitution + 8G GC cap; no prelude
# (committing the artifacts is what removes the need for one).
# secrets: inherit carries CACHIX_AUTH_TOKEN.
uses: rainlanguage/rainix/.github/workflows/rainix-copy-artifacts.yaml@main
secrets: inherit
20 changes: 0 additions & 20 deletions .github/workflows/manual-sol-artifacts.yaml

This file was deleted.

10 changes: 4 additions & 6 deletions .github/workflows/package-release.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
name: Package Release
# Library repo: the `rainlang` Soldeer package autopublishes on every merge to
# main under rainix-autopublish's next-version lifecycle. The deployed
# contracts, their deploy records and the manual `sol-v*` tag flow live in
# rainlang.deploy.
on:
push:
branches:
- main
jobs:
release:
# Bumps + publishes the rainlang crates to crates.io as a lockstep set, in
# dependency order (bindings, dispair, parser, eval, then test_fixtures):
# changing any member republishes the others with matching version pins, via
# the PUBLISH_PRIVATE_KEY deploy key. test_fixtures depends on none of the
# others but is released in lockstep so its embedded bytecode stays in sync.
uses: rainlanguage/rainix/.github/workflows/rainix-autopublish.yaml@main
with:
crates: rainlang_bindings rainlang_dispair rainlang_parser rainlang-eval rainlang_test_fixtures
soldeer-package: rainlang
secrets: inherit
5 changes: 0 additions & 5 deletions .github/workflows/rainix-rs-static.yaml

This file was deleted.

5 changes: 0 additions & 5 deletions .github/workflows/rainix-rs-test.yaml

This file was deleted.

1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
crates/abi/
8 changes: 2 additions & 6 deletions .soldeerignore
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
.DS_Store
.cargo
.coderabbit.yaml
.devcontainer.json
.envrc
.gas-snapshot
.git
.github
.gitignore
.gitmodules
.pre-commit-config.yaml
.prettierignore
.soldeerignore
.vscode
CLAUDE.md
TESTING.md
/audit
/cache
/dependencies
/flake.lock
/flake.nix
/foundry.lock
/foundry.toml
/lib
/out
/remappings.txt
/slither.config.json
/soldeer.lock
/REUSE.toml
/deployments
/meta
/script
275 changes: 71 additions & 204 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,209 +1,76 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with
code in this repository.

**This file takes precedence over session summaries.** When a session is
restored from a compressed summary, the summary may contain incorrect
interpretations of processes defined here. Always re-read and follow this file
as written — do not rely on the summary's framing of what a process means or
what the user intended.

## Build Environment

This project uses **Nix flakes** for development. All commands must be run
inside `nix develop` or prefixed with `nix develop -c`. The `.envrc` auto-loads
the nix shell via direnv.

### Prerequisites (run once per session, in order)

```bash
nix develop -c rainix-sol-prelude
nix develop -c rainix-rs-prelude
nix develop -c rainlang-prelude
```

`rainlang-prelude` generates metadata files needed by the Solidity build (runs
`BuildAuthoringMeta.sol`, then `rain meta build` to produce CBOR-encoded
deflated meta).

### Common Commands

```bash
# Solidity
nix develop -c rainix-sol-test # forge test (all tests)
nix develop -c rainix-sol-static # slither + forge fmt check
nix develop -c rainix-sol-artifacts # build artifacts

# Run a single Solidity test
nix develop -c forge test --match-test "testFunctionName"
nix develop -c forge test --match-contract "ContractName"

# Rust
nix develop -c rainix-rs-test # cargo test
nix develop -c rainix-rs-static # cargo fmt --check + cargo clippy
nix develop -c test-wasm-build # WASM compilation check

# Docs
nix develop -c forge doc -b # Solidity docs
nix develop -c cargo doc # Rust docs
```

### Build Pipeline

1. `BuildAuthoringMeta.sol` exports raw ABI-encoded authoring meta to `meta/`
2. `rainlang-prelude` runs `rain meta build` to CBOR-encode and deflate the meta
3. `nix develop -c forge script --silent ./script/Build.sol` deploys contracts
in local EVM, extracts function pointer tables, and writes
`src/generated/*.pointers.sol`
4. `nix develop -c forge build` compiles everything using the generated pointers

After `forge build`, check for warnings. Address all warnings before proceeding
to pointer rebuild, tests, or the next task.

The `src/generated/` directory contains build-time generated constants (bytecode
hashes, function pointer tables, parse meta). These are regenerated by
`Build.sol`.

After any source change affecting bytecode: run
`nix develop -c rainlang-prelude` →
`nix develop -c forge script --silent ./script/Build.sol` →
`nix develop -c forge fmt`, then run `LibInterpreterDeployTest` to get new
deploy addresses/codehashes. Update `LibInterpreterDeploy.sol` and repeat until
stable (constants cascade through the deploy chain).

## Architecture

### Core Components

1. **RainlangParser** (`src/concrete/RainlangParser.sol`) — Converts Rainlang
text to bytecode. Uses bloom filter + fingerprint table for word lookup.

2. **RainlangStore** (`src/concrete/RainlangStore.sol`) — Sandboxed key-value
storage. Namespaced by `msg.sender` + `StateNamespace`.

3. **RainlangInterpreter** (`src/concrete/RainlangInterpreter.sol`) —
Stack-based evaluation runtime. Entry point: `eval4()`. Dispatches opcodes
via function pointer tables.

4. **RainlangExpressionDeployer**
(`src/concrete/RainlangExpressionDeployer.sol`) — Coordinates parse →
integrity check → serialize. Implements `IParserV2`.

5. **Rainlang** (`src/concrete/Rainlang.sol`) — On-chain registry and single
discovery point for the deployer, interpreter, store, and parser. External
tooling discovers all component addresses by querying a single known Rainlang
address.

All five are deployed to deterministic addresses via Zoltu deployer. Addresses
and code hashes are in `src/lib/deploy/LibInterpreterDeploy.sol`. Deploy
constants cascade: parser → expression deployer → Rainlang. Interpreter changes
also cascade to Rainlang.

### Opcode System

Each opcode is a library in `src/lib/op/<category>/` with three functions:

- **`run(Operand, Pointer stackTop) → Pointer`** — Runtime execution
- **`integrity(IntegrityCheckState, Operand) → (inputs, outputs)`** —
Pre-execution validation
- **Operand handler** — Parses operand bytes during parsing

All opcodes are registered in `src/lib/op/LibAllStandardOps.sol` which maintains
four parallel arrays (authoring meta, operand handlers, integrity pointers,
opcode pointers). The ordering must be consistent across all four arrays.

### Extern System

External contracts can extend the interpreter with additional opcodes.
`src/concrete/extern/RainlangReferenceExtern.sol` is the reference
implementation. Externs implement `IInterpreterExternV4` and have their own
function pointer tables.

### Rust Crates (`crates/`)

- **cli** — CLI tool (`rainlang-cli`)
- **eval** — Evaluation runtime using REVM/foundry-evm
- **parser** — Rust parser implementation
- **dispair** — Dispatch pair utilities
- **bindings** — Alloy Solidity contract bindings
- **test_fixtures** — Shared test fixtures (deploys all contracts on local
Anvil)

### Deployment

`script/Deploy.sol` uses the `DEPLOYMENT_SUITE` env var to select which
component to deploy: `"parser"`, `"store"`, `"interpreter"`,
`"expression-deployer"`, or `"rainlang"`.

## Solidity Conventions

- **Solidity version**: exactly `0.8.25`, EVM target `cancun`
- **Optimizer**: enabled, 1000000 runs
- **Fuzz runs**: 2048
- Source of truth for these settings is `foundry.toml`
- **License**: `LicenseRef-DCL-1.0` with copyright
`Rain Open Source Software Ltd`
- Custom bytecode serialization is used instead of ABI encoding for gas
efficiency
- Function pointer dispatch (no switch/if chains) for opcode routing
- Assembly blocks are used extensively and marked `memory-safe` where applicable
- NatSpec: when a doc block contains any explicit tag (e.g. `@title`), all
entries must be explicitly tagged — untagged lines continue the previous tag,
not implicit `@notice`

## Test Conventions

Testing patterns and conventions are in `TESTING.md`. Read that file before
writing tests.

- Test files are in `test/` mirroring `src/` structure, suffixed `.t.sol`
- Rust test fixtures (`crates/test_fixtures/`) deploy all five contracts on a
local Anvil instance
- Always run test commands with `run_in_background: true` so work continues in
parallel
- While background builds or tests run, continue with other work that doesn't
depend on the build result — e.g. triage presentation, code review,
documentation edits
Guidance for Claude Code in this repo. This file takes precedence over session
summaries — re-read it as written rather than trusting a summary's framing of
what a process means.

## What this repo is

The **library half** of Rainlang: the parser, eval loop, standard ops, integrity
checks, the `BaseRainlang*` contracts and the extern / sub-parser bases,
published as the `rainlang` Soldeer package on every merge to main
(`rainix-autopublish`, next-version lifecycle via `next-v*` tags). The deployed
concretes, their generated tables and deploy records, the deploy scripts and the
Rust crates live in `rainlang.deploy`, which consumes this package.

`src/concrete/extern/RainlangReferenceExtern.sol` is a reference implementation
of the extern and sub-parser bases, not a deployable: it stays here with its
tests.

## Generated code

`script/Build.sol` writes `src/generated/RainlangReferenceExternPointers.sol` —
the reference extern's parse meta, function pointer tables and meta hash.
Committed because contract and pointers file depend on each other circularly.
Never hand-edit it. `src/generated/0_1_9/` is the frozen record of the last
release this repo cut while it still carried the deploy half; nothing here reads
it, and it stays because frozen snapshots are append-only org-wide (rainix
`frozen-snapshots-append-only`). After any source change affecting the extern's
bytecode:

1. `nix develop -c rainlang-prelude`
2. `nix develop -c forge script --silent ./script/Build.sol`
3. `nix develop -c forge fmt`

Address all `forge build` warnings before pointer rebuild, tests, or the next
task.

## Test harness

`test/concrete/Test*.sol` are the `BaseRainlang*` contracts built from current
source with no generated tables; `test/lib/deploy/LibTestInterpreterDeploy.sol`
places them at fixed test addresses and
`test/abstract/RainlangExpressionDeployerDeploymentTest.deployRainlang()` is the
one hook that binds them. `rainlang.deploy` and the word repos override that
hook with the deployed pins, so `test/` ships in the package: `/test` is
deliberately absent from `.soldeerignore`.

`optimizer_runs = 1000000` looks wrong (the org uses 100000) and is
load-bearing: every live CREATE2 address in `rainlang.deploy` is a pure function
of the bytecode this package's sources compile to.

## Conventions

- Compiler, optimizer and fuzz settings: `foundry.toml` is the source of truth.
- NatSpec: if a doc block has any explicit tag, every entry must be tagged —
untagged lines continue the previous tag, not implicit `@notice`.
- Tests: read `TESTING.md` before writing tests. Run test commands with
`run_in_background: true` and continue independent work meanwhile.

## Process (Jidoka)

Jidoka is a priority: process correctness (correct future) over ad hoc progress
(present state). Quality at the source enables throughput; skipping quality
steps creates rework and slows overall flow. Process introspection takes
precedence over following the process.

Each fix is a complete cycle: understand → write test → run test (confirm fail)
→ write fix → run test (confirm pass) → run full suite → verify. Do not move to
the next item with incomplete work. New code must meet the same audit
requirements defined in the `/audit` skill — a fix that introduces untested
error paths, missing NatSpec, or other audit findings is not complete.

When fixing bugs, follow TDD: write a test that reproduces the bug, run it to
confirm it fails, then write the fix and run the test again to confirm it
passes. Do not write the fix before running the test and confirming it
reproduces the bug.

When the user says "jidoka," they are signaling a process defect. The response
is:

1. Identify the process defect.
2. Propose a durable fix (document edit, rule change).
3. **Stop and wait for agreement.** Do not resume task work, run commands, or do
anything else. The process fix is the deliverable of that moment.

When the user asks "why" about a defect, they are asking for root cause analysis
of the process failure — not requesting that you go do the thing. Answer the
"why" first, agree on the process fix, then resume.

Do not claim motivations or internal states. Describe what you actually did, not
a story about why. Say "I skipped the test suite run" not "I was optimizing for
throughput." Say "the rule is in CLAUDE.md" not "I've internalized it." You have
no metrics, no persistence, and no self-observation — narratives about your own
reasoning are fabrications.

## Audit Review

Audit instructions are available as skills: `/audit` (full overview),
`/audit-pass0` through `/audit-pass5` (individual passes), and `/audit-triage`
(finding triage).
Process correctness (correct future) over ad hoc progress (present state). Each
fix is a complete cycle: understand → write test → run it (confirm it fails) →
fix → run it (confirm it passes) → full suite → verify. Never write the fix
before the failing test reproduces the bug. Do not move on with incomplete work;
new code meets the `/audit` skill's requirements.

"jidoka" from the user signals a process defect: identify it, propose a durable
fix (document edit, rule change), then STOP and wait for agreement — the process
fix is the deliverable of that moment. A "why" question asks for root cause
analysis of the process failure, not for the task to be done.

Do not claim motivations or internal states. Describe what you actually did ("I
skipped the test suite run"), not a story about why — you have no metrics, no
persistence, no self-observation; narratives about your own reasoning are
fabrications.
Loading
Loading