Skip to content

Migrate to the compiler-derived candidate source anchor, and answer the no-artifact candidate: rain-deploy removes DeployCandidate.sourceCreationCode #27

Description

@thedavidmeister

Upstream change

rainlanguage/rain.deploy#242 removes DeployCandidate.sourceCreationCode and
makes checkCandidatesAnchoredToSource resolve the candidate's own
snapshot.artifactPath through vm.getCode instead. The source operand now
comes from the compiler rather than from the declaration.

The removed field was one a consumer filled in. Pointing it at the same
generated constant as the record made the one check that catches a snapshot of
the wrong contract compare a value with itself — green for any candidate at all,
in CI and on the irreversible RainDeployBroadcast.run() path alike. That is
rainlanguage/rain.factory.deploy#34, which #242 closes.

This is a BREAKING change. This repo has two candidates: one migrates
mechanically, and one cannot be expressed under #242 as written.

BLOCKER: the log-tables candidate has no compiler artifact to anchor to

src/abstract/DecimalFloatDeploySuites.sol, logTablesCandidate() (lines
64-77):

artifactPath: "",
...
sourceCreationCode: LibDataContract.contractCreationCode(LibDecimalFloatDeploy.combinedTables())

There is no Solidity contract behind this suite. Its creation code is
LibDataContract's data-contract wrapper around the bytes
LibDecimalFloatDeploy.combinedTables() (src/lib/deploy/LibDecimalFloatDeploy.sol:59,
internal pure) concatenates out of src/generated/LogTables.pointers.sol. The
declaration's own doc comment says so, and says the artifact path is empty
"because there is no source file for an explorer to verify against".

After #242 the anchor runs vm.getCode(candidates[i].snapshot.artifactPath) over
every candidate, with NoDeployCandidates refusing a declaration that names
none and no way to spell an exemption. vm.getCode("") resolves to no artifact.
So this candidate does not merely lose a field — it fails the anchor, and it
fails it inside RainDeployBroadcast.run() before the broadcast, not only in CI.

This is an upstream gap rather than a local slip: #242's migration text assumes
every candidate's source is a compiler artifact, and this one legitimately is
not. Resolving it is a precondition for this repo's migration, not a detail of
it.
It needs an answer in rainlanguage/rain.deploy#242 (or a follow-up there)
before the edits below are worth making. Directions, none of them chosen here:

  • a documented way for a candidate to declare that its source is derived rather
    than compiled, which the anchor honours without becoming an exemption a
    consumer can spell for an ordinary contract;
  • emitting a real Solidity artifact for the log tables so artifactPath has
    something to resolve to;
  • keeping the log tables out of the candidate set entirely and anchoring them by
    some other check.

raindex has the same problem from a different direction — see its issue, whose
route-processor candidate is a vendored bytecode constant with
artifactPath: "RouteProcessor4".

What migrates cleanly, once the blocker is answered

Current pin: "rain-deploy" = "0.1.10" (foundry.toml:80).

1. src/abstract/DecimalFloatDeploySuites.sol — the decimal-float candidate

  • Line 100 — delete sourceCreationCode: type(DecimalFloat).creationCode,
    and the trailing comma on the snapshot: DeploySuite({...}) entry above it.
  • Line 7 — delete import {DecimalFloat} from "../concrete/DecimalFloat.sol";.
    It becomes unused: line 100 is its only use in this file.
  • Line 6 — import {LibDataContract} from "rain-datacontract-0.1.9/src/lib/LibDataContract.sol";
    becomes unused too, but only once the log-tables blocker above is resolved:
    line 74 is its only use.

artifactPath at line 98 is "src/concrete/DecimalFloat.sol:DecimalFloat".
Checked against the tree: that file exists and declares contract DecimalFloat,
so it resolves and needs no correction.

The doc comment at lines 52-58 explains why sourceCreationCode is "that same
pure expression rather than a type(X).creationCode" and needs rewriting
whichever way the blocker is answered.

2. script/Build.sol

  • Line 146 — contracts[i].candidate.sourceCreationCode, becomes
    vm.getCode(contracts[i].candidate.snapshot.artifactPath),. Note this is the
    same call the blocker breaks: regenerateSnapshots writing the log-tables
    snapshot cannot read it from an artifact that does not exist, so
    script/Build.sol is blocked on the same answer.
  • Line 34 — the GeneratedContract doc comment names sourceCreationCode.

3. Version pin, when there is one to move to

Eight files spell the versioned remapping prefix rain-deploy-0.1.10/ and each
has to be rewritten together with foundry.toml and soldeer.lock:

  • src/abstract/RainDeploySuitesBase.sol (the re-export shim holding the one
    local spelling of the package path, which the generated libs reach through a
    relative import and so cannot be skipped)
  • script/Build.sol, script/Deploy.sol
  • test/src/abstract/DecimalFloatDeployChain.t.sol,
    test/src/abstract/DecimalFloatDeploySnapshot.t.sol,
    test/src/lib/deploy/LibDecimalFloatDeployCandidate.t.sol,
    test/src/lib/deploy/LibDecimalFloatDeployProd.t.sol,
    test/src/lib/deploy/LibDecimalFloatDeploy.t.sol

The version to bump to does not exist yet

rainlanguage/rain.deploy#242 is open, unmerged and unreleased. There is no
published rain-deploy version carrying this change, so this issue deliberately
names none. The bump target has to be filled in once #242 merges and a Soldeer
release is cut; until then this issue is the record of what the edit will be,
not a request to make it.

Not affected in this repo

Migration item 3 of #242 — "any consumer wrapper marked pure must become
view" — needs no edit here. This repo inherits RainDeployVerifySnapshot
without redeclaring testSnapshotMatchesSource or wrapping
checkCandidatesAnchoredToSource, so the mutability change lands entirely
inside the package.

Migration item 4 — no foundry.toml change is required, because vm.getCode
does not go through fs_permissions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions