Skip to content
Open
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
70 changes: 70 additions & 0 deletions test/src/concrete/Flow.construction.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {Vm} from "forge-std/Test.sol";
import {EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol";
import {FlowTest} from "test/abstract/FlowTest.sol";
import {EmptyFlowConfig} from "src/error/ErrFlow.sol";
import {ICloneableV2} from "rain.factory/src/interface/ICloneableV2.sol";
import {Flow} from "src/concrete/Flow.sol";

contract FlowConstructionTest is FlowTest {
function testFlowConstructionEmptyConfigReverts() external {
Expand All @@ -16,6 +18,74 @@ contract FlowConstructionTest is FlowTest {
I_CLONE_FACTORY.clone(impl, abi.encode(emptyConfig));
}

/// The typed `initialize(EvaluableConfigV3[])` overload is mandated by
/// `ICloneableV2` to revert with `InitializeSignatureFn` so that it is
/// NEVER accidentally called in place of the canonical `initialize(bytes)`.
/// forge-config: default.fuzz.runs = 100
function testFlowImplementationInitializeStructOverloadAlwaysReverts(EvaluableConfigV3[] memory evaluableConfigs)
external
{
Flow impl = Flow(deployFlowImplementation());
vm.expectRevert(ICloneableV2.InitializeSignatureFn.selector);
impl.initialize(evaluableConfigs);
}

/// The typed overload must revert even on an already-initialized clone.
/// forge-config: default.fuzz.runs = 100
function testFlowCloneInitializeStructOverloadAlwaysReverts(
address expression,
bytes memory bytecode,
uint256[] memory constants,
EvaluableConfigV3[] memory secondCallConfigs
) external {
expressionDeployerDeployExpression2MockCall(expression, bytes(hex"0007"));

EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](1);
flowConfig[0] = EvaluableConfigV3(DEPLOYER, bytecode, constants);

address clone = I_CLONE_FACTORY.clone(deployFlowImplementation(), abi.encode(flowConfig));

vm.expectRevert(ICloneableV2.InitializeSignatureFn.selector);
Flow(clone).initialize(secondCallConfigs);
}

/// `_disableInitializers` in the implementation constructor must block
/// any direct `initialize(bytes)` call on the implementation.
/// forge-config: default.fuzz.runs = 100
function testFlowImplementationInitializeBytesAlwaysReverts(
address expression,
bytes memory bytecode,
uint256[] memory constants
) external {
expressionDeployerDeployExpression2MockCall(expression, bytes(hex"0007"));

EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](1);
flowConfig[0] = EvaluableConfigV3(DEPLOYER, bytecode, constants);

Flow impl = Flow(deployFlowImplementation());
vm.expectRevert(bytes("Initializable: contract is already initialized"));
impl.initialize(abi.encode(flowConfig));
}

/// A successfully initialized clone must reject a second
/// `initialize(bytes)` call.
/// forge-config: default.fuzz.runs = 100
function testFlowCloneInitializeBytesOnceOnly(
address expression,
bytes memory bytecode,
uint256[] memory constants
) external {
expressionDeployerDeployExpression2MockCall(expression, bytes(hex"0007"));

EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](1);
flowConfig[0] = EvaluableConfigV3(DEPLOYER, bytecode, constants);

address clone = I_CLONE_FACTORY.clone(deployFlowImplementation(), abi.encode(flowConfig));

vm.expectRevert(bytes("Initializable: contract is already initialized"));
Flow(clone).initialize(abi.encode(flowConfig));
}

function testFlowConstructionInitialize(address expression, bytes memory bytecode, uint256[] memory constants)
external
{
Expand Down
Loading