Skip to content
Merged
Show file tree
Hide file tree
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
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ Mutation and coverage campaigns: see `.claude/rules/mutation-profile.md`.
- One contract per `.sol` file. No `@custom:` NatSpec. No skipped tests.
- Comments describe current behaviour only.
- Soldeer deps carry the version in the import path, e.g.
`rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol`. `recursive_deps`
is off, so every package an import resolves through is declared in
`foundry.toml`.
`rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol`.
`recursive_deps` is off, so every package an import resolves through is
declared in `foundry.toml`.

## Deployment and releases

Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ candidate is a snapshot of this repo's source, and every frozen
`src/generated/<tag>/` record is declared. `ExtrospectDeployChainTest` inherits
`RainDeployVerifyChain`, which holds every RELEASED suite live on every
supported network — with no release cut it has no subject and forks nothing.
`ExtrospectConstantsTest` ties the generated candidate to the live V1 deployment
(`0x1BE878af679C1a0A6AC15108b0F4398de1f94506`) byte for byte, and executes the
recorded creation bytecode through the Zoltu factory's own bytecode, etched
offline. The whole record is a pure function of the creation code, so none of
that needs a network.
`ExtrospectConstantsTest` ties the generated candidate to the pinned V2
deployment (`0x01A8116e07D63348c02818Af858769EaCdaF134A`, deployed by the next
release; V1 remains live at `0x1BE878af679C1a0A6AC15108b0F4398de1f94506` and
recorded in `src/generated/0_1_0/`) byte for byte, and executes the recorded
creation bytecode through the Zoltu factory's own bytecode, etched offline. The
whole record is a pure function of the creation code, so none of that needs a
network.

## Releases

Expand Down
4 changes: 2 additions & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ no_match_contract = "ExtrospectConstantsTest|ExtrospectDeploySnapshotTest"
# `LibExtrospectBytecode`.
[dependencies]
forge-std = "1.16.2"
"rain-extrospection" = "0.1.6"
"rain-solmem" = "0.1.3"
"rain-extrospection" = "0.1.13"
"rain-solmem" = "0.1.26"
"rain-deploy" = "0.1.7"
# `LibRainDeploySnapshot` — reached from `script/Build.sol` and the shipped
# verify abstracts — emits the generated record via `LibCodeGen`/`LibFs`.
Expand Down
16 changes: 8 additions & 8 deletions soldeer.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ integrity = "e51da6f2b3a0f427a0aac5d7714bed2027f5cf0f39b31f0692e9623ceeaa47f2"

[[dependencies]]
name = "rain-extrospection"
version = "0.1.6"
url = "https://soldeer-revisions.s3.amazonaws.com/rain-extrospection/0_1_6_18-08-2026_12:57:47_rain.zip"
checksum = "4e580128b89eebe9ddb7f3ae36e2dffa8351a062168092962a99de234add7cf8"
integrity = "d8cb335c2f69ad31230b7ba0612ab05100aa6ff9e300b2c60fd5b81f8704c133"
version = "0.1.13"
url = "https://soldeer-revisions.s3.amazonaws.com/rain-extrospection/0_1_13_20-08-2026_09:08:24_rain.zip"
checksum = "8cf77283049994469090ceecee5944c9a580a624463fbae1861d637ba35515e5"
integrity = "5727c7553eb165eb66ac529aa2d9d0d2032bb20824c45acf7b09c82c8c546141"

[[dependencies]]
name = "rain-sol-codegen"
Expand All @@ -28,7 +28,7 @@ integrity = "164e2655ac8b66bcf52c799421706d3dfaab987addaaeadd74574e70fd2eb6ed"

[[dependencies]]
name = "rain-solmem"
version = "0.1.3"
url = "https://soldeer-revisions.s3.amazonaws.com/rain-solmem/0_1_3_09-05-2026_19:49:33_rain.zip"
checksum = "1d405bb81f7c9e56d1717de0d60da918d2fc2fa4db083efd2abe9906378d019f"
integrity = "e879d2743f9d884f647b9dd489889a83f2cea5f76eb69409a113e1baa69d3643"
version = "0.1.26"
url = "https://soldeer-revisions.s3.amazonaws.com/rain-solmem/0_1_26_18-08-2026_16:20:17_rain.zip"
checksum = "291a0acf805b8acd65dfb9e848e6670bde158120bb5b0bcdeeaf17c4084a134c"
integrity = "54e56c1b10d05df72c1c3dcc8df92b99b9f01cd946363158b077c779ce4d20fa"
10 changes: 5 additions & 5 deletions src/concrete/Extrospect.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
pragma solidity =0.8.25;

import {IExtrospectV1} from "rain-extrospection-0.1.6/src/interface/IExtrospectV1.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectMetamorphic} from "rain-extrospection-0.1.6/src/lib/LibExtrospectMetamorphic.sol";
import {LibExtrospectERC1167Proxy} from "rain-extrospection-0.1.6/src/lib/LibExtrospectERC1167Proxy.sol";
import {LibExtrospectERC1967BeaconProxy} from "rain-extrospection-0.1.6/src/lib/LibExtrospectERC1967BeaconProxy.sol";
import {IExtrospectV1} from "rain-extrospection-0.1.13/src/interface/IExtrospectV1.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectMetamorphic} from "rain-extrospection-0.1.13/src/lib/LibExtrospectMetamorphic.sol";
import {LibExtrospectERC1167Proxy} from "rain-extrospection-0.1.13/src/lib/LibExtrospectERC1167Proxy.sol";
import {LibExtrospectERC1967BeaconProxy} from "rain-extrospection-0.1.13/src/lib/LibExtrospectERC1967BeaconProxy.sol";

/// @title Extrospect
/// @notice Concrete implementation of `IExtrospectV1`. Parameterless
Expand Down
8 changes: 4 additions & 4 deletions src/generated/candidate/Extrospect.sol

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions test/concrete/MockBeacon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
pragma solidity =0.8.25;

import {IBeacon} from "rain-extrospection-0.1.6/src/interface/IBeacon.sol";
import {IOwnable} from "rain-extrospection-0.1.6/src/interface/IOwnable.sol";
import {IBeacon} from "rain-extrospection-0.1.13/src/interface/IBeacon.sol";
import {IOwnable} from "rain-extrospection-0.1.13/src/interface/IOwnable.sol";

/// @dev Minimal beacon test fixture implementing both `IBeacon` and
/// `IOwnable` so selector and return-type match the lib's expectations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {SOLIDITY_CBOR_RUNTIME_FIXTURE} from "test/concrete/SolidityCBORFixture.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol";

contract ExtrospectCheckCBORTrimmedBytecodeHashTest is ExtrospectEquivalence {
//forge-lint: disable-next-line(mixed-case-function)
Expand Down
21 changes: 17 additions & 4 deletions test/src/concrete/Extrospect.checkNoSolidityCBORMetadata.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {SOLIDITY_CBOR_RUNTIME_FIXTURE} from "test/concrete/SolidityCBORFixture.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol";

contract ExtrospectCheckNoSolidityCBORMetadataTest is ExtrospectEquivalence {
//forge-lint: disable-next-line(mixed-case-function)
Expand All @@ -13,9 +13,22 @@ contract ExtrospectCheckNoSolidityCBORMetadataTest is ExtrospectEquivalence {
}

function testCheckNoSolidityCBORMetadataEquivalencePass() external view {
// Account with no code passes both.
extrospect.checkNoSolidityCBORMetadata(address(0xdead));
LibExtrospectBytecode.checkNoSolidityCBORMetadata(address(0xdead));
// Account with code and no metadata passes both. `Extrospect`
// itself compiles with `cbor_metadata = false`, so its own
// runtime bytecode is the fixture.
extrospect.checkNoSolidityCBORMetadata(address(extrospect));
LibExtrospectBytecode.checkNoSolidityCBORMetadata(address(extrospect));
}

function testCheckNoSolidityCBORMetadataEquivalenceCodeless() external {
// Account with no code reverts both with `CodelessAccount`:
// absence of code is not absence of metadata risk, so the
// check refuses to vouch for it.
address codeless = address(0xdead);
vm.expectRevert(abi.encodeWithSelector(LibExtrospectBytecode.CodelessAccount.selector, codeless));
extrospect.checkNoSolidityCBORMetadata(codeless);
vm.expectRevert(abi.encodeWithSelector(LibExtrospectBytecode.CodelessAccount.selector, codeless));
this.libCheckNoSolidityCBORMetadataExternal(codeless);
}

function testCheckNoSolidityCBORMetadataEquivalenceRevert() external {
Expand Down
2 changes: 1 addition & 1 deletion test/src/concrete/Extrospect.checkNotEOFBytecode.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol";

contract ExtrospectCheckNotEOFBytecodeTest is ExtrospectEquivalence {
function libCheckNotEOFBytecodeExternal(bytes memory bytecode) external pure {
Expand Down
2 changes: 1 addition & 1 deletion test/src/concrete/Extrospect.checkNotMetamorphic.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectMetamorphic} from "rain-extrospection-0.1.6/src/lib/LibExtrospectMetamorphic.sol";
import {LibExtrospectMetamorphic} from "rain-extrospection-0.1.13/src/lib/LibExtrospectMetamorphic.sol";

contract ExtrospectCheckNotMetamorphicTest is ExtrospectEquivalence {
/// External re-exposure of the library function so it can be reached via a
Expand Down
50 changes: 26 additions & 24 deletions test/src/concrete/Extrospect.constants.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,46 @@ import {
} from "src/generated/candidate/Extrospect.sol";
import {LibRainDeploy} from "rain-deploy-0.1.7/src/lib/LibRainDeploy.sol";

/// @dev The address the V1 `Extrospect` deployment is live at. The generated
/// candidate MUST derive this address for as long as the source still
/// compiles to the deployed V1 bytecode — a drift here is a new deployment,
/// not a constant to update.
address constant EXTROSPECT_ZOLTU_ADDRESS_V1 = address(0x1BE878af679C1a0A6AC15108b0F4398de1f94506);
/// @dev Deterministic Zoltu address recorded for the current V2 candidate
/// bytecode. The V1 deployment remains live at
/// 0x1BE878af679C1a0A6AC15108b0F4398de1f94506, recorded in
/// `src/generated/0_1_0/`. The generated candidate MUST derive this address
/// for as long as the source compiles to the V2 bytecode — a drift here is a
/// new deployment, not a constant to update.
address constant EXTROSPECT_ZOLTU_ADDRESS_V2 = address(0x01A8116e07D63348c02818Af858769EaCdaF134A);

/// @dev The runtime codehash of the V1 deployment.
bytes32 constant EXTROSPECT_RUNTIME_CODEHASH_V1 = 0x6f34c52c30411783d48eb81ac33c9cf7c108e61f86b2c5403ad49c8680cc71cf;
/// @dev The runtime codehash of the V2 candidate bytecode.
bytes32 constant EXTROSPECT_RUNTIME_CODEHASH_V2 = 0xd036244004bdb66e7d31e3aa2a7a3306e46fd04ceb85b713bfe8b7547232032d;

/// @dev `keccak256` of the V1 creation bytecode. Pinned as a hash because the
/// @dev `keccak256` of the V2 creation bytecode. Pinned as a hash because the
/// bytes themselves live in the generated snapshot, and a second copy here
/// would be a second source of truth.
bytes32 constant EXTROSPECT_CREATION_KECCAK_V1 = 0x5a56765a85cfcb3d9ca721de9dce9f1eb770ee9c7b873b50bd7727c20a344efd;
bytes32 constant EXTROSPECT_CREATION_KECCAK_V2 = 0x24ac88b85bc285f8be255968b680ae632f12f0b78f8d15330e988d0eea498e18;

/// @title ExtrospectConstantsTest
/// @notice Ties the generated candidate snapshot to the existing V1
/// deployment and to the compiler's current output, so the snapshot cannot
/// drift from either without failing loud.
/// @notice Ties the generated candidate snapshot to the pinned V2 deployment
/// and to the compiler's current output, so the snapshot cannot drift from
/// either without failing loud.
/// @dev These pin compiler output, not behaviour: they fail for any edit to
/// any source file reachable from `Extrospect`. The `mutation` foundry
/// profile excludes this contract by name.
contract ExtrospectConstantsTest is Test {
/// The generated candidate IS the V1 deployment, byte for byte: the
/// recorded creation code hashes to the V1 creation bytecode's hash, the
/// recorded address is the V1 address and the recorded codehash is the V1
/// The generated candidate IS the V2 deployment, byte for byte: the
/// recorded creation code hashes to the V2 creation bytecode's hash, the
/// recorded address is the V2 address and the recorded codehash is the V2
/// runtime codehash.
function testGeneratedCandidateIsTheV1Deployment() external pure {
function testGeneratedCandidateIsTheV2Deployment() external pure {
assertEq(
keccak256(CREATION_CODE),
EXTROSPECT_CREATION_KECCAK_V1,
"generated creation code is not the V1 creation bytecode"
EXTROSPECT_CREATION_KECCAK_V2,
"generated creation code is not the V2 creation bytecode"
);
assertEq(DEPLOYED_ADDRESS, EXTROSPECT_ZOLTU_ADDRESS_V1, "generated address is not the V1 Zoltu address");
assertEq(BYTECODE_HASH, EXTROSPECT_RUNTIME_CODEHASH_V1, "generated codehash is not the V1 runtime codehash");
assertEq(DEPLOYED_ADDRESS, EXTROSPECT_ZOLTU_ADDRESS_V2, "generated address is not the V2 Zoltu address");
assertEq(BYTECODE_HASH, EXTROSPECT_RUNTIME_CODEHASH_V2, "generated codehash is not the V2 runtime codehash");
}

/// The recorded creation code matches the current compiler output, so the
/// V1 tie above is a statement about the contract this repo compiles and
/// V2 tie above is a statement about the contract this repo compiles and
/// not about a stale snapshot.
function testExtrospectCreationBytecode() external pure {
assertEq(
Expand Down Expand Up @@ -90,7 +92,7 @@ contract ExtrospectConstantsTest is Test {
/// The recorded constants describe one deployment, so they must agree
/// with each other when the recorded creation bytecode is actually
/// executed. Running it through the real Zoltu factory bytecode lands at
/// the V1 address and leaves code hashing to the V1 codehash, and that
/// the V2 address and leaves code hashing to the V2 codehash, and that
/// runtime code is byte for byte both `RUNTIME_CODE` and
/// `type(Extrospect).runtimeCode`. Deterministic and offline: the factory
/// is etched from its own pinned bytecode, so no network is involved.
Expand All @@ -99,9 +101,9 @@ contract ExtrospectConstantsTest is Test {

address deployed = LibRainDeploy.deployZoltu(CREATION_CODE);

assertEq(deployed, EXTROSPECT_ZOLTU_ADDRESS_V1, "recorded creation bytecode does not deploy to the V1 address");
assertEq(deployed, EXTROSPECT_ZOLTU_ADDRESS_V2, "recorded creation bytecode does not deploy to the V2 address");
assertEq(
deployed.codehash, EXTROSPECT_RUNTIME_CODEHASH_V1, "deployed runtime code does not hash to the V1 codehash"
deployed.codehash, EXTROSPECT_RUNTIME_CODEHASH_V2, "deployed runtime code does not hash to the V2 codehash"
);
assertEq(deployed.code, RUNTIME_CODE, "deployed runtime code differs from the recorded runtime code");
assertEq(deployed.code, type(Extrospect).runtimeCode, "deployed runtime code differs from compiler output");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectERC1967BeaconProxy} from "rain-extrospection-0.1.6/src/lib/LibExtrospectERC1967BeaconProxy.sol";
import {LibExtrospectERC1967BeaconProxy} from "rain-extrospection-0.1.13/src/lib/LibExtrospectERC1967BeaconProxy.sol";
import {MockBeacon} from "test/concrete/MockBeacon.sol";
import {EmptyContract} from "test/concrete/EmptyContract.sol";

Expand Down
2 changes: 1 addition & 1 deletion test/src/concrete/Extrospect.isBeaconOwner.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectERC1967BeaconProxy} from "rain-extrospection-0.1.6/src/lib/LibExtrospectERC1967BeaconProxy.sol";
import {LibExtrospectERC1967BeaconProxy} from "rain-extrospection-0.1.13/src/lib/LibExtrospectERC1967BeaconProxy.sol";
import {MockBeacon} from "test/concrete/MockBeacon.sol";
import {EmptyContract} from "test/concrete/EmptyContract.sol";

Expand Down
2 changes: 1 addition & 1 deletion test/src/concrete/Extrospect.isEOFBytecode.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol";

contract ExtrospectIsEOFBytecodeTest is ExtrospectEquivalence {
function testIsEOFBytecodeEquivalenceFuzz(bytes memory bytecode) external view {
Expand Down
2 changes: 1 addition & 1 deletion test/src/concrete/Extrospect.isERC1167Proxy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectERC1167Proxy} from "rain-extrospection-0.1.6/src/lib/LibExtrospectERC1167Proxy.sol";
import {LibExtrospectERC1167Proxy} from "rain-extrospection-0.1.13/src/lib/LibExtrospectERC1167Proxy.sol";

contract ExtrospectIsERC1167ProxyTest is ExtrospectEquivalence {
function testIsERC1167ProxyEquivalenceFuzz(bytes memory bytecode) external view {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol";

contract ExtrospectScanEVMOpcodesPresentInBytecodeTest is ExtrospectEquivalence {
/// External re-exposure of the library function so it can be reached via a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol";

contract ExtrospectScanEVMOpcodesReachableInBytecodeTest is ExtrospectEquivalence {
/// External re-exposure of the library function so it can be reached via a
Expand Down
2 changes: 1 addition & 1 deletion test/src/concrete/Extrospect.scanMetamorphicRisk.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {LibExtrospectMetamorphic} from "rain-extrospection-0.1.6/src/lib/LibExtrospectMetamorphic.sol";
import {LibExtrospectMetamorphic} from "rain-extrospection-0.1.13/src/lib/LibExtrospectMetamorphic.sol";

contract ExtrospectScanMetamorphicRiskTest is ExtrospectEquivalence {
/// External re-exposure of the library function so it can be reached via a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity =0.8.25;

import {ExtrospectEquivalence} from "test/concrete/ExtrospectEquivalence.sol";
import {SOLIDITY_CBOR_RUNTIME_FIXTURE} from "test/concrete/SolidityCBORFixture.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.6/src/lib/LibExtrospectBytecode.sol";
import {LibExtrospectBytecode} from "rain-extrospection-0.1.13/src/lib/LibExtrospectBytecode.sol";

contract ExtrospectTryTrimSolidityCBORMetadataTest is ExtrospectEquivalence {
function testTryTrimSolidityCBORMetadataEquivalenceTrim() external view {
Expand Down
Loading