# Upgrading to 0.7

0.7 changes what `deployoor generate` writes and what you do with it. Two things move:

* **Generated deployers no longer inline `standardJsonInput`.** They carry a name, a fully-qualified name and an ABI; everything else is read from your compiled artifacts when a deploy runs. Files that were hundreds of kilobytes are now a few.
* **`deployers/` is committed.** It used to be build output you gitignored. It is now small enough to diff and needed for a fresh clone to typecheck, so it belongs in the repo.

There is also a new command, [`deployoor verify`](/reference/cli#verify), which verifies a deployment from its record long after the deploy — see [verifying later](/concepts/version-control#verifying-later).

## Point an agent at this page

The whole upgrade is mechanical except for two judgement calls, both flagged below. If you use a coding agent, this works:

```text
Upgrade this project to deployoor 0.7 by following
https://deployoor.dev/guides/upgrading. Work through the steps in order.
Stop and ask me at the two points marked "ask first".
```

## 1. Bump the packages

`deployoor` 0.7 and, if you use them, the verifier plugins — their `onVerify` hook needs the new core, so their peer range requires it.

```bash
pnpm add -D deployoor@^0.7.0
pnpm add -D @deployoor/etherscan@^0.3.0 @deployoor/sourcify@^0.3.0   # if you use them
```

`@deployoor/hardhat`, `@deployoor/testing`, `@deployoor/slack` and `@deployoor/wagmi` need no bump — nothing they call changed shape.

## 2. Recompile, then regenerate

Order matters. `generate` reads compiled artifacts, and from 0.7 so does every deploy — so an artifacts directory that is stale or absent is now an error at both points rather than something the old inlined deployers papered over.

```bash
npx hardhat compile && npx deployoor generate
# or
forge build && npx deployoor generate
```

Delete any previously generated tree first if your `out` directory changed. Otherwise `generate` overwrites in place and stale files for contracts you have since deleted stay behind.

## 3. Commit `deployers/`

`generate` checks whether git is ignoring its own output and offers to remove the rule:

```text
deployoor: generated 3 file(s)
deployoor: git is ignoring output that is meant to be committed:
  .gitignore:4 (`deployers`) ignores deployers/ — the generated deployers, which a fresh
  clone cannot typecheck or deploy without
deployoor: remove line 4 of .gitignore now? [y/N]
```

Accepting takes the rule and any deployoor comment introducing it, so you are not left with `# generated by deployoor generate` above nothing. `deploymentsPath` is checked the same way, since a rule ignoring your records is the worse of the two.

The question is put to `git check-ignore`, not answered by reading `.gitignore`, so a nested ignore file or a `!deployers/` you already added is accounted for — if you overrode the rule yourself, you are not asked again.

Two cases report and stop there rather than offering an edit:

* **The pattern covers more than deployoor's output** — `build` when your `out` is `./build/deployers`. Removing it would un-ignore everything else under `build/`, which is your call, not deployoor's. Add `!build/deployers/` below it, or move `out`.
* **The rule lives outside the project** — `.git/info/exclude` or a global `core.excludesFile`. Those are clone- or machine-wide, so they are named and left alone.

Then exclude the directory from your formatter and linter. An ABI is emitted as one long line, so both will want to rewrite files that regenerating puts straight back — see [version control](/concepts/version-control#tell-your-formatter-to-skip-them).

:::warning[Ask first]
Committing `deployers/` is a repository convention, not a correctness requirement. Everything still works if you keep ignoring them, as long as everyone who clones the repo knows to run `generate` before typechecking. Ask before editing a `.gitignore`.
:::

## 4. Deploys and tests now need compiled artifacts

A deployer resolves its bytecode, compiler version and sources from `artifacts/` (or `out/`) at the moment you call it. Nothing is inlined, so nothing can be deployed from a tree that has not been compiled. The failure names the toolchain it found and the command to run:

```text
No compiled artifacts in /repo/artifacts.

This is a Hardhat project (found hardhat.config.ts), so deployoor looked in the default output
directory. Either:
  1. Nothing compiled yet — run `npx hardhat compile`.
  2. The output lives elsewhere — deployoor reads paths.artifacts in hardhat.config
     when it can, so if that is set and this path is still wrong, name it directly:
       export default defineConfig({ artifactsPath: "./build/artifacts" })
```

If your test script ran `vitest` directly, it now needs a compile in front of it:

```json
{
  "scripts": {
    "test": "hardhat compile && vitest run"
  }
}
```

Tests that build a `TypedArtifact` by hand, and `@deployoor/testing`, are unaffected — a full artifact is used as given and never sends deployoor to disk.

## 5. A changed ABI is now an error, not a silent mismatch

The generated ABI is compared against the compiled one on every deploy. Drift means the deployers were generated from an older compile, so the run stops and names what moved:

```text
contracts/Counter.sol:Counter's abi no longer matches its compiled artifact.

Re-run `deployoor generate`, then deploy again.

  - function gone() view
```

This is the failure that previously did not exist: the old inlined ABI would have encoded your constructor arguments against an interface the deployed contract does not have, and written that ABI into the record. Regenerating is the whole fix.

Reordered entries are not drift — the comparison ignores entry order, key order, and `internalType`, all of which solc varies freely.

## 6. Deployments recorded before 0.7

Your existing records in `deployments/` are read unchanged: no field changed shape, and the pinned sources under `deployments/sources/` keep resolving because the sidecar format and the way its hash is computed are both untouched.

One case needs your attention. A record can only be verified after the fact if it has a `sourcesHash` and the blob it points at is still in the repo:

```bash
# records with no pinned sources (use your deploymentsPath if you changed it)
grep -LE '"sourcesHash"[[:space:]]*:[[:space:]]*"0x' deployments/*/*.json \
  | grep -vE '^deployments/sources/|\.sources\.json$'
```

Both halves earn their keep.

The pattern matches the **field**, not the word. A record whose ABI happens to contain an entry named `sourcesHash` would satisfy a bare `grep -L sourcesHash` and drop out of the list while still having no pinned sources — a silent omission from the one list where that matters.

The second `grep` drops two kinds of file that live under `deployments/` without being records: the pinned blobs in `deployments/sources/`, and the per-deployment `<Name>.sources.json` sidecars older projects have from before pinning was content-addressed. Neither carries a `sourcesHash` of its own, so without it every one is listed as a deployment needing attention — and this being an upgrade guide, those are exactly the projects that have them. `fsStore` skips both when it reads records; this makes the one-liner agree with it.

Anything listed there cannot be verified by `deployoor verify` at all — not "only while the source tree matches". The fully-qualified contract name and the standard-json input live solely in the sidecar, so with no `sourcesHash` there is nothing to submit, and the record is reported `unverifiable` before any plugin runs. A matching working tree does not help, because nothing reads it.

Two ways forward, neither free:

* **Verify it with your explorer's own tooling**, against the source tree at the commit it was deployed from. That is the only route that verifies *that* address.
* **Redeploy.** The new deploy pins its sources and is verifiable from then on — but it is a new contract at a new address, recorded alongside the old one. It does not make the historic deployment verifiable.

:::warning[Ask first]
Deciding what to do about unverifiable historic records depends on which of those contracts anyone actually needs verified. Ask rather than guessing.
:::

## 7. If you wrote a plugin

`VerifyContext` is new and `onVerify` is optional, so an existing plugin keeps working with no change. If you add `onVerify`, note that its context carries `deployment` and `metadata` and nothing else — there is no `options`, because a plugin instance already closes over its own options.

See [plugins](/guides/plugins#onverify) for the hook and what it receives.

## Nothing else changed

`getOrDeploy*`, `register`, `reset`, the shape of a deployment record, `deployoor.config.ts`, the store adapters, and the `@wagmi/cli` bridge are all as they were.
