diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index e00c2e040fd0a0d002d0587e39eb8ef9841810d2..a834e40a41718c015cdaab12dd9736412e94cba9 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -71,12 +71,12 @@ L2OutputOracleTest:test_deleteL2Output() (gas: 64338) L2OutputOracleTest:test_getL2Output() (gas: 74601) L2OutputOracleTest:test_latestBlockTimestamp() (gas: 68377) L2OutputOracleTest:test_nextTimestamp() (gas: 9236) -L2StandardBridge_Test:test_finalizeDeposit() (gas: 93169) +L2StandardBridge_Test:test_finalizeDeposit() (gas: 93143) L2StandardBridge_Test:test_finalizeDeposit_failsToCompleteOutboundTransfer() (gas: 140106) L2StandardBridge_Test:test_initialize() (gas: 14812) L2StandardBridge_Test:test_receive() (gas: 136415) -L2StandardBridge_Test:test_withdraw() (gas: 352632) -L2StandardBridge_Test:test_withdrawTo() (gas: 353484) +L2StandardBridge_Test:test_withdraw() (gas: 352612) +L2StandardBridge_Test:test_withdrawTo() (gas: 353463) L2ToL1MessagePasserTest:test_burn() (gas: 112046) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromContract() (gas: 67890) L2ToL1MessagePasserTest:test_initiateWithdrawal_fromEOA() (gas: 74851) @@ -89,17 +89,18 @@ OVM_ETH_Test:test_metadata() (gas: 15608) OVM_ETH_Test:test_mint() (gas: 10621) OVM_ETH_Test:test_transfer() (gas: 10726) OVM_ETH_Test:test_transferFrom() (gas: 13008) -OptimismMintableERC20_Test:test_bridge() (gas: 9850) +OptimismMintableERC20_Test:test_bridge() (gas: 9785) OptimismMintableERC20_Test:test_burn() (gas: 52791) OptimismMintableERC20_Test:test_burnRevertsFromNotBridge() (gas: 13211) +OptimismMintableERC20_Test:test_erc165_supportsInterface() (gas: 10999) OptimismMintableERC20_Test:test_l1Token() (gas: 9779) -OptimismMintableERC20_Test:test_l2Bridge() (gas: 9768) -OptimismMintableERC20_Test:test_mint() (gas: 65732) -OptimismMintableERC20_Test:test_mintRevertsFromNotBridge() (gas: 13213) -OptimismMintableERC20_Test:test_remoteToken() (gas: 9762) +OptimismMintableERC20_Test:test_l2Bridge() (gas: 9790) +OptimismMintableERC20_Test:test_mint() (gas: 65687) +OptimismMintableERC20_Test:test_mintRevertsFromNotBridge() (gas: 13235) +OptimismMintableERC20_Test:test_remoteToken() (gas: 9784) OptimismMintableTokenFactory_Test:test_bridge() (gas: 9707) -OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1106538) -OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2193987) +OptimismMintableTokenFactory_Test:test_createStandardL2Token() (gas: 1100125) +OptimismMintableTokenFactory_Test:test_createStandardL2TokenSameTwice() (gas: 2181161) OptimismMintableTokenFactory_Test:test_createStandardL2TokenShouldRevertIfRemoteIsZero() (gas: 9374) OptimismMintableTokenFactory_Test:test_initializeShouldRevert() (gas: 12696) OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 11413) @@ -161,4 +162,4 @@ SequencerFeeVault_Test:test_constructor() (gas: 7611) SequencerFeeVault_Test:test_minWithdrawalAmount() (gas: 5429) SequencerFeeVault_Test:test_receive() (gas: 17280) SequencerFeeVault_Test:test_revertWithdraw() (gas: 9245) -SequencerFeeVault_Test:test_withdraw() (gas: 147275) +SequencerFeeVault_Test:test_withdraw() (gas: 147297) diff --git a/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol b/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol index 3c6ee99f790ba4ca5b75a81111693f53af39b4a5..991a7ec3b415527b78425595b59f343834012c4b 100644 --- a/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol +++ b/packages/contracts-bedrock/contracts/test/OptimismMintableERC20.t.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.10; import { Bridge_Initializer } from "./CommonTest.t.sol"; import { LibRLP } from "./Lib_RLP.t.sol"; +import "../universal/SupportedInterfaces.sol"; +import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; contract OptimismMintableERC20_Test is Bridge_Initializer { event Mint(address indexed _account, uint256 _amount); @@ -64,4 +66,24 @@ contract OptimismMintableERC20_Test is Bridge_Initializer { vm.prank(address(alice)); L2Token.burn(alice, 100); } + + function test_erc165_supportsInterface() external { + // The assertEq calls in this test are comparing the manual calculation of the iface, + // with what is returned by the solidity's type().interfaceId, just to be safe. + bytes4 iface1 = bytes4(keccak256("supportsInterface(bytes4)")); + assertEq(iface1, type(IERC165).interfaceId); + assert(L2Token.supportsInterface(iface1)); + emit log_bytes32(bytes32(iface1)); + + bytes4 iface2 = L2Token.l1Token.selector ^ L2Token.mint.selector ^ L2Token.burn.selector; + assertEq(iface2, type(IL1Token).interfaceId); + assert(L2Token.supportsInterface(iface2)); + emit log_bytes32(bytes32(iface2)); + + bytes4 iface3 = L2Token.remoteToken.selector ^ L2Token.mint.selector ^ L2Token.burn.selector; + assertEq(iface3, type(IRemoteToken).interfaceId); + assert(L2Token.supportsInterface(iface3)); + emit log_bytes32(bytes32(iface3)); + + } } diff --git a/packages/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol b/packages/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol index 90decd2439543cd0763dcc46f65c68fb63cc2df2..e9e1a46bcde3cee1487a7de229c128e9f5755a0a 100644 --- a/packages/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol +++ b/packages/contracts-bedrock/contracts/universal/OptimismMintableERC20.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.9; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "./SupportedInterfaces.sol"; /** * @title OptimismMintableERC20 @@ -72,10 +73,10 @@ contract OptimismMintableERC20 is ERC20 { */ // slither-disable-next-line external-function function supportsInterface(bytes4 _interfaceId) public pure returns (bool) { - bytes4 iface1 = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165 - bytes4 iface2 = this.l1Token.selector ^ this.mint.selector ^ this.burn.selector; - bytes4 iface3 = this.remoteToken.selector ^ this.mint.selector ^ this.burn.selector; - return _interfaceId == iface1 || _interfaceId == iface3 || _interfaceId == iface2; + bytes4 iface1 = type(IERC165).interfaceId; + bytes4 iface2 = type(IL1Token).interfaceId; + bytes4 iface3 = type(IRemoteToken).interfaceId; + return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3; } /** diff --git a/packages/contracts-bedrock/contracts/universal/StandardBridge.sol b/packages/contracts-bedrock/contracts/universal/StandardBridge.sol index 9e4068c3f3044e5663dd0cc230d47c46b88f3cf7..5344abafc40cce318faf29f8f256702c7e2702d2 100644 --- a/packages/contracts-bedrock/contracts/universal/StandardBridge.sol +++ b/packages/contracts-bedrock/contracts/universal/StandardBridge.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.9; /* Interface Imports */ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "./SupportedInterfaces.sol"; /* Library Imports */ import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; @@ -377,8 +378,7 @@ abstract contract StandardBridge { * @return True if the token is an OptimismMintableERC20. */ function _isOptimismMintableERC20(address _token) internal view returns (bool) { - // 0x1d1d8b63 is mint ^ burn ^ l1Token - return ERC165Checker.supportsInterface(_token, 0x1d1d8b63); + return ERC165Checker.supportsInterface(_token, type(IL1Token).interfaceId); } /** diff --git a/packages/contracts-bedrock/contracts/universal/SupportedInterfaces.sol b/packages/contracts-bedrock/contracts/universal/SupportedInterfaces.sol new file mode 100644 index 0000000000000000000000000000000000000000..a616b92ccd7a143192861c53b2d77c22aa9a8a9d --- /dev/null +++ b/packages/contracts-bedrock/contracts/universal/SupportedInterfaces.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +// Import this here to make it available just by importing this file +import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +interface IRemoteToken { + function mint(address _to, uint256 _amount) external virtual; + + function burn(address _from, uint256 _amount) external virtual; + + function remoteToken() external virtual; +} + +interface IL1Token { + function mint(address _to, uint256 _amount) external virtual; + + function burn(address _from, uint256 _amount) external virtual; + + function l1Token() external virtual; +}