diff --git a/.gas-snapshot b/.gas-snapshot deleted file mode 100644 index e19acb7..0000000 --- a/.gas-snapshot +++ /dev/null @@ -1,8 +0,0 @@ -CloneFactoryCloneTest:testCloneBytecode(bytes) (runs: 2048, μ: 350833, ~: 341941) -CloneFactoryCloneTest:testCloneInitializeData(bytes) (runs: 2048, μ: 355388, ~: 346399) -CloneFactoryCloneTest:testCloneInitializeEvent(bytes) (runs: 2048, μ: 356010, ~: 347118) -CloneFactoryCloneTest:testCloneInitializeFailureFails(bytes32) (runs: 2048, μ: 159643, ~: 159643) -CloneFactoryCloneTest:testCloneUninitializableFails(address,bytes) (runs: 2048, μ: 9882, ~: 9844) -CloneFactoryCloneTest:testZeroImplementationCodeSizeError(address,bytes) (runs: 2048, μ: 10539, ~: 10557) -LibCloneFactoryDeployTest:testDeployAddress() (gas: 242794) -LibCloneFactoryDeployTest:testExpectedCodeHash() (gas: 235395) \ No newline at end of file diff --git a/.github/workflows/manual-sol-artifacts.yaml b/.github/workflows/manual-sol-artifacts.yaml deleted file mode 100644 index 88c7d0b..0000000 --- a/.github/workflows/manual-sol-artifacts.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: Manual sol artifacts -on: - workflow_dispatch: -jobs: - deploy: - uses: rainlanguage/rainix/.github/workflows/rainix-manual-sol-artifacts.yaml@main - with: - suite: clone-factory - secrets: inherit diff --git a/.github/workflows/package-release.yaml b/.github/workflows/package-release.yaml index ee3dcba..c98e526 100644 --- a/.github/workflows/package-release.yaml +++ b/.github/workflows/package-release.yaml @@ -7,13 +7,9 @@ jobs: release: uses: rainlanguage/rainix/.github/workflows/rainix-autopublish.yaml@main with: - # `foundry.toml` version is the NEXT (in-development) release. On merge, - # publish that version and bump to the next — the bump no longer generates - # artifacts. A version's deploy-pin snapshot is built by the PR that changes - # the bytecode: run `forge script ./script/BuildPointers.sol` and commit the - # new `src/generated//` snapshot + LibCloneFactoryDeploy. The - # LibCloneFactoryDeploy fork/deploy tests fail if that snapshot is stale, and - # the rainix append-only check rejects any change to a snapshot already on - # main, so snapshots stay frozen once merged. + # Library repo: the ICloneable* interface surface. `foundry.toml` version is + # the NEXT (in-development) release; on a content change on merge, autopublish + # publishes it and bumps to the next. The deploy half (concrete + deploy-pin + # snapshots) lives in rain.factory.deploy (rainlanguage/rain.factory#46). soldeer-package: rain-factory secrets: inherit diff --git a/CLAUDE.md b/CLAUDE.md index 4ceabb4..28cce6c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,9 +5,19 @@ code in this repository. ## Project Overview -rain.factory is a Solidity library providing EIP1167 minimal proxy (clone) -factory contracts for the Rain ecosystem. The core contract `CloneFactory` -clones any contract implementing `ICloneableV2` and atomically initializes it. +rain.factory is a Solidity **library** repo: the `ICloneable*` interface surface +for EIP1167 minimal proxy (clone) factories in the Rain ecosystem. It is the +library half of the library/deploy split (rainlanguage/rain.factory#46) and holds +interfaces only — no concrete contract, no deploy pins, no deploy script, and no +tests. + +The concrete `CloneFactory` that implements these interfaces, its deployed +address + codehash pins (`LibCloneFactoryDeploy`), the frozen +`src/generated//` deploy-pin snapshots and `script/Deploy.sol` all live in +[`rain.factory.deploy`](https://github.com/rainlanguage/rain.factory.deploy) and +publish as the `rain-factory-deploy` Soldeer package. Consumers that need only +the interfaces depend on `rain-factory`; consumers that need the deployed +address/codehash pins depend on `rain-factory-deploy`. License: LicenseRef-DCL-1.0 (DecentraLicense). All source files must include SPDX headers. @@ -23,9 +33,6 @@ nix develop Then use rainix tasks: ```bash -# Run all tests -nix develop -c rainix-sol-test - # Static analysis (Slither) nix develop -c rainix-sol-static @@ -34,20 +41,16 @@ nix develop -c rainix-sol-legal # Prelude (dependency setup, run before other tasks) nix develop -c rainix-sol-prelude + +# Runs, but there is no test suite here: the interfaces have no behaviour to +# test. The tests that exercise them live in rain.factory.deploy, against the +# concrete. +nix develop -c rainix-sol-test ``` Direct Forge commands also work inside the nix shell: ```bash -# Run all tests -forge test - -# Run a specific test -forge test --match-test testCloneDeterministic - -# Run tests in a specific file -forge test --match-path test/src/concrete/CloneFactoryCloneDeterministic.t.sol - # Build forge build ``` @@ -59,42 +62,52 @@ forge build success. - `src/interface/ICloneableFactoryV2.sol` — Legacy factory interface: the nonce-dependent `clone(address, bytes)` and `NewClone` event. Superseded by - `ICloneableFactoryV3` for `CloneFactory`; still published for other consumers. + `ICloneableFactoryV3` for the concrete factory in rain.factory.deploy; still + published for other consumers. - `src/interface/ICloneableFactoryV3.sol` — Current factory interface. Deterministic-only: `cloneDeterministic(address, bytes, bytes32)` + `predictDeterministicAddress(address, bytes32, address)` (CREATE2, salt namespaced by `msg.sender`) and its own `NewClone` event. Standalone — does NOT extend `ICloneableFactoryV2`, because the non-deterministic `clone()` was intentionally dropped. -- `src/concrete/CloneFactory.sol` — The single concrete implementation of - `ICloneableFactoryV3`. Uses OpenZeppelin `Clones.cloneDeterministic()`; there - is no plain `clone()`. -- `src/lib/LibCloneFactoryDeploy.sol` — Deterministic deployment address and - codehash constants (generated; aliases the current tag's - `src/generated//` snapshot). - `src/interface/deprecated/` — Legacy interfaces (`ICloneableV1`, `ICloneableFactoryV1`, `IFactory`). Do not use for new work. +`src/` holds nothing else. The interfaces import nothing — not each other, not a +third-party library — which is what makes this half a standalone publish. + ## Solidity Conventions -- Solidity version: concrete contracts pin `=0.8.25` (exact); interface and - library files float `^` (the interfaces use `^0.8.18`) so downstream soldeer - consumers on a different `0.8.x` can still compile them +- Solidity version: every file here is an interface and floats `^` (the + interfaces use `^0.8.18`) so downstream soldeer consumers on a different + `0.8.x` can still compile them. The `=0.8.25` exact-pin rule applies to + concrete contracts, scripts and tests, which live in rain.factory.deploy. - EVM target: Cancun - Optimizer: enabled, 100,000 runs - No CBOR metadata (`cbor_metadata = false`, `bytecode_hash = "none"`) - Dependencies are managed with Soldeer (`[dependencies]` in `foundry.toml` + - `soldeer.lock`, vendored under `dependencies/`): forge-std, - @openzeppelin-contracts, rain-extrospection, rain-deploy, rain-sol-codegen + `soldeer.lock`, vendored under `dependencies/`). The interfaces import nothing, + so the only entry is forge-std. `@openzeppelin-contracts`, `rain-extrospection`, + `rain-deploy` and `rain-sol-codegen` went with the deploy half and must not + come back: adding one here means concrete code has landed in a library repo. ## Deployment -Deployed via deterministic Zoltu deployer (from `rain.deploy`). The canonical -deployment address and codehash are committed in `LibCloneFactoryDeploy.sol`. -Deployment scripts are in `script/Deploy.sol` targeting Arbitrum, Base, Base -Sepolia, Flare, and Polygon. +Nothing in this repo is deployed. The deterministic Zoltu deploy of the concrete +`CloneFactory`, its canonical address and codehash, and the deploy scripts +targeting Arbitrum, Base, Base Sepolia, Flare and Polygon are all in +rain.factory.deploy. + +## Releases + +Library repo, so `package-release.yaml` runs `rainix-autopublish`: +`[package].version` in `foundry.toml` is the NEXT, unpublished version, and a +content change on merge publishes it and bumps to the next. Nothing here is +tag-released, and no snapshot is frozen — that lifecycle belongs to the deploy +half. ## CI GitHub Actions runs three parallel jobs on every push: `rainix-sol-test`, -`rainix-sol-static`, `rainix-sol-legal`. Fork tests require RPC URL secrets. +`rainix-sol-static`, `rainix-sol-legal`. There are no fork tests and no RPC +secrets are needed. diff --git a/README.md b/README.md index 862a228..9cf98df 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,24 @@ Docs at https://rainprotocol.github.io/rain.factory +This repo is the **library** half of the library/deploy split +([#46](https://github.com/rainlanguage/rain.factory/issues/46)): the +`ICloneable*` interface surface, and nothing else. It publishes to Soldeer as +`rain-factory`. + ## Concrete implementations -`CloneFactory` implements `ICloneableFactoryV2` allowing any -compatible `ICloneableV2` contract to be cloned as an EIP1167 proxy and -initialized. +`CloneFactory` — the concrete that implements these interfaces, letting any +compatible `ICloneableV2` contract be cloned as an EIP1167 proxy and initialized +— lives in +[`rain.factory.deploy`](https://github.com/rainlanguage/rain.factory.deploy), +together with its deployed address + codehash pins, its frozen per-release +deploy-pin snapshots and its deploy script. That repo publishes as +`rain-factory-deploy`. + +Depend on `rain-factory` if you need only the interfaces. Depend on +`rain-factory-deploy` if you need the deployed address or codehash of a live +`CloneFactory`. ## Interfaces @@ -32,8 +45,14 @@ The onchain tooling for analysis is found at https://github.com/rainprotocol/rai The current interfaces in this repository are for +- `ICloneableFactoryV3`, the current factory interface: deterministic-only + (`cloneDeterministic` + `predictDeterministicAddress`, CREATE2 with the salt + namespaced by `msg.sender`). Standalone rather than extending + `ICloneableFactoryV2`, because the non-deterministic `clone()` was + intentionally dropped - `ICloneableFactoryV2` that is expected to clone proxies from a reference - implementation + implementation. Superseded by `ICloneableFactoryV3` for the concrete factory, + still published for other consumers - A small interface `ICloneableV2` designed for cloneable proxy contracts to expose an `initialize` function that the factory can call to act like a constructor diff --git a/REUSE.toml b/REUSE.toml index 0c042e3..c4a3e48 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -2,7 +2,6 @@ version = 1 [[annotations]] path = [ - ".gas-snapshot", ".github/workflows/**/", ".vscode/**/", ".coderabbitai.yaml", diff --git a/foundry.toml b/foundry.toml index ad08875..59c625e 100644 --- a/foundry.toml +++ b/foundry.toml @@ -18,40 +18,17 @@ evm_version = "cancun" bytecode_hash = "none" cbor_metadata = false -# Build metadata used for testing rain meta aware contracts in this folder rather -# than expose ffi to forge. -fs_permissions = [ - { access = "read", path = "./meta" }, - # BuildPointers reads the version from foundry.toml and writes the generated - # per-tag snapshots + the current-pin lib under src/. - { access = "read", path = "./foundry.toml" }, - { access = "read-write", path = "./src" }, -] libs = ["dependencies"] [fuzz] runs = 2048 +# Library repo: the ICloneable* interface surface only. The concrete CloneFactory, +# its deploy-pin snapshots and deploy scripts live in rain.factory.deploy +# (rainlanguage/rain.factory#46). Interfaces import nothing, so there are no +# Solidity dependencies beyond the test harness. [dependencies] forge-std = "1.16.1" -"@openzeppelin-contracts" = "5.6.1" -"rain-extrospection" = "0.1.1" -"rain-deploy" = "0.1.3" -"rain-sol-codegen" = "0.1.0" [soldeer] recursive_deps = false - -[rpc_endpoints] -arbitrum = "${ARBITRUM_RPC_URL}" -base = "${BASE_RPC_URL}" -base_sepolia = "${BASE_SEPOLIA_RPC_URL}" -flare = "${FLARE_RPC_URL}" -polygon = "${POLYGON_RPC_URL}" - -[etherscan] -arbitrum = { key = "${CI_DEPLOY_ARBITRUM_ETHERSCAN_API_KEY}" } -base = { key = "${CI_DEPLOY_BASE_ETHERSCAN_API_KEY}" } -base_sepolia = { key = "${CI_DEPLOY_BASE_SEPOLIA_ETHERSCAN_API_KEY}" } -flare = { key = "${CI_DEPLOY_FLARE_ETHERSCAN_API_KEY}" } -polygon = { key = "${CI_DEPLOY_POLYGON_ETHERSCAN_API_KEY}" } diff --git a/script/BuildPointers.sol b/script/BuildPointers.sol deleted file mode 100644 index e108599..0000000 --- a/script/BuildPointers.sol +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Script} from "forge-std-1.16.1/src/Script.sol"; -import {LibCodeGen} from "rain-sol-codegen-0.1.0/src/lib/LibCodeGen.sol"; -import {LibFs} from "rain-sol-codegen-0.1.0/src/lib/LibFs.sol"; -import {LibRainDeploy} from "rain-deploy-0.1.3/src/lib/LibRainDeploy.sol"; -import {CloneFactory} from "../src/concrete/CloneFactory.sol"; - -/// @title BuildPointers -/// @notice Generates the deterministic-deploy pins for `CloneFactory`: -/// 1. A frozen per-release snapshot `src/generated//CloneFactory.pointers.sol` -/// (`BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `CREATION_CODE`, `RUNTIME_CODE`) for -/// the current `deployTag()`. Historical tags are never regenerated; a -/// release bump writes a new `/` snapshot beside them. -/// 2. `src/lib/LibCloneFactoryDeploy.sol` — the current-release address and -/// codehash, aliased from the current `deployTag()` snapshot so that -/// snapshot stays the single source of truth (never a duplicated literal). -/// Kept in `src/lib` so consumers' import path is stable across releases. -/// -/// Run as `forge script script/BuildPointers.sol`. Wired into the autopublish -/// `soldeer-generate-cmd` so the pins regenerate born-green on each release. -contract BuildPointers is Script { - string constant GEN_LIB_PATH = "src/lib/LibCloneFactoryDeploy.sol"; - - // REUSE-IgnoreStart (the two SPDX lines below are the header EMITTED into the - // generated lib, not this script's own license — hide from reuse lint) - string constant GEN_SPDX_LICENSE = "// SPDX-License-Identifier: LicenseRef-DCL-1.0"; - string constant GEN_SPDX_COPYRIGHT = "// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd"; - - // REUSE-IgnoreEnd - - /// @notice The canonical release tag. Read from `foundry.toml` - /// `[package].version` — the single source of truth — with dots converted to - /// underscores for the Solidity dir form (`0.1.3` -> `0_1_3`). - function deployTag() internal view returns (string memory) { - string memory version = vm.parseTomlString(vm.readFile("foundry.toml"), ".package.version"); - bytes memory b = bytes(version); - bytes memory out = new bytes(b.length); - for (uint256 i = 0; i < b.length; i++) { - out[i] = b[i] == "." ? bytes1("_") : b[i]; - } - return string(out); - } - - function addressConstantString(address addr) internal pure returns (string memory) { - return string.concat( - "\n", - "/// @dev The deterministic deploy address of the contract when deployed via\n", - "/// the Zoltu factory.\n", - "address constant DEPLOYED_ADDRESS = address(", - vm.toString(addr), - ");\n" - ); - } - - function run() external { - LibRainDeploy.etchZoltuFactory(vm); - - // A fresh next-version slot has no `/` dir yet, and `vm.writeFile` - // won't create one. - vm.createDir(string.concat("src/generated/", deployTag()), true); - - bytes memory creationCode = type(CloneFactory).creationCode; - address deployed = LibRainDeploy.deployZoltu(creationCode); - - // Frozen per-tag snapshot. - LibFs.buildFileForContract( - vm, - deployed, - string.concat(deployTag(), "/CloneFactory"), - string.concat( - addressConstantString(deployed), - LibCodeGen.bytesConstantString( - vm, "/// @dev The creation bytecode of the contract.", "CREATION_CODE", creationCode - ), - LibCodeGen.bytesConstantString( - vm, "/// @dev The runtime bytecode of the contract.", "RUNTIME_CODE", deployed.code - ) - ) - ); - - // Current-release pin lib. - genLibCloneFactoryDeploy(); - } - - /// @notice (Re)generate `src/lib/LibCloneFactoryDeploy.sol`, aliasing the - /// current `deployTag()` snapshot's `DEPLOYED_ADDRESS` + `BYTECODE_HASH` as - /// the current-release constants — the snapshot stays the single source of - /// truth (never a duplicated literal). Emitted line-by-line to match the - /// generated-file convention. - function genLibCloneFactoryDeploy() internal { - string memory importPath = string.concat("../generated/", deployTag(), "/CloneFactory.pointers.sol"); - vm.writeFile(GEN_LIB_PATH, ""); - vm.writeLine(GEN_LIB_PATH, GEN_SPDX_LICENSE); - vm.writeLine(GEN_LIB_PATH, GEN_SPDX_COPYRIGHT); - vm.writeLine(GEN_LIB_PATH, "pragma solidity ^0.8.25;"); - vm.writeLine(GEN_LIB_PATH, ""); - vm.writeLine(GEN_LIB_PATH, "// THIS FILE IS AUTOGENERATED BY ./script/BuildPointers.sol"); - vm.writeLine(GEN_LIB_PATH, ""); - vm.writeLine(GEN_LIB_PATH, "import {"); - vm.writeLine(GEN_LIB_PATH, " DEPLOYED_ADDRESS as CLONE_FACTORY_ADDR,"); - vm.writeLine(GEN_LIB_PATH, " BYTECODE_HASH as CLONE_FACTORY_HASH"); - vm.writeLine(GEN_LIB_PATH, string.concat("} from \"", importPath, "\";")); - vm.writeLine(GEN_LIB_PATH, ""); - vm.writeLine(GEN_LIB_PATH, "/// @title LibCloneFactoryDeploy"); - vm.writeLine(GEN_LIB_PATH, "/// @notice The deterministic Zoltu deploy address and code hash of the current"); - vm.writeLine(GEN_LIB_PATH, "/// `CloneFactory` release, aliased from the frozen per-release snapshot in"); - vm.writeLine(GEN_LIB_PATH, "/// `src/generated//CloneFactory.pointers.sol` so that snapshot stays the"); - vm.writeLine(GEN_LIB_PATH, "/// single source of truth. Lets consumers verify/deploy against a precommitted"); - vm.writeLine(GEN_LIB_PATH, "/// address + hash rather than a registry."); - vm.writeLine(GEN_LIB_PATH, "library LibCloneFactoryDeploy {"); - vm.writeLine(GEN_LIB_PATH, " address constant CLONE_FACTORY_DEPLOYED_ADDRESS = CLONE_FACTORY_ADDR;"); - vm.writeLine(GEN_LIB_PATH, " bytes32 constant CLONE_FACTORY_DEPLOYED_CODEHASH = CLONE_FACTORY_HASH;"); - vm.writeLine(GEN_LIB_PATH, "}"); - } -} diff --git a/script/Deploy.sol b/script/Deploy.sol deleted file mode 100644 index eb7a3d4..0000000 --- a/script/Deploy.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Script} from "forge-std-1.16.1/src/Script.sol"; -import {CloneFactory} from "../src/concrete/CloneFactory.sol"; -import {LibRainDeploy} from "rain-deploy-0.1.3/src/lib/LibRainDeploy.sol"; -import {LibCloneFactoryDeploy} from "../src/lib/LibCloneFactoryDeploy.sol"; - -/// @dev Hash of the "clone-factory" deployment suite string. -bytes32 constant DEPLOYMENT_SUITE_CLONE_FACTORY = keccak256("clone-factory"); - -/// @title Deploy -/// @notice A script that deploys a CloneFactory. -contract Deploy is Script { - mapping(string => mapping(address => bytes32)) internal sDepCodeHashes; - - function run() external { - uint256 deployerPrivateKey = vm.envUint("DEPLOYMENT_KEY"); - - bytes32 suite = keccak256(bytes(vm.envOr("DEPLOYMENT_SUITE", string("clone-factory")))); - if (suite == DEPLOYMENT_SUITE_CLONE_FACTORY) { - LibRainDeploy.deployAndBroadcast( - vm, - LibRainDeploy.supportedNetworks(), - deployerPrivateKey, - type(CloneFactory).creationCode, - "src/concrete/CloneFactory.sol:CloneFactory", - LibCloneFactoryDeploy.CLONE_FACTORY_DEPLOYED_ADDRESS, - LibCloneFactoryDeploy.CLONE_FACTORY_DEPLOYED_CODEHASH, - new address[](0), - sDepCodeHashes - ); - } else { - revert( - "Invalid deployment suite specified. Please set the DEPLOYMENT_SUITE environment variable to 'clone-factory'." - ); - } - } -} diff --git a/slither.config.json b/slither.config.json index 1e19395..522c8ae 100644 --- a/slither.config.json +++ b/slither.config.json @@ -1,4 +1,4 @@ { "detectors_to_exclude": "assembly-usage,solc-version,pragma,unindexed-event-address", - "filter_paths": "dependencies/forge-std-1.16.1,dependencies/@openzeppelin-contracts-5.6.1" + "filter_paths": "dependencies/forge-std-1.16.1" } diff --git a/soldeer.lock b/soldeer.lock index 8de9186..e9184e4 100644 --- a/soldeer.lock +++ b/soldeer.lock @@ -1,34 +1,6 @@ -[[dependencies]] -name = "@openzeppelin-contracts" -version = "5.6.1" -url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/5_6_1_15-03-2026_09:19:50_contracts.zip" -checksum = "a3b6bc661be858c7c27f60a1708cbebe8c71034b4cc1e9fe270d0a05b069352f" -integrity = "bce03af7ada1eee21a7fff393f238bcd7cd75a022a4db55ffb6b0dbb32433d35" - [[dependencies]] name = "forge-std" version = "1.16.1" url = "https://soldeer-revisions.s3.amazonaws.com/forge-std/1_16_1_08-05-2026_08:51:16_forge-std-1.16.zip" checksum = "839b61832925c7152c7b6dffbfa4998d9e606211179bd8f604733124e8a7cb57" integrity = "60e55d10150354ca4a1e2985c5456c834b92b82ef85ab0e1d92a7786cddbd219" - -[[dependencies]] -name = "rain-deploy" -version = "0.1.3" -url = "https://soldeer-revisions.s3.amazonaws.com/rain-deploy/0_1_3_20-05-2026_13:02:35_rain.zip" -checksum = "6e9a7a1562ee2766a1cc3a4a077b853ec628a3070b282e6e9102a252f2a6a5b5" -integrity = "10bff708d9e5d8b77655b8a8fc0c755cef8e3fc876cc3ff100425d27b08294a0" - -[[dependencies]] -name = "rain-extrospection" -version = "0.1.1" -url = "https://soldeer-revisions.s3.amazonaws.com/rain-extrospection/0_1_1_20-05-2026_13:01:40_rain.zip" -checksum = "c2d1ad4b6a749a788616535635c8a19bbe61e514ecc907291ff270a67f832aed" -integrity = "aa7366cac7d9c7610350a49b8126c667d83812a974539e79ccd38a5577cd626b" - -[[dependencies]] -name = "rain-sol-codegen" -version = "0.1.0" -url = "https://soldeer-revisions.s3.amazonaws.com/rain-sol-codegen/0_1_0_09-05-2026_20:30:25_rain.sol.zip" -checksum = "6b5abd394c5db86ac64214262b7a5115158f480b2fbd74442672dfe52bb67310" -integrity = "e22748ce2ba7eca3ce71e23b2271d1c0f370b989507e784b0a4850a7a9e52157" diff --git a/src/concrete/CloneFactory.sol b/src/concrete/CloneFactory.sol deleted file mode 100644 index be28c91..0000000 --- a/src/concrete/CloneFactory.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {ICloneableV2, ICLONEABLE_V2_SUCCESS} from "../interface/ICloneableV2.sol"; -import {ICloneableFactoryV3} from "../interface/ICloneableFactoryV3.sol"; -import {Clones} from "@openzeppelin-contracts-5.6.1/proxy/Clones.sol"; - -/// Thrown when an implementation has zero code size which is always a mistake. -error ZeroImplementationCodeSize(); - -/// Thrown when initialization fails. -error InitializationFailed(); - -/// @title CloneFactory -/// @notice A fairly minimal implementation of `ICloneableFactoryV3` that uses -/// Open Zeppelin `Clones` to create EIP1167 clones of a reference bytecode. The -/// reference bytecode MUST implement `ICloneableV2`. -/// -/// `cloneDeterministic` deploys via `CREATE2` at a pre-computable address -/// (`predictDeterministicAddress`), namespacing the caller-supplied salt by -/// `msg.sender` so a caller's `(implementation, salt)` address cannot be squatted -/// by another account. -contract CloneFactory is ICloneableFactoryV3 { - /// @inheritdoc ICloneableFactoryV3 - function cloneDeterministic(address implementation, bytes calldata data, bytes32 salt) external returns (address) { - _requireImplementationCode(implementation); - // CREATE2 clone at a salt namespaced by the caller (see `_effectiveSalt`). - address child = Clones.cloneDeterministic(implementation, _effectiveSalt(msg.sender, salt)); - return _initializeClone(implementation, child, data, salt); - } - - /// @inheritdoc ICloneableFactoryV3 - function predictDeterministicAddress(address implementation, bytes32 salt, address deployer) - external - view - returns (address) - { - return Clones.predictDeterministicAddress(implementation, _effectiveSalt(deployer, salt), address(this)); - } - - /// @dev The CREATE2 salt actually used: the caller-supplied `salt` namespaced - /// by the deploying account. Prevents a caller's `(implementation, salt)` - /// address being front-run/squatted by another account, while still letting a - /// single caller mint many clones of one implementation via distinct salts. - /// Equal to `keccak256(abi.encode(deployer, salt))`, hashed directly in the - /// scratch space; `deployer` is a clean address so it occupies a full word. - function _effectiveSalt(address deployer, bytes32 salt) internal pure returns (bytes32 effectiveSalt) { - assembly ("memory-safe") { - mstore(0, deployer) - mstore(0x20, salt) - effectiveSalt := keccak256(0, 0x40) - } - } - - /// @dev Reverts with a clear error if `implementation` has no code. - function _requireImplementationCode(address implementation) internal view { - if (implementation.code.length == 0) { - revert ZeroImplementationCodeSize(); - } - } - - /// @dev Emit `NewClone` (with the caller `salt` and init `data`, so the event - /// fully describes the deterministic deploy) and run the mandatory - /// `ICloneableV2.initialize` check. - function _initializeClone(address implementation, address child, bytes calldata data, bytes32 salt) - internal - returns (address) - { - emit NewClone(msg.sender, implementation, child, salt, data); - // Checking the return value of initialize is mandatory as per - // ICloneableFactoryV3. - if (ICloneableV2(child).initialize(data) != ICLONEABLE_V2_SUCCESS) { - revert InitializationFailed(); - } - return child; - } -} diff --git a/src/generated/0_1_3/CloneFactory.pointers.sol b/src/generated/0_1_3/CloneFactory.pointers.sol deleted file mode 100644 index 8f125c5..0000000 --- a/src/generated/0_1_3/CloneFactory.pointers.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity ^0.8.25; - -// THIS FILE IS AUTOGENERATED BY ./script/BuildPointers.sol - -// This file is committed to the repository because there is a circular -// dependency between the contract and its pointers file. The contract -// needs the pointers file to exist so that it can compile, and the pointers -// file needs the contract to exist so that it can be compiled. - -/// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0xf21b813c7075a1621285df3a8369d0652c31ea80cb807be1aaadafeecd134475); - -/// @dev The deterministic deploy address of the contract when deployed via -/// the Zoltu factory. -address constant DEPLOYED_ADDRESS = address(0x444acC29d63fa643E8adCC35FD9aa6DE111dCb39); - -/// @dev The creation bytecode of the contract. -bytes constant CREATION_CODE = - hex"6080604052348015600e575f80fd5b506103f48061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630fbe133c1461002d575b5f80fd5b61004061003b3660046102fb565b610069565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b5f8373ffffffffffffffffffffffffffffffffffffffff163b5f036100ba576040517ff432283200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6100c485610213565b6040805133815273ffffffffffffffffffffffffffffffffffffffff888116602083015283168183015290519192507f274b5f356634f32a865af65bdc3d8205939d9413d75e1f367652e4f3b24d0c3a919081900360600190a16040517f439fab910000000000000000000000000000000000000000000000000000000081527fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc39073ffffffffffffffffffffffffffffffffffffffff83169063439fab91906101949088908890600401610391565b6020604051808303815f875af11580156101b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d491906103dd565b1461020b576040517f19b991a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b949350505050565b5f61021e825f610224565b92915050565b5f8147101561026c576040517fcf4791810000000000000000000000000000000000000000000000000000000081524760048201526024810183905260440160405180910390fd5b763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c175f526e5af43d82803e903d91602b57fd5bf38360781b176020526037600983f0905073ffffffffffffffffffffffffffffffffffffffff811661021e576040517fb06ebf3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f6040848603121561030d575f80fd5b833573ffffffffffffffffffffffffffffffffffffffff81168114610330575f80fd5b9250602084013567ffffffffffffffff8082111561034c575f80fd5b818601915086601f83011261035f575f80fd5b81358181111561036d575f80fd5b87602082850101111561037e575f80fd5b6020830194508093505050509250925092565b60208152816020820152818360408301375f818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b5f602082840312156103ed575f80fd5b505191905056"; - -/// @dev The runtime bytecode of the contract. -bytes constant RUNTIME_CODE = - hex"608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630fbe133c1461002d575b5f80fd5b61004061003b3660046102fb565b610069565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b5f8373ffffffffffffffffffffffffffffffffffffffff163b5f036100ba576040517ff432283200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6100c485610213565b6040805133815273ffffffffffffffffffffffffffffffffffffffff888116602083015283168183015290519192507f274b5f356634f32a865af65bdc3d8205939d9413d75e1f367652e4f3b24d0c3a919081900360600190a16040517f439fab910000000000000000000000000000000000000000000000000000000081527fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc39073ffffffffffffffffffffffffffffffffffffffff83169063439fab91906101949088908890600401610391565b6020604051808303815f875af11580156101b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d491906103dd565b1461020b576040517f19b991a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b949350505050565b5f61021e825f610224565b92915050565b5f8147101561026c576040517fcf4791810000000000000000000000000000000000000000000000000000000081524760048201526024810183905260440160405180910390fd5b763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c175f526e5af43d82803e903d91602b57fd5bf38360781b176020526037600983f0905073ffffffffffffffffffffffffffffffffffffffff811661021e576040517fb06ebf3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f6040848603121561030d575f80fd5b833573ffffffffffffffffffffffffffffffffffffffff81168114610330575f80fd5b9250602084013567ffffffffffffffff8082111561034c575f80fd5b818601915086601f83011261035f575f80fd5b81358181111561036d575f80fd5b87602082850101111561037e575f80fd5b6020830194508093505050509250925092565b60208152816020820152818360408301375f818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b5f602082840312156103ed575f80fd5b505191905056"; diff --git a/src/generated/0_1_4/CloneFactory.pointers.sol b/src/generated/0_1_4/CloneFactory.pointers.sol deleted file mode 100644 index 8f125c5..0000000 --- a/src/generated/0_1_4/CloneFactory.pointers.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity ^0.8.25; - -// THIS FILE IS AUTOGENERATED BY ./script/BuildPointers.sol - -// This file is committed to the repository because there is a circular -// dependency between the contract and its pointers file. The contract -// needs the pointers file to exist so that it can compile, and the pointers -// file needs the contract to exist so that it can be compiled. - -/// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0xf21b813c7075a1621285df3a8369d0652c31ea80cb807be1aaadafeecd134475); - -/// @dev The deterministic deploy address of the contract when deployed via -/// the Zoltu factory. -address constant DEPLOYED_ADDRESS = address(0x444acC29d63fa643E8adCC35FD9aa6DE111dCb39); - -/// @dev The creation bytecode of the contract. -bytes constant CREATION_CODE = - hex"6080604052348015600e575f80fd5b506103f48061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630fbe133c1461002d575b5f80fd5b61004061003b3660046102fb565b610069565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b5f8373ffffffffffffffffffffffffffffffffffffffff163b5f036100ba576040517ff432283200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6100c485610213565b6040805133815273ffffffffffffffffffffffffffffffffffffffff888116602083015283168183015290519192507f274b5f356634f32a865af65bdc3d8205939d9413d75e1f367652e4f3b24d0c3a919081900360600190a16040517f439fab910000000000000000000000000000000000000000000000000000000081527fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc39073ffffffffffffffffffffffffffffffffffffffff83169063439fab91906101949088908890600401610391565b6020604051808303815f875af11580156101b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d491906103dd565b1461020b576040517f19b991a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b949350505050565b5f61021e825f610224565b92915050565b5f8147101561026c576040517fcf4791810000000000000000000000000000000000000000000000000000000081524760048201526024810183905260440160405180910390fd5b763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c175f526e5af43d82803e903d91602b57fd5bf38360781b176020526037600983f0905073ffffffffffffffffffffffffffffffffffffffff811661021e576040517fb06ebf3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f6040848603121561030d575f80fd5b833573ffffffffffffffffffffffffffffffffffffffff81168114610330575f80fd5b9250602084013567ffffffffffffffff8082111561034c575f80fd5b818601915086601f83011261035f575f80fd5b81358181111561036d575f80fd5b87602082850101111561037e575f80fd5b6020830194508093505050509250925092565b60208152816020820152818360408301375f818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b5f602082840312156103ed575f80fd5b505191905056"; - -/// @dev The runtime bytecode of the contract. -bytes constant RUNTIME_CODE = - hex"608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630fbe133c1461002d575b5f80fd5b61004061003b3660046102fb565b610069565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b5f8373ffffffffffffffffffffffffffffffffffffffff163b5f036100ba576040517ff432283200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6100c485610213565b6040805133815273ffffffffffffffffffffffffffffffffffffffff888116602083015283168183015290519192507f274b5f356634f32a865af65bdc3d8205939d9413d75e1f367652e4f3b24d0c3a919081900360600190a16040517f439fab910000000000000000000000000000000000000000000000000000000081527fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc39073ffffffffffffffffffffffffffffffffffffffff83169063439fab91906101949088908890600401610391565b6020604051808303815f875af11580156101b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101d491906103dd565b1461020b576040517f19b991a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b949350505050565b5f61021e825f610224565b92915050565b5f8147101561026c576040517fcf4791810000000000000000000000000000000000000000000000000000000081524760048201526024810183905260440160405180910390fd5b763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c175f526e5af43d82803e903d91602b57fd5bf38360781b176020526037600983f0905073ffffffffffffffffffffffffffffffffffffffff811661021e576040517fb06ebf3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f805f6040848603121561030d575f80fd5b833573ffffffffffffffffffffffffffffffffffffffff81168114610330575f80fd5b9250602084013567ffffffffffffffff8082111561034c575f80fd5b818601915086601f83011261035f575f80fd5b81358181111561036d575f80fd5b87602082850101111561037e575f80fd5b6020830194508093505050509250925092565b60208152816020820152818360408301375f818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b5f602082840312156103ed575f80fd5b505191905056"; diff --git a/src/generated/0_1_5/CloneFactory.pointers.sol b/src/generated/0_1_5/CloneFactory.pointers.sol deleted file mode 100644 index f0b9c14..0000000 --- a/src/generated/0_1_5/CloneFactory.pointers.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity ^0.8.25; - -// THIS FILE IS AUTOGENERATED BY ./script/BuildPointers.sol - -// This file is committed to the repository because there is a circular -// dependency between the contract and its pointers file. The contract -// needs the pointers file to exist so that it can compile, and the pointers -// file needs the contract to exist so that it can be compiled. - -/// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0x3ec02e2f27d73f603f5b37a7dc228956004e9154c6d1f9c5335bd60036379d00); - -/// @dev The deterministic deploy address of the contract when deployed via -/// the Zoltu factory. -address constant DEPLOYED_ADDRESS = address(0x7053c1D000192f1FeC1fbe20350139F3300dBBaD); - -/// @dev The creation bytecode of the contract. -bytes constant CREATION_CODE = - hex"6080604052348015600e575f80fd5b506105708061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806340419eec1461003857806393a7e71114610074575b5f80fd5b61004b6100463660046103f1565b610087565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004b610082366004610473565b6100c7565b5f61009185610159565b5f6100ae866100a933865f9182526020526040902090565b6101ac565b90506100bd86828787876101b8565b9695505050505050565b5f61014f846100df84865f9182526020526040902090565b6040513060388201526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012073ffffffffffffffffffffffffffffffffffffffff1690565b90505b9392505050565b8073ffffffffffffffffffffffffffffffffffffffff163b5f036101a9576040517ff432283200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61015283835f6102f1565b5f7f3b3e5b48cfaf4a4b3b2b36425ddec21c2c507fd502d2aea55eb7ffa36b0ca2053387878588886040516101f2969594939291906104f3565b60405180910390a16040517f439fab910000000000000000000000000000000000000000000000000000000081527fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc39073ffffffffffffffffffffffffffffffffffffffff87169063439fab91906102709088908890600401610546565b6020604051808303815f875af115801561028c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b09190610559565b146102e7576040517f19b991a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092949350505050565b5f81471015610339576040517fcf4791810000000000000000000000000000000000000000000000000000000081524760048201526024810183905260440160405180910390fd5b763d602d80600a3d3981f3363d3d373d3d3d363d730000008460601b60e81c175f526e5af43d82803e903d91602b57fd5bf38460781b17602052826037600984f5905073ffffffffffffffffffffffffffffffffffffffff8116610152576040517fb06ebf3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff811681146103ec575f80fd5b919050565b5f805f8060608587031215610404575f80fd5b61040d856103c9565b9350602085013567ffffffffffffffff80821115610429575f80fd5b818701915087601f83011261043c575f80fd5b81358181111561044a575f80fd5b88602082850101111561045b575f80fd5b95986020929092019750949560400135945092505050565b5f805f60608486031215610485575f80fd5b61048e846103c9565b9250602084013591506104a3604085016103c9565b90509250925092565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015280871660408401525084606083015260a0608083015261053a60a0830184866104ac565b98975050505050505050565b602081525f61014f6020830184866104ac565b5f60208284031215610569575f80fd5b505191905056"; - -/// @dev The runtime bytecode of the contract. -bytes constant RUNTIME_CODE = - hex"608060405234801561000f575f80fd5b5060043610610034575f3560e01c806340419eec1461003857806393a7e71114610074575b5f80fd5b61004b6100463660046103f1565b610087565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004b610082366004610473565b6100c7565b5f61009185610159565b5f6100ae866100a933865f9182526020526040902090565b6101ac565b90506100bd86828787876101b8565b9695505050505050565b5f61014f846100df84865f9182526020526040902090565b6040513060388201526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012073ffffffffffffffffffffffffffffffffffffffff1690565b90505b9392505050565b8073ffffffffffffffffffffffffffffffffffffffff163b5f036101a9576040517ff432283200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61015283835f6102f1565b5f7f3b3e5b48cfaf4a4b3b2b36425ddec21c2c507fd502d2aea55eb7ffa36b0ca2053387878588886040516101f2969594939291906104f3565b60405180910390a16040517f439fab910000000000000000000000000000000000000000000000000000000081527fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc39073ffffffffffffffffffffffffffffffffffffffff87169063439fab91906102709088908890600401610546565b6020604051808303815f875af115801561028c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102b09190610559565b146102e7576040517f19b991a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092949350505050565b5f81471015610339576040517fcf4791810000000000000000000000000000000000000000000000000000000081524760048201526024810183905260440160405180910390fd5b763d602d80600a3d3981f3363d3d373d3d3d363d730000008460601b60e81c175f526e5af43d82803e903d91602b57fd5bf38460781b17602052826037600984f5905073ffffffffffffffffffffffffffffffffffffffff8116610152576040517fb06ebf3d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff811681146103ec575f80fd5b919050565b5f805f8060608587031215610404575f80fd5b61040d856103c9565b9350602085013567ffffffffffffffff80821115610429575f80fd5b818701915087601f83011261043c575f80fd5b81358181111561044a575f80fd5b88602082850101111561045b575f80fd5b95986020929092019750949560400135945092505050565b5f805f60608486031215610485575f80fd5b61048e846103c9565b9250602084013591506104a3604085016103c9565b90509250925092565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015280871660408401525084606083015260a0608083015261053a60a0830184866104ac565b98975050505050505050565b602081525f61014f6020830184866104ac565b5f60208284031215610569575f80fd5b505191905056"; diff --git a/src/lib/LibCloneFactoryDeploy.sol b/src/lib/LibCloneFactoryDeploy.sol deleted file mode 100644 index d63d7ef..0000000 --- a/src/lib/LibCloneFactoryDeploy.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity ^0.8.25; - -// THIS FILE IS AUTOGENERATED BY ./script/BuildPointers.sol - -import { - DEPLOYED_ADDRESS as CLONE_FACTORY_ADDR, - BYTECODE_HASH as CLONE_FACTORY_HASH -} from "../generated/0_1_5/CloneFactory.pointers.sol"; - -/// @title LibCloneFactoryDeploy -/// @notice The deterministic Zoltu deploy address and code hash of the current -/// `CloneFactory` release, aliased from the frozen per-release snapshot in -/// `src/generated//CloneFactory.pointers.sol` so that snapshot stays the -/// single source of truth. Lets consumers verify/deploy against a precommitted -/// address + hash rather than a registry. -library LibCloneFactoryDeploy { - address constant CLONE_FACTORY_DEPLOYED_ADDRESS = CLONE_FACTORY_ADDR; - bytes32 constant CLONE_FACTORY_DEPLOYED_CODEHASH = CLONE_FACTORY_HASH; -} diff --git a/test/src/concrete/CloneFactoryCloneDeterministic.t.sol b/test/src/concrete/CloneFactoryCloneDeterministic.t.sol deleted file mode 100644 index 52b4fff..0000000 --- a/test/src/concrete/CloneFactoryCloneDeterministic.t.sol +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Test, Vm} from "forge-std-1.16.1/src/Test.sol"; - -import {Clones} from "@openzeppelin-contracts-5.6.1/proxy/Clones.sol"; -import {LibExtrospectERC1167Proxy} from "rain-extrospection-0.1.1/src/lib/LibExtrospectERC1167Proxy.sol"; -import {ICLONEABLE_V2_SUCCESS} from "../../../src/interface/ICloneableV2.sol"; -import {CloneFactory, ZeroImplementationCodeSize, InitializationFailed} from "../../../src/concrete/CloneFactory.sol"; -import {TestCloneable} from "./TestCloneable.sol"; -import {TestCloneableFailure} from "./TestCloneableFailure.sol"; - -/// @title CloneFactoryCloneDeterministicTest -/// @notice A test suite for `CloneFactory`'s `cloneDeterministic` / -/// `predictDeterministicAddress` functions. -contract CloneFactoryCloneDeterministicTest is Test { - /// The `CloneFactory` instance under test. Stateless, so reused everywhere. - CloneFactory internal immutable I_CLONE_FACTORY; - - constructor() { - I_CLONE_FACTORY = new CloneFactory(); - } - - /// The effective CREATE2 salt is exactly `keccak256(abi.encode(deployer, - /// salt))`, so an off-chain caller can reproduce the predicted address from - /// the two inputs. Pins the salt derivation — including the scratch-space - /// assembly that computes it — against OZ's own prediction under that salt. - function testCloneDeterministicSaltIsAbiEncodeHash(address implementation, bytes32 salt, address deployer) - external - view - { - bytes32 effectiveSalt = keccak256(abi.encode(deployer, salt)); - address expected = Clones.predictDeterministicAddress(implementation, effectiveSalt, address(I_CLONE_FACTORY)); - assertEq(I_CLONE_FACTORY.predictDeterministicAddress(implementation, salt, deployer), expected); - } - - /// The deployed clone lands at the predicted address, is an EIP1167 proxy of - /// the implementation, and is initialized with the data. `predict` therefore - /// lets a caller pin the address before deploying. - function testCloneDeterministicMatchesPredict(bytes32 salt, bytes memory data) external { - TestCloneable implementation = new TestCloneable(); - - address predicted = I_CLONE_FACTORY.predictDeterministicAddress(address(implementation), salt, address(this)); - address child = I_CLONE_FACTORY.cloneDeterministic(address(implementation), data, salt); - - assertEq(child, predicted); - (bool isProxy, address proxyImplementation) = LibExtrospectERC1167Proxy.isERC1167Proxy(child.code); - assertEq(isProxy, true); - assertEq(proxyImplementation, address(implementation)); - assertEq(TestCloneable(child).sData(), data); - } - - /// Distinct salts yield distinct clones of the same implementation — many - /// clones per impl (unlike a salt-free / one-per-impl deterministic deploy). - function testCloneDeterministicManyClonesPerImpl(bytes32 salt1, bytes32 salt2, bytes memory data) external { - vm.assume(salt1 != salt2); - TestCloneable implementation = new TestCloneable(); - - address child1 = I_CLONE_FACTORY.cloneDeterministic(address(implementation), data, salt1); - address child2 = I_CLONE_FACTORY.cloneDeterministic(address(implementation), data, salt2); - assertTrue(child1 != child2); - } - - /// The same `(implementation, salt)` from different callers yields different - /// addresses: the salt is namespaced by `msg.sender`, so no caller can squat - /// or front-run another's address. `predict` reflects the deployer. - function testCloneDeterministicSenderScoped(bytes32 salt, bytes memory data, address alice, address bob) external { - vm.assume(alice != bob); - TestCloneable implementation = new TestCloneable(); - - address predictedAlice = I_CLONE_FACTORY.predictDeterministicAddress(address(implementation), salt, alice); - address predictedBob = I_CLONE_FACTORY.predictDeterministicAddress(address(implementation), salt, bob); - assertTrue(predictedAlice != predictedBob); - - vm.prank(alice); - address childAlice = I_CLONE_FACTORY.cloneDeterministic(address(implementation), data, salt); - assertEq(childAlice, predictedAlice); - - vm.prank(bob); - address childBob = I_CLONE_FACTORY.cloneDeterministic(address(implementation), data, salt); - assertEq(childBob, predictedBob); - - assertTrue(childAlice != childBob); - } - - /// `NewClone` is emitted with the caller, implementation and child. - function testCloneDeterministicEvent(bytes32 salt, bytes memory data) external { - TestCloneable implementation = new TestCloneable(); - - vm.recordLogs(); - address child = I_CLONE_FACTORY.cloneDeterministic(address(implementation), data, salt); - Vm.Log[] memory entries = vm.getRecordedLogs(); - - assertEq(entries.length, 1); - assertEq(entries[0].topics[0], bytes32(uint256(keccak256("NewClone(address,address,address,bytes32,bytes)")))); - assertEq(entries[0].data, abi.encode(address(this), address(implementation), child, salt, data)); - } - - /// An implementation that initializes to a non-success code reverts - /// `InitializationFailed`. - function testCloneDeterministicInitializeFailureFails(bytes32 notSuccess, bytes32 salt) external { - vm.assume(notSuccess != ICLONEABLE_V2_SUCCESS); - TestCloneableFailure implementation = new TestCloneableFailure(); - - vm.expectRevert(abi.encodeWithSelector(InitializationFailed.selector)); - I_CLONE_FACTORY.cloneDeterministic(address(implementation), abi.encode(notSuccess), salt); - } - - /// A zero-code implementation reverts `ZeroImplementationCodeSize`. - function testCloneDeterministicZeroImplementationCodeSize(address implementation, bytes memory data, bytes32 salt) - external - { - vm.assume(implementation.code.length == 0); - vm.expectRevert(abi.encodeWithSelector(ZeroImplementationCodeSize.selector)); - I_CLONE_FACTORY.cloneDeterministic(implementation, data, salt); - } -} diff --git a/test/src/concrete/TestCloneable.sol b/test/src/concrete/TestCloneable.sol deleted file mode 100644 index f1ec7b6..0000000 --- a/test/src/concrete/TestCloneable.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {ICloneableV2, ICLONEABLE_V2_SUCCESS} from "../../../src/interface/ICloneableV2.sol"; - -/// @title TestCloneable -/// @notice A cloneable contract that implements `ICloneableV2`. Initializes -/// whatever data is passed to `initialize` as `sData`. As `sData` is public, -/// we can easily test that it is set correctly. -contract TestCloneable is ICloneableV2 { - bytes public sData; - - /// @inheritdoc ICloneableV2 - function initialize(bytes memory data) external returns (bytes32) { - sData = data; - return ICLONEABLE_V2_SUCCESS; - } -} diff --git a/test/src/concrete/TestCloneableFailure.sol b/test/src/concrete/TestCloneableFailure.sol deleted file mode 100644 index 87d657e..0000000 --- a/test/src/concrete/TestCloneableFailure.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {ICloneableV2} from "../../../src/interface/ICloneableV2.sol"; - -/// @title TestCloneableFailure -/// @notice A cloneable contract that implements `ICloneableV2` but always -/// fails initialization. Specifically, it returns whatever data is passed to -/// `initialize`, which is expected NOT to be `ICLONEABLE_V2_SUCCESS` for the -/// purposes of testing. -contract TestCloneableFailure is ICloneableV2 { - /// @inheritdoc ICloneableV2 - function initialize(bytes memory data) external pure returns (bytes32 notSuccess) { - (notSuccess) = abi.decode(data, (bytes32)); - } -} diff --git a/test/src/lib/LibCloneFactoryDeploy.t.sol b/test/src/lib/LibCloneFactoryDeploy.t.sol deleted file mode 100644 index c319fec..0000000 --- a/test/src/lib/LibCloneFactoryDeploy.t.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Test} from "forge-std-1.16.1/src/Test.sol"; -import {LibRainDeploy} from "rain-deploy-0.1.3/src/lib/LibRainDeploy.sol"; -import {LibCloneFactoryDeploy} from "../../../src/lib/LibCloneFactoryDeploy.sol"; -import {CloneFactory} from "../../../src/concrete/CloneFactory.sol"; - -contract LibCloneFactoryDeployTest is Test { - function testDeployAddress() external { - LibRainDeploy.etchZoltuFactory(vm); - - address deployedAddress = LibRainDeploy.deployZoltu(type(CloneFactory).creationCode); - - assertEq(deployedAddress, LibCloneFactoryDeploy.CLONE_FACTORY_DEPLOYED_ADDRESS); - assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); - - assertEq(address(deployedAddress).codehash, LibCloneFactoryDeploy.CLONE_FACTORY_DEPLOYED_CODEHASH); - } - - function testExpectedCodeHash() external { - CloneFactory cloneFactory = new CloneFactory(); - - assertEq(address(cloneFactory).codehash, LibCloneFactoryDeploy.CLONE_FACTORY_DEPLOYED_CODEHASH); - } -} diff --git a/test/src/lib/LibCloneFactoryDeployProd.t.sol b/test/src/lib/LibCloneFactoryDeployProd.t.sol deleted file mode 100644 index ac4c5ba..0000000 --- a/test/src/lib/LibCloneFactoryDeployProd.t.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Test} from "forge-std-1.16.1/src/Test.sol"; -import {LibRainDeploy} from "rain-deploy-0.1.3/src/lib/LibRainDeploy.sol"; -import {LibCloneFactoryDeploy} from "../../../src/lib/LibCloneFactoryDeploy.sol"; - -/// @title LibCloneFactoryDeployProdTest -/// @notice Forks each supported network and verifies that CloneFactory is -/// deployed at the expected address with the expected codehash. -contract LibCloneFactoryDeployProdTest is Test { - function _checkAllContracts() internal view { - assertTrue(LibCloneFactoryDeploy.CLONE_FACTORY_DEPLOYED_ADDRESS.code.length > 0, "CloneFactory not deployed"); - assertEq( - LibCloneFactoryDeploy.CLONE_FACTORY_DEPLOYED_ADDRESS.codehash, - LibCloneFactoryDeploy.CLONE_FACTORY_DEPLOYED_CODEHASH - ); - } - - /// CloneFactory MUST be deployed on Arbitrum. - function testProdDeployArbitrum() external { - vm.createSelectFork(LibRainDeploy.ARBITRUM_ONE); - _checkAllContracts(); - } - - /// CloneFactory MUST be deployed on Base. - function testProdDeployBase() external { - vm.createSelectFork(LibRainDeploy.BASE); - _checkAllContracts(); - } - - /// CloneFactory MUST be deployed on Base Sepolia. - function testProdDeployBaseSepolia() external { - vm.createSelectFork(LibRainDeploy.BASE_SEPOLIA); - _checkAllContracts(); - } - - /// CloneFactory MUST be deployed on Flare. - function testProdDeployFlare() external { - vm.createSelectFork(LibRainDeploy.FLARE); - _checkAllContracts(); - } - - /// CloneFactory MUST be deployed on Polygon. - function testProdDeployPolygon() external { - vm.createSelectFork(LibRainDeploy.POLYGON); - _checkAllContracts(); - } -} diff --git a/test/src/lib/LibCloneFactoryDeployTaggedConstants.t.sol b/test/src/lib/LibCloneFactoryDeployTaggedConstants.t.sol deleted file mode 100644 index a13cb31..0000000 --- a/test/src/lib/LibCloneFactoryDeployTaggedConstants.t.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Test} from "forge-std-1.16.1/src/Test.sol"; -import {LibRainDeploy} from "rain-deploy-0.1.3/src/lib/LibRainDeploy.sol"; -import { - BYTECODE_HASH as CLONE_FACTORY_BYTECODE_HASH_0_1_3, - DEPLOYED_ADDRESS as CLONE_FACTORY_DEPLOYED_ADDRESS_0_1_3, - CREATION_CODE as CLONE_FACTORY_CREATION_CODE_0_1_3, - RUNTIME_CODE as CLONE_FACTORY_RUNTIME_CODE_0_1_3 -} from "../../../src/generated/0_1_3/CloneFactory.pointers.sol"; -import { - BYTECODE_HASH as CLONE_FACTORY_BYTECODE_HASH_0_1_4, - DEPLOYED_ADDRESS as CLONE_FACTORY_DEPLOYED_ADDRESS_0_1_4, - CREATION_CODE as CLONE_FACTORY_CREATION_CODE_0_1_4, - RUNTIME_CODE as CLONE_FACTORY_RUNTIME_CODE_0_1_4 -} from "../../../src/generated/0_1_4/CloneFactory.pointers.sol"; -import { - BYTECODE_HASH as CLONE_FACTORY_BYTECODE_HASH_0_1_5, - DEPLOYED_ADDRESS as CLONE_FACTORY_DEPLOYED_ADDRESS_0_1_5, - CREATION_CODE as CLONE_FACTORY_CREATION_CODE_0_1_5, - RUNTIME_CODE as CLONE_FACTORY_RUNTIME_CODE_0_1_5 -} from "../../../src/generated/0_1_5/CloneFactory.pointers.sol"; - -/// @title LibCloneFactoryDeployTaggedConstantsTest -/// @notice Each frozen per-tag `CloneFactory` snapshot must be self-consistent -/// and reproducible: its recorded `BYTECODE_HASH` is the keccak of its recorded -/// `RUNTIME_CODE`, and Zoltu-deploying its recorded `CREATION_CODE` lands at the -/// recorded `DEPLOYED_ADDRESS` with the recorded codehash. A new release adds a -/// tag import + a test pair here. -contract LibCloneFactoryDeployTaggedConstantsTest is Test { - /// `keccak256(RUNTIME_CODE) == BYTECODE_HASH` for the tag — the pin is - /// internally consistent. - function testCloneFactory_0_1_3_RuntimeHashesToBytecodeHash() external pure { - assertEq(keccak256(CLONE_FACTORY_RUNTIME_CODE_0_1_3), CLONE_FACTORY_BYTECODE_HASH_0_1_3); - } - - /// Deploying the frozen `CREATION_CODE` via the Zoltu factory lands at the - /// recorded `DEPLOYED_ADDRESS` with the recorded codehash — the snapshot - /// reproduces its own deployment. - function testCloneFactory_0_1_3_CreationDeploysToPinnedAddress() external { - LibRainDeploy.etchZoltuFactory(vm); - address deployed = LibRainDeploy.deployZoltu(CLONE_FACTORY_CREATION_CODE_0_1_3); - assertEq(deployed, CLONE_FACTORY_DEPLOYED_ADDRESS_0_1_3); - assertEq(deployed.codehash, CLONE_FACTORY_BYTECODE_HASH_0_1_3); - assertEq(keccak256(deployed.code), CLONE_FACTORY_BYTECODE_HASH_0_1_3); - } - - /// `keccak256(RUNTIME_CODE) == BYTECODE_HASH` for the tag — the pin is - /// internally consistent. - function testCloneFactory_0_1_4_RuntimeHashesToBytecodeHash() external pure { - assertEq(keccak256(CLONE_FACTORY_RUNTIME_CODE_0_1_4), CLONE_FACTORY_BYTECODE_HASH_0_1_4); - } - - /// Deploying the frozen `CREATION_CODE` via the Zoltu factory lands at the - /// recorded `DEPLOYED_ADDRESS` with the recorded codehash — the snapshot - /// reproduces its own deployment. - function testCloneFactory_0_1_4_CreationDeploysToPinnedAddress() external { - LibRainDeploy.etchZoltuFactory(vm); - address deployed = LibRainDeploy.deployZoltu(CLONE_FACTORY_CREATION_CODE_0_1_4); - assertEq(deployed, CLONE_FACTORY_DEPLOYED_ADDRESS_0_1_4); - assertEq(deployed.codehash, CLONE_FACTORY_BYTECODE_HASH_0_1_4); - assertEq(keccak256(deployed.code), CLONE_FACTORY_BYTECODE_HASH_0_1_4); - } - - /// `keccak256(RUNTIME_CODE) == BYTECODE_HASH` for the tag — the pin is - /// internally consistent. - function testCloneFactory_0_1_5_RuntimeHashesToBytecodeHash() external pure { - assertEq(keccak256(CLONE_FACTORY_RUNTIME_CODE_0_1_5), CLONE_FACTORY_BYTECODE_HASH_0_1_5); - } - - /// Deploying the frozen `CREATION_CODE` via the Zoltu factory lands at the - /// recorded `DEPLOYED_ADDRESS` with the recorded codehash — the snapshot - /// reproduces its own deployment. - function testCloneFactory_0_1_5_CreationDeploysToPinnedAddress() external { - LibRainDeploy.etchZoltuFactory(vm); - address deployed = LibRainDeploy.deployZoltu(CLONE_FACTORY_CREATION_CODE_0_1_5); - assertEq(deployed, CLONE_FACTORY_DEPLOYED_ADDRESS_0_1_5); - assertEq(deployed.codehash, CLONE_FACTORY_BYTECODE_HASH_0_1_5); - assertEq(keccak256(deployed.code), CLONE_FACTORY_BYTECODE_HASH_0_1_5); - } -}