diff --git a/src/concrete/erc1155/FlowERC1155.sol b/src/concrete/erc1155/FlowERC1155.sol index 53df6544..4c7e89f1 100644 --- a/src/concrete/erc1155/FlowERC1155.sol +++ b/src/concrete/erc1155/FlowERC1155.sol @@ -33,9 +33,6 @@ import {SourceIndexV2} from "rain.interpreter.interface/interface/unstable/IInte import {FlowCommon, ERC1155Receiver} from "../../abstract/FlowCommon.sol"; import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol"; -/// @dev The hash of the meta data expected by the `FlowCommon` constructor. -bytes32 constant CALLER_META_HASH = bytes32(0x7ea70f837234357ec1bb5b777e04453ebaf3ca778a98805c4bb20a738d559a21); - /// @title FlowERC1155 /// See `IFlowERC1155V4` for documentation. contract FlowERC1155 is ICloneableV2, IFlowERC1155V4, FlowCommon, ERC1155 { @@ -47,10 +44,7 @@ contract FlowERC1155 is ICloneableV2, IFlowERC1155V4, FlowCommon, ERC1155 { bool private sEvalHandleTransfer; /// The `Evaluable` that handles transfers. - Evaluable internal sEvaluable; - - /// Forwards the `FlowCommon` constructor. - constructor(DeployerDiscoverableMetaV2ConstructionConfig memory config) FlowCommon(CALLER_META_HASH, config) {} + EvaluableV2 internal sEvaluable; /// Overloaded typed initialize function MUST revert with this error. /// As per `ICloneableV2` interface. @@ -67,7 +61,7 @@ contract FlowERC1155 is ICloneableV2, IFlowERC1155V4, FlowCommon, ERC1155 { // Set state before external calls here. bool evalHandleTransfer = LibBytecode.sourceCount(flowERC1155Config.evaluableConfig.bytecode) > 0 && LibBytecode.sourceOpsCount( - flowERC1155Config.evaluableConfig.bytecode, SourceIndex.unwrap(FLOW_ERC1155_HANDLE_TRANSFER_ENTRYPOINT) + flowERC1155Config.evaluableConfig.bytecode, SourceIndexV2.unwrap(FLOW_ERC1155_HANDLE_TRANSFER_ENTRYPOINT) ) > 0; sEvalHandleTransfer = evalHandleTransfer; @@ -167,7 +161,7 @@ contract FlowERC1155 is ICloneableV2, IFlowERC1155V4, FlowCommon, ERC1155 { } /// @inheritdoc IFlowERC1155V4 - function flow(Evaluable memory evaluable, uint256[] memory callerContext, SignedContextV1[] memory signedContexts) + function flow(EvaluableV2 memory evaluable, uint256[] memory callerContext, SignedContextV1[] memory signedContexts) external virtual returns (FlowERC1155IOV1 memory) @@ -207,7 +201,7 @@ contract FlowERC1155 is ICloneableV2, IFlowERC1155V4, FlowCommon, ERC1155 { /// of the flow contract itself. This involves consuming the mint/burn /// sentinels from the stack and minting/burning the tokens accordingly, then /// calling `LibFlow.flow` to handle the rest of the flow. - function _flow(Evaluable memory evaluable, uint256[] memory callerContext, SignedContextV1[] memory signedContexts) + function _flow(EvaluableV2 memory evaluable, uint256[] memory callerContext, SignedContextV1[] memory signedContexts) internal virtual nonReentrant diff --git a/src/interface/IFlowERC1155V3.sol b/src/interface/IFlowERC1155V3.sol deleted file mode 100644 index 1ec09470..00000000 --- a/src/interface/IFlowERC1155V3.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity ^0.8.18; - -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; - -import "./IFlowV3.sol"; - -/// @dev Entrypont of the `handleTransfer` evaluation. -SourceIndex constant FLOW_ERC1155_HANDLE_TRANSFER_ENTRYPOINT = SourceIndex.wrap(0); - -/// @dev Minimum number of outputs of the `handleTransfer` evaluation. -/// This is 0 because the return stack is ignored. -uint256 constant FLOW_ERC1155_HANDLE_TRANSFER_MIN_OUTPUTS = 0; - -/// @dev Maximum number of outputs of the `handleTransfer` evaluation. -/// This is 0 because the return stack is ignored. -uint16 constant FLOW_ERC1155_HANDLE_TRANSFER_MAX_OUTPUTS = 0; - -/// @dev Minimum number of sentinels required by `FlowERC1155`. -/// This is 2 more than the minimum required by `FlowCommon` because the -/// mints and burns are included in the stack. -uint256 constant FLOW_ERC1155_MIN_FLOW_SENTINELS = MIN_FLOW_SENTINELS + 2; - -/// @dev v3 of `FlowERC1155` expected a sentinel different to -/// `RAIN_FLOW_SENTINEL`, but this was generally more confusing than helpful. -Sentinel constant RAIN_FLOW_ERC1155_SENTINEL = - Sentinel.wrap(uint256(keccak256(bytes("RAIN_FLOW_ERC1155_SENTINEL")) | SENTINEL_HIGH_BITS)); - -/// Initializer config. -/// @param uri As per Open Zeppelin `ERC1155Upgradeable`. -/// @param evaluableConfig The `EvaluableConfigV2` to use to build the -/// `evaluable` that can be used to handle transfers. -/// @param flowConfig Constructor config for the `Evaluable`s that define the -/// flow behaviours including self mints/burns. -struct FlowERC1155Config { - string uri; - EvaluableConfig evaluableConfig; - EvaluableConfig[] flowConfig; -} - -/// Represents a single mint or burn of a single ERC1155 token. Whether this is -/// a mint or burn must be implied by the context. -/// @param account The address the token is being minted/burned to/from. -/// @param id The id of the token being minted/burned. -/// @param amount The amount of the token being minted/burned. -struct ERC1155SupplyChange { - address account; - uint256 id; - uint256 amount; -} - -/// Represents a set of ERC1155 transfers, including self mints/burns. -/// @param mints The mints that occurred. -/// @param burns The burns that occurred. -/// @param flow The transfers that occured. -struct FlowERC1155IOV1 { - ERC1155SupplyChange[] mints; - ERC1155SupplyChange[] burns; - FlowTransferV1 flow; -} - -/// @title IFlowERC1155V3 -/// Conceptually identical to `IFlowV3`, but the flow contract itself is an -/// ERC1155 token. This means that ERC1155 self mints and burns are included in -/// the stack that the flows must evaluate to. As stacks are processed by flow -/// from bottom to top, this means that the self mint/burn will be the last thing -/// evaluated, with mints at the bottom and burns next, followed by the flows. -/// -/// As the flow is an ERC1155 token it also includes an evaluation to be run on -/// every token transfer. This is the `handleTransfer` entrypoint. The return -/// stack of this evaluation is ignored, but reverts MUST be respected. This -/// allows expression authors to prevent transfers from occurring if they don't -/// want them to, by reverting within the expression. -/// -/// Otherwise the flow contract is identical to `IFlowV3`. -interface IFlowERC1155V3 { - /// Contract has initialized. - event Initialize(address sender, FlowERC1155Config config); - - /// As per `IFlowV3` but returns a `FlowERC1155IOV1` instead of a - /// `FlowTransferV1`. - /// @param evaluable The `Evaluable` that is flowing. - /// @param callerContext The context of the caller. - /// @param signedContexts The signed contexts of the caller. - /// @return flowERC1155IO The `FlowERC1155IOV1` that occurred. - function previewFlow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external view returns (FlowERC1155IOV1 calldata flowERC1155IO); - - /// As per `IFlowV3` but returns a `FlowERC1155IOV1` instead of a - /// `FlowTransferV1` and mints/burns itself as an ERC1155 accordingly. - /// @param evaluable The `Evaluable` that is flowing. - /// @param callerContext The context of the caller. - /// @param signedContexts The signed contexts of the caller. - /// @return flowERC1155IO The `FlowERC1155IOV1` that occurred. - function flow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external returns (FlowERC1155IOV1 calldata flowERC1155IO); -} diff --git a/src/interface/IFlowERC20V3.sol b/src/interface/IFlowERC20V3.sol deleted file mode 100644 index bb4d93ef..00000000 --- a/src/interface/IFlowERC20V3.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity ^0.8.18; - -import "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; -import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -import {MIN_FLOW_SENTINELS, SENTINEL_HIGH_BITS, FlowTransferV1} from "./IFlowV3.sol"; - -/// @dev v3 of `FlowERC20` expected a sentinel different to -/// `RAIN_FLOW_SENTINEL`, but this was generally more confusing than helpful. -Sentinel constant RAIN_FLOW_ERC20_SENTINEL = - Sentinel.wrap(uint256(keccak256(bytes("RAIN_FLOW_ERC20_SENTINEL")) | SENTINEL_HIGH_BITS)); - -/// @dev Entrypont of the `handleTransfer` evaluation. -SourceIndex constant FLOW_ERC20_HANDLE_TRANSFER_ENTRYPOINT = SourceIndex.wrap(0); - -/// @dev Minimum number of outputs of the `handleTransfer` evaluation. -/// This is 0 because the return stack is ignored. -uint256 constant FLOW_ERC20_HANDLE_TRANSFER_MIN_OUTPUTS = 0; - -/// @dev Maximum number of outputs of the `handleTransfer` evaluation. -/// This is 0 because the return stack is ignored. -uint16 constant FLOW_ERC20_HANDLE_TRANSFER_MAX_OUTPUTS = 0; - -/// @dev Minimum number of sentinels required by `FlowERC20`. -/// This is 2 more than the minimum required by `FlowCommon` because the -/// mints and burns are included in the stack. -uint256 constant FLOW_ERC20_MIN_FLOW_SENTINELS = MIN_FLOW_SENTINELS + 2; - -/// Represents a single mint or burn of a single ERC20 token. Whether this is -/// a mint or burn must be implied by the context. -/// @param account The address the token is being minted/burned to/from. -/// @param amount The amount of the token being minted/burned. -struct ERC20SupplyChange { - address account; - uint256 amount; -} - -/// Represents a set of ERC20 transfers, including self mints/burns. -/// @param mints The mints that occurred. -/// @param burns The burns that occurred. -/// @param flow The transfers that occured. -struct FlowERC20IOV1 { - ERC20SupplyChange[] mints; - ERC20SupplyChange[] burns; - FlowTransferV1 flow; -} - -/// Initializer config. -/// @param name As per Open Zeppelin `ERC20Upgradeable`. -/// @param symbol As per Open Zeppelin `ERC20Upgradeable`. -/// @param evaluableConfig The `EvaluableConfigV2` to use to build the -/// `evaluable` that can be used to handle transfers. -/// @param flowConfig Initializer config for the `Evaluable`s that define the -/// flow behaviours including self mints/burns. -struct FlowERC20Config { - string name; - string symbol; - EvaluableConfig evaluableConfig; - EvaluableConfig[] flowConfig; -} - -/// @title IFlowERC20V3 -/// @notice Mints itself according to some predefined schedule. The schedule is -/// expressed as an expression and the `claim` function is world-callable. -/// Intended behaviour is to avoid sybils infinitely minting by putting the -/// claim functionality behind a `TierV2` contract. The flow contract -/// itself implements `ReadOnlyTier` and every time a claim is processed it -/// logs the block number of the claim against every tier claimed. So the block -/// numbers in the tier report for `FlowERC20` are the last time that tier -/// was claimed against this contract. The simplest way to make use of this -/// information is to take the max block for the underlying tier and the last -/// claim and then diff it against the current block number. -/// See `test/Claim/FlowERC20.sol.ts` for examples, including providing -/// staggered rewards where more tokens are minted for higher tier accounts. -interface IFlowERC20V3 { - /// Contract has initialized. - /// @param sender `msg.sender` initializing the contract (factory). - /// @param config All initialized config. - event Initialize(address sender, FlowERC20Config config); - - /// As per `IFlowV3` but returns a `FlowERC20IOV1` instead of a - /// `FlowTransferV1`. - /// @param evaluable The `Evaluable` to use to evaluate the flow. - /// @param callerContext The caller context to use to evaluate the flow. - /// @param signedContexts The signed contexts to use to evaluate the flow. - /// @return flowERC20IO The `FlowERC20IOV1` that occurred. - function previewFlow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external view returns (FlowERC20IOV1 calldata flowERC20IO); - - /// As per `IFlowV3` but returns a `FlowERC20IOV1` instead of a - /// `FlowTransferV1` and mints/burns itself as an ERC20 accordingly. - /// @param evaluable The `Evaluable` to use to evaluate the flow. - /// @param callerContext The caller context to use to evaluate the flow. - /// @param signedContexts The signed contexts to use to evaluate the flow. - /// @return flowERC20IO The `FlowERC20IOV1` that occurred. - function flow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external returns (FlowERC20IOV1 calldata flowERC20IO); -} diff --git a/src/interface/IFlowERC721V3.sol b/src/interface/IFlowERC721V3.sol deleted file mode 100644 index 0af859da..00000000 --- a/src/interface/IFlowERC721V3.sol +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity ^0.8.18; - -import "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; - -import "./IFlowV3.sol"; - -/// @dev Entrypont of the `handleTransfer` evaluation. -SourceIndex constant FLOW_ERC721_HANDLE_TRANSFER_ENTRYPOINT = SourceIndex.wrap(0); -/// @dev Entrypont of the `tokenURI` evaluation. -SourceIndex constant FLOW_ERC721_TOKEN_URI_ENTRYPOINT = SourceIndex.wrap(1); - -/// @dev Minimum number of outputs of the `handleTransfer` evaluation. -/// This is 0 because the return stack is ignored. -uint256 constant FLOW_ERC721_HANDLE_TRANSFER_MIN_OUTPUTS = 0; -/// @dev Minimum number of outputs of the `tokenURI` evaluation. -/// This is 1 because we can only handle a single token ID value. -uint256 constant FLOW_ERC721_TOKEN_URI_MIN_OUTPUTS = 1; - -/// @dev Maximum number of outputs of the `handleTransfer` evaluation. -/// This is 0 because the return stack is ignored. -uint16 constant FLOW_ERC721_HANDLE_TRANSFER_MAX_OUTPUTS = 0; -/// @dev Maximum number of outputs of the `tokenURI` evaluation. -/// This is 1 because we can only handle a single token ID value. -uint16 constant FLOW_ERC721_TOKEN_URI_MAX_OUTPUTS = 1; - -/// @dev v3 of `FlowERC721` expected a sentinel different to -/// `RAIN_FLOW_SENTINEL`, but this was generally more confusing than helpful. -Sentinel constant RAIN_FLOW_ERC721_SENTINEL = - Sentinel.wrap(uint256(keccak256(bytes("RAIN_FLOW_ERC721_SENTINEL")) | SENTINEL_HIGH_BITS)); - -/// @dev Minimum number of sentinels required by `FlowERC721`. -/// This is 2 more than the minimum required by `FlowCommon` because the -/// mints and burns are included in the stack. -uint256 constant FLOW_ERC721_MIN_FLOW_SENTINELS = MIN_FLOW_SENTINELS + 2; - -/// Initializer config. -/// @param name As per Open Zeppelin `ERC721Upgradeable`. -/// @param symbol As per Open Zeppelin `ERC721Upgradeable`. -/// @param baseURI As per Open Zeppelin `ERC721Upgradeable`. -/// @param evaluableConfig The `EvaluableConfigV2` to use to build the -/// `evaluable` that can be used to handle transfers and token URIs. The token -/// URI entrypoint is optional. -/// @param flowConfig Constructor config for the `Evaluable`s that define the -/// flow behaviours including self mints/burns. -struct FlowERC721Config { - string name; - string symbol; - string baseURI; - EvaluableConfig evaluableConfig; - EvaluableConfig[] flowConfig; -} - -/// Represents a single mint or burn of a single ERC721 token. Whether this is -/// a mint or burn must be implied by the context. -/// @param account The address the token is being minted/burned to/from. -/// @param id The id of the token being minted/burned. -struct ERC721SupplyChange { - address account; - uint256 id; -} - -/// Represents a set of ERC721 transfers, including self mints/burns. -/// @param mints The mints that occurred. -/// @param burns The burns that occurred. -/// @param flow The transfers that occured. -struct FlowERC721IOV1 { - ERC721SupplyChange[] mints; - ERC721SupplyChange[] burns; - FlowTransferV1 flow; -} - -/// @title IFlowERC721V3 -/// Conceptually identical to `IFlowV3`, but the flow contract itself is an -/// ERC721 token. This means that ERC721 self mints and burns are included in -/// the stack. -/// -/// As the flow is an ERC721 token, there are two entrypoints in addition to -/// the flows: -/// - `handleTransfer` is called when the flow is transferred. -/// - `tokenURI` is called when the token URI is requested. -/// -/// The `handleTransfer` entrypoint is mandatory, but the `tokenURI` entrypoint -/// is optional. If the `tokenURI` entrypoint is not provided, the default -/// Open Zeppelin implementation will be used. -/// -/// The `handleTransfer` entrypoint may be used to restrict transfers of the -/// flow token. For example, it may be used to restrict transfers to only -/// occur when the flow is in a certain state. -/// -/// The `tokenURI` entrypoint may be used to provide a custom token ID to build -/// a token URI for the flow token. -/// -/// Otherwise the flow contract behaves identically to `IFlowV3`. -interface IFlowERC721V3 { - /// Contract has initialized. - /// @param sender `msg.sender` initializing the contract (factory). - /// @param config All initialized config. - event Initialize(address sender, FlowERC721Config config); - - /// As per `IFlowV3` but returns a `FlowERC721IOV1` instead of a - /// `FlowTransferV1`. - /// @param evaluable The `Evaluable` that is flowing. - /// @param callerContext The context of the caller. - /// @param signedContexts The signed contexts of the caller. - /// @return flowERC721IO The `FlowERC721IOV1` that would occur if the flow - /// was executed. - function previewFlow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external view returns (FlowERC721IOV1 calldata flowERC721IO); - - /// As per `IFlowV3` but returns a `FlowERC721IOV1` instead of a - /// `FlowTransferV1` and mints/burns itself as an ERC721 accordingly. - /// @param evaluable The `Evaluable` that is flowing. - /// @param callerContext The context of the caller. - /// @param signedContexts The signed contexts of the caller. - /// @return flowERC721IO The `FlowERC721IOV1` that occurred. - function flow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external returns (FlowERC721IOV1 calldata flowERC721IO); -} diff --git a/src/interface/IFlowV3.sol b/src/interface/IFlowV3.sol deleted file mode 100644 index c6a24565..00000000 --- a/src/interface/IFlowV3.sol +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity ^0.8.18; - -import {Evaluable, EvaluableConfig} from "rain.interpreter.interface/interface/deprecated/IInterpreterCallerV1.sol"; -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; -import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; - -/// Thrown when the flow being evaluated is unregistered. -/// @param unregisteredHash Hash of the unregistered flow. -error UnregisteredFlow(bytes32 unregisteredHash); - -/// Thrown for unsupported native transfers. -error UnsupportedNativeFlow(); - -/// Thrown for unsupported erc20 transfers. -error UnsupportedERC20Flow(); - -/// Thrown for unsupported erc721 transfers. -error UnsupportedERC721Flow(); - -/// Thrown for unsupported erc1155 transfers. -error UnsupportedERC1155Flow(); - -/// @dev The number of sentinels required by `FlowCommon`. An evaluable can never -/// have fewer minimum outputs than required sentinels. -uint256 constant MIN_FLOW_SENTINELS = 3; - -/// @dev Sets the high bits of all flow sentinels to guarantee that the numeric -/// value of the sentinel will never collide with a token amount or address. This -/// guarantee holds as long as the token supply is less than 2^252, and the -/// that token IDs have no specific reason to collide with the sentinel. -/// i.e. There won't be random collisions because the space of token IDs is -/// too large. -bytes32 constant SENTINEL_HIGH_BITS = bytes32(0xF000000000000000000000000000000000000000000000000000000000000000); - -/// @dev We want a sentinel with the following properties: -/// - Won't collide with token amounts (| with very large number) -/// - Won't collide with token addresses -/// - Won't collide with common values like `type(uint256).max` and -/// `type(uint256).min` -/// - Won't collide with other sentinels from unrelated contexts -Sentinel constant RAIN_FLOW_SENTINEL = - Sentinel.wrap(uint256(keccak256(bytes("RAIN_FLOW_SENTINEL")) | SENTINEL_HIGH_BITS)); - -/// Wraps `EvaluableConfig[]` to workaround a Solidity bug. -/// https://github.com/ethereum/solidity/issues/13597 -/// @param dummyConfig A dummy config to workaround a Solidity bug. -/// @param config The list of evaluable configs that define the flows. -struct FlowConfig { - EvaluableConfig dummyConfig; - EvaluableConfig[] config; -} - -/// Represents a single transfer of a single ERC20 token. -/// @param token The address of the ERC20 token being transferred. -/// @param from The address the token is being transferred from. -/// @param to The address the token is being transferred to. -/// @param amount The amount of the token being transferred. -struct ERC20Transfer { - address token; - address from; - address to; - uint256 amount; -} - -/// Represents a single transfer of a single ERC721 token. -/// @param token The address of the ERC721 token being transferred. -/// @param from The address the token is being transferred from. -/// @param to The address the token is being transferred to. -/// @param id The id of the token being transferred. -struct ERC721Transfer { - address token; - address from; - address to; - uint256 id; -} - -/// Represents a single transfer of a single ERC1155 token. -/// @param token The address of the ERC1155 token being transferred. -/// @param from The address the token is being transferred from. -/// @param to The address the token is being transferred to. -/// @param id The id of the token being transferred. -/// @param amount The amount of the token being transferred. -struct ERC1155Transfer { - address token; - address from; - address to; - uint256 id; - uint256 amount; -} - -/// Represents an ordered set of transfers that will be or have been executed. -/// Supports ERC20, ERC721, and ERC1155 transfers. -/// @param erc20 An array of ERC20 transfers. -/// @param erc721 An array of ERC721 transfers. -/// @param erc1155 An array of ERC1155 transfers. -struct FlowTransferV1 { - ERC20Transfer[] erc20; - ERC721Transfer[] erc721; - ERC1155Transfer[] erc1155; -} - -/// @title IFlowV3 -/// At a high level, identical to `IFlowV4` but with an older, less flexible -/// previewing system, and the older `FlowConfig` struct that was used with -/// older versions of the interpreter. -interface IFlowV3 { - /// MUST be emitted when the flow contract is initialized. - /// @param sender The EOA that deployed the flow contract. - /// @param config The list of evaluable configs that define the flows. - event Initialize(address sender, FlowConfig config); - - /// "Dry run" of a flow, returning the resulting token transfers without - /// actually executing them. - /// @param evaluable The evaluable to evaluate. - /// @param callerContext The caller context to use when evaluating the - /// flow. - /// @param signedContexts The signed contexts to use when evaluating the - /// flow. - function previewFlow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external view returns (FlowTransferV1 calldata flowTransfer); - - /// Given an evaluable, caller context, and signed contexts, evaluate the - /// evaluable and return the resulting flow transfer. MUST process the - /// flow transfer atomically, either all of it succeeds or none of it - /// succeeds. MUST revert if the evaluable is not registered with the flow - /// contract. MUST revert if the evaluable reverts. MUST revert if the - /// evaluable returns a stack that is malformed. MUST revert if the evaluable - /// returns a stack that contains a token transfer that is not allowed by - /// the flow contract (e.g. if a token is being moved from an address that - /// is not the caller or the flow contract). - /// @param evaluable The evaluable to evaluate. - /// @param callerContext The caller context to pass to the evaluable. - /// @param signedContexts The signed contexts to pass to the evaluable. - /// @return flowTransfer The resulting flow transfer. - function flow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external returns (FlowTransferV1 calldata flowTransfer); -} diff --git a/src/interface/unstable/IFlowERC1155V4.sol b/src/interface/unstable/IFlowERC1155V4.sol deleted file mode 100644 index 96f45f78..00000000 --- a/src/interface/unstable/IFlowERC1155V4.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity ^0.8.18; - -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; -import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -import {RAIN_FLOW_SENTINEL} from "./IFlowV4.sol"; - -import { - FlowERC1155IOV1, - ERC1155SupplyChange, - FLOW_ERC1155_HANDLE_TRANSFER_MAX_OUTPUTS, - FLOW_ERC1155_HANDLE_TRANSFER_ENTRYPOINT, - FLOW_ERC1155_HANDLE_TRANSFER_MIN_OUTPUTS, - FLOW_ERC1155_MIN_FLOW_SENTINELS -} from "../IFlowERC1155V3.sol"; - -/// Initialization config. -/// @param uri As per Open Zeppelin `ERC1155Upgradeable`. -/// @param evaluableConfig The `EvaluableConfigV2` to use to build the -/// `evaluable` that can be used to handle transfers. -/// @param flowConfig Initialization config for the `Evaluable`s that define the -/// flow behaviours outside self mints/burns. -struct FlowERC1155ConfigV2 { - string uri; - EvaluableConfigV2 evaluableConfig; - EvaluableConfigV2[] flowConfig; -} - -/// @title IFlowERC1155V4 -/// Conceptually identical to `IFlowV4`, but the flow contract itself is an -/// ERC1155 token. This means that ERC1155 self mints and burns are included in -/// the stack that the flows must evaluate to. As stacks are processed by flow -/// from bottom to top, this means that the self mint/burn will be the last thing -/// evaluated, with mints at the bottom and burns next, followed by the flows. -/// -/// As the flow is an ERC1155 token it also includes an evaluation to be run on -/// every token transfer. This is the `handleTransfer` entrypoint. The return -/// stack of this evaluation is ignored, but reverts MUST be respected. This -/// allows expression authors to prevent transfers from occurring if they don't -/// want them to, by reverting within the expression. -/// -/// Otherwise the flow contract is identical to `IFlowV4`. -interface IFlowERC1155V4 { - /// Contract has initialized. - /// @param sender `msg.sender` initializing the contract (factory). - /// @param config All initialized config. - event Initialize(address sender, FlowERC1155ConfigV2 config); - - /// As per `IFlowV4` but returns a `FlowERC1155IOV1` instead of a - /// `FlowTransferV1`. - /// @param stack The stack to convert to a `FlowERC1155IOV1`. - /// @return flowERC1155IO The `FlowERC1155IOV1` representation of the stack. - function stackToFlow(uint256[] memory stack) external pure returns (FlowERC1155IOV1 memory flowERC1155IO); - - /// As per `IFlowV4` but returns a `FlowERC1155IOV1` instead of a - /// `FlowTransferV1` and mints/burns itself as an ERC1155 accordingly. - /// @param evaluable The `Evaluable` to use to evaluate the flow. - /// @param callerContext The caller context to use to evaluate the flow. - /// @param signedContexts The signed contexts to use to evaluate the flow. - /// @return flowERC1155IO The `FlowERC1155IOV1` representing all token - /// mint/burns and transfers that occurred during the flow. - function flow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external returns (FlowERC1155IOV1 calldata); -} diff --git a/src/interface/unstable/IFlowERC20V4.sol b/src/interface/unstable/IFlowERC20V4.sol deleted file mode 100644 index 728e093a..00000000 --- a/src/interface/unstable/IFlowERC20V4.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity ^0.8.18; - -import {SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; -import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -import { - FlowERC20IOV1, - ERC20SupplyChange, - FLOW_ERC20_HANDLE_TRANSFER_ENTRYPOINT, - FLOW_ERC20_HANDLE_TRANSFER_MIN_OUTPUTS, - FLOW_ERC20_HANDLE_TRANSFER_MAX_OUTPUTS, - FLOW_ERC20_MIN_FLOW_SENTINELS -} from "../IFlowERC20V3.sol"; -import {RAIN_FLOW_SENTINEL} from "./IFlowV4.sol"; - -/// Initialization config. -/// @param name As per Open Zeppelin `ERC20Upgradeable`. -/// @param symbol As per Open Zeppelin `ERC20Upgradeable`. -/// @param evaluableConfig The `EvaluableConfigV2` to use to build the -/// `evaluable` that can be used to evaluate `handleTransfer`. -/// @param flowConfig The `EvaluableConfigV2[]` to use to build the -/// `evaluable`s for all the flows, including self minting and burning. -struct FlowERC20ConfigV2 { - string name; - string symbol; - EvaluableConfigV2 evaluableConfig; - EvaluableConfigV2[] flowConfig; -} - -/// @title IFlowERC20V4 -/// Conceptually identical to `IFlowV4`, but the flow contract itself is an -/// ERC20 token. This means that ERC20 self mints and burns are included in the -/// stack that the flows must evaluate to. As stacks are processed by flow from -/// bottom to top, this means that the self mint/burn will be the last thing -/// evaluated, with mints at the bottom and burns next, followed by the flows. -/// -/// As the flow is an ERC20 token it also includes an evaluation to be run on -/// every token transfer. This is the `handleTransfer` entrypoint. The return -/// stack of this evaluation is ignored, but reverts MUST be respected. This -/// allows expression authors to prevent transfers from occurring if they don't -/// want them to, by reverting within the expression. -/// -/// Otherwise the flow contract is identical to `IFlowV4`. -interface IFlowERC20V4 { - /// Contract has initialized. - /// @param sender `msg.sender` initializing the contract (factory). - /// @param config All initialized config. - event Initialize(address sender, FlowERC20ConfigV2 config); - - /// As per `IFlowV4` but returns a `FlowERC20IOV1` instead of a - /// `FlowTransferV1`. - /// @param stack The stack to convert to a `FlowERC20IOV1`. - /// @return flowERC20IO The `FlowERC20IOV1` representation of the stack. - function stackToFlow(uint256[] memory stack) external pure returns (FlowERC20IOV1 memory flowERC20IO); - - /// As per `IFlowV4` but returns a `FlowERC20IOV1` instead of a - /// `FlowTransferV1` and mints/burns itself as an ERC20 accordingly. - /// @param evaluable The `Evaluable` to use to evaluate the flow. - /// @param callerContext The caller context to use to evaluate the flow. - /// @param signedContexts The signed contexts to use to evaluate the flow. - /// @return flowERC20IO The `FlowERC20IOV1` representing all token mint/burns - /// and transfers that occurred during the flow. - function flow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external returns (FlowERC20IOV1 calldata flowERC20IO); -} diff --git a/src/interface/unstable/IFlowERC721V4.sol b/src/interface/unstable/IFlowERC721V4.sol deleted file mode 100644 index d76a94a2..00000000 --- a/src/interface/unstable/IFlowERC721V4.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity ^0.8.18; - -import "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; - -import { - FlowERC721IOV1, - ERC721SupplyChange, - FLOW_ERC721_TOKEN_URI_MIN_OUTPUTS, - FLOW_ERC721_TOKEN_URI_MAX_OUTPUTS, - FLOW_ERC721_HANDLE_TRANSFER_MIN_OUTPUTS, - FLOW_ERC721_HANDLE_TRANSFER_MAX_OUTPUTS, - FLOW_ERC721_TOKEN_URI_ENTRYPOINT, - FLOW_ERC721_HANDLE_TRANSFER_ENTRYPOINT, - FLOW_ERC721_MIN_FLOW_SENTINELS -} from "../IFlowERC721V3.sol"; - -import {RAIN_FLOW_SENTINEL} from "./IFlowV4.sol"; - -/// Thrown when burner of tokens is not the owner of tokens. -error BurnerNotOwner(); - -/// Initialization config. -/// @param name As per Open Zeppelin `ERC721Upgradeable`. -/// @param symbol As per Open Zeppelin `ERC721Upgradeable`. -/// @param baseURI As per Open Zeppelin `ERC721Upgradeable`. -/// @param evaluableConfig The `EvaluableConfigV2` to use to build the -/// `evaluable` that can be used to handle transfers and build token IDs for the -/// token URI. -/// @param flowConfig Initialization config for the `Evaluable`s that define the -/// flow behaviours outside self mints/burns. -struct FlowERC721ConfigV2 { - string name; - string symbol; - string baseURI; - EvaluableConfigV2 evaluableConfig; - EvaluableConfigV2[] flowConfig; -} - -/// @title IFlowERC721V4 -/// Conceptually identical to `IFlowV4`, but the flow contract itself is an -/// ERC721 token. This means that ERC721 self mints and burns are included in the -/// stack that the flows must evaluate to. As stacks are processed by flow from -/// bottom to top, this means that the self mint/burn will be the last thing -/// evaluated, with mints at the bottom and burns next, followed by the flows. -/// -/// As the flow is an ERC721 token it also includes an evaluation to be run on -/// every token transfer. This is the `handleTransfer` entrypoint. The return -/// stack of this evaluation is ignored, but reverts MUST be respected. This -/// allows expression authors to prevent transfers from occurring if they don't -/// want them to, by reverting within the expression. -/// -/// The flow contract also includes an evaluation to be run on every token URI -/// request. This is the `tokenURI` entrypoint. The return value of this -/// evaluation is the token ID to use for the token URI. This entryoint is -/// optional, and if not provided the token URI will be the default Open Zeppelin -/// token URI logic. -/// -/// Otherwise the flow contract is identical to `IFlowV4`. -interface IFlowERC721V4 { - /// Contract has initialized. - /// @param sender `msg.sender` initializing the contract (factory). - /// @param config All initialized config. - event Initialize(address sender, FlowERC721ConfigV2 config); - - /// As per `IFlowV4` but returns a `FlowERC721IOV1` instead of a - /// `FlowTransferV1`. - function stackToFlow(uint256[] memory stack) external pure returns (FlowERC721IOV1 memory flowERC721IO); - - /// As per `IFlowV4` but returns a `FlowERC721IOV1` instead of a - /// `FlowTransferV1` and mints/burns itself as an ERC721 accordingly. - /// @param evaluable The `Evaluable` to use to evaluate the flow. - /// @param callerContext The caller context to use to evaluate the flow. - /// @param signedContexts The signed contexts to use to evaluate the flow. - /// @return flowERC721IO The `FlowERC721IOV1` representing all token - /// mint/burns and transfers that occurred during the flow. - function flow( - Evaluable calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external returns (FlowERC721IOV1 calldata flowERC721IO); -} diff --git a/src/interface/unstable/IFlowV4.sol b/src/interface/unstable/IFlowV4.sol deleted file mode 100644 index 27998b5e..00000000 --- a/src/interface/unstable/IFlowV4.sol +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity ^0.8.18; - -import {SignedContextV1, EvaluableConfigV3} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; -import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; -import {Sentinel} from "rain.solmem/lib/LibStackSentinel.sol"; -import {Pointer} from "rain.solmem/lib/LibPointer.sol"; - -import { - FlowTransferV1, - ERC20Transfer, - ERC721Transfer, - ERC1155Transfer, - RAIN_FLOW_SENTINEL, - UnregisteredFlow, - UnsupportedERC20Flow, - UnsupportedERC721Flow, - UnsupportedERC1155Flow, - MIN_FLOW_SENTINELS -} from "../IFlowV3.sol"; - -/// @title IFlowV4 -/// @notice Interface for a flow contract that does NOT require native minting -/// or burning of itself as a token. This is the base case that all other flow -/// interfaces model themselves after, with the addition of token minting and -/// burning. -/// -/// Current functionality only allows for moving third party tokens between -/// accounts. Token standards ERC20, ERC721, and ERC1155 are supported. -/// -/// The basic lifecycle of a flow is: -/// - `Flow` is deployed as a reference implementation to be cloned, with its -/// initializers disabled on construction. -/// - `Flow` is cloned and initialized with an abi encoded list of evaluable -/// configs that define every possible movement of tokens that can occur due -/// to the clone. The EOA that deployed the clone DOES NOT have any special -/// privileges over the clone, although they could grant themselves privileges -/// by flowing tokens to themselves or similar within the evaluables. Ideally -/// the EOA doesn't introduce "admin" features as it would be a security risk -/// to themselves and others. In the case that they do, all priviledges will -/// be visible in the rainlang code of the evaluable, there's no hidden -/// functionality that can be introduced to the clone bytecode. -/// - Anyone can call `flow` on the clone, passing in one of the evaluables set -/// during initialization. If the evaluable passed by the caller does not -/// match an initialized evaluable, the flow MUST revert with -/// `UnregisteredFlow`. The entirety of the resulting stack from the evaluation -/// defines all the token movements that MUST occur as a result of the flow. -/// ANY failures during the flow MUST revert the entire flow, leaving the -/// state of the tokens unchanged. -/// -/// The structure of the stack can be thought of as a simple list of transfers. -/// All the erc20 tokens are moved first, then the erc721 tokens, then the -/// erc1155 tokens. Each token type is separated in the stack by a sentinel -/// value. The sentinel is a constant, `RAIN_FLOW_SENTINEL`, that is guaranteed -/// to not collide with any token amounts or addresses. The sentinel is also -/// guaranteed to not collide with any other sentinels from other contexts, to -/// the extent that we can guarantee that with raw cryptographic collision -/// resistance. This sentinel can be thought of as similar to the null terminator -/// in a c string, it's a value that is guaranteed to not be a valid value for -/// the type of data it's separating. The main benefit in this context, for -/// rainlang authors, is that they can always use the same constant value in -/// all their rainlang code to separate the different token types, rather than -/// needing to manually calculate the length of the tuples they're wanting to -/// flow over in each token type (which would be very error prone). -/// -/// Currently every token transfer type MUST be present in every flow stack, -/// which is awkward as it means that if you want to flow erc20 tokens, you -/// MUST also flow erc721 and erc1155 tokens, even if you don't want to. This -/// is a limitation of the current implementation, and will be fixed in a future -/// version. -/// -/// Each individual token transfer is simply a list of values, where the values -/// are specific to the token type. -/// - erc20 transfers are a list of 4 values: -/// - address of the token contract -/// - address of the token sender -/// - address of the token recipient -/// - amount of tokens to transfer -/// - erc721 transfers are a list of 4 values: -/// - address of the token contract -/// - address of the token sender -/// - address of the token recipient -/// - token id to transfer -/// - erc1155 transfers are a list of 5 values: -/// - address of the token contract -/// - address of the token sender -/// - address of the token recipient -/// - token id to transfer -/// - amount of tokens to transfer -/// -/// The final stack is processed from the bottom up, so the first token transfer -/// in the stack is the last one to be processed. -/// -/// For example, a rainlang expression that transfers 1e18 erc20 token 0xf00baa -/// from the flow contract to the address 0xdeadbeef, and 1 erc721 token address -/// 0x1234 and id 5678 from the address 0xdeadbeef to the flow contract, would -/// result in the following rainlang/stack: -/// -/// ``` -/// /* sentinel is always the same. */ -/// sentinel: 0xfea74d0c9bf4a3c28f0dd0674db22a3d7f8bf259c56af19f4ac1e735b156974f, -/// /* erc1155 transfers are first, just a sentinel as there's nothing to do */ -/// _: sentinel, -/// /* erc721 transfers are next, with the token id as the last value */ -/// _: 0x1234 0xdeadbeef context<0 1>() 5678, -/// /* erc20 transfers are last, with the amount as the last value */ -/// _: 0xf00baa context<0 1>() 0xdeadbeef 1e18; -/// ``` -/// -/// Note that for all token transfers the sender of the tokens MUST be either -/// the flow contract itself, or the caller of the flow contract. This is to -/// prevent the flow contract from being able to transfer tokens from arbitrary -/// addresses without their consent. Even if some address has approved the flow -/// contract to transfer tokens on their behalf, the flow contract MUST NOT -/// transfer tokens from that address unless the caller of the flow contract -/// is that address. -/// -/// Note that native gas movements are not supported in this version of the -/// flow contract. This is because the current reference implementation uses -/// `Multicall` to batch together multiple calls to the flow contract, and -/// this involves a loop over a delegate call, which is not safe to do with -/// native gas movements. This will be fixed in a future version of the interface -/// where batching is handled by the flow contract itself, rather than relying -/// on `Multicall`. -interface IFlowV4 { - /// MUST be emitted when the flow contract is initialized. - /// @param sender The EOA that deployed the flow contract. - /// @param config The list of evaluable configs that define the flows. - event Initialize(address sender, EvaluableConfigV3[] config); - - /// Given a stack of values, convert it to a flow transfer. MUST NOT modify - /// state but MAY revert if the stack is malformed. The intended workflow is - /// that the interpreter contract is called to produce a stack then the stack - /// is converted to a flow transfer struct, to allow the caller to preview - /// a flow before actually executing it. By accepting a stack as input, the - /// caller can preview any possible flow, not just ones that have been - /// registered with the flow contract, and can preview flows that may not - /// even be possible to execute due to the state of the tokens, or access - /// gating that would exclude the caller, etc. - /// @param stack The stack of values to convert to a flow transfer. - /// @return flowTransfer The resulting flow transfer. - function stackToFlow(uint256[] memory stack) external pure returns (FlowTransferV1 calldata flowTransfer); - - /// Given an evaluable, caller context, and signed contexts, evaluate the - /// evaluable and return the resulting flow transfer. MUST process the - /// flow transfer atomically, either all of it succeeds or none of it - /// succeeds. MUST revert if the evaluable is not registered with the flow - /// contract. MUST revert if the evaluable reverts. MUST revert if the - /// evaluable returns a stack that is malformed. MUST revert if the evaluable - /// returns a stack that contains a token transfer that is not allowed by - /// the flow contract (e.g. if a token is being moved from an address that - /// is not the caller or the flow contract). - /// @param evaluable The evaluable to evaluate. - /// @param callerContext The caller context to pass to the evaluable. - /// @param signedContexts The signed contexts to pass to the evaluable. - /// @return flowTransfer The resulting flow transfer. - function flow( - EvaluableV2 calldata evaluable, - uint256[] calldata callerContext, - SignedContextV1[] calldata signedContexts - ) external returns (FlowTransferV1 calldata flowTransfer); -}