Skip to content

Initializations: version-addressed init contracts run atomically at publish - #86

Merged
charlesHetterich merged 10 commits into
versioned-proxiesfrom
initializations
Sep 3, 2026
Merged

Initializations: version-addressed init contracts run atomically at publish#86
charlesHetterich merged 10 commits into
versioned-proxiesfrom
initializations

Conversation

@charlesHetterich

@charlesHetterich charlesHetterich commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Adds initializations: code that runs exactly once, in the same transaction that publishes a version, against the name's proxy storage. Covers both first-publish setup and upgrade-time storage migration. Closes #77.

How it works

An initialization is addressed by (contract, version) and runs when that version is published. No file for a version → plain publish. A file for an already-published version never runs again.

# Rust                                 # Solidity
counter/                               contracts/
  src/lib.rs                             Counter.sol
  initializations/                       initializations/
    0.1.0.rs                               Counter/
    1.3.0.rs                                 0.1.0.sol

Each file exposes initialize(uint128 from, address owner)from is the previous latest version (0 on first publish), owner the name's registry owner. A revert rolls back the whole publish.

  • Rust: no Cargo.toml changes — cdm deploy builds the file through a generated shim crate. Each file declares its own copy of the contract's storage fields, so old initializations are frozen text that later contract changes can't break.
  • Solidity: the file's contract inherits the target (contract Init is Counter); the directory name routes it.

A deploy-time layout guard compares the initialization's storage layout against the implementation's and refuses on mismatch.

On-chain changes

  • Per-name proxy gains one admin-only meta op, callCode(address, bytes) — delegatecall into proxy storage, live while frozen (so freeze → publish+init → unfreeze works). The frozen proxy blob is regenerated: 0x9c918a8b…542e86.
  • Registry gains publishWithInit(...), which publishes and then calls callCode on the proxy. Initialization contracts are never registered versions, so callCode is the only path to them — no access-control boilerplate needed in user code.

Also

@charlesHetterich

Copy link
Copy Markdown
Collaborator Author

Revised the Solidity convention per review: initializations are now addressed by (contract, version) uniformly — Rust <crate>/initializations/<version>.rs (the crate names the contract), Solidity initializations/<Contract>/<version>.sol (the directory names the contract, mandatory even for single-contract projects). The flat inheritance-routed form collided the moment two contracts needed an initialization at the same version and interleaved per-contract histories; the directory is now the router and inheritance is demoted to validation, with sharp errors for flat-placed files and directories naming no detected contract. PR body updated; foundry template, tests, and docs moved to the nested layout.

@charlesHetterich
charlesHetterich merged commit fef1c0a into versioned-proxies Sep 3, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant