Skip to content

Commit

Permalink
bump i9r
Browse files Browse the repository at this point in the history
  • Loading branch information
thedavidmeister committed Feb 28, 2024
1 parent 5f2cae7 commit 0ea3300
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 37 deletions.
32 changes: 28 additions & 4 deletions src/abstract/FlowCommon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ import {
import {ReentrancyGuardUpgradeable as ReentrancyGuard} from
"openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol";
import {LibUint256Matrix} from "rain.solmem/lib/LibUint256Matrix.sol";
import {LibNamespace, StateNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol";
import {
UnsupportedFlowInputs,
InsufficientFlowOutputs
} from "../error/ErrFlow.sol";

/// Thrown when the min outputs for a flow is fewer than the sentinels.
/// This is always an implementation bug as the min outputs and sentinel count
Expand Down Expand Up @@ -84,6 +89,7 @@ abstract contract FlowCommon is ERC721Holder, ERC1155Holder, Multicall, Reentran
using LibUint256Array for uint256[];
using LibUint256Matrix for uint256[];
using LibEvaluable for EvaluableV2;
using LibNamespace for StateNamespace;

/// @dev This mapping tracks all flows that are registered at initialization.
/// This is used to ensure that only registered flows are evaluated.
Expand Down Expand Up @@ -148,9 +154,26 @@ abstract contract FlowCommon is ERC721Holder, ERC1155Holder, Multicall, Reentran
// 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.
(IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression) = config
(IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression, bytes memory io) = config
.deployer
.deployExpression2(config.bytecode, config.constants, LibUint256Array.arrayFrom(flowMinOutputs));
.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);
// There's no way to set this mapping before the external
// contract call because the output of the external contract
Expand Down Expand Up @@ -200,9 +223,10 @@ abstract contract FlowCommon is ERC721Holder, ERC1155Holder, Multicall, Reentran

(uint256[] memory stack, uint256[] memory kvs) = evaluable.interpreter.eval2(
evaluable.store,
DEFAULT_STATE_NAMESPACE,
DEFAULT_STATE_NAMESPACE.qualifyNamespace(address(this)),
LibEncodedDispatch.encode2(evaluable.expression, FLOW_ENTRYPOINT, FLOW_MAX_OUTPUTS),
context
context,
new uint256[](0)
);
return (stack.dataPointer(), stack.endPointer(), kvs);
}
Expand Down
35 changes: 30 additions & 5 deletions src/concrete/erc1155/FlowERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,19 @@ import {LibFlow} from "../../lib/LibFlow.sol";
import {SourceIndexV2} from "rain.interpreter.interface/interface/unstable/IInterpreterV2.sol";
import {FlowCommon, ERC1155Receiver} from "../../abstract/FlowCommon.sol";
import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol";
import {LibNamespace, StateNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol";
import {
InsufficientHandleTransferOutputs,
UnsupportedHandleTransferInputs
} from "../../error/ErrFlow.sol";

/// @title FlowERC1155
/// See `IFlowERC1155V4` for documentation.
contract FlowERC1155 is ICloneableV2, IFlowERC1155V4, FlowCommon, ERC1155 {
using LibStackSentinel for Pointer;
using LibUint256Matrix for uint256[];
using LibUint256Array for uint256[];
using LibNamespace for StateNamespace;

/// True if the evaluable needs to be called on every transfer.
bool private sEvalHandleTransfer;
Expand Down Expand Up @@ -68,14 +74,32 @@ contract FlowERC1155 is ICloneableV2, IFlowERC1155V4, FlowCommon, ERC1155 {
flowCommonInit(flowERC1155Config.flowConfig, FLOW_ERC1155_MIN_FLOW_SENTINELS);

if (evalHandleTransfer) {
(IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression) = flowERC1155Config
(IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression, bytes memory io) = flowERC1155Config
.evaluableConfig
.deployer
.deployExpression2(
flowERC1155Config.evaluableConfig.bytecode,
flowERC1155Config.evaluableConfig.constants,
LibUint256Array.arrayFrom(FLOW_ERC1155_HANDLE_TRANSFER_MIN_OUTPUTS)
flowERC1155Config.evaluableConfig.constants
);

{
uint256 handleTransferInputs;
uint256 handleTransferOutputs;
assembly ("memory-safe") {
let ioWord := mload(add(io, 0x20))
handleTransferInputs := byte(0, ioWord)
handleTransferOutputs := byte(1, ioWord)
}

if (handleTransferInputs != 0) {
revert UnsupportedHandleTransferInputs();
}

if (handleTransferOutputs < FLOW_ERC1155_HANDLE_TRANSFER_MIN_OUTPUTS) {
revert InsufficientHandleTransferOutputs();
}
}

// There's no way to set this before the external call because the
// output of the `deployExpression` call is the input to `Evaluable`.
// Even if we could set it before the external call, we wouldn't want
Expand Down Expand Up @@ -134,13 +158,14 @@ contract FlowERC1155 is ICloneableV2, IFlowERC1155V4, FlowCommon, ERC1155 {

(uint256[] memory stack, uint256[] memory kvs) = evaluable.interpreter.eval2(
evaluable.store,
DEFAULT_STATE_NAMESPACE,
DEFAULT_STATE_NAMESPACE.qualifyNamespace(address(this)),
LibEncodedDispatch.encode2(
evaluable.expression,
FLOW_ERC1155_HANDLE_TRANSFER_ENTRYPOINT,
FLOW_ERC1155_HANDLE_TRANSFER_MAX_OUTPUTS
),
context
context,
new uint256[](0)
);
(stack);
if (kvs.length > 0) {
Expand Down
33 changes: 27 additions & 6 deletions src/concrete/erc20/FlowERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {IInterpreterStoreV2} from "rain.interpreter.interface/interface/unstable
import {Pointer} from "rain.solmem/lib/LibPointer.sol";
import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol";
import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol";
import {LibNamespace, StateNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol";
import {UnsupportedHandleTransferInputs, InsufficientHandleTransferOutputs} from "../../error/ErrFlow.sol";

/// @dev The hash of the meta data expected to be passed to `FlowCommon`'s
/// constructor.
Expand All @@ -43,6 +45,7 @@ contract FlowERC20 is ICloneableV2, IFlowERC20V5, FlowCommon, ERC20 {
using LibStackSentinel for Pointer;
using LibUint256Matrix for uint256[];
using LibUint256Array for uint256[];
using LibNamespace for StateNamespace;

/// @dev True if we need to eval `handleTransfer` on every transfer. For many
/// tokens this will be false, so we don't want to invoke the external
Expand Down Expand Up @@ -75,14 +78,31 @@ contract FlowERC20 is ICloneableV2, IFlowERC20V5, FlowCommon, ERC20 {
flowCommonInit(flowERC20Config.flowConfig, FLOW_ERC20_MIN_FLOW_SENTINELS);

if (evalHandleTransfer) {
(IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression) = flowERC20Config
(IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression, bytes memory io) = flowERC20Config
.evaluableConfig
.deployer
.deployExpression2(
flowERC20Config.evaluableConfig.bytecode,
flowERC20Config.evaluableConfig.constants,
LibUint256Array.arrayFrom(FLOW_ERC20_HANDLE_TRANSFER_MIN_OUTPUTS)
);
flowERC20Config.evaluableConfig.constants);

{
uint256 handleTransferInputs;
uint256 handleTransferOutputs;
assembly ("memory-safe") {
let ioWord := mload(add(io, 0x20))
handleTransferInputs := byte(0, ioWord)
handleTransferOutputs := byte(1, ioWord)
}

if (handleTransferInputs != 0) {
revert UnsupportedHandleTransferInputs();
}

if (handleTransferOutputs < FLOW_ERC20_HANDLE_TRANSFER_MIN_OUTPUTS) {
revert InsufficientHandleTransferOutputs();
}
}

// There's no way to set this before the external call because the
// output of the `deployExpression` call is the input to `Evaluable`.
// Even if we could set it before the external call, we wouldn't want
Expand Down Expand Up @@ -126,7 +146,7 @@ contract FlowERC20 is ICloneableV2, IFlowERC20V5, FlowCommon, ERC20 {
EvaluableV2 memory evaluable = sEvaluable;
(uint256[] memory stack, uint256[] memory kvs) = evaluable.interpreter.eval2(
evaluable.store,
DEFAULT_STATE_NAMESPACE,
DEFAULT_STATE_NAMESPACE.qualifyNamespace(address(this)),
LibEncodedDispatch.encode2(
evaluable.expression,
FLOW_ERC20_HANDLE_TRANSFER_ENTRYPOINT,
Expand All @@ -137,7 +157,8 @@ contract FlowERC20 is ICloneableV2, IFlowERC20V5, FlowCommon, ERC20 {
// is triggering the transfer.
LibUint256Array.arrayFrom(uint256(uint160(from)), uint256(uint160(to)), amount).matrixFrom(),
new SignedContextV1[](0)
)
),
new uint256[](0)
);
(stack);
if (kvs.length > 0) {
Expand Down
58 changes: 43 additions & 15 deletions src/concrete/erc721/FlowERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ import {
import {IInterpreterStoreV2} from "rain.interpreter.interface/interface/unstable/IInterpreterStoreV2.sol";
import {Pointer} from "rain.solmem/lib/LibPointer.sol";
import {BurnerNotOwner} from "../../error/ErrFlow.sol";


/// @dev The hash of the meta data expected to be passed to `FlowCommon`'s
/// constructor.
bytes32 constant CALLER_META_HASH = bytes32(0xf0003e81ff90467c9933f3ac68db3ca49df8b30ab83a0b88e1ed8381ed28fdd6);
import {LibNamespace, StateNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol";
import {
InsufficientHandleTransferOutputs,
InsufficientTokenURIOutputs,
UnsupportedHandleTransferInputs,
UnsupportedTokenURIInputs
} from "../../error/ErrFlow.sol";

/// @title FlowERC721
/// See `IFlowERC721V4` for documentation.
Expand Down Expand Up @@ -110,18 +112,43 @@ contract FlowERC721 is ICloneableV2, IFlowERC721V5, FlowCommon, ERC721 {
flowCommonInit(flowERC721Config.flowConfig, FLOW_ERC721_MIN_FLOW_SENTINELS);

if (evalHandleTransfer) {
// Include the token URI min outputs if we expect to eval it,
// otherwise only include the handle transfer min outputs.
uint256[] memory minOutputs = evalTokenURI
? LibUint256Array.arrayFrom(FLOW_ERC721_HANDLE_TRANSFER_MIN_OUTPUTS, FLOW_ERC721_TOKEN_URI_MIN_OUTPUTS)
: LibUint256Array.arrayFrom(FLOW_ERC721_HANDLE_TRANSFER_MIN_OUTPUTS);

(IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression) = flowERC721Config
(IInterpreterV2 interpreter, IInterpreterStoreV2 store, address expression, bytes memory io) = flowERC721Config
.evaluableConfig
.deployer
.deployExpression2(
flowERC721Config.evaluableConfig.bytecode, flowERC721Config.evaluableConfig.constants, minOutputs
flowERC721Config.evaluableConfig.bytecode, flowERC721Config.evaluableConfig.constants
);

{
uint256 handleTransferInputs;
uint256 handleTransferOutputs;
uint256 tokenURIInputs;
uint256 tokenURIOutputs;
assembly ("memory-safe") {
let ioWords := add(io, 0x20)
handleTransferInputs := byte(0, ioWords)
handleTransferOutputs := byte(1, ioWords)
tokenURIInputs := byte(2, ioWords)
tokenURIOutputs := byte(3, ioWords)
}

if (handleTransferInputs != 0) {
revert UnsupportedHandleTransferInputs();
}

if (handleTransferOutputs < FLOW_ERC721_HANDLE_TRANSFER_MIN_OUTPUTS) {
revert InsufficientHandleTransferOutputs();
}

if (evalTokenURI && tokenURIInputs != 0) {
revert UnsupportedTokenURIInputs();
}

if (evalTokenURI && tokenURIOutputs < FLOW_ERC721_TOKEN_URI_MIN_OUTPUTS) {
revert InsufficientTokenURIOutputs();
}
}

// There's no way to set this before the external call because the
// output of the `deployExpression` call is the input to `Evaluable`.
// Even if we could set it before the external call, we wouldn't want
Expand Down Expand Up @@ -154,11 +181,12 @@ contract FlowERC721 is ICloneableV2, IFlowERC721V5, FlowCommon, ERC721 {
EvaluableV2 memory evaluable = sEvaluable;
(uint256[] memory stack, uint256[] memory kvs) = evaluable.interpreter.eval2(
evaluable.store,
DEFAULT_STATE_NAMESPACE,
DEFAULT_STATE_NAMESPACE.qualifyNamespace(address(this)),
LibEncodedDispatch.encode2(
evaluable.expression, FLOW_ERC721_TOKEN_URI_ENTRYPOINT, FLOW_ERC721_TOKEN_URI_MAX_OUTPUTS
),
LibContext.build(LibUint256Array.arrayFrom(tokenId).matrixFrom(), new SignedContextV1[](0))
LibContext.build(LibUint256Array.arrayFrom(tokenId).matrixFrom(), new SignedContextV1[](0)),
new uint256[](0)
);
// @todo it would be nice if we could do something with the kvs here,
// but the interface is view.
Expand Down
9 changes: 8 additions & 1 deletion src/error/ErrFlow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,11 @@ error UnsupportedERC1155Flow();
contract ErrFLow {}

/// Thrown when burner of tokens is not the owner of tokens.
error BurnerNotOwner();
error BurnerNotOwner();

error UnsupportedHandleTransferInputs();
error InsufficientHandleTransferOutputs();
error UnsupportedTokenURIInputs();
error InsufficientTokenURIOutputs();
error UnsupportedFlowInputs();
error InsufficientFlowOutputs();
4 changes: 3 additions & 1 deletion src/interface/unstable/IFlowERC1155V5.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {SourceIndexV2} from "rain.interpreter.interface/interface/unstable/IInterpreterV2.sol";
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";
Expand All @@ -10,11 +11,12 @@ 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 "../deprecated/v4/IFlowERC1155V4.sol";

SourceIndexV2 constant FLOW_ERC1155_HANDLE_TRANSFER_ENTRYPOINT = SourceIndexV2.wrap(0);

/// Initialization config.
/// @param uri As per Open Zeppelin `ERC1155Upgradeable`.
/// @param evaluableConfig The `EvaluableConfigV2` to use to build the
Expand Down
4 changes: 3 additions & 1 deletion src/interface/unstable/IFlowERC20V5.sol
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.18;

import {SourceIndexV2} from "rain.interpreter.interface/interface/unstable/IInterpreterV2.sol";
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 {
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 "../deprecated/v4/IFlowERC20V4.sol";
import {RAIN_FLOW_SENTINEL} from "./IFlowV5.sol";

SourceIndexV2 constant FLOW_ERC20_HANDLE_TRANSFER_ENTRYPOINT = SourceIndexV2.wrap(0);

/// Initialization config.
/// @param name As per Open Zeppelin `ERC20Upgradeable`.
/// @param symbol As per Open Zeppelin `ERC20Upgradeable`.
Expand Down
7 changes: 4 additions & 3 deletions src/interface/unstable/IFlowERC721V5.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ 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 {SourceIndexV2} from "rain.interpreter.interface/interface/unstable/IInterpreterV2.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 "../deprecated/v4/IFlowERC721V4.sol";

SourceIndexV2 constant FLOW_ERC721_HANDLE_TRANSFER_ENTRYPOINT = SourceIndexV2.wrap(0);
SourceIndexV2 constant FLOW_ERC721_TOKEN_URI_ENTRYPOINT = SourceIndexV2.wrap(1);

import {RAIN_FLOW_SENTINEL} from "../deprecated/v4/IFlowV4.sol";

/// Initialization config.
Expand Down

0 comments on commit 0ea3300

Please sign in to comment.