diff --git a/onchain/rollups/.changeset/quick-dodos-accept.md b/onchain/rollups/.changeset/quick-dodos-accept.md new file mode 100644 index 00000000..6450e274 --- /dev/null +++ b/onchain/rollups/.changeset/quick-dodos-accept.md @@ -0,0 +1,7 @@ +--- +"@cartesi/rollups": major +--- + +Implemented EIP-165 for CartesiDApp contract. +Also updated `ICartesiDApp` to include `IERC721Receiver`, `IERC1155Receiver` (which inherits from `IERC165`). +We made the `ICartesiDApp` interface inherit from `ERC165` so that it would be possible to detect contracts that do not support such interface. diff --git a/onchain/rollups/contracts/dapp/CartesiDApp.sol b/onchain/rollups/contracts/dapp/CartesiDApp.sol index ad2e00b0..54fe72b3 100644 --- a/onchain/rollups/contracts/dapp/CartesiDApp.sol +++ b/onchain/rollups/contracts/dapp/CartesiDApp.sol @@ -12,9 +12,11 @@ import {Bitmask} from "@cartesi/util/contracts/Bitmask.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; -import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import {ERC1155Holder, ERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; +import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /// @title Cartesi DApp /// @@ -124,6 +126,15 @@ contract CartesiDApp is _consensus.join(); } + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(ERC1155Receiver, IERC165) returns (bool) { + return + interfaceId == type(ICartesiDApp).interfaceId || + interfaceId == type(IERC721Receiver).interfaceId || + super.supportsInterface(interfaceId); + } + function executeVoucher( address _destination, bytes calldata _payload, diff --git a/onchain/rollups/contracts/dapp/ICartesiDApp.sol b/onchain/rollups/contracts/dapp/ICartesiDApp.sol index bde92005..23206088 100644 --- a/onchain/rollups/contracts/dapp/ICartesiDApp.sol +++ b/onchain/rollups/contracts/dapp/ICartesiDApp.sol @@ -8,6 +8,9 @@ import {IInputBox} from "../inputs/IInputBox.sol"; import {IInputRelay} from "../inputs/IInputRelay.sol"; import {OutputValidityProof} from "../library/LibOutputValidation.sol"; +import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; + /// @notice Data for validating outputs. /// @param validity A validity proof for the output /// @param context Data for querying the right claim from the current consensus contract @@ -18,7 +21,7 @@ struct Proof { } /// @title Cartesi DApp interface -interface ICartesiDApp { +interface ICartesiDApp is IERC721Receiver, IERC1155Receiver { // Events /// @notice The DApp has migrated to another consensus contract. diff --git a/onchain/rollups/test/foundry/dapp/CartesiDApp.t.sol b/onchain/rollups/test/foundry/dapp/CartesiDApp.t.sol index 50b3d640..d36f4eb0 100644 --- a/onchain/rollups/test/foundry/dapp/CartesiDApp.t.sol +++ b/onchain/rollups/test/foundry/dapp/CartesiDApp.t.sol @@ -7,7 +7,7 @@ pragma solidity ^0.8.8; import {TestBase} from "../util/TestBase.sol"; import {CartesiDApp} from "contracts/dapp/CartesiDApp.sol"; -import {Proof} from "contracts/dapp/ICartesiDApp.sol"; +import {ICartesiDApp, Proof} from "contracts/dapp/ICartesiDApp.sol"; import {IConsensus} from "contracts/consensus/IConsensus.sol"; import {IInputBox} from "contracts/inputs/IInputBox.sol"; import {IInputRelay} from "contracts/inputs/IInputRelay.sol"; @@ -17,6 +17,8 @@ import {OutputEncoding} from "contracts/common/OutputEncoding.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {LibServerManager} from "../util/LibServerManager.sol"; import {LibBytes} from "../util/LibBytes.sol"; @@ -124,6 +126,21 @@ contract CartesiDAppTest is TestBase { readFinishEpochResponse(); } + function testSupportsInterface(bytes4 _randomInterfaceId) public { + assertTrue(dapp.supportsInterface(type(ICartesiDApp).interfaceId)); + assertTrue(dapp.supportsInterface(type(IERC721Receiver).interfaceId)); + assertTrue(dapp.supportsInterface(type(IERC1155Receiver).interfaceId)); + assertTrue(dapp.supportsInterface(type(IERC165).interfaceId)); + + assertFalse(dapp.supportsInterface(bytes4(0xffffffff))); + + vm.assume(_randomInterfaceId != type(ICartesiDApp).interfaceId); + vm.assume(_randomInterfaceId != type(IERC721Receiver).interfaceId); + vm.assume(_randomInterfaceId != type(IERC1155Receiver).interfaceId); + vm.assume(_randomInterfaceId != type(IERC165).interfaceId); + assertFalse(dapp.supportsInterface(_randomInterfaceId)); + } + function testConstructorWithOwnerAsZeroAddress( IInputBox _inputBox, IInputRelay[] calldata _inputRelays,