Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
51 changes: 27 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,47 @@ 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 The address the V2 `Extrospect` deployment will be live at: the Zoltu
/// address of the current candidate bytecode. Not yet deployed — the next
/// release deploys it. 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.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
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 +93,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 +102,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