diff --git a/.github/workflows/git-clean.yaml b/.github/workflows/git-clean.yaml new file mode 100644 index 00000000..2324c624 --- /dev/null +++ b/.github/workflows/git-clean.yaml @@ -0,0 +1,6 @@ +name: Git is clean +on: [push] +jobs: + copy-artifacts: + uses: rainlanguage/rainix/.github/workflows/rainix-copy-artifacts.yaml@main + secrets: inherit diff --git a/.github/workflows/manual-sol-artifacts.yaml b/.github/workflows/manual-sol-artifacts.yaml index 4f1b2dec..425e66ed 100644 --- a/.github/workflows/manual-sol-artifacts.yaml +++ b/.github/workflows/manual-sol-artifacts.yaml @@ -2,35 +2,15 @@ name: Manual sol artifacts on: workflow_dispatch: inputs: - network: - description: 'Network to deploy to' + suite: + description: "The suite to deploy" required: true type: choice options: - - polygon - - songbird - - flare - - base - + - flow jobs: deploy: - runs-on: ubuntu-latest - env: - DEPLOYMENT_KEY: ${{ secrets.PRIVATE_KEY }} - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-depth: 0 - - - uses: DeterminateSystems/nix-installer-action@v4 - - uses: DeterminateSystems/magic-nix-cache-action@v2 - - - run: nix develop --command rainix-sol-prelude - - run: nix develop --command rainix-sol-artifacts - env: - ETH_RPC_URL: ${{ inputs.network == 'polygon' && secrets.CI_DEPLOY_POLYGON_RPC_URL || inputs.network == 'songbird' && secrets.CI_DEPLOY_SONGBIRD_RPC_URL || inputs.network == 'flare' && secrets.CI_DEPLOY_FLARE_RPC_URL || inputs.network == 'base' && secrets.CI_DEPLOY_BASE_RPC_URL || '' }} - # Flare has hardcoded api key https://flarescan.com/documentation/recipes/foundry-verification - ETHERSCAN_API_KEY: ${{ inputs.network == 'flare' && 'verifyContract' || secrets.EXPLORER_VERIFICATION_KEY }} - DEPLOY_VERIFIER: ${{ inputs.network == 'songbird' && 'blockscout' || inputs.network == 'polygon' && 'etherscan' || '' }} - DEPLOY_VERIFIER_URL: ${{ inputs.network == 'songbird' && 'https://songbird-explorer.flare.network/api' || inputs.network == 'flare' && 'https://api.routescan.io/v2/network/mainnet/evm/14/etherscan' || '' }} + uses: rainlanguage/rainix/.github/workflows/rainix-manual-sol-artifacts.yaml@main + with: + suite: ${{ inputs.suite }} + secrets: inherit diff --git a/.github/workflows/rainix.yaml b/.github/workflows/rainix.yaml index f2b73de9..827ab306 100644 --- a/.github/workflows/rainix.yaml +++ b/.github/workflows/rainix.yaml @@ -1,45 +1,6 @@ -name: Rainix CI +name: rainix-sol on: [push] - jobs: - standard-tests: - strategy: - matrix: - os: [ubuntu-latest] - task: [rainix-sol-test, rainix-sol-static, rainix-sol-legal] - fail-fast: false - runs-on: ${{ matrix.os }} - env: - DEPLOYMENT_KEY: ${{ secrets.PRIVATE_KEY }} - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-depth: 0 - - - uses: nixbuild/nix-quick-install-action@v30 - with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - - uses: cachix/cachix-action@v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v6 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 1G - - - run: nix develop --command rainix-sol-prelude - - - name: Run ${{ matrix.task }} - env: - ETH_RPC_URL: ${{ secrets.CI_DEPLOY_RPC_URL }} - ETHERSCAN_API_KEY: ${{ secrets.EXPLORER_VERIFICATION_KEY }} - DEPLOY_VERIFIER: 'etherscan' - run: nix develop --command ${{ matrix.task }} \ No newline at end of file + rainix-sol: + uses: rainlanguage/rainix/.github/workflows/rainix-sol.yaml@main + secrets: inherit diff --git a/.gitignore b/.gitignore index 73816921..ec240101 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ out cache - -.pre-commit-config.yaml \ No newline at end of file +dependencies +node_modules +.pre-commit-config.yaml diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 07cb22d5..00000000 --- a/.gitmodules +++ /dev/null @@ -1,18 +0,0 @@ -[submodule "lib/forge-std"] - path = lib/forge-std - url = https://github.com/foundry-rs/forge-std -[submodule "lib/rain.math.fixedpoint"] - path = lib/rain.math.fixedpoint - url = https://github.com/rainprotocol/rain.math.fixedpoint -[submodule "lib/rain.factory"] - path = lib/rain.factory - url = https://github.com/rainprotocol/rain.factory -[submodule "lib/openzeppelin-contracts-upgradeable"] - path = lib/openzeppelin-contracts-upgradeable - url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable -[submodule "lib/rain.solmem"] - path = lib/rain.solmem - url = https://github.com/rainprotocol/rain.solmem -[submodule "lib/rain.interpreter.interface"] - path = lib/rain.interpreter.interface - url = https://github.com/rainlanguage/rain.interpreter.interface diff --git a/REUSE.toml b/REUSE.toml index 63997131..1270a999 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -15,6 +15,9 @@ path = [ "foundry.lock", "foundry.toml", "slither.config.json", + "soldeer.lock", + "remappings.txt", + "src/generated/**", ] SPDX-FileCopyrightText = "Copyright (c) 2020 Rain Open Source Software Ltd" SPDX-License-Identifier = "LicenseRef-DCL-1.0" diff --git a/foundry.toml b/foundry.toml index 14996b0c..76f7b20c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,7 +1,7 @@ [profile.default] src = 'src' out = 'out' -libs = ['lib'] +libs = ['dependencies'] # See more config options https://github.com/foundry-rs/foundry/tree/master/config @@ -18,7 +18,51 @@ optimizer_runs = 1000000 bytecode_hash = "none" cbor_metadata = false +fs_permissions = [{ access = "read-write", path = "./src/generated"}] +remappings = [ + "forge-std/=dependencies/forge-std-1.16.1/src/", + "rain.factory/=dependencies/rain-factory-0.1.1/", + "rain.interpreter.interface/=dependencies/rain-interpreter-interface-0.1.0/src/", + "rain.solmem/=dependencies/rain-solmem-0.1.3/src/", + "openzeppelin-contracts-upgradeable/contracts/=dependencies/@openzeppelin-contracts-upgradeable-5.6.1/", + "openzeppelin-contracts/contracts/=dependencies/@openzeppelin-contracts-5.6.1/", + "openzeppelin/=dependencies/@openzeppelin-contracts-upgradeable-5.6.1/", + "@openzeppelin/contracts-upgradeable/=dependencies/@openzeppelin-contracts-upgradeable-5.6.1/", + "@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.6.1/", +] [fuzz] runs = 2048 -seed = "0xdeadbeef" \ No newline at end of file +seed = "0xdeadbeef" + +[dependencies] +forge-std = "1.16.1" +"@openzeppelin-contracts" = "5.6.1" +"@openzeppelin-contracts-upgradeable" = "5.6.1" +rain-factory = "0.1.1" +rain-interpreter-interface = "0.1.0" +rain-math-fixedpoint = "0.2.0" +rain-solmem = "0.1.3" +rain-lib-hash = "0.1.0" +rain-math-float = "0.1.1" +rain-metadata = "0.1.0" +rain-lib-typecast = "0.1.0" +rain-deploy = "0.1.2" +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/lib/forge-std b/lib/forge-std deleted file mode 160000 index 1d9650e9..00000000 --- a/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1d9650e951204a0ddce9ff89c32f1997984cef4d diff --git a/lib/openzeppelin-contracts-upgradeable b/lib/openzeppelin-contracts-upgradeable deleted file mode 160000 index 3d4c0d57..00000000 --- a/lib/openzeppelin-contracts-upgradeable +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3d4c0d5741b131c231e558d7a6213392ab3672a5 diff --git a/lib/rain.factory b/lib/rain.factory deleted file mode 160000 index 0b55d7e7..00000000 --- a/lib/rain.factory +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0b55d7e770633c443577e4eddf6ac832fac5daeb diff --git a/lib/rain.interpreter.interface b/lib/rain.interpreter.interface deleted file mode 160000 index dab8e3dd..00000000 --- a/lib/rain.interpreter.interface +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dab8e3dd110ef984e0c056cee085a4d7ee99cbb7 diff --git a/lib/rain.math.fixedpoint b/lib/rain.math.fixedpoint deleted file mode 160000 index 65df07e8..00000000 --- a/lib/rain.math.fixedpoint +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 65df07e8c1a93adb5766ec00a05a93e474277067 diff --git a/lib/rain.solmem b/lib/rain.solmem deleted file mode 160000 index 6414ab88..00000000 --- a/lib/rain.solmem +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6414ab88a017eacf2b263e9e08d0787fbd677192 diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 00000000..28432609 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,13 @@ +@openzeppelin-contracts-5.6.1/=dependencies/@openzeppelin-contracts-5.6.1/ +@openzeppelin-contracts-upgradeable-5.6.1/=dependencies/@openzeppelin-contracts-upgradeable-5.6.1/ +forge-std-1.16.1/=dependencies/forge-std-1.16.1/ +rain-deploy-0.1.2/=dependencies/rain-deploy-0.1.2/ +rain-factory-0.1.1/=dependencies/rain-factory-0.1.1/ +rain-interpreter-interface-0.1.0/=dependencies/rain-interpreter-interface-0.1.0/ +rain-lib-hash-0.1.0/=dependencies/rain-lib-hash-0.1.0/ +rain-lib-typecast-0.1.0/=dependencies/rain-lib-typecast-0.1.0/ +rain-math-fixedpoint-0.2.0/=dependencies/rain-math-fixedpoint-0.2.0/ +rain-math-float-0.1.1/=dependencies/rain-math-float-0.1.1/ +rain-metadata-0.1.0/=dependencies/rain-metadata-0.1.0/ +rain-sol-codegen-0.1.0/=dependencies/rain-sol-codegen-0.1.0/ +rain-solmem-0.1.3/=dependencies/rain-solmem-0.1.3/ diff --git a/script/BuildPointers.sol b/script/BuildPointers.sol new file mode 100644 index 00000000..801a196b --- /dev/null +++ b/script/BuildPointers.sol @@ -0,0 +1,42 @@ +// 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/Script.sol"; +import {LibRainDeploy} from "rain-deploy-0.1.2/src/lib/LibRainDeploy.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 {Flow} from "../src/concrete/Flow.sol"; + +/// @title BuildPointers +/// @notice Deploys the Flow implementation via the Zoltu factory in a local +/// environment and generates `Flow.pointers.sol` with the deterministic deploy +/// address and bytecode hash. +contract BuildPointers is Script { + 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); + address deployed = LibRainDeploy.deployZoltu(type(Flow).creationCode); + LibFs.buildFileForContract( + vm, + deployed, + "Flow", + string.concat( + addressConstantString(deployed), + LibCodeGen.bytesConstantString( + vm, "/// @dev The creation bytecode of the contract.", "CREATION_CODE", type(Flow).creationCode + ) + ) + ); + } +} diff --git a/script/Deploy.sol b/script/Deploy.sol new file mode 100644 index 00000000..67b26bb1 --- /dev/null +++ b/script/Deploy.sol @@ -0,0 +1,42 @@ +// 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/Script.sol"; +import {LibRainDeploy} from "rain-deploy-0.1.2/src/lib/LibRainDeploy.sol"; +import {Flow} from "../src/concrete/Flow.sol"; +import { + DEPLOYED_ADDRESS as FLOW_DEPLOYED_ADDRESS, + BYTECODE_HASH as FLOW_BYTECODE_HASH +} from "../src/generated/Flow.pointers.sol"; + +bytes32 constant DEPLOYMENT_SUITE_FLOW = keccak256("flow"); + +/// @title Deploy +/// @notice Deterministic deployment of the Flow implementation via the Zoltu +/// factory across all supported networks. Requires DEPLOYMENT_KEY + +/// DEPLOYMENT_SUITE=flow. +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.envString("DEPLOYMENT_SUITE"))); + + if (suite == DEPLOYMENT_SUITE_FLOW) { + LibRainDeploy.deployAndBroadcast( + vm, + LibRainDeploy.supportedNetworks(), + deployerPrivateKey, + type(Flow).creationCode, + "src/concrete/Flow.sol:Flow", + FLOW_DEPLOYED_ADDRESS, + FLOW_BYTECODE_HASH, + new address[](0), + sDepCodeHashes + ); + } else { + revert("Unknown deployment suite"); + } + } +} diff --git a/soldeer.lock b/soldeer.lock new file mode 100644 index 00000000..b930f31d --- /dev/null +++ b/soldeer.lock @@ -0,0 +1,76 @@ +[[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 = "@openzeppelin-contracts-upgradeable" +version = "5.6.1" +url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts-upgradeable/5_6_1_15-03-2026_09:19:56_contracts-upgradeable.zip" +checksum = "f6257dbc993c2499fe08fdc93f66e12459fe3458ee62ce716b92e1d95ee0b504" +integrity = "2f539b6241258fc3c127c97225b3cb1b5e9225e422d2c1cb233c52a6f5c29002" + +[[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-factory" +version = "0.1.1" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-factory/0_1_1_20-05-2026_13:02:17_rain.zip" +checksum = "6b02e2b87983e196bc88cb8fb802a2720b252783429567864cd13336167c369d" +integrity = "be6a3343d0ea247d8b495b584cd21c3bf64f0a1396ca21aaa8ce31715df29842" + +[[dependencies]] +name = "rain-interpreter-interface" +version = "0.1.0" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-interpreter-interface/0_1_0_12-05-2026_18:43:02_rain.interpreter.zip" +checksum = "887c4d5f1a87713c49f015b3fcdb295defbb495b126d15f9850c0ce72ef79639" +integrity = "c1b89f8a7ad02507ceb051b6c0f2750f6abe1ba99ffdfe1c9ac93905db90e75d" + +[[dependencies]] +name = "rain-lib-hash" +version = "0.1.0" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-lib-hash/0_1_0_12-05-2026_16:24:56_rain.lib.zip" +checksum = "648f3e38b297dbd3ecb32b82c8b24c322f484e1734eb50fd393bc547c72b59b0" +integrity = "91f5f679a0a27f096fdbc1e41195dd9f42cacfab15735efeb1101cc1b9215b47" + +[[dependencies]] +name = "rain-lib-typecast" +version = "0.1.0" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-lib-typecast/0_1_0_12-05-2026_16:31:39_rain.lib.zip" +checksum = "5c0419501e4c763ef161a3489934af192219f994cb2c9187699bc4dee0b4e2bb" +integrity = "092781f87fd9227c4c95aafde59300c503d6a9a355beaeb5c5732fe6e36676d6" + +[[dependencies]] +name = "rain-math-fixedpoint" +version = "0.2.0" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-math-fixedpoint/0_2_0_09-05-2026_21:16:31_rain.math.zip" +checksum = "dd24665a7c3bc82878fdbcfe5ea8efe8471ec9c8546615dc94debc38529117d9" +integrity = "81a144050f76b662c91f1611ec18f41dce0994208617123cde80aad2fc9b441c" + +[[dependencies]] +name = "rain-math-float" +version = "0.1.1" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-math-float/0_1_1_13-05-2026_13:48:34_rain.math.zip" +checksum = "322956f272ae3073ee02b0e7301b8834f08f2de62bcd6c309c44e946d7cd7056" +integrity = "dccdd4406a37db6af690872b805084a7dbe5211c57961a61ef083a7912ddbdc9" + +[[dependencies]] +name = "rain-metadata" +version = "0.1.0" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-metadata/0_1_0_12-05-2026_20:20:51_rain.zip" +checksum = "801d2b97b393d346c19a2f4f454d0279ba8f7d0f81fa3eb4fe8609da7291203d" +integrity = "f17f10aa50e9e2b254c689c83f41b3cabab81c95bad06424b9b3e9c92d02e577" + +[[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" diff --git a/src/concrete/Flow.sol b/src/concrete/Flow.sol index 476e1aaf..c1180a55 100644 --- a/src/concrete/Flow.sol +++ b/src/concrete/Flow.sol @@ -5,36 +5,31 @@ pragma solidity =0.8.25; import {LibUint256Array} from "rain.solmem/lib/LibUint256Array.sol"; import {Pointer} from "rain.solmem/lib/LibPointer.sol"; import { - IInterpreterCallerV2, + IInterpreterCallerV4, SignedContextV1, - EvaluableConfigV3 -} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {LibEncodedDispatch} from "rain.interpreter.interface/lib/caller/LibEncodedDispatch.sol"; + EvaluableV4 +} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol"; -import {UnregisteredFlow} from "../interface/IFlowV5.sol"; -import {LibEvaluable, EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {UnregisteredFlow} from "../interface/IFlowV6.sol"; +import {LibEvaluable} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; import { + IInterpreterV4, + EvalV4, + StackItem, SourceIndexV2, - IInterpreterV2, - IInterpreterStoreV2, DEFAULT_STATE_NAMESPACE -} from "rain.interpreter.interface/interface/IInterpreterV2.sol"; +} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; +import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import { MulticallUpgradeable as Multicall } from "openzeppelin-contracts-upgradeable/contracts/utils/MulticallUpgradeable.sol"; -import { - ERC721HolderUpgradeable as ERC721Holder -} from "openzeppelin-contracts-upgradeable/contracts/token/ERC721/utils/ERC721HolderUpgradeable.sol"; -import { - ERC1155HolderUpgradeable as ERC1155Holder -} from "openzeppelin-contracts-upgradeable/contracts/token/ERC1155/utils/ERC1155HolderUpgradeable.sol"; -import { - ReentrancyGuardUpgradeable as ReentrancyGuard -} from "openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; -import {LibUint256Matrix} from "rain.solmem/lib/LibUint256Matrix.sol"; +import {ERC721Holder} from "openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol"; +import {ERC1155Holder} from "openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import {ReentrancyGuard} from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; +import {LibBytes32Matrix} from "rain.solmem/lib/LibBytes32Matrix.sol"; import {LibNamespace, StateNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol"; -import {UnsupportedFlowInputs, InsufficientFlowOutputs, EmptyFlowConfig} from "../error/ErrFlow.sol"; -import {IFlowV5, MIN_FLOW_SENTINELS, FlowTransferV1} from "../interface/IFlowV5.sol"; +import {EmptyFlowConfig} from "../error/ErrFlow.sol"; +import {IFlowV6, MIN_FLOW_SENTINELS, FlowTransferV1} from "../interface/IFlowV6.sol"; import {ICloneableV2, ICLONEABLE_V2_SUCCESS} from "rain.factory/src/interface/ICloneableV2.sol"; import {LibFlow} from "../lib/LibFlow.sol"; @@ -88,10 +83,10 @@ uint256 constant FLOW_IS_NOT_REGISTERED = 0; /// This is a known issue with `Multicall` so in the future, we may refactor /// `Flow` to not use `Multicall` and instead implement flow batching /// directly in the flow contracts. -contract Flow is ERC721Holder, ERC1155Holder, Multicall, ReentrancyGuard, IInterpreterCallerV2, ICloneableV2, IFlowV5 { +contract Flow is ERC721Holder, ERC1155Holder, Multicall, ReentrancyGuard, IInterpreterCallerV4, ICloneableV2, IFlowV6 { using LibUint256Array for uint256[]; - using LibUint256Matrix for uint256[]; - using LibEvaluable for EvaluableV2; + using LibBytes32Matrix for bytes32[]; + using LibEvaluable for EvaluableV4; using LibNamespace for StateNamespace; /// @dev This mapping tracks all flows that are registered at initialization. @@ -107,7 +102,7 @@ contract Flow is ERC721Holder, ERC1155Holder, Multicall, ReentrancyGuard, IInter /// @param evaluable The evaluable of the flow that was registered. The hash /// of this evaluable is used as the key in `registeredFlows` so users MUST /// provide the same evaluable when they evaluate the flow. - event FlowInitialized(address sender, EvaluableV2 evaluable); + event FlowInitialized(address sender, EvaluableV4 evaluable); /// Forwards config to `DeployerDiscoverableMetaV2` and disables /// initializers. The initializers are disabled because inheriting contracts @@ -122,32 +117,36 @@ contract Flow is ERC721Holder, ERC1155Holder, Multicall, ReentrancyGuard, IInter /// Overloaded typed initialize function MUST revert with this error. /// As per `ICloneableV2` interface. - function initialize(EvaluableConfigV3[] memory) external pure { + function initialize(EvaluableV4[] memory) external pure { revert InitializeSignatureFn(); } /// @inheritdoc ICloneableV2 function initialize(bytes calldata data) external initializer returns (bytes32) { - EvaluableConfigV3[] memory flowConfig = abi.decode(data, (EvaluableConfigV3[])); + EvaluableV4[] memory flowConfig = abi.decode(data, (EvaluableV4[])); emit Initialize(msg.sender, flowConfig); flowInit(flowConfig, MIN_FLOW_SENTINELS); return ICLONEABLE_V2_SUCCESS; } - /// @inheritdoc IFlowV5 - function stackToFlow(uint256[] memory stack) external pure virtual override returns (FlowTransferV1 memory) { - return LibFlow.stackToFlow(stack.dataPointer(), stack.endPointer()); + /// @inheritdoc IFlowV6 + function stackToFlow(StackItem[] memory stack) external pure virtual override returns (FlowTransferV1 memory) { + uint256[] memory stackU; + assembly ("memory-safe") { + stackU := stack + } + return LibFlow.stackToFlow(stackU.dataPointer(), stackU.endPointer()); } - /// @inheritdoc IFlowV5 - function flow(EvaluableV2 memory evaluable, uint256[] memory callerContext, SignedContextV1[] memory signedContexts) + /// @inheritdoc IFlowV6 + function flow(EvaluableV4 memory evaluable, bytes32[] memory callerContext, SignedContextV1[] memory signedContexts) external virtual nonReentrant returns (FlowTransferV1 memory) { - (Pointer stackBottom, Pointer stackTop, uint256[] memory kvs) = + (Pointer stackBottom, Pointer stackTop, bytes32[] memory kvs) = _flowStack(evaluable, callerContext, signedContexts); FlowTransferV1 memory flowTransfer = LibFlow.stackToFlow(stackBottom, stackTop); LibFlow.flow(flowTransfer, evaluable.store, kvs); @@ -156,23 +155,20 @@ contract Flow is ERC721Holder, ERC1155Holder, Multicall, ReentrancyGuard, IInter /// Common initialization logic for inheriting contracts. This MUST be /// called by inheriting contracts in their initialization logic (and only). - /// @param evaluableConfigs The evaluable configs to register at + /// @param evaluables The evaluable configs to register at /// initialization. Each of these represents a flow that defines valid token /// movements at runtime for the inheriting contract. /// @param flowMinOutputs The minimum number of outputs for each flow. All /// flows share the same minimum number of outputs for simplicity. - function flowInit(EvaluableConfigV3[] memory evaluableConfigs, uint256 flowMinOutputs) internal onlyInitializing { + function flowInit(EvaluableV4[] memory evaluables, uint256 flowMinOutputs) internal onlyInitializing { unchecked { // First dispatch all the Open Zeppelin initializers. - __ERC721Holder_init(); - __ERC1155Holder_init(); __Multicall_init(); - __ReentrancyGuard_init(); // Reject empty configs at init time — an empty config would // produce a permanently inert clone where every `flow()` call // reverts with `UnregisteredFlow`. - if (evaluableConfigs.length == 0) { + if (evaluables.length == 0) { revert EmptyFlowConfig(); } @@ -183,39 +179,14 @@ contract Flow is ERC721Holder, ERC1155Holder, Multicall, ReentrancyGuard, IInter revert BadMinStackLength(flowMinOutputs); } - EvaluableConfigV3 memory config; - EvaluableV2 memory evaluable; - // Every evaluable MUST deploy cleanly (e.g. pass integrity checks) - // otherwise the entire initialization will fail. - for (uint256 i = 0; i < evaluableConfigs.length; ++i) { - config = evaluableConfigs[i]; - // Well behaved deployers SHOULD NOT be reentrant into the flow - // contract. It is up to the EOA that is initializing this - // flow contract to select a deployer that is trustworthy. - // Reentrancy is just one of many ways that a malicious deployer - // can cause problems, and it's probably the least of your - // worries if you're using a malicious deployer. - //slither-disable-next-line calls-loop - (IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression, bytes memory io) = - config.deployer.deployExpression2(config.bytecode, config.constants); - - { - uint256 flowInputs; - uint256 flowOutputs; - assembly ("memory-safe") { - let ioWord := mload(add(io, 0x20)) - flowInputs := byte(0, ioWord) - flowOutputs := byte(1, ioWord) - } - if (flowInputs != 0) { - revert UnsupportedFlowInputs(); - } - if (flowOutputs < flowMinOutputs) { - revert InsufficientFlowOutputs(); - } - } - - evaluable = EvaluableV2(interpreter, store, expression); + EvaluableV4 memory evaluable; + // In V4 the caller provides already-compiled evaluables + // (interpreter, store, bytecode) directly; there is no deploy-time + // integrity check. Flow validity is enforced at eval time by + // sentinel consumption against MIN_FLOW_SENTINELS, matching the + // upstream RaindexV6 caller model. + for (uint256 i = 0; i < evaluables.length; ++i) { + evaluable = evaluables[i]; // There's no way to set this mapping before the external // contract call because the output of the external contract // call is used to build the evaluable that we're registering. @@ -247,12 +218,12 @@ contract Flow is ERC721Holder, ERC1155Holder, Multicall, ReentrancyGuard, IInter /// @return The top of the stack after evaluation. /// @return The key-value pairs that were emitted during evaluation. function _flowStack( - EvaluableV2 memory evaluable, - uint256[] memory callerContext, + EvaluableV4 memory evaluable, + bytes32[] memory callerContext, SignedContextV1[] memory signedContexts - ) internal returns (Pointer, Pointer, uint256[] memory) { - uint256[][] memory context = LibContext.build(callerContext.matrixFrom(), signedContexts); - emit Context(msg.sender, context); + ) internal returns (Pointer, Pointer, bytes32[] memory) { + bytes32[][] memory context = LibContext.build(callerContext.matrixFrom(), signedContexts); + emit ContextV2(msg.sender, context); // Refuse to evaluate unregistered flows. { @@ -262,14 +233,22 @@ contract Flow is ERC721Holder, ERC1155Holder, Multicall, ReentrancyGuard, IInter } } - (uint256[] memory stack, uint256[] memory kvs) = evaluable.interpreter - .eval2( - evaluable.store, - DEFAULT_STATE_NAMESPACE.qualifyNamespace(address(this)), - LibEncodedDispatch.encode2(evaluable.expression, FLOW_ENTRYPOINT, FLOW_MAX_OUTPUTS), - context, - new uint256[](0) + (StackItem[] memory stack, bytes32[] memory kvs) = evaluable.interpreter + .eval4( + EvalV4({ + store: evaluable.store, + namespace: DEFAULT_STATE_NAMESPACE.qualifyNamespace(address(this)), + bytecode: evaluable.bytecode, + sourceIndex: FLOW_ENTRYPOINT, + context: context, + inputs: new StackItem[](0), + stateOverlay: new bytes32[](0) + }) ); - return (stack.dataPointer(), stack.endPointer(), kvs); + uint256[] memory stackU; + assembly ("memory-safe") { + stackU := stack + } + return (stackU.dataPointer(), stackU.endPointer(), kvs); } } diff --git a/src/generated/Flow.pointers.sol b/src/generated/Flow.pointers.sol new file mode 100644 index 00000000..5497c24e --- /dev/null +++ b/src/generated/Flow.pointers.sol @@ -0,0 +1,21 @@ +// 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(0x9c3aaa52a59e42744e7e2f4db32b2b28c20a4f3dad7bbc82416df9a3628f4096); + +/// @dev The deterministic deploy address of the contract when deployed via +/// the Zoltu factory. +address constant DEPLOYED_ADDRESS = address(0x502DcAb53948f43af1Fc3a63D14A47daC44C2992); + +/// @dev The creation bytecode of the contract. +bytes constant CREATION_CODE = + hex"608060405234801561000f575f80fd5b5060017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005561003c610041565b6100f3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100915760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100f05780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b612a67806101005f395ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c806374ee296111610072578063ac9650d811610058578063ac9650d81461019c578063bc197c81146101bc578063f23a6e61146101f4575f80fd5b806374ee2961146101745780638b0451b314610187575f80fd5b806301ffc9a7146100a3578063150b7a02146100cb578063439fab91146101335780635141fa5014610154575b5f80fd5b6100b66100b1366004611b86565b61022c565b60405190151581526020015b60405180910390f35b6101026100d9366004611d18565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016100c2565b610146610141366004611d80565b6102c4565b6040519081526020016100c2565b610167610162366004611e0f565b61049f565b6040516100c29190611f21565b61016761018236600461214e565b6104e1565b61019a6101953660046122c1565b61056b565b005b6101af6101aa36600461236b565b61059d565b6040516100c29190612414565b6101026101ca366004612494565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b61010261020236600461253b565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806102be57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b5f806102ce610683565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156102fa5750825b90505f8267ffffffffffffffff1660011480156103165750303b155b905081158015610324575080155b1561035b576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156103bc5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b5f6103c9888a018a6122c1565b90507f45836ca64537496d04d68ba085419b97dc4a1604e069da6ab6600137cacc100533826040516103fc9291906125e9565b60405180910390a161040f8160036106ab565b7fe0e57eda3f08f2a93bbe980d3df7f9c315eac41181f58b865a13d917fe769fc396505083156104945784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505092915050565b6104c360405180606001604052806060815260200160608152602001606081525090565b816104da60208201825160209081028401016107f7565b9392505050565b61050560405180606001604052806060815260200160608152602001606081525090565b61050d61097d565b5f805f61051b8787876109ab565b9250925092505f61052c84846107f7565b905061053d81896020015184610bfa565b93505050506104da60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b6040517faf1fbb2100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f8152602081019091526060908267ffffffffffffffff8111156105c7576105c7611be9565b6040519080825280602002602001820160405280156105fa57816020015b60608152602001906001900390816105e55790505b5091505f5b8381101561067b576106563086868481811061061d5761061d612687565b905060200281019061062f91906126b4565b856040516020016106429392919061271c565b604051602081830303815290604052610ca3565b83828151811061066857610668612687565b60209081029190910101526001016105ff565b505092915050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102be565b6106b3610d8f565b6106bb610dcf565b81515f036106f5576040517fd49a3ae700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003811015610738576040517fb0682cf3000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b60408051606080820183525f8083526020830181905292820152905b83518110156107f15783818151811061076f5761076f612687565b6020026020010151915060015f8061079f85604080820151918190205f9081528251602093840120909252902090565b81526020019081526020015f20819055507f1454fb0416b1cf656a24af9ccad993ea0595b0b7c0a9bf67d23162c65c5f4b2333836040516107e192919061273f565b60405180910390a1600101610754565b50505050565b61081b60405180606001604052806060815260200160608152602001606081525090565b60408051808201909152601281527f5241494e5f464c4f575f53454e54494e454c0000000000000000000000000000602090910152606080805f61088287877ffea74d0c9bf4a3c28f0dd0674db22a3d7f8bf259c56af19f4ac1e735b156974f6004610dd7565b60408051808201909152601281527f5241494e5f464c4f575f53454e54494e454c000000000000000000000000000060209091015290965093508390506108ec87877ffea74d0c9bf4a3c28f0dd0674db22a3d7f8bf259c56af19f4ac1e735b156974f6004610dd7565b60408051808201909152601281527f5241494e5f464c4f575f53454e54494e454c0000000000000000000000000000602090910152909650925082905061095687877ffea74d0c9bf4a3c28f0dd0674db22a3d7f8bf259c56af19f4ac1e735b156974f6005610dd7565b60408051606081018252968752602087019590955293850193909352509195945050505050565b610985610efe565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5f8060605f6109d56109cf8760408051600181526020810192909252818101905290565b86610f59565b90507f4cb6e22a3e7e651d7cf0376cff48f20f5007a54147777865be7f5f6c38c50f4a3382604051610a08929190612812565b60405180910390a16040878101518189205f90815281516020928301208252828120808252918190529190912054610a6f576040517f7a80ba4d0000000000000000000000000000000000000000000000000000000081526004810182905260240161072f565b505f80885f015173ffffffffffffffffffffffffffffffffffffffff1663d04dfe236040518060e001604052808c6020015173ffffffffffffffffffffffffffffffffffffffff168152602001610acf305f61126190919063ffffffff16565b81526020018c6040015181526020015f81526020018681526020015f67ffffffffffffffff811115610b0357610b03611be9565b604051908082528060200260200182016040528015610b2c578160200160208202803683370190505b5081526020015f604051908082528060200260200182016040528015610b5c578160200160208202803683370190505b508152506040518263ffffffff1660e01b8152600401610b7c9190612840565b5f60405180830381865afa158015610b96573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610bdb919081019061296c565b815160208084019d9181029093019092019a5098509650505050505050565b805115610c83576040517f04b19db400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906304b19db490610c55905f908590600401612a22565b5f604051808303815f87803b158015610c6c575f80fd5b505af1158015610c7e573d5f803e3d5ffd5b505050505b610c8c8361126f565b610c95836113ef565b610c9e83611579565b505050565b60605f610cb08484611722565b9050808015610cde57505f3d1180610cde57505f8473ffffffffffffffffffffffffffffffffffffffff163b115b15610cf357610ceb611735565b9150506102be565b8015610d43576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161072f565b3d15610d5657610d5161174e565b610d88565b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b610d97611759565b610dcd576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b610dcd610d8f565b5f80825f03610e12576040517f933ea90f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208302855b87811115610e3c576020810386815103610e33579350610e3c565b50819003610e18565b50825f03610ebd5786861015610e88576040517fd2031c8f000000000000000000000000000000000000000000000000000000008152600481018890526024810187905260440161072f565b6040517fd457746f0000000000000000000000000000000000000000000000000000000081526004810186905260240161072f565b604051915060208201602084015b87811015610ee3578082526020909101908201610ecb565b50806040526001602084830304038352505094509492505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054600203610dcd576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60605f825167ffffffffffffffff811115610f7657610f76611be9565b604051908082528060200260200182016040528015610f9f578160200160208202803683370190505b5090505f80845111610fb1575f610fb7565b83516001015b85516001010190505f8167ffffffffffffffff811115610fd957610fd9611be9565b60405190808252806020026020018201604052801561100c57816020015b6060815260200190600190039081610ff75790505b5090505f611030604080516002815233602082015230818301526060810190915290565b82828151811061104257611042612687565b60200260200101819052505f5b875181101561109f57818060010192505087818151811061107257611072612687565b602002602001015183838151811061108c5761108c612687565b602090810291909101015260010161104f565b50855115611257578080600101915050838282815181106110c2576110c2612687565b60200260200101819052505f5b86518110156112555761117e8782815181106110ed576110ed612687565b60200260200101515f015161115b6111298a858151811061111057611110612687565b6020026020010151602001518051602090810291012090565b7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f908152601c91909152603c902090565b89848151811061116d5761116d612687565b602002602001015160400151611777565b6111b7576040517f52bf98480000000000000000000000000000000000000000000000000000000081526004810182905260240161072f565b8681815181106111c9576111c9612687565b60200260200101515f015173ffffffffffffffffffffffffffffffffffffffff165f1b8582815181106111fe576111fe612687565b602002602001018181525050818060010192505086818151811061122457611224612687565b60200260200101516020015183838151811061124257611242612687565b60209081029190910101526001016110cf565b505b5095945050505050565b5f9182526020526040902090565b604080516080810182525f8082526020820181905291810182905260608101829052905b825151811015610c9e5782518051829081106112b1576112b1612687565b602002602001015191503373ffffffffffffffffffffffffffffffffffffffff16826020015173ffffffffffffffffffffffffffffffffffffffff16141580156113155750602082015173ffffffffffffffffffffffffffffffffffffffff163014155b1561134c576040517fa521c60f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16826020015173ffffffffffffffffffffffffffffffffffffffff16036113b9576040820151606083015183516113b49273ffffffffffffffffffffffffffffffffffffffff9091169133919061180e565b6113e7565b6040820151606083015183516113e79273ffffffffffffffffffffffffffffffffffffffff9091169161186a565b600101611293565b604080516080810182525f8082526020820181905291810182905260608101829052905b826020015151811015610c9e578260200151818151811061143657611436612687565b602002602001015191503373ffffffffffffffffffffffffffffffffffffffff16826020015173ffffffffffffffffffffffffffffffffffffffff161415801561149a5750602082015173ffffffffffffffffffffffffffffffffffffffff163014155b156114d1576040517f3a5befc500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516020830151604080850151606086015191517f42842e0e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9384166004820152908316602482015260448101919091529116906342842e0e906064015f604051808303815f87803b158015611558575f80fd5b505af115801561156a573d5f803e3d5ffd5b50505050806001019050611413565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101829052905b826040015151811015610c9e57826040015181815181106115c7576115c7612687565b602002602001015191503373ffffffffffffffffffffffffffffffffffffffff16826020015173ffffffffffffffffffffffffffffffffffffffff161415801561162b5750602082015173ffffffffffffffffffffffffffffffffffffffff163014155b15611662576040517fc6a91ecc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160208301516040808501516060860151608087015192517ff242432a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff948516600482015291841660248301526044820152606481019190915260a060848201525f60a482015291169063f242432a9060c4015f604051808303815f87803b158015611700575f80fd5b505af1158015611712573d5f803e3d5ffd5b5050600190920191506115a49050565b5f805f835160208501865af49392505050565b6040513d81523d5f602083013e3d602001810160405290565b6040513d5f823e3d81fd5b5f611762610683565b5468010000000000000000900460ff16919050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b5f036117fc575f806117a285856118c5565b5090925090505f8160038111156117bb576117bb612a3a565b1480156117f357508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b925050506104da565b61180784848461190e565b90506104da565b61181c848484846001611978565b6107f1576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161072f565b6118778383836001611a0b565b610c9e576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161072f565b5f805f83516041036118fc576020840151604085015160608601515f1a6118ee88828585611a93565b955095509550505050611907565b505081515f91506002905b9250925092565b8051604080517f1626ba7e000000000000000000000000000000000000000000000000000000008082526004820186905260248201929092525f92906020820185604483015e60205f60648401838a5afa9050825f5114601f3d1116811693505050509392505050565b6040517f23b872dd000000000000000000000000000000000000000000000000000000005f81815273ffffffffffffffffffffffffffffffffffffffff8781166004528616602452604485905291602083606481808c5af1925060015f511483166119fa5783831516156119ee573d5f823e3d81fd5b5f883b113d1516831692505b604052505f60605295945050505050565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000005f81815273ffffffffffffffffffffffffffffffffffffffff8616600452602485905291602083604481808b5af1925060015f51148316611a87578383151615611a7b573d5f823e3d81fd5b5f873b113d1516831692505b60405250949350505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611acc57505f91506003905082611b7c565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015611b1d573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611b7357505f925060019150829050611b7c565b92505f91508190505b9450945094915050565b5f60208284031215611b96575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146104da575f80fd5b73ffffffffffffffffffffffffffffffffffffffff81168114611be6575f80fd5b50565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611c3957611c39611be9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611c8657611c86611be9565b604052919050565b5f82601f830112611c9d575f80fd5b813567ffffffffffffffff811115611cb757611cb7611be9565b611ce860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611c3f565b818152846020838601011115611cfc575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611d2b575f80fd5b8435611d3681611bc5565b93506020850135611d4681611bc5565b925060408501359150606085013567ffffffffffffffff811115611d68575f80fd5b611d7487828801611c8e565b91505092959194509250565b5f8060208385031215611d91575f80fd5b823567ffffffffffffffff80821115611da8575f80fd5b818501915085601f830112611dbb575f80fd5b813581811115611dc9575f80fd5b866020828501011115611dda575f80fd5b60209290920196919550909350505050565b5f67ffffffffffffffff821115611e0557611e05611be9565b5060051b60200190565b5f6020808385031215611e20575f80fd5b823567ffffffffffffffff811115611e36575f80fd5b8301601f81018513611e46575f80fd5b8035611e59611e5482611dec565b611c3f565b81815260059190911b82018301908381019087831115611e77575f80fd5b928401925b82841015611e9557833582529284019290840190611e7c565b979650505050505050565b5f815180845260208085019450602084015f5b83811015611f16578151805173ffffffffffffffffffffffffffffffffffffffff9081168952848201518116858a015260408083015190911690890152606080820151908901526080908101519088015260a09096019590820190600101611eb3565b509495945050505050565b5f60208083526080808401855160608487015281815180845260a08801915085830193505f92505b80831015611fad57611f9982855173ffffffffffffffffffffffffffffffffffffffff80825116835280602083015116602084015280604083015116604084015250606081015160608301525050565b928501926001929092019190840190611f49565b50848801517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0888303810160408a01528151808452918701945092505f918601905b808310156120535761203f82865173ffffffffffffffffffffffffffffffffffffffff80825116835280602083015116602084015280604083015116604084015250606081015160608301525050565b938601936001929092019190850190611fef565b50604089015195508288820301606089015261206f8187611ea0565b9998505050505050505050565b5f6060828403121561208c575f80fd5b612094611c16565b905081356120a181611bc5565b815260208201356120b181611bc5565b6020820152604082013567ffffffffffffffff8111156120cf575f80fd5b6120db84828501611c8e565b60408301525092915050565b5f82601f8301126120f6575f80fd5b81356020612106611e5483611dec565b8083825260208201915060208460051b870101935086841115612127575f80fd5b602086015b84811015612143578035835291830191830161212c565b509695505050505050565b5f805f60608486031215612160575f80fd5b833567ffffffffffffffff80821115612177575f80fd5b6121838783880161207c565b9450602091508186013581811115612199575f80fd5b6121a5888289016120e7565b9450506040860135818111156121b9575f80fd5b8601601f810188136121c9575f80fd5b80356121d7611e5482611dec565b81815260059190911b8201840190848101908a8311156121f5575f80fd5b8584015b838110156122b05780358681111561220f575f80fd5b85016060818e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215612242575f80fd5b61224a611c16565b8882013561225781611bc5565b815260408201358881111561226a575f80fd5b6122788f8b838601016120e7565b8a8301525060608201358881111561228e575f80fd5b61229c8f8b83860101611c8e565b6040830152508452509186019186016121f9565b508096505050505050509250925092565b5f60208083850312156122d2575f80fd5b823567ffffffffffffffff808211156122e9575f80fd5b818501915085601f8301126122fc575f80fd5b813561230a611e5482611dec565b81815260059190911b83018401908481019088831115612328575f80fd5b8585015b8381101561235e57803585811115612342575f80fd5b6123508b89838a010161207c565b84525091860191860161232c565b5098975050505050505050565b5f806020838503121561237c575f80fd5b823567ffffffffffffffff80821115612393575f80fd5b818501915085601f8301126123a6575f80fd5b8135818111156123b4575f80fd5b8660208260051b8501011115611dda575f80fd5b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015612487577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526124758583516123c8565b9450928501929085019060010161243b565b5092979650505050505050565b5f805f805f60a086880312156124a8575f80fd5b85356124b381611bc5565b945060208601356124c381611bc5565b9350604086013567ffffffffffffffff808211156124df575f80fd5b6124eb89838a016120e7565b94506060880135915080821115612500575f80fd5b61250c89838a016120e7565b93506080880135915080821115612521575f80fd5b5061252e88828901611c8e565b9150509295509295909350565b5f805f805f60a0868803121561254f575f80fd5b853561255a81611bc5565b9450602086013561256a81611bc5565b93506040860135925060608601359150608086013567ffffffffffffffff811115612593575f80fd5b61252e88828901611c8e565b5f73ffffffffffffffffffffffffffffffffffffffff808351168452806020840151166020850152506040820151606060408501526125e160608501826123c8565b949350505050565b5f6040820173ffffffffffffffffffffffffffffffffffffffff8516835260206040602085015281855180845260608601915060608160051b8701019350602087015f5b82811015612679577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301845261266786835161259f565b9550928401929084019060010161262d565b509398975050505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126126e7575f80fd5b83018035915067ffffffffffffffff821115612701575f80fd5b602001915036819003821315612715575f80fd5b9250929050565b828482375f8382015f815283518060208601835e5f910190815295945050505050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f6125e1604083018461259f565b5f815180845260208085019450602084015f5b83811015611f1657815187529582019590820190600101612780565b5f8282518085526020808601955060208260051b840101602086015f5b84811015612805577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08684030189526127f383835161276d565b988401989250908301906001016127b9565b5090979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f6125e1604083018461279c565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152602082015160408201525f604083015160e060608401526128866101008401826123c8565b90506060840151608084015260808401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160a08601526128cc838361279c565b925060a08601519150808584030160c08601526128e9838361276d565b925060c08601519150808584030160e086015250612907828261276d565b95945050505050565b5f82601f83011261291f575f80fd5b8151602061292f611e5483611dec565b8083825260208201915060208460051b870101935086841115612950575f80fd5b602086015b848110156121435780518352918301918301612955565b5f806040838503121561297d575f80fd5b825167ffffffffffffffff80821115612994575f80fd5b818501915085601f8301126129a7575f80fd5b815160206129b7611e5483611dec565b82815260059290921b840181019181810190898411156129d5575f80fd5b948201945b838610156129f3578551825294820194908201906129da565b91880151919650909350505080821115612a0b575f80fd5b50612a1885828601612910565b9150509250929050565b828152604060208201525f6125e1604083018461276d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd"; diff --git a/src/interface/IFlowV5.sol b/src/interface/IFlowV5.sol index 17568fbd..3ac21ec3 100644 --- a/src/interface/IFlowV5.sol +++ b/src/interface/IFlowV5.sol @@ -2,8 +2,11 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SignedContextV1, EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import { + SignedContextV1, + EvaluableConfigV3 +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {EvaluableV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; //forge-lint: disable-next-line(unused-import) diff --git a/src/interface/IFlowV6.sol b/src/interface/IFlowV6.sol new file mode 100644 index 00000000..e066f239 --- /dev/null +++ b/src/interface/IFlowV6.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity ^0.8.25; + +import {SignedContextV1, EvaluableV4} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; +import {StackItem} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; +//forge-lint: disable-next-line(unused-import) +import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; +//forge-lint: disable-next-line(unused-import) +import {Pointer} from "rain.solmem/lib/LibPointer.sol"; +import { + FlowTransferV1, + + //forge-lint: disable-next-line(unused-import) + ERC20Transfer, + + //forge-lint: disable-next-line(unused-import) + ERC721Transfer, + + //forge-lint: disable-next-line(unused-import) + ERC1155Transfer, + + //forge-lint: disable-next-line(unused-import) + RAIN_FLOW_SENTINEL, + + //forge-lint: disable-next-line(unused-import) + MIN_FLOW_SENTINELS +} from "./deprecated/v4/IFlowV4.sol"; +//forge-lint: disable-next-line(unused-import) +import {UnregisteredFlow} from "../error/ErrFlow.sol"; + +/// @title IFlowV6 +/// @notice V4-interpreter flow: evaluables carry bytecode directly (no expression +/// deployment), context + stack are bytes32-based. +interface IFlowV6 { + /// Emitted when a flow contract is initialized with its evaluables. + /// @param sender The `msg.sender` that initialized the flow. + /// @param config The evaluables registered at initialization. + event Initialize(address sender, EvaluableV4[] config); + + function stackToFlow(StackItem[] memory stack) external pure returns (FlowTransferV1 memory flowTransfer); + function flow( + EvaluableV4 calldata evaluable, + bytes32[] calldata callerContext, + SignedContextV1[] calldata signedContexts + ) external returns (FlowTransferV1 memory flowTransfer); +} diff --git a/src/interface/deprecated/v1/IFlowERC1155V1.sol b/src/interface/deprecated/v1/IFlowERC1155V1.sol index 57d6f10a..b190cc40 100644 --- a/src/interface/deprecated/v1/IFlowERC1155V1.sol +++ b/src/interface/deprecated/v1/IFlowERC1155V1.sol @@ -6,7 +6,7 @@ import { EvaluableConfig, Evaluable, SignedContext -} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; import {FlowTransfer} from "./IFlowV1.sol"; diff --git a/src/interface/deprecated/v1/IFlowERC20V1.sol b/src/interface/deprecated/v1/IFlowERC20V1.sol index 4e5818a3..772fb77b 100644 --- a/src/interface/deprecated/v1/IFlowERC20V1.sol +++ b/src/interface/deprecated/v1/IFlowERC20V1.sol @@ -6,7 +6,7 @@ import { EvaluableConfig, Evaluable, SignedContext -} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; import {FlowTransfer} from "./IFlowV1.sol"; diff --git a/src/interface/deprecated/v1/IFlowERC721V1.sol b/src/interface/deprecated/v1/IFlowERC721V1.sol index dbf07e88..00ca3197 100644 --- a/src/interface/deprecated/v1/IFlowERC721V1.sol +++ b/src/interface/deprecated/v1/IFlowERC721V1.sol @@ -6,7 +6,7 @@ import { EvaluableConfig, Evaluable, SignedContext -} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; import {FlowTransfer} from "./IFlowV1.sol"; /// Thrown when burner of tokens is not the owner of tokens. diff --git a/src/interface/deprecated/v1/IFlowV1.sol b/src/interface/deprecated/v1/IFlowV1.sol index 52fba302..492796a1 100644 --- a/src/interface/deprecated/v1/IFlowV1.sol +++ b/src/interface/deprecated/v1/IFlowV1.sol @@ -6,7 +6,7 @@ import { EvaluableConfig, Evaluable, SignedContext -} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; /// Thrown for unsupported native transfers. error UnsupportedNativeFlow(); diff --git a/src/interface/deprecated/v2/IFlowERC1155V2.sol b/src/interface/deprecated/v2/IFlowERC1155V2.sol index 96efd41e..019f7432 100644 --- a/src/interface/deprecated/v2/IFlowERC1155V2.sol +++ b/src/interface/deprecated/v2/IFlowERC1155V2.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {EvaluableConfig, FlowTransfer, Evaluable} from "./IFlowV2.sol"; diff --git a/src/interface/deprecated/v2/IFlowERC20V2.sol b/src/interface/deprecated/v2/IFlowERC20V2.sol index 2ac55fc5..b7f2b806 100644 --- a/src/interface/deprecated/v2/IFlowERC20V2.sol +++ b/src/interface/deprecated/v2/IFlowERC20V2.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {FlowTransfer, EvaluableConfig, Evaluable} from "./IFlowV2.sol"; diff --git a/src/interface/deprecated/v2/IFlowERC721V2.sol b/src/interface/deprecated/v2/IFlowERC721V2.sol index 4a7f274a..43296b2b 100644 --- a/src/interface/deprecated/v2/IFlowERC721V2.sol +++ b/src/interface/deprecated/v2/IFlowERC721V2.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {EvaluableConfig, FlowTransfer, Evaluable} from "./IFlowV2.sol"; /// Constructor config. diff --git a/src/interface/deprecated/v2/IFlowV2.sol b/src/interface/deprecated/v2/IFlowV2.sol index 73482a6c..2dd28398 100644 --- a/src/interface/deprecated/v2/IFlowV2.sol +++ b/src/interface/deprecated/v2/IFlowV2.sol @@ -2,8 +2,8 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {Evaluable, EvaluableConfig} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {Evaluable, EvaluableConfig} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) import {UnsupportedNativeFlow} from "../v1/IFlowV1.sol"; diff --git a/src/interface/deprecated/v3/IFlowERC1155V3.sol b/src/interface/deprecated/v3/IFlowERC1155V3.sol index b5c88941..318bb6f4 100644 --- a/src/interface/deprecated/v3/IFlowERC1155V3.sol +++ b/src/interface/deprecated/v3/IFlowERC1155V3.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import { SourceIndex, diff --git a/src/interface/deprecated/v3/IFlowERC20V3.sol b/src/interface/deprecated/v3/IFlowERC20V3.sol index aa046b97..0d62e9b3 100644 --- a/src/interface/deprecated/v3/IFlowERC20V3.sol +++ b/src/interface/deprecated/v3/IFlowERC20V3.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SourceIndex} from "rain.interpreter.interface/interface/deprecated/IInterpreterV1.sol"; -import {EvaluableConfig, Evaluable} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SourceIndex} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterV1.sol"; +import {EvaluableConfig, Evaluable} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; import {MIN_FLOW_SENTINELS, SENTINEL_HIGH_BITS, FlowTransferV1} from "./IFlowV3.sol"; import {UnsupportedHandleTransferInputs, InsufficientHandleTransferOutputs} from "./IFlowERC1155V3.sol"; diff --git a/src/interface/deprecated/v3/IFlowERC721V3.sol b/src/interface/deprecated/v3/IFlowERC721V3.sol index a8dcfbea..83d25f0a 100644 --- a/src/interface/deprecated/v3/IFlowERC721V3.sol +++ b/src/interface/deprecated/v3/IFlowERC721V3.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import { SourceIndex, diff --git a/src/interface/deprecated/v3/IFlowV3.sol b/src/interface/deprecated/v3/IFlowV3.sol index 24b3b6ed..5207e656 100644 --- a/src/interface/deprecated/v3/IFlowV3.sol +++ b/src/interface/deprecated/v3/IFlowV3.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.25; //forge-lint: disable-next-line(unused-import) -import {SourceIndex} from "rain.interpreter.interface/interface/deprecated/IInterpreterV1.sol"; -import {Evaluable, EvaluableConfig} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SourceIndex} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterV1.sol"; +import {Evaluable, EvaluableConfig} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; /// @dev The number of sentinels required by `FlowCommon`. An evaluable can never diff --git a/src/interface/deprecated/v4/IFlowERC1155V4.sol b/src/interface/deprecated/v4/IFlowERC1155V4.sol index f60b72b5..02281ef0 100644 --- a/src/interface/deprecated/v4/IFlowERC1155V4.sol +++ b/src/interface/deprecated/v4/IFlowERC1155V4.sol @@ -2,10 +2,13 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {EvaluableConfigV2, Evaluable} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import { + EvaluableConfigV2, + Evaluable +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {EvaluableV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; //forge-lint: disable-next-line(unused-import) diff --git a/src/interface/deprecated/v4/IFlowERC20V4.sol b/src/interface/deprecated/v4/IFlowERC20V4.sol index f1263e28..c18b6bac 100644 --- a/src/interface/deprecated/v4/IFlowERC20V4.sol +++ b/src/interface/deprecated/v4/IFlowERC20V4.sol @@ -2,8 +2,11 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {Evaluable, EvaluableConfigV2} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import { + Evaluable, + EvaluableConfigV2 +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; import { diff --git a/src/interface/deprecated/v4/IFlowERC721V4.sol b/src/interface/deprecated/v4/IFlowERC721V4.sol index 67697986..dabc4170 100644 --- a/src/interface/deprecated/v4/IFlowERC721V4.sol +++ b/src/interface/deprecated/v4/IFlowERC721V4.sol @@ -2,8 +2,11 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {Evaluable, EvaluableConfigV2} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import { + Evaluable, + EvaluableConfigV2 +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import { FlowERC721IOV1, diff --git a/src/interface/deprecated/v4/IFlowV4.sol b/src/interface/deprecated/v4/IFlowV4.sol index c01ca8b4..18b02008 100644 --- a/src/interface/deprecated/v4/IFlowV4.sol +++ b/src/interface/deprecated/v4/IFlowV4.sol @@ -2,10 +2,13 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {EvaluableConfigV2, Evaluable} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import { + EvaluableConfigV2, + Evaluable +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV1.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {EvaluableV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; //forge-lint: disable-next-line(unused-import) diff --git a/src/interface/deprecated/v5/IFlowERC1155V5.sol b/src/interface/deprecated/v5/IFlowERC1155V5.sol index b95735c4..20935dc8 100644 --- a/src/interface/deprecated/v5/IFlowERC1155V5.sol +++ b/src/interface/deprecated/v5/IFlowERC1155V5.sol @@ -2,9 +2,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV2.sol"; -import {SignedContextV1, EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {SourceIndexV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterV2.sol"; +import { + SignedContextV1, + EvaluableConfigV3 +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {EvaluableV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; //forge-lint: disable-next-line(unused-import) diff --git a/src/interface/deprecated/v5/IFlowERC20V5.sol b/src/interface/deprecated/v5/IFlowERC20V5.sol index 172c00d4..721c86c7 100644 --- a/src/interface/deprecated/v5/IFlowERC20V5.sol +++ b/src/interface/deprecated/v5/IFlowERC20V5.sol @@ -2,9 +2,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV2.sol"; -import {SignedContextV1, EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {SourceIndexV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterV2.sol"; +import { + SignedContextV1, + EvaluableConfigV3 +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {EvaluableV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; //forge-lint: disable-next-line(unused-import) import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; import { diff --git a/src/interface/deprecated/v5/IFlowERC721V5.sol b/src/interface/deprecated/v5/IFlowERC721V5.sol index ccdafbe4..c2ec0622 100644 --- a/src/interface/deprecated/v5/IFlowERC721V5.sol +++ b/src/interface/deprecated/v5/IFlowERC721V5.sol @@ -2,9 +2,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {SignedContextV1, EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; -import {SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV2.sol"; +import { + SignedContextV1, + EvaluableConfigV3 +} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {EvaluableV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {SourceIndexV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterV2.sol"; import { FlowERC721IOV1, diff --git a/src/lib/LibFlow.sol b/src/lib/LibFlow.sol index 3bfe7ce9..6454ae84 100644 --- a/src/lib/LibFlow.sol +++ b/src/lib/LibFlow.sol @@ -11,11 +11,11 @@ import { RAIN_FLOW_SENTINEL, //forge-lint: disable-next-line(unused-import) - IFlowV5 -} from "../interface/IFlowV5.sol"; -import {IInterpreterStoreV2} from "rain.interpreter.interface/interface/IInterpreterStoreV2.sol"; + IFlowV6 +} from "../interface/IFlowV6.sol"; +import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import {LibStackSentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -import {DEFAULT_STATE_NAMESPACE} from "rain.interpreter.interface/interface/IInterpreterV2.sol"; +import {DEFAULT_STATE_NAMESPACE} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -149,7 +149,7 @@ library LibFlow { /// @param flowTransfer The `FlowTransferV1` to process. /// @param interpreterStore The `IInterpreterStoreV1` to set state on. /// @param kvs The key value pairs to set on the interpreter store. - function flow(FlowTransferV1 memory flowTransfer, IInterpreterStoreV2 interpreterStore, uint256[] memory kvs) + function flow(FlowTransferV1 memory flowTransfer, IInterpreterStoreV3 interpreterStore, bytes32[] memory kvs) internal { if (kvs.length > 0) { diff --git a/test/abstract/FlowTest.sol b/test/abstract/FlowTest.sol index 392b308c..b83955d6 100644 --- a/test/abstract/FlowTest.sol +++ b/test/abstract/FlowTest.sol @@ -5,21 +5,19 @@ pragma solidity ^0.8.25; import {Vm} from "forge-std/Test.sol"; import {FlowTransferOperation} from "test/abstract/FlowTransferOperation.sol"; import {InterpreterMockTest} from "test/abstract/InterpreterMockTest.sol"; -import {EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {EvaluableV4} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; import {CloneFactory} from "rain.factory/src/concrete/CloneFactory.sol"; import {LibLogHelper} from "test/lib/LibLogHelper.sol"; import {LibStackGeneration} from "test/lib/LibStackGeneration.sol"; -import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol"; -import {FlowTransferV1, IFlowV5, RAIN_FLOW_SENTINEL, Sentinel} from "../../src/interface/IFlowV5.sol"; +import {FlowTransferV1, IFlowV6, RAIN_FLOW_SENTINEL, Sentinel} from "../../src/interface/IFlowV6.sol"; import {Flow} from "../../src/concrete/Flow.sol"; +import {StackItem} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {LibUint256Matrix} from "rain.solmem/lib/LibUint256Matrix.sol"; import {LibUint256Array} from "rain.solmem/lib/LibUint256Array.sol"; abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { using LibLogHelper for Vm.Log[]; using LibStackGeneration for uint256; - using Address for address; using LibUint256Matrix for uint256[]; using LibUint256Array for uint256[]; @@ -31,19 +29,40 @@ abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { vm.resumeGasMetering(); } - function expressionDeployer(address expression, uint256[] memory constants, bytes memory bytecode) + /// Reinterpret a `uint256[]` as `bytes32[]` (identical 32-byte layout) for + /// passing as V4 caller context. + function asBytes32(uint256[] memory a) internal pure returns (bytes32[] memory b) { + assembly ("memory-safe") { + b := a + } + } + + /// Reinterpret a `uint256[]` stack as `StackItem[]` for V4 `stackToFlow`. + function asStackItems(uint256[] memory a) internal pure returns (StackItem[] memory b) { + assembly ("memory-safe") { + b := a + } + } + + /// Build a mock V4 evaluable. There is no expression deployment in V4 — the + /// evaluable carries bytecode directly. The `expression`/`constants` params + /// are retained for call-site compatibility but unused (constants are + /// embedded in bytecode); `bytecode` is unique per flow so registered hashes + /// differ. + function expressionDeployer(address, uint256[] memory, bytes memory bytecode) internal - returns (EvaluableConfigV3 memory) + view + returns (EvaluableV4 memory) { - expressionDeployerDeployExpression2MockCall(bytecode, constants, expression, bytes(hex"00060001")); - return EvaluableConfigV3(DEPLOYER, bytecode, constants); + return EvaluableV4(INTERPRETER, STORE, bytecode); } function expressionDeployer(uint256 key, address expression, uint256[] memory constants) internal - returns (EvaluableConfigV3 memory) + view + returns (EvaluableV4 memory) { - return expressionDeployer(expression, constants, abi.encodePacked(vm.addr(key))); + return expressionDeployer(expression, constants, abi.encodePacked(expression)); } function deployFlow( @@ -53,11 +72,11 @@ abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { address[] memory expressions, address configExpression, uint256[][] memory constants - ) internal returns (address flow, EvaluableV2[] memory evaluables) { + ) internal returns (address flow, EvaluableV4[] memory evaluables) { require(expressions.length == constants.length, "Expressions and constants array lengths must match"); { - EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](expressions.length); + EvaluableV4[] memory flowConfig = new EvaluableV4[](expressions.length); for (uint256 i = 0; i < expressions.length; i++) { flowConfig[i] = expressionDeployer(i + 1, expressions[i], constants[i]); @@ -71,32 +90,16 @@ abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { { Vm.Log[] memory logs = vm.getRecordedLogs(); - logs = logs.findEvents(keccak256("FlowInitialized(address,(address,address,address))")); - evaluables = new EvaluableV2[](logs.length); + logs = logs.findEvents(keccak256("FlowInitialized(address,(address,address,bytes))")); + evaluables = new EvaluableV4[](logs.length); for (uint256 i = 0; i < logs.length; i++) { - (, EvaluableV2 memory evaluable) = abi.decode(logs[i].data, (address, EvaluableV2)); + (, EvaluableV4 memory evaluable) = abi.decode(logs[i].data, (address, EvaluableV4)); evaluables[i] = evaluable; } } } function createMockBytecode() internal pure virtual returns (bytes memory) { - /* - Bytecode structure: - - First byte: 0x03 (sourceCount = 3) - - Next 2 bytes: 0x0002 (offset for sourceIndex = 0) - - Next 2 bytes: 0x0005 (offset for sourceIndex = 1) - - Next 2 bytes: 0x0008 (offset for sourceIndex = 2) - - Data for sourceIndex = 0: - - opsCount: 0x0A - - opcode: 0xAA - - Data for sourceIndex = 1: - - opsCount: 0x0B - - opcode: 0xBB - - Data for sourceIndex = 2: - - opsCount: 0x0C - - opcode: 0xCC - */ return hex"030002000500080AAA0BBB0CCC"; } @@ -106,7 +109,6 @@ abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { function assumeEtchable(address account, address expression) internal view { assumeNotPrecompile(account); - vm.assume(account != address(DEPLOYER)); vm.assume(account != address(INTERPRETER)); vm.assume(account != address(STORE)); vm.assume(account != address(I_CLONE_FACTORY)); @@ -114,7 +116,7 @@ abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { vm.assume(account != address(vm)); vm.assume(Sentinel.unwrap(RAIN_FLOW_SENTINEL) != uint256(uint160(account))); vm.assume(account != address(expression)); - vm.assume(!account.isContract()); + vm.assume(account.code.length == 0); // The console. vm.assume(account != address(0x000000000000000000636F6e736F6c652e6c6f67)); } @@ -139,7 +141,7 @@ abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { return (stack, transferHash); } - function buildConfig(string memory, string memory, string memory, address, EvaluableConfigV3[] memory flowConfig) + function buildConfig(string memory, string memory, string memory, address, EvaluableV4[] memory flowConfig) internal pure returns (bytes memory) @@ -151,19 +153,19 @@ abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { return address(new Flow()); } - function deployFlow() internal returns (IFlowV5, EvaluableV2 memory) { + function deployFlow() internal returns (IFlowV6, EvaluableV4 memory) { address[] memory expressions = new address[](1); expressions[0] = address(uint160(uint256(keccak256("expression")))); - (IFlowV5 flow, EvaluableV2[] memory evaluables) = + (IFlowV6 flow, EvaluableV4[] memory evaluables) = deployFlow({expressions: expressions, constants: new uint256[](0).matrixFrom()}); return (flow, evaluables[0]); } function deployFlow(address[] memory expressions, uint256[][] memory constants) internal - returns (IFlowV5, EvaluableV2[] memory) + returns (IFlowV6, EvaluableV4[] memory) { - (address flow, EvaluableV2[] memory evaluables) = deployFlow({ + (address flow, EvaluableV4[] memory evaluables) = deployFlow({ name: "", symbol: "", baseURI: "", @@ -171,7 +173,7 @@ abstract contract FlowTest is FlowTransferOperation, InterpreterMockTest { configExpression: address(uint160(uint256(keccak256("configExpression")))), constants: constants }); - return (IFlowV5(flow), evaluables); + return (IFlowV6(flow), evaluables); } function mintAndBurnFlowStack(address, uint256, uint256, uint256, FlowTransferV1 memory transfer) diff --git a/test/abstract/FlowTransferOperation.sol b/test/abstract/FlowTransferOperation.sol index cd8edad5..3b43268f 100644 --- a/test/abstract/FlowTransferOperation.sol +++ b/test/abstract/FlowTransferOperation.sol @@ -9,7 +9,7 @@ import { ERC721Transfer, ERC1155Transfer, RAIN_FLOW_SENTINEL -} from "../../src/interface/IFlowV5.sol"; +} from "../../src/interface/IFlowV6.sol"; import {REVERTING_MOCK_BYTECODE} from "./TestConstants.sol"; import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; diff --git a/test/abstract/FlowUtilsAbstractTest.sol b/test/abstract/FlowUtilsAbstractTest.sol index 3cb8b7a3..1abd1fc1 100644 --- a/test/abstract/FlowUtilsAbstractTest.sol +++ b/test/abstract/FlowUtilsAbstractTest.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.25; import {Vm} from "forge-std/Test.sol"; -import {FlowTransferV1, RAIN_FLOW_SENTINEL} from "../../src/interface/IFlowV5.sol"; +import {FlowTransferV1, RAIN_FLOW_SENTINEL} from "../../src/interface/IFlowV6.sol"; import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; import {LibStackGeneration} from "test/lib/LibStackGeneration.sol"; import {LibLogHelper} from "test/lib/LibLogHelper.sol"; diff --git a/test/abstract/InterpreterMockTest.sol b/test/abstract/InterpreterMockTest.sol index cbf1c946..80a03c55 100644 --- a/test/abstract/InterpreterMockTest.sol +++ b/test/abstract/InterpreterMockTest.sol @@ -4,106 +4,51 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {REVERTING_MOCK_BYTECODE} from "./TestConstants.sol"; -import {IInterpreterStoreV2} from "rain.interpreter.interface/interface/IInterpreterStoreV2.sol"; +import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import { - IInterpreterV2, - EncodedDispatch, + IInterpreterV4, + StackItem, DEFAULT_STATE_NAMESPACE -} from "rain.interpreter.interface/interface/IInterpreterV2.sol"; -import {IExpressionDeployerV3} from "rain.interpreter.interface/interface/IExpressionDeployerV3.sol"; +} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {LibNamespace, StateNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol"; abstract contract InterpreterMockTest is Test { using LibNamespace for StateNamespace; - IInterpreterV2 constant INTERPRETER = IInterpreterV2(address(uint160(uint256(keccak256("interpreter.rain.test"))))); - IInterpreterStoreV2 constant STORE = IInterpreterStoreV2(address(uint160(uint256(keccak256("store.rain.test"))))); - IExpressionDeployerV3 constant DEPLOYER = - IExpressionDeployerV3(address(uint160(uint256(keccak256("deployer.rain.test"))))); + IInterpreterV4 constant INTERPRETER = IInterpreterV4(address(uint160(uint256(keccak256("interpreter.rain.test"))))); + IInterpreterStoreV3 constant STORE = IInterpreterStoreV3(address(uint160(uint256(keccak256("store.rain.test"))))); constructor() { vm.pauseGasMetering(); vm.etch(address(INTERPRETER), REVERTING_MOCK_BYTECODE); vm.etch(address(STORE), REVERTING_MOCK_BYTECODE); - vm.etch(address(DEPLOYER), REVERTING_MOCK_BYTECODE); vm.resumeGasMetering(); } + /// Mock `eval4` to return the given stack/writes. Provided as `uint256[]` + /// for convenience and reinterpreted as `StackItem[]` / `bytes32[]` + /// (identical 32-byte memory layout). function interpreterEval2MockCall(uint256[] memory stack, uint256[] memory writes) internal { - vm.mockCall( - address(INTERPRETER), abi.encodeWithSelector(IInterpreterV2.eval2.selector), abi.encode(stack, writes) - ); - } - - function interpreterEval2MockCall( - address nameSpaceSender, - EncodedDispatch dispatch, - uint256[] memory stack, - uint256[] memory writes - ) internal { - vm.mockCall( - address(INTERPRETER), - abi.encodeWithSelector( - IInterpreterV2.eval2.selector, - STORE, - DEFAULT_STATE_NAMESPACE.qualifyNamespace(nameSpaceSender), - dispatch - ), - abi.encode(stack, writes) - ); + StackItem[] memory s; + bytes32[] memory w; + assembly ("memory-safe") { + s := stack + w := writes + } + vm.mockCall(address(INTERPRETER), abi.encodeWithSelector(IInterpreterV4.eval4.selector), abi.encode(s, w)); } - function interpreterEval2ExpectCall(address nameSpaceSender, EncodedDispatch dispatch, uint256[][] memory context) - internal - { - vm.expectCall( - address(INTERPRETER), - abi.encodeWithSelector( - IInterpreterV2.eval2.selector, - STORE, - DEFAULT_STATE_NAMESPACE.qualifyNamespace(nameSpaceSender), - dispatch, - context, - new uint256[](0) - ) - ); + /// Expect that `eval4` is called on the interpreter. V4 has no encoded + /// dispatch; the bytecode + source index live inside the `EvalV4` calldata, + /// so callers match on the selector. + function interpreterEval2ExpectCall(address, uint256[][] memory) internal { + vm.expectCall(address(INTERPRETER), abi.encodeWithSelector(IInterpreterV4.eval4.selector)); } - function interpreterEval2RevertCall(address nameSpaceSender, EncodedDispatch dispatch, uint256[][] memory context) - internal - { + /// Mock `eval4` to revert. + function interpreterEval2RevertCall(address, uint256[][] memory) internal { vm.mockCallRevert( - address(INTERPRETER), - abi.encodeWithSelector( - IInterpreterV2.eval2.selector, - STORE, - DEFAULT_STATE_NAMESPACE.qualifyNamespace(nameSpaceSender), - dispatch, - context, - new uint256[](0) - ), - "REVERT_EVAL2_CALL" - ); - } - - function expressionDeployerDeployExpression2MockCall(address expression, bytes memory io) internal { - vm.mockCall( - address(DEPLOYER), - abi.encodeWithSelector(IExpressionDeployerV3.deployExpression2.selector), - abi.encode(INTERPRETER, STORE, expression, io) - ); - } - - function expressionDeployerDeployExpression2MockCall( - bytes memory bytecode, - uint256[] memory constants, - address expression, - bytes memory io - ) internal { - vm.mockCall( - address(DEPLOYER), - abi.encodeWithSelector(IExpressionDeployerV3.deployExpression2.selector, bytecode, constants), - abi.encode(INTERPRETER, STORE, expression, io) + address(INTERPRETER), abi.encodeWithSelector(IInterpreterV4.eval4.selector), "REVERT_EVAL4_CALL" ); } } diff --git a/test/interface/IFlowV5.t.sol b/test/interface/IFlowV5.t.sol index cce81911..c84da380 100644 --- a/test/interface/IFlowV5.t.sol +++ b/test/interface/IFlowV5.t.sol @@ -7,7 +7,7 @@ import {Test} from "forge-std/Test.sol"; import {RAIN_FLOW_SENTINEL} from "../../src/interface/deprecated/v4/IFlowV4.sol"; import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -contract IFlowV5Test is Test { +contract IFlowV6Test is Test { function testSentinelValue() external { assertEq( 0xfea74d0c9bf4a3c28f0dd0674db22a3d7f8bf259c56af19f4ac1e735b156974f, Sentinel.unwrap(RAIN_FLOW_SENTINEL) diff --git a/test/lib/LibContextWrapper.sol b/test/lib/LibContextWrapper.sol index e1d01854..653ab179 100644 --- a/test/lib/LibContextWrapper.sol +++ b/test/lib/LibContextWrapper.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.25; import {LibUint256Matrix} from "rain.solmem/lib/LibUint256Matrix.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol"; /** @@ -21,10 +21,18 @@ library LibContextWrapper { address caller, address flowAddress ) internal view returns (uint256[][] memory) { - uint256[][] memory buildContextInput = LibContext.build(context, signedContext); - buildContextInput[0][0] = uint256(uint160(caller)); - buildContextInput[0][1] = uint256(uint160(flowAddress)); - return buildContextInput; + bytes32[][] memory ctx; + assembly ("memory-safe") { + ctx := context + } + bytes32[][] memory built = LibContext.build(ctx, signedContext); + built[0][0] = bytes32(uint256(uint160(caller))); + built[0][1] = bytes32(uint256(uint160(flowAddress))); + uint256[][] memory out; + assembly ("memory-safe") { + out := built + } + return out; } function buildAndSetContext( diff --git a/test/lib/LibStackGeneration.sol b/test/lib/LibStackGeneration.sol index 3ae45343..26bac723 100644 --- a/test/lib/LibStackGeneration.sol +++ b/test/lib/LibStackGeneration.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import {FlowTransferV1} from "../../src/interface/IFlowV5.sol"; +import {FlowTransferV1} from "../../src/interface/IFlowV6.sol"; library LibStackGeneration { function generateFlowStack(uint256 sentinel, FlowTransferV1 memory flowTransfer) diff --git a/test/lib/SignContextLib.sol b/test/lib/SignContextLib.sol index 4ba77078..b4a0ddc6 100644 --- a/test/lib/SignContextLib.sol +++ b/test/lib/SignContextLib.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.25; import {Vm} from "forge-std/Test.sol"; -import {ECDSAUpgradeable as ECDSA} from "openzeppelin/utils/cryptography/ECDSAUpgradeable.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {MessageHashUtils} from "openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; library SignContextLib { function signContext(Vm vm, uint256 signerPrivateKey, uint256 signaturePrivateKey, uint256[] memory context) @@ -17,11 +17,15 @@ library SignContextLib { // Store the signer's address in the struct signedContext.signer = vm.addr(signerPrivateKey); - signedContext.context = context; // copy the context data into the struct + bytes32[] memory ctx; + assembly ("memory-safe") { + ctx := context + } + signedContext.context = ctx; // copy the context data into the struct // Create a digest of the context data bytes32 contextHash = keccak256(abi.encodePacked(context)); - bytes32 digest = ECDSA.toEthSignedMessageHash(contextHash); + bytes32 digest = MessageHashUtils.toEthSignedMessageHash(contextHash); // Create the signature using the cheatCode 'sign' (uint8 v, bytes32 r, bytes32 s) = vm.sign(signaturePrivateKey, digest); diff --git a/test/src/concrete/Flow.construction.t.sol b/test/src/concrete/Flow.construction.t.sol index e210f957..460aba78 100644 --- a/test/src/concrete/Flow.construction.t.sol +++ b/test/src/concrete/Flow.construction.t.sol @@ -4,100 +4,37 @@ pragma solidity =0.8.25; import {Vm} from "forge-std/Test.sol"; -import {EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {EvaluableV4} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; import {FlowTest} from "test/abstract/FlowTest.sol"; -import {EmptyFlowConfig, InsufficientFlowOutputs, UnsupportedFlowInputs} from "../../../src/error/ErrFlow.sol"; -import {MIN_FLOW_SENTINELS} from "../../../src/interface/IFlowV5.sol"; +import {EmptyFlowConfig} from "../../../src/error/ErrFlow.sol"; import {LibLogHelper} from "test/lib/LibLogHelper.sol"; contract FlowConstructionTest is FlowTest { function testFlowConstructionEmptyConfigReverts() external { - EvaluableConfigV3[] memory emptyConfig = new EvaluableConfigV3[](0); + EvaluableV4[] memory emptyConfig = new EvaluableV4[](0); address impl = deployFlowImplementation(); vm.expectRevert(EmptyFlowConfig.selector); I_CLONE_FACTORY.clone(impl, abi.encode(emptyConfig)); } - /// Reverts with `InsufficientFlowOutputs` when the deployer reports a - /// `flowOutputs` byte below `MIN_FLOW_SENTINELS` (= 3). Pinning this - /// protects the lower-bound guard at `Flow.flowInit` against regression. - /// forge-config: default.fuzz.runs = 100 - function testFlowConstructionRevertsOnInsufficientFlowOutputs( - address expression, - bytes memory bytecode, - uint256[] memory constants, - uint8 flowOutputs - ) external { - vm.assume(flowOutputs < uint8(MIN_FLOW_SENTINELS)); - bytes memory io = abi.encodePacked(uint8(0), flowOutputs); - expressionDeployerDeployExpression2MockCall(expression, io); + // Note: under the V4 interpreter there is no deploy-time integrity check — + // evaluables carry bytecode directly with no `deployExpression2`/`io`, so the + // former `InsufficientFlowOutputs`/`UnsupportedFlowInputs` construction-time + // guards (and their tests) no longer apply. Flow validity is enforced at eval + // time via sentinel consumption against `MIN_FLOW_SENTINELS`. - EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](1); - flowConfig[0] = EvaluableConfigV3(DEPLOYER, bytecode, constants); - - address impl = deployFlowImplementation(); - vm.expectRevert(InsufficientFlowOutputs.selector); - I_CLONE_FACTORY.clone(impl, abi.encode(flowConfig)); - } - - /// `flowOutputs == MIN_FLOW_SENTINELS` is the lowest accepted value. - /// Pinning this boundary against regression complements the negative - /// test above. - function testFlowConstructionAcceptsFlowOutputsAtMin( - address expression, - bytes memory bytecode, - uint256[] memory constants - ) external { - bytes memory io = abi.encodePacked(uint8(0), uint8(MIN_FLOW_SENTINELS)); - expressionDeployerDeployExpression2MockCall(expression, io); - - EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](1); - flowConfig[0] = EvaluableConfigV3(DEPLOYER, bytecode, constants); - - I_CLONE_FACTORY.clone(deployFlowImplementation(), abi.encode(flowConfig)); - } - - /// Reverts with `UnsupportedFlowInputs` when the deployer reports any - /// non-zero `flowInputs` byte in the IO string. Pinning this protects - /// against a future deployer behaviour change leaking non-zero inputs - /// through the guard at `Flow.flowInit`. - /// forge-config: default.fuzz.runs = 100 - function testFlowConstructionRevertsOnNonZeroFlowInputs( - address expression, - bytes memory bytecode, - uint256[] memory constants, - uint8 flowInputs - ) external { - vm.assume(flowInputs != 0); - // io: byte0 = flowInputs (non-zero), byte1 = 7 (>= MIN_FLOW_SENTINELS). - bytes memory io = abi.encodePacked(flowInputs, uint8(7)); - expressionDeployerDeployExpression2MockCall(expression, io); - - EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](1); - flowConfig[0] = EvaluableConfigV3(DEPLOYER, bytecode, constants); - - address impl = deployFlowImplementation(); - vm.expectRevert(UnsupportedFlowInputs.selector); - I_CLONE_FACTORY.clone(impl, abi.encode(flowConfig)); - } - - function testFlowConstructionInitialize(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); + function testFlowConstructionInitialize(bytes memory bytecode) external { + EvaluableV4[] memory flowConfig = new EvaluableV4[](1); + flowConfig[0] = EvaluableV4(INTERPRETER, STORE, bytecode); vm.recordLogs(); I_CLONE_FACTORY.clone(deployFlowImplementation(), abi.encode(flowConfig)); Vm.Log[] memory logs = vm.getRecordedLogs(); - bytes32 eventSignature = keccak256("Initialize(address,(address,bytes,uint256[])[])"); + bytes32 eventSignature = keccak256("Initialize(address,(address,address,bytes)[])"); Vm.Log memory concreteEvent = LibLogHelper.findEvent(logs, eventSignature); - (address sender, EvaluableConfigV3[] memory config) = - abi.decode(concreteEvent.data, (address, EvaluableConfigV3[])); + (address sender, EvaluableV4[] memory config) = abi.decode(concreteEvent.data, (address, EvaluableV4[])); assertEq(sender, address(I_CLONE_FACTORY), "wrong sender in Initialize event"); assertEq(keccak256(abi.encode(flowConfig)), keccak256(abi.encode(config)), "wrong compare Structs"); diff --git a/test/src/concrete/Flow.context.t.sol b/test/src/concrete/Flow.context.t.sol index 5f164223..b6ff1473 100644 --- a/test/src/concrete/Flow.context.t.sol +++ b/test/src/concrete/Flow.context.t.sol @@ -3,12 +3,11 @@ pragma solidity =0.8.25; import {FlowTest} from "test/abstract/FlowTest.sol"; -import {IFlowV5, RAIN_FLOW_SENTINEL} from "../../../src/interface/IFlowV5.sol"; +import {IFlowV6, RAIN_FLOW_SENTINEL} from "../../../src/interface/IFlowV6.sol"; import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {EvaluableV4} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; import {FLOW_MAX_OUTPUTS, FLOW_ENTRYPOINT} from "../../../src/concrete/Flow.sol"; -import {LibEncodedDispatch} from "rain.interpreter.interface/lib/caller/LibEncodedDispatch.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {LibContextWrapper} from "test/lib/LibContextWrapper.sol"; import {LibStackGeneration} from "test/lib/LibStackGeneration.sol"; @@ -22,7 +21,7 @@ contract FlowContextTest is FlowTest { SignedContextV1[] memory signedContext = new SignedContextV1[](0); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); uint256[][] memory context = LibContextWrapper.buildAndSetContext(callerContext, signedContext, address(alice), address(flow)); @@ -33,14 +32,10 @@ contract FlowContextTest is FlowTest { interpreterEval2MockCall(stack, new uint256[](0)); - interpreterEval2ExpectCall( - address(flow), - LibEncodedDispatch.encode2(evaluable.expression, FLOW_ENTRYPOINT, FLOW_MAX_OUTPUTS), - context - ); + interpreterEval2ExpectCall(address(flow), context); } vm.startPrank(alice); - flow.flow(evaluable, callerContext, signedContext); + flow.flow(evaluable, asBytes32(callerContext), signedContext); vm.stopPrank(); } } diff --git a/test/src/concrete/Flow.expression.t.sol b/test/src/concrete/Flow.expression.t.sol index 904ab4e5..7c5899de 100644 --- a/test/src/concrete/Flow.expression.t.sol +++ b/test/src/concrete/Flow.expression.t.sol @@ -5,12 +5,12 @@ pragma solidity =0.8.25; import {Vm} from "forge-std/Test.sol"; import {FlowTest} from "test/abstract/FlowTest.sol"; -import {IFlowV5} from "../../../src/interface/IFlowV5.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {IFlowV6} from "../../../src/interface/IFlowV6.sol"; +import {EvaluableV4} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {LibUint256Matrix} from "rain.solmem/lib/LibUint256Matrix.sol"; import {LibContextWrapper} from "test/lib/LibContextWrapper.sol"; -import {IInterpreterCallerV2} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {IInterpreterCallerV2} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {SignContextLib} from "test/lib/SignContextLib.sol"; import {LibLogHelper} from "test/lib/LibLogHelper.sol"; @@ -32,10 +32,10 @@ contract FlowExpressionTest is FlowTest, IInterpreterCallerV2 { uint256[][] memory constants = new uint256[][](expressions.length); - (, EvaluableV2[] memory evaluables) = deployFlow(expressions, constants); + (, EvaluableV4[] memory evaluables) = deployFlow(expressions, constants); for (uint256 i = 0; i < evaluables.length; i++) { - assertEq(evaluables[i].expression, expressions[i]); + assertEq(evaluables[i].bytecode, abi.encodePacked(expressions[i])); } } @@ -52,7 +52,7 @@ contract FlowExpressionTest is FlowTest, IInterpreterCallerV2 { fuzzedcallerContext1, fuzzedcallerContext0 ); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); SignedContextV1[] memory signedContext = new SignedContextV1[](matrixCallerContext.length); { @@ -66,7 +66,7 @@ contract FlowExpressionTest is FlowTest, IInterpreterCallerV2 { interpreterEval2MockCall(stack, new uint256[](0)); vm.recordLogs(); - flow.flow(evaluable, fuzzedcallerContext0, signedContext); + flow.flow(evaluable, asBytes32(fuzzedcallerContext0), signedContext); } { @@ -75,8 +75,8 @@ contract FlowExpressionTest is FlowTest, IInterpreterCallerV2 { ); Vm.Log[] memory logs = vm.getRecordedLogs(); - Vm.Log memory log = LibLogHelper.findEvent(logs, keccak256("Context(address,uint256[][])")); - (address sender, uint256[][] memory buildContextOutput) = abi.decode(log.data, (address, uint256[][])); + Vm.Log memory log = LibLogHelper.findEvent(logs, keccak256("ContextV2(address,bytes32[][])")); + (address sender, bytes32[][] memory buildContextOutput) = abi.decode(log.data, (address, bytes32[][])); assertEq(sender, address(this), "wrong sender"); assertEq( diff --git a/test/src/concrete/Flow.multicall.t.sol b/test/src/concrete/Flow.multicall.t.sol index 18079402..9e8080f5 100644 --- a/test/src/concrete/Flow.multicall.t.sol +++ b/test/src/concrete/Flow.multicall.t.sol @@ -3,21 +3,40 @@ pragma solidity =0.8.25; import {FlowTest} from "test/abstract/FlowTest.sol"; -import {IFlowV5} from "../../../src/interface/IFlowV5.sol"; -import {FLOW_MAX_OUTPUTS, FLOW_ENTRYPOINT} from "../../../src/concrete/Flow.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {LibEncodedDispatch} from "rain.interpreter.interface/lib/caller/LibEncodedDispatch.sol"; +import {IFlowV6} from "../../../src/interface/IFlowV6.sol"; +import {EvaluableV4} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {IInterpreterV4, StackItem} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {LibUint256Matrix} from "rain.solmem/lib/LibUint256Matrix.sol"; import {Multicall} from "openzeppelin-contracts/contracts/utils/Multicall.sol"; contract FlowMulticallTest is FlowTest { using LibUint256Matrix for uint256[]; - /** - * @dev Should call multiple flows from same flow contract at once using multicall - * - */ + /// In V4 there is no encoded dispatch, so a per-flow `eval4` mock keyed on + /// the expression no longer differentiates the two flows. The multicall calls + /// `eval4` once per flow in order, so a sequential mock returns flow A's stack + /// to the first call and flow B's stack to the second. Kept in a helper to + /// avoid "stack too deep" in the test body. + function mockBothFlows(address flow, address bob, uint256 tokenId, uint256 amount) internal { + (uint256[] memory stackA,) = + mintAndBurnFlowStack(bob, 20 ether, 10 ether, 5, transfersERC20toERC20(bob, flow, amount, amount)); + (uint256[] memory stackB,) = mintAndBurnFlowStack( + bob, 20 ether, 10 ether, 5, transferERC721ToERC1155(flow, bob, tokenId, amount, tokenId) + ); + StackItem[] memory sA; + StackItem[] memory sB; + assembly ("memory-safe") { + sA := stackA + sB := stackB + } + bytes[] memory returns_ = new bytes[](2); + returns_[0] = abi.encode(sA, new bytes32[](0)); + returns_[1] = abi.encode(sB, new bytes32[](0)); + vm.mockCalls(address(INTERPRETER), abi.encodeWithSelector(IInterpreterV4.eval4.selector), returns_); + } + + /// @dev Should call multiple flows from same flow contract at once using multicall. function testFlowBasicMulticallFlows( address bob, uint256 tokenId, @@ -27,52 +46,22 @@ contract FlowMulticallTest is FlowTest { ) external { vm.assume(expressionA != expressionB); vm.label(bob, "Bob"); - vm.label(expressionA, "expressionA"); - vm.label(expressionB, "expressionB"); address[] memory expressions = new address[](2); expressions[0] = expressionA; expressions[1] = expressionB; - (IFlowV5 flow, EvaluableV2[] memory evaluables) = + (IFlowV6 flow, EvaluableV4[] memory evaluables) = deployFlow(expressions, new uint256[](0).matrixFrom(new uint256[](0))); assumeEtchable(bob, address(flow)); - executeFlowA(bob, address(flow), evaluables[0], amount); - executeFlowB(bob, address(flow), evaluables[1], tokenId, amount); - - { - bytes[] memory calldatas = new bytes[](2); - calldatas[0] = abi.encodeCall(flow.flow, (evaluables[0], new uint256[](0), new SignedContextV1[](0))); - calldatas[1] = abi.encodeCall(flow.flow, (evaluables[1], new uint256[](0), new SignedContextV1[](0))); - - vm.startPrank(bob); - Multicall(address(flow)).multicall(calldatas); - } - } + mockBothFlows(address(flow), bob, tokenId, amount); - function executeFlowA(address bob, address flow, EvaluableV2 memory evaluable, uint256 amount) internal { - (uint256[] memory stack,) = - mintAndBurnFlowStack(bob, 20 ether, 10 ether, 5, transfersERC20toERC20(bob, flow, amount, amount)); - interpreterEval2MockCall( - address(flow), - LibEncodedDispatch.encode2(evaluable.expression, FLOW_ENTRYPOINT, FLOW_MAX_OUTPUTS), - stack, - new uint256[](0) - ); - } + bytes[] memory calldatas = new bytes[](2); + calldatas[0] = abi.encodeCall(flow.flow, (evaluables[0], new bytes32[](0), new SignedContextV1[](0))); + calldatas[1] = abi.encodeCall(flow.flow, (evaluables[1], new bytes32[](0), new SignedContextV1[](0))); - function executeFlowB(address bob, address flow, EvaluableV2 memory evaluable, uint256 tokenId, uint256 amount) - internal - { - (uint256[] memory stack,) = mintAndBurnFlowStack( - bob, 20 ether, 10 ether, 5, transferERC721ToERC1155(flow, bob, tokenId, amount, tokenId) - ); - interpreterEval2MockCall( - flow, - LibEncodedDispatch.encode2(evaluable.expression, FLOW_ENTRYPOINT, FLOW_MAX_OUTPUTS), - stack, - new uint256[](0) - ); + vm.startPrank(bob); + Multicall(address(flow)).multicall(calldatas); } } diff --git a/test/src/concrete/Flow.preview.t.sol b/test/src/concrete/Flow.preview.t.sol index 856e749b..bf6ba1b4 100644 --- a/test/src/concrete/Flow.preview.t.sol +++ b/test/src/concrete/Flow.preview.t.sol @@ -5,20 +5,20 @@ pragma solidity =0.8.25; import {FlowTest} from "test/abstract/FlowTest.sol"; import {MissingSentinel, Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; import { - IFlowV5, + IFlowV6, FlowTransferV1, ERC20Transfer, ERC721Transfer, ERC1155Transfer, RAIN_FLOW_SENTINEL, Sentinel -} from "../../../src/interface/IFlowV5.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +} from "../../../src/interface/IFlowV6.sol"; +import {EvaluableV4} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; import {LibEvaluable} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; import {LibStackGeneration} from "test/lib/LibStackGeneration.sol"; contract FlowPreviewTest is FlowTest { - using LibEvaluable for EvaluableV2; + using LibEvaluable for EvaluableV4; /** * @dev Tests the preview of defined Flow IO for ERC1155 @@ -32,7 +32,7 @@ contract FlowPreviewTest is FlowTest { ) external { vm.label(alice, "alice"); - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); assumeEtchable(alice, address(flow)); { (uint256[] memory stack, bytes32 transferHash) = mintAndBurnFlowStack( @@ -43,7 +43,9 @@ contract FlowPreviewTest is FlowTest { multiTransferERC1155(alice, address(flow), erc1155TokenId, erc1155Amount, erc1155TokenId, erc1155Amount) ); - assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(stack))), "wrong compare Structs"); + assertEq( + transferHash, keccak256(abi.encode(flow.stackToFlow(asStackItems(stack)))), "wrong compare Structs" + ); } } @@ -59,14 +61,14 @@ contract FlowPreviewTest is FlowTest { ) external { vm.label(alice, "alice"); - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); assumeEtchable(alice, address(flow)); (uint256[] memory stack, bytes32 transferHash) = mintAndBurnFlowStack( alice, 20 ether, 10 ether, 5, multiTransferERC721(alice, address(flow), erc721TokenIdA, erc721TokenIdB) ); - assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(stack))), "wrong compare Structs"); + assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(asStackItems(stack)))), "wrong compare Structs"); } /** @@ -81,14 +83,14 @@ contract FlowPreviewTest is FlowTest { ) external { vm.label(alice, "alice"); - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); assumeEtchable(alice, address(flow)); (uint256[] memory stack, bytes32 transferHash) = mintAndBurnFlowStack( alice, 20 ether, 10 ether, 5, multiTransfersERC20(alice, address(flow), erc20AmountA, erc20AmountB) ); - assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(stack))), "wrong compare Structs"); + assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(asStackItems(stack)))), "wrong compare Structs"); } /** @@ -103,7 +105,7 @@ contract FlowPreviewTest is FlowTest { ) external { vm.label(alice, "alice"); - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); assumeEtchable(alice, address(flow)); (uint256[] memory stack, bytes32 transferHash) = mintAndBurnFlowStack( @@ -116,7 +118,7 @@ contract FlowPreviewTest is FlowTest { ) ); - assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(stack))), "wrong compare Structs"); + assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(asStackItems(stack)))), "wrong compare Structs"); } /** @@ -131,7 +133,7 @@ contract FlowPreviewTest is FlowTest { ) external { vm.label(alice, "alice"); - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); assumeEtchable(alice, address(flow)); (uint256[] memory stack, bytes32 transferHash) = mintAndBurnFlowStack( @@ -142,7 +144,7 @@ contract FlowPreviewTest is FlowTest { createTransferERC721ToERC721(alice, address(flow), erc721TokenInId, erc721TokenOutId) ); - assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(stack))), "wrong compare Structs"); + assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(asStackItems(stack)))), "wrong compare Structs"); } /** @@ -157,7 +159,7 @@ contract FlowPreviewTest is FlowTest { ) external { vm.label(alice, "alice"); - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); assumeEtchable(alice, address(flow)); (uint256[] memory stack, bytes32 transferHash) = mintAndBurnFlowStack( @@ -168,7 +170,7 @@ contract FlowPreviewTest is FlowTest { createTransfersERC20toERC20(alice, address(flow), erc20AmountIn, erc20AmountOut) ); - assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(stack))), "wrong compare Structs"); + assertEq(transferHash, keccak256(abi.encode(flow.stackToFlow(asStackItems(stack)))), "wrong compare Structs"); } /** @@ -176,13 +178,15 @@ contract FlowPreviewTest is FlowTest { */ /// forge-config: default.fuzz.runs = 100 function testFlowBasePreviewEmptyFlowIO() public { - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); FlowTransferV1 memory flowTransfer = FlowTransferV1(new ERC20Transfer[](0), new ERC721Transfer[](0), new ERC1155Transfer[](0)); uint256[] memory stack = LibStackGeneration.generateFlowStack(Sentinel.unwrap(RAIN_FLOW_SENTINEL), flowTransfer); assertEq( - keccak256(abi.encode(flowTransfer)), keccak256(abi.encode(flow.stackToFlow(stack))), "wrong compare Structs" + keccak256(abi.encode(flowTransfer)), + keccak256(abi.encode(flow.stackToFlow(asStackItems(stack)))), + "wrong compare Structs" ); } @@ -192,7 +196,7 @@ contract FlowPreviewTest is FlowTest { /// rainlang author writes — so that any future reorder of the struct /// fields produces field-named assertions that fail. function testFlowStackToFlowFieldOrderPinned() external { - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); // Stack layout (low index = bottom of stack, high index = top; top is // consumed first by stackToFlow): @@ -217,7 +221,7 @@ contract FlowPreviewTest is FlowTest { stack[14] = uint256(uint160(0xA2)); // erc20 to stack[15] = 0xA3A3; // erc20 amount - FlowTransferV1 memory result = flow.stackToFlow(stack); + FlowTransferV1 memory result = flow.stackToFlow(asStackItems(stack)); assertEq(result.erc20.length, 1, "erc20 length"); assertEq(result.erc20[0].token, address(uint160(0xA0)), "erc20 token"); @@ -239,31 +243,31 @@ contract FlowPreviewTest is FlowTest { assertEq(result.erc1155[0].amount, 0xC4C4, "erc1155 amount"); } - /// `IFlowV5.stackToFlow` MAY revert if the stack is malformed. The + /// `IFlowV6.stackToFlow` MAY revert if the stack is malformed. The /// observable revert is `MissingSentinel(RAIN_FLOW_SENTINEL)` from /// `LibStackSentinel.consumeSentinelTuples` when any of the three /// required sentinels is absent. function testStackToFlowRevertsOnEmptyStack() external { - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); uint256[] memory stack = new uint256[](0); vm.expectRevert(abi.encodeWithSelector(MissingSentinel.selector, RAIN_FLOW_SENTINEL)); - flow.stackToFlow(stack); + flow.stackToFlow(asStackItems(stack)); } function testStackToFlowRevertsOnOneSentinelOnly() external { - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); uint256[] memory stack = new uint256[](1); stack[0] = Sentinel.unwrap(RAIN_FLOW_SENTINEL); vm.expectRevert(abi.encodeWithSelector(MissingSentinel.selector, RAIN_FLOW_SENTINEL)); - flow.stackToFlow(stack); + flow.stackToFlow(asStackItems(stack)); } function testStackToFlowRevertsOnTwoSentinelsOnly() external { - (IFlowV5 flow,) = deployFlow(); + (IFlowV6 flow,) = deployFlow(); uint256[] memory stack = new uint256[](2); stack[0] = Sentinel.unwrap(RAIN_FLOW_SENTINEL); stack[1] = Sentinel.unwrap(RAIN_FLOW_SENTINEL); vm.expectRevert(abi.encodeWithSelector(MissingSentinel.selector, RAIN_FLOW_SENTINEL)); - flow.stackToFlow(stack); + flow.stackToFlow(asStackItems(stack)); } } diff --git a/test/src/concrete/Flow.signedContext.t.sol b/test/src/concrete/Flow.signedContext.t.sol index a632c3b1..161e510d 100644 --- a/test/src/concrete/Flow.signedContext.t.sol +++ b/test/src/concrete/Flow.signedContext.t.sol @@ -5,9 +5,9 @@ pragma solidity =0.8.25; import {Vm} from "forge-std/Test.sol"; import {FlowTest} from "test/abstract/FlowTest.sol"; import {SignContextLib} from "test/lib/SignContextLib.sol"; -import {IFlowV5, RAIN_FLOW_SENTINEL} from "../../../src/interface/IFlowV5.sol"; +import {IFlowV6, RAIN_FLOW_SENTINEL} from "../../../src/interface/IFlowV6.sol"; import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -import {EvaluableV2, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {EvaluableV4, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; import {InvalidSignature} from "rain.interpreter.interface/lib/caller/LibContext.sol"; import {LibStackGeneration} from "test/lib/LibStackGeneration.sol"; @@ -23,7 +23,7 @@ contract FlowSignedContextTest is FlowTest { uint256 fuzzedKeyBob ) public { vm.assume(fuzzedKeyBob != fuzzedKeyAlice); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); // Ensure the fuzzed key is within the valid range for secp256k1 uint256 aliceKey = (fuzzedKeyAlice % (SECP256K1_ORDER - 1)) + 1; @@ -38,7 +38,7 @@ contract FlowSignedContextTest is FlowTest { LibStackGeneration.generateFlowStack(Sentinel.unwrap(RAIN_FLOW_SENTINEL), transferEmpty()); interpreterEval2MockCall(stack, new uint256[](0)); - flow.flow(evaluable, new uint256[](0), signedContexts); + flow.flow(evaluable, new bytes32[](0), signedContexts); // With bad signature in second signed context SignedContextV1[] memory signedContexts1 = new SignedContextV1[](2); @@ -46,7 +46,7 @@ contract FlowSignedContextTest is FlowTest { signedContexts1[1] = vm.signContext(aliceKey, bobKey, context1); vm.expectRevert(abi.encodeWithSelector(InvalidSignature.selector, 1)); - flow.flow(evaluable, new uint256[](0), signedContexts1); + flow.flow(evaluable, new bytes32[](0), signedContexts1); } /// Should validate a signed context @@ -57,7 +57,7 @@ contract FlowSignedContextTest is FlowTest { uint256 fuzzedKeyBob ) public { vm.assume(fuzzedKeyBob != fuzzedKeyAlice); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); // Ensure the fuzzed key is within the valid range for secp256k1 uint256 aliceKey = (fuzzedKeyAlice % (SECP256K1_ORDER - 1)) + 1; @@ -69,13 +69,13 @@ contract FlowSignedContextTest is FlowTest { uint256[] memory stack = LibStackGeneration.generateFlowStack(Sentinel.unwrap(RAIN_FLOW_SENTINEL), transferEmpty()); interpreterEval2MockCall(stack, new uint256[](0)); - flow.flow(evaluable, new uint256[](0), signedContext); + flow.flow(evaluable, new bytes32[](0), signedContext); // With bad signature in second signed context SignedContextV1[] memory signedContext1 = new SignedContextV1[](1); signedContext1[0] = vm.signContext(aliceKey, bobKey, context0); vm.expectRevert(abi.encodeWithSelector(InvalidSignature.selector, 0)); - flow.flow(evaluable, new uint256[](0), signedContext1); + flow.flow(evaluable, new bytes32[](0), signedContext1); } } diff --git a/test/src/concrete/Flow.time.t.sol b/test/src/concrete/Flow.time.t.sol index c2cfe097..64bde52a 100644 --- a/test/src/concrete/Flow.time.t.sol +++ b/test/src/concrete/Flow.time.t.sol @@ -3,39 +3,39 @@ pragma solidity =0.8.25; import {FlowTest} from "test/abstract/FlowTest.sol"; -import {IFlowV5, RAIN_FLOW_SENTINEL} from "../../../src/interface/IFlowV5.sol"; +import {IFlowV6, RAIN_FLOW_SENTINEL} from "../../../src/interface/IFlowV6.sol"; import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -import {EvaluableV2, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {DEFAULT_STATE_NAMESPACE} from "rain.interpreter.interface/interface/IInterpreterV2.sol"; -import {IInterpreterStoreV2} from "rain.interpreter.interface/interface/IInterpreterStoreV2.sol"; +import {EvaluableV4, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; +import {DEFAULT_STATE_NAMESPACE} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterV2.sol"; +import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import {LibStackGeneration} from "test/lib/LibStackGeneration.sol"; contract FlowTimeTest is FlowTest { function testFlowBasicFlowTime(uint256[] memory writeToStore) public { vm.assume(writeToStore.length != 0); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); uint256[] memory stack = LibStackGeneration.generateFlowStack(Sentinel.unwrap(RAIN_FLOW_SENTINEL), transferEmpty()); interpreterEval2MockCall(stack, writeToStore); - vm.mockCall(address(STORE), abi.encodeWithSelector(IInterpreterStoreV2.set.selector), abi.encode()); + vm.mockCall(address(STORE), abi.encodeWithSelector(IInterpreterStoreV3.set.selector), abi.encode()); vm.expectCall( address(STORE), - abi.encodeWithSelector(IInterpreterStoreV2.set.selector, DEFAULT_STATE_NAMESPACE, writeToStore) + abi.encodeWithSelector(IInterpreterStoreV3.set.selector, DEFAULT_STATE_NAMESPACE, asBytes32(writeToStore)) ); - flow.flow(evaluable, writeToStore, new SignedContextV1[](0)); + flow.flow(evaluable, asBytes32(writeToStore), new SignedContextV1[](0)); } /// `LibFlow.flow` short-circuits the `interpreterStore.set` call when /// `kvs.length == 0`. Pin this with an explicit count=0 expectCall so /// a future refactor that drops the short-circuit is caught. function testFlowBasicFlowTimeNoStoreSetWhenKvsEmpty() public { - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); uint256[] memory stack = LibStackGeneration.generateFlowStack(Sentinel.unwrap(RAIN_FLOW_SENTINEL), transferEmpty()); @@ -43,10 +43,10 @@ contract FlowTimeTest is FlowTest { // Mock set to a no-op so the existing REVERTING_MOCK_BYTECODE on // STORE doesn't accidentally pass the test for the wrong reason. - vm.mockCall(address(STORE), abi.encodeWithSelector(IInterpreterStoreV2.set.selector), abi.encode()); - vm.expectCall(address(STORE), abi.encodeWithSelector(IInterpreterStoreV2.set.selector), 0); + vm.mockCall(address(STORE), abi.encodeWithSelector(IInterpreterStoreV3.set.selector), abi.encode()); + vm.expectCall(address(STORE), abi.encodeWithSelector(IInterpreterStoreV3.set.selector), 0); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); } /// A revert from `interpreterStore.set` MUST propagate out of `flow` @@ -55,15 +55,15 @@ contract FlowTimeTest is FlowTest { function testFlowBasicFlowTimeStoreSetRevertBubbles(uint256[] memory writeToStore) public { vm.assume(writeToStore.length != 0); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); uint256[] memory stack = LibStackGeneration.generateFlowStack(Sentinel.unwrap(RAIN_FLOW_SENTINEL), transferEmpty()); interpreterEval2MockCall(stack, writeToStore); - vm.mockCallRevert(address(STORE), abi.encodeWithSelector(IInterpreterStoreV2.set.selector), "STORE_SET_FAILED"); + vm.mockCallRevert(address(STORE), abi.encodeWithSelector(IInterpreterStoreV3.set.selector), "STORE_SET_FAILED"); vm.expectRevert("STORE_SET_FAILED"); - flow.flow(evaluable, writeToStore, new SignedContextV1[](0)); + flow.flow(evaluable, asBytes32(writeToStore), new SignedContextV1[](0)); } } diff --git a/test/src/concrete/Flow.transfer.t.sol b/test/src/concrete/Flow.transfer.t.sol index f3686fcc..249503ed 100644 --- a/test/src/concrete/Flow.transfer.t.sol +++ b/test/src/concrete/Flow.transfer.t.sol @@ -4,17 +4,17 @@ pragma solidity =0.8.25; import {FlowTest} from "test/abstract/FlowTest.sol"; import { - IFlowV5, + IFlowV6, FlowTransferV1, ERC20Transfer, ERC721Transfer, ERC1155Transfer, RAIN_FLOW_SENTINEL, Sentinel -} from "../../../src/interface/IFlowV5.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +} from "../../../src/interface/IFlowV6.sol"; +import {EvaluableV4} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {LibEvaluable} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; import { UnsupportedERC20Flow, @@ -24,7 +24,6 @@ import { } from "../../../src/error/ErrFlow.sol"; import {FLOW_ENTRYPOINT, FLOW_MAX_OUTPUTS} from "../../../src/concrete/Flow.sol"; -import {LibEncodedDispatch} from "rain.interpreter.interface/lib/caller/LibEncodedDispatch.sol"; import {LibContextWrapper} from "test/lib/LibContextWrapper.sol"; import {IERC721} from "openzeppelin-contracts/contracts/token/ERC721/IERC721.sol"; import {IERC1155} from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol"; @@ -42,7 +41,7 @@ interface IERC721SafeTransferFromV3 { bytes4 constant ERC721_SAFE_TRANSFER_FROM_3 = IERC721SafeTransferFromV3.safeTransferFrom.selector; contract FlowTransferTest is FlowTest { - using LibEvaluable for EvaluableV2; + using LibEvaluable for EvaluableV4; /// forge-config: default.fuzz.runs = 100 function testFlowERC721ToERC1155( @@ -54,7 +53,7 @@ contract FlowTransferTest is FlowTest { vm.assume(address(0) != alice); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); { @@ -70,7 +69,7 @@ contract FlowTransferTest is FlowTest { { vm.startPrank(alice); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } } @@ -79,7 +78,7 @@ contract FlowTransferTest is FlowTest { function testFlowERC20ToERC721(address alice, uint256 erc20InAmount, uint256 erc721OutTokenId) external { vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); { @@ -94,7 +93,7 @@ contract FlowTransferTest is FlowTest { } vm.startPrank(alice); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -102,7 +101,7 @@ contract FlowTransferTest is FlowTest { function testFlowERC1155ToERC1155(address alice, uint256 erc1155TokenId, uint256 erc1155Amount) external { vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); { @@ -119,7 +118,7 @@ contract FlowTransferTest is FlowTest { } vm.startPrank(alice); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -129,7 +128,7 @@ contract FlowTransferTest is FlowTest { vm.assume(Sentinel.unwrap(RAIN_FLOW_SENTINEL) != erc721InTokenId); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); { @@ -144,7 +143,7 @@ contract FlowTransferTest is FlowTest { } vm.startPrank(alice); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -152,7 +151,7 @@ contract FlowTransferTest is FlowTest { function testFlowERC20ToERC20(address alice, uint256 erc20OutAmount, uint256 erc20InAmount) external { vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); { @@ -163,7 +162,7 @@ contract FlowTransferTest is FlowTest { } vm.startPrank(alice); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -178,7 +177,7 @@ contract FlowTransferTest is FlowTest { vm.label(alice, "Alice"); vm.label(bob, "Bob"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); assumeEtchable(bob, address(flow)); @@ -197,7 +196,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(abi.encodeWithSelector(UnsupportedERC20Flow.selector)); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); { @@ -216,7 +215,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(abi.encodeWithSelector(UnsupportedERC20Flow.selector)); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -232,7 +231,7 @@ contract FlowTransferTest is FlowTest { vm.label(alice, "Alice"); vm.label(bob, "Bob"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); assumeEtchable(bob, address(flow)); @@ -251,7 +250,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(abi.encodeWithSelector(UnsupportedERC721Flow.selector)); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -272,7 +271,7 @@ contract FlowTransferTest is FlowTest { vm.label(alice, "Alice"); vm.label(bob, "Bob"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); assumeEtchable(bob, address(flow)); @@ -297,7 +296,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(abi.encodeWithSelector(UnsupportedERC1155Flow.selector)); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -314,15 +313,15 @@ contract FlowTransferTest is FlowTest { address[] memory expressionsA = new address[](1); expressionsA[0] = expressionA; - (, EvaluableV2[] memory evaluables) = deployFlow(expressionsA, new uint256[][](1)); + (, EvaluableV4[] memory evaluables) = deployFlow(expressionsA, new uint256[][](1)); address[] memory expressionsB = new address[](1); expressionsB[0] = expressionB; - (IFlowV5 flowB,) = deployFlow(expressionsB, new uint256[][](1)); + (IFlowV6 flowB,) = deployFlow(expressionsB, new uint256[][](1)); vm.startPrank(alice); vm.expectRevert(abi.encodeWithSelector(UnregisteredFlow.selector, evaluables[0].hash())); - flowB.flow(evaluables[0], new uint256[](0), new SignedContextV1[](0)); + flowB.flow(evaluables[0], new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -331,7 +330,7 @@ contract FlowTransferTest is FlowTest { */ /// forge-config: default.fuzz.runs = 100 function testFlowHaltIfEnsureRequirementNotMet() external { - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(address(0), address(flow)); (uint256[] memory stack,) = mintAndBurnFlowStack(address(this), 20 ether, 10 ether, 5, transferEmpty()); @@ -341,16 +340,14 @@ contract FlowTransferTest is FlowTest { new uint256[](0), new SignedContextV1[](0), address(this), address(flow) ); - interpreterEval2RevertCall( - address(flow), LibEncodedDispatch.encode2(evaluable.expression, FLOW_ENTRYPOINT, FLOW_MAX_OUTPUTS), context - ); + interpreterEval2RevertCall(address(flow), context); - vm.expectRevert("REVERT_EVAL2_CALL"); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + vm.expectRevert("REVERT_EVAL4_CALL"); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); } /// Pins the execution order ERC20 → ERC721 → ERC1155 against the upstream - /// invariant in `IFlowV5` and `LibFlow.flow`. If ERC20 reverts, neither + /// invariant in `IFlowV6` and `LibFlow.flow`. If ERC20 reverts, neither /// ERC721 nor ERC1155 must be called — this proves ERC20 is processed /// before the other two types. /// forge-config: default.fuzz.runs = 100 @@ -368,7 +365,7 @@ contract FlowTransferTest is FlowTest { vm.assume(Sentinel.unwrap(RAIN_FLOW_SENTINEL) != erc1155Amount); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); ERC20Transfer[] memory erc20Transfers = new ERC20Transfer[](1); @@ -391,7 +388,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -412,7 +409,7 @@ contract FlowTransferTest is FlowTest { vm.assume(Sentinel.unwrap(RAIN_FLOW_SENTINEL) != erc1155Amount); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); ERC20Transfer[] memory erc20Transfers = new ERC20Transfer[](1); @@ -434,7 +431,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -447,7 +444,7 @@ contract FlowTransferTest is FlowTest { vm.assume(Sentinel.unwrap(RAIN_FLOW_SENTINEL) != amount); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); ERC20Transfer[] memory erc20Transfers = new ERC20Transfer[](1); @@ -463,7 +460,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(bytes("TOKEN_REVERT")); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -474,7 +471,7 @@ contract FlowTransferTest is FlowTest { vm.assume(Sentinel.unwrap(RAIN_FLOW_SENTINEL) != tokenId); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); ERC721Transfer[] memory erc721Transfers = new ERC721Transfer[](1); @@ -490,7 +487,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(bytes("ERC721_REVERT")); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -502,7 +499,7 @@ contract FlowTransferTest is FlowTest { vm.assume(Sentinel.unwrap(RAIN_FLOW_SENTINEL) != amount); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); ERC1155Transfer[] memory erc1155Transfers = new ERC1155Transfer[](1); @@ -519,11 +516,11 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(bytes("ERC1155_REVERT")); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } - /// `IFlowV5.flow()` MUST process the flow atomically. When a later + /// `IFlowV6.flow()` MUST process the flow atomically. When a later /// transfer fails, the entire flow MUST revert and earlier transfers /// must NOT have observable side effects. With mocks, we observe this /// by asserting the outer revert (transaction revert rolls back any @@ -545,7 +542,7 @@ contract FlowTransferTest is FlowTest { vm.label(alice, "Alice"); vm.label(bob, "Bob"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); assumeEtchable(bob, address(flow)); @@ -568,11 +565,11 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(UnsupportedERC1155Flow.selector); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } - /// `IFlowV5.flow()` MUST revert if the evaluable returns a malformed + /// `IFlowV6.flow()` MUST revert if the evaluable returns a malformed /// stack. The observable revert is `MissingSentinel(RAIN_FLOW_SENTINEL)` /// from `LibStackSentinel.consumeSentinelTuples`. /// forge-config: default.fuzz.runs = 100 @@ -580,7 +577,7 @@ contract FlowTransferTest is FlowTest { vm.assume(alice != address(0)); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); uint256[] memory stack = new uint256[](0); @@ -588,7 +585,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(abi.encodeWithSelector(MissingSentinel.selector, RAIN_FLOW_SENTINEL)); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } @@ -597,7 +594,7 @@ contract FlowTransferTest is FlowTest { vm.assume(alice != address(0)); vm.label(alice, "Alice"); - (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + (IFlowV6 flow, EvaluableV4 memory evaluable) = deployFlow(); assumeEtchable(alice, address(flow)); uint256[] memory stack = new uint256[](1); @@ -606,7 +603,7 @@ contract FlowTransferTest is FlowTest { vm.startPrank(alice); vm.expectRevert(abi.encodeWithSelector(MissingSentinel.selector, RAIN_FLOW_SENTINEL)); - flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + flow.flow(evaluable, new bytes32[](0), new SignedContextV1[](0)); vm.stopPrank(); } }