From fd0ae2b206c6cb3e6f4b6f5ec238d477cf3059fc Mon Sep 17 00:00:00 2001 From: Erik Dubovyk Date: Mon, 5 Aug 2024 12:01:10 +0300 Subject: [PATCH] Ported test for ERC721 to ERC1155 token flow. --- test/abstract/FlowBaseTest.sol | 55 +++++++++++ .../concrete/Flow/FlowERC721ToERC1155Test.sol | 94 +++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 test/abstract/FlowBaseTest.sol create mode 100644 test/concrete/Flow/FlowERC721ToERC1155Test.sol diff --git a/test/abstract/FlowBaseTest.sol b/test/abstract/FlowBaseTest.sol new file mode 100644 index 00000000..457e437d --- /dev/null +++ b/test/abstract/FlowBaseTest.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: CAL +pragma solidity ^0.8.18; + +import {Vm} from "forge-std/Test.sol"; +import { + FlowUtilsAbstractTest, + ERC1155Transfer, + ERC721Transfer, + ERC20Transfer +} from "test/abstract/FlowUtilsAbstractTest.sol"; +import {InterpreterMockTest} from "test/abstract/InterpreterMockTest.sol"; +import {IFlowV5} from "src/interface/unstable/IFlowV5.sol"; +import {Flow} from "src/concrete/basic/Flow.sol"; +import {EvaluableConfigV3, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {STUB_EXPRESSION_BYTECODE} from "./TestConstants.sol"; +import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {CloneFactory} from "rain.factory/src/concrete/CloneFactory.sol"; + +abstract contract FlowBaseTest is FlowUtilsAbstractTest, InterpreterMockTest { + CloneFactory internal immutable _iCloneFactory; + IFlowV5 internal immutable _flowImplementation; + + constructor() { + vm.pauseGasMetering(); + _iCloneFactory = new CloneFactory(); + _flowImplementation = new Flow(); + vm.resumeGasMetering(); + } + + function deployFlow() internal returns (IFlowV5 flow, EvaluableV2 memory evaluable) { + expressionDeployerDeployExpression2MockCall(address(0), bytes(hex"0006")); + + EvaluableConfigV3[] memory flowConfig = new EvaluableConfigV3[](1); + flowConfig[0] = EvaluableConfigV3(iDeployer, STUB_EXPRESSION_BYTECODE, new uint256[](0)); + vm.recordLogs(); + flow = IFlowV5(_iCloneFactory.clone(address(_flowImplementation), abi.encode(flowConfig))); + Vm.Log[] memory logs = vm.getRecordedLogs(); + Vm.Log memory concreteEvent = findEvent(logs, keccak256("FlowInitialized(address,(address,address,address))")); + (, evaluable) = abi.decode(concreteEvent.data, (address, EvaluableV2)); + } + + function performFlow( + IFlowV5 flow, + EvaluableV2 memory evaluable, + ERC20Transfer[] memory erc20Transfers, + ERC721Transfer[] memory erc721Transfers, + ERC1155Transfer[] memory erc1155Transfers + ) internal { + vm.pauseGasMetering(); + uint256[] memory stack = generateTokenTransferStack(erc1155Transfers, erc721Transfers, erc20Transfers); + interpreterEval2MockCall(stack, new uint256[](0)); + vm.resumeGasMetering(); + flow.flow(evaluable, new uint256[](0), new SignedContextV1[](0)); + } +} diff --git a/test/concrete/Flow/FlowERC721ToERC1155Test.sol b/test/concrete/Flow/FlowERC721ToERC1155Test.sol new file mode 100644 index 00000000..102e8152 --- /dev/null +++ b/test/concrete/Flow/FlowERC721ToERC1155Test.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: CAL +pragma solidity ^0.8.18; + +import {FlowBaseTest} from "test/abstract/FlowBaseTest.sol"; +import {IFlowV5, ERC20Transfer, ERC721Transfer, ERC1155Transfer} from "src/interface/unstable/IFlowV5.sol"; +import {EvaluableV2} from "rain.interpreter.interface/lib/caller/LibEvaluable.sol"; +import {IERC721} from "openzeppelin-contracts/contracts/token/ERC721/IERC721.sol"; +import {IERC1155} from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol"; +import {REVERTING_MOCK_BYTECODE} from "test/abstract/TestConstants.sol"; + +contract FlowERC721ToERC1155Test is FlowBaseTest { + function setUp() public {} + + address internal immutable _iERC721; + address internal immutable _iERC1155; + + constructor() { + vm.pauseGasMetering(); + _iERC721 = address(uint160(uint256(keccak256("erc721.test")))); + vm.etch(address(_iERC721), REVERTING_MOCK_BYTECODE); + + _iERC1155 = address(uint160(uint256(keccak256("store.rain.test")))); + vm.etch(address(_iERC1155), REVERTING_MOCK_BYTECODE); + vm.resumeGasMetering(); + } + + function testFlowERC721ToERC1155( + address alice, + uint256 erc721InTokenId, + uint256 erc1155OutTokenId, + uint256 erc1155OutAmmount + ) external { + vm.assume(alice != address(0)); + vm.label(alice, "Alice"); + + (IFlowV5 flow, EvaluableV2 memory evaluable) = deployFlow(); + + ERC721Transfer[] memory erc721Transfers = new ERC721Transfer[](1); + erc721Transfers[0] = + ERC721Transfer({token: address(_iERC721), from: alice, to: address(flow), id: erc721InTokenId}); + + ERC1155Transfer[] memory erc1155Transfers = new ERC1155Transfer[](1); + erc1155Transfers[0] = ERC1155Transfer({ + token: address(_iERC1155), + from: address(flow), + to: alice, + id: erc1155OutTokenId, + amount: erc1155OutAmmount + }); + + vm.mockCall( + _iERC1155, + abi.encodeWithSelector( + bytes4(keccak256("safeTransferFrom(address,address,uint256,uint256,bytes)")), + flow, + alice, + erc1155OutTokenId, + erc1155OutAmmount, + "" + ), + abi.encode() + ); + vm.expectCall( + _iERC1155, + abi.encodeWithSelector( + bytes4(keccak256("safeTransferFrom(address,address,uint256,uint256,bytes)")), + flow, + alice, + erc1155OutTokenId, + erc1155OutAmmount, + "" + ) + ); + + vm.mockCall( + _iERC721, + abi.encodeWithSelector( + bytes4(keccak256("safeTransferFrom(address,address,uint256)")), alice, flow, erc721InTokenId + ), + abi.encode() + ); + + vm.expectCall( + _iERC721, + abi.encodeWithSelector( + bytes4(keccak256("safeTransferFrom(address,address,uint256)")), alice, flow, erc721InTokenId + ) + ); + + vm.startPrank(alice); + performFlow(flow, evaluable, new ERC20Transfer[](0), erc721Transfers, erc1155Transfers); + vm.stopPrank(); + } +}