Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions test/src/lib/GeneratedSnapshotShape.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,71 @@ contract GeneratedSnapshotShapeTest is RegistryDeploySuites, Test {
}
}

/// PROPERTY: every declared artifact path RESOLVES — it is `<path>:<Name>`,
/// the path is a file this repo has, and the artifact that whole string
/// selects is the contract the candidate is anchored to.
///
/// `artifactPath` is the one field of a suite that nothing derives, and
/// until this assertion nothing checked either. It is load bearing twice
/// over: `LibRainDeploy` prints it as the `forge verify-contract` command a
/// human runs against a freshly broadcast contract, and
/// `candidateContractName` above takes the contract this whole shape spec
/// is about out of it. Only the `:<Name>` half was ever read by a check —
/// `testEveryCandidateHasASnapshot` matches it against the generator's
/// output — so a path left behind by a moved or renamed source file passed
/// every assertion in this repo, including all of the ones here, because
/// the half that moved is the half nothing read. `bytecode_hash = "none"`
/// and `cbor_metadata = false` mean moving a file changes no creation code,
/// no address and no code hash either, so there is nothing else for it to
/// be caught by.
///
/// Resolved through `vm.getCode`, which is foundry's own resolution of a
/// `<path>:<Name>` artifact id — the same form `forge verify-contract`
/// takes — rather than by searching the file's text for `contract <Name>`.
/// A text search asserts formatting: it is satisfied by the name occurring
/// in a comment or in a longer identifier, and defeated by a declaration
/// written with no space before its brace.
///
/// `vm.isFile` on the path half AS WELL, because `vm.getCode` resolves an
/// artifact id by path SUFFIX while the printed command is run from the
/// repo root. `concrete/AddressRegistry.sol:AddressRegistry` resolves for
/// `vm.getCode` — uniquely, and to the right contract — and still names no
/// file anybody can point `forge verify-contract` at. That is the one shape
/// of wrong path nothing else in this repo goes red on.
///
/// A path outside the `fs_permissions` roots fails here as a cheatcode
/// revert naming the path rather than as this assertion's own message,
/// which is foundry refusing to look rather than looking and not finding.
///
/// Compared against the candidate's own `sourceCreationCode` rather than
/// merely required to resolve to something, because resolving is not the
/// same as resolving to the RIGHT contract. Two candidates whose declared
/// paths are swapped resolve perfectly, and every other assertion in this
/// repo stays green through it — including `testEveryCandidateHasASnapshot`
/// above, because swapping both halves leaves the SET of declared names
/// exactly as it was. This is the assertion that says each candidate's path
/// names ITS own contract rather than one of its siblings'.
///
/// Hashed rather than compared as bytes, for the reason
/// `CandidateSourceMismatch` gives for hashing: creation codes run to tens
/// of kilobytes, and a failure message carrying two of them is a failure
/// message nobody reads.
function testEveryCandidateArtifactPathResolves() external view {
DeployCandidate[] memory candidates = checkedCandidateSuites();
for (uint256 i = 0; i < candidates.length; i++) {
string memory declared = candidates[i].snapshot.artifactPath;
string[] memory parts = vm.split(declared, ":");

assertEq(parts.length, 2, string.concat("artifact path is not <path>:<Name>: ", declared));
assertTrue(vm.isFile(parts[0]), string.concat("artifact path names no such file: ", declared));
assertEq(
keccak256(vm.getCode(declared)),
keccak256(candidates[i].sourceCreationCode),
string.concat("artifact path resolves to another contract: ", declared)
);
}
}

/// PROPERTY: every snapshot declares exactly the five constants a deploy
/// record is for, of these types, in this order. A rename, a retype, a
/// reorder or a sixth constant each fail here and name what broke.
Expand Down
Loading