Anchor v0.29 → v0.30 Codemod
Automated migration tool for upgrading Solana Anchor projects from v0.29 to v0.30.
Built with ast-grep (sg/jssg engine) + Codemod workflow.
Submitted to the Boring AI Hackathon on DoraHacks.
Quick Start
bash
Version note: this codemod upgrades on-chain crates to anchor-lang / anchor-spl 0.30.1, which matches the commonly installed anchor-cli 0.30.1 patch line and avoids patch-mismatch warnings.
Migration Coverage
Covers all 23 breaking changes from the official Anchor 0.30.0 changelog (release notes); migrate-cargo.sh pins anchor-lang / anchor-spl 0.30.1 to match common anchor-cli 0.30.1 installs:
Automation Boundary (for evaluation)
| Layer | What it handles | Evaluation claim |
|---|---|---|
| Deterministic rules/scripts | Well-scoped mechanical rewrites only | Primary automation claim (safety first) |
| AI step | Edge cases, project-specific cleanup, semantic decisions | Coverage extension, not counted as deterministic fix |
| Manual follow-up | Rare repo-specific dependency/build reconciliation | Explicitly tracked in validation notes |
Current practical claim:
- Deterministic auto-fix: 6 high-confidence migration classes
- AI-assisted coverage: 11 classes
- Reminder/separate handling: 6 classes
- Overall workflow automation target: 80%+ with deterministic + AI pipeline
Auto-fixed (6 items)
| Change | Rule / Script |
|---|---|
ctx.bumps.get("x").unwrap() → .copied() | anchor-bumps-option-type.yml |
AnchorProvider(conn, wallet, {}) → 2 args | anchor-ts-provider-init.yml |
new Program(idl, programId[/PROGRAM_ID][, provider]) migration | anchor-ts-program-id-arg-* (4 scoped Program rules) |
anchor-lang = "0.29.x" → 0.30.1 (optional --with-idl-build) | migrate-cargo.sh |
anchor-spl = "0.29.x" → 0.30.1 | migrate-cargo.sh |
Remove idl-parse / seeds features + add overflow-checks | migrate-cargo.sh |
Marked for AI review (11 items)
| Change | Rule / Handler |
|---|---|
anchor_spl::shared_memory removed | anchor-remove-shared-memory.yml (TODO) |
CLOSED_ACCOUNT_DISCRIMINATOR removed | anchor-remove-closed-account-discriminator.yml (warning) |
anchor_syn::idl → anchor_lang_idl imports | anchor-idl-import-path.yml (TODO) |
Optional account bump types u8 → Option<u8> | AI step |
IDL enums #[non_exhaustive] | AI step |
accounts() no longer accepts resolvable accounts | anchor-ts-auto-accounts-system-program, anchor-ts-auto-accounts-clock, anchor-ts-auto-accounts-rent, anchor-ts-auto-accounts-token-program |
| camelCase method names | AI step |
| Remove discriminator functions | AI step |
Remove associated / associatedAddress methods | AI step |
Remove anchor-deprecated-state feature | AI step |
anchor-syn features removed | AI step |
Zero-FP Guardrails
Programconstructor rewrite is now strictly scoped to explicitprogramId/PROGRAM_IDforms (2-arg and 3-arg with provider); it does not rewrite arbitrary argument forms..accounts()migration rules are scoped to explicit.accounts({...})calls only; non-.accounts()object arguments are ignored.- Cargo feature cleanup only edits
anchor-lang/anchor-syndependency lines (no global string replacement across unrelated crates).
CLI reminders (4 items)
| Change | Handler |
|---|---|
build-bpf → build-sbf | AI step prompt |
idl upgrade closes buffer | AI step prompt |
Remove --jest option | AI step prompt |
| Solana upgraded to 1.18.8 | AI step prompt |
Separate codemod (2 items)
| Change | Handler |
|---|---|
| IDL v0 → v1 schema migration | Tracked as separate codemod |
anchor-syn idl-parse/seeds removal | AI step + Cargo.toml sed (anchor-lang/anchor-syn lines) |
Project Structure
text
Testing
Synthetic fixtures
bash
Real-world projects (validated)
| Project | Git | Dry-run | Apply | Build | Notes |
|---|---|---|---|---|---|
Anchor official v0.29.0 (framework mono-repo) | https://github.com/solana-foundation/anchor/tree/v0.29.0 | PASS | PASS | FAIL | Workflow works, but this repo is Anchor framework source (not a typical target program repo), so build failures are not used as codemod success criteria. |
solana-presale-smart-contract | https://github.com/rustjesty/solana-presale-smart-contract | PASS | PASS | PASS (anchor build --no-idl) | Required post-migration dependency cleanup in target repo: remove hard-pinned legacy deps and align to Anchor 0.30 dependency graph. |
Validation date: 2026-05-01 (UTC+8)
Command shape used in both real repos:
bash
Local verification in this repository
Verified in this repo (2026-04-30):
npx codemod workflow validate -w workflow.yamlpassednpx codemod workflow run -w workflow.yaml -t <fixture> --param target=<fixture> --dry-runpassed (ast-grep steps + workflow wiring)sg scan --config sgconfig.yml test-fixtures/old_program.rsmatched expected Rust patternssg scan --config sgconfig.yml test-fixtures/old_program.tsmatched expected TypeScript patterns
For reproducible real-repo evidence recording, use local template: REAL_WORLD_VALIDATION_TEMPLATE.md.
Safety vs Coverage Modes
- Safe mode (default script behavior): prioritizes lower false-positive risk; does not force
idl-build. - Coverage mode (workflow default):
workflow.yamlrunsmigrate-cargo.sh --with-idl-buildto align with Anchor 0.30 breaking requirement around IDL build.
Using the Full Workflow
If you have the Codemod CLI installed:
bash
Notes:
- YAML
ast-grepsteps expectconfig_fileto point at rule YAML (each rule has a top-levelid). That is what lives underrules/. Do not pointconfig_fileatsgconfig.yml(that file usesruleDirsand will fail Codemod parsing withmissing field id). - Shell steps (
migrate-cargo.sh,cargo fmt) run with the host working directory, not-t. Pass the same Anchor repo path for-tand--param target=...so Cargo steps execute inside the project being migrated.
Hackathon
- Category: Production-grade Migration Recipes (XL tier)
- Pre-approved: Anchor v0.29 → v0.30 Rust API changes — Changelog
- Coverage: 23/23 breaking changes mapped (6 deterministic auto-fix + 11 AI-assisted + 6 reminders/separate handling)
- False-positive policy: deterministic rules are intentionally narrow; zero-FP target applies to deterministic transforms (AI/manual layer handles ambiguous cases)
Evaluator Notes
- Deterministic transforms are intentionally conservative to minimize false positives on real repositories.
- Ambiguous or project-specific migration cases are explicitly delegated to the AI/manual layer instead of risky auto-rewrites.
- Workflow execution is reproducible on real open-source repos with documented dry-run/apply/build evidence.
- Safety-first defaults are provided for scripts, while workflow mode enables stronger breaking-change coverage when required.
License
MIT