Skip to content

Latest commit

 

History

History
72 lines (57 loc) · 4.07 KB

057.md

File metadata and controls

72 lines (57 loc) · 4.07 KB

Special Caramel Loris

Medium

ERC1155 Token Minting May Fail in L2ERC1155Gateway

Summary

The L2ERC1155Gateway contract may fail to mint ERC1155 tokens when finalizing deposits if the recipient address _to is a contract that does not implement the IERC1155Receiver interface. This issue can cause transaction reversion on Layer 2 (L2), resulting in tokens not being minted on L2 and potentially locking funds on Layer 1 (L1).

Vulnerability Detail

In the L2ERC1155Gateway contract, the functions finalizeDepositERC1155 and finalizeBatchDepositERC1155 are responsible for minting ERC1155 tokens on L2 when a deposit is finalized. These functions call the mint or batchMint methods of the ERC1155 token contract (IMorphERC1155):

IMorphERC1155(_l2Token).mint(_to, _tokenId, _amount, "");

When tokens are minted or transferred to a contract address, a safe transfer check is performed by calling _doSafeTransferAcceptanceCheck. This function invokes onERC1155Received on the recipient contract:

_doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);

If the recipient contract (_to) does not implement the IERC1155Receiver interface and the onERC1155Received function, the safe transfer acceptance check fails, causing the entire transaction to revert.

Why This Is a Problem?:

  1. Reverting the transaction means that the minting process fails, and the tokens are not minted on L2.
  2. The user's tokens remain on L1, but since the corresponding minting on L2 failed, the user cannot access their funds on L2.
  3. Users depositing tokens to contracts not compatible with IERC1155Receiver may lose access to their assets without an obvious cause.

Impact

Users may be unable to access their tokens on L2 after deposit because a reversion could result in the ERC1155 tokens becoming stuck in the L1 gateway

Code Snippet

    /// @inheritdoc IL2ERC1155Gateway
    function finalizeDepositERC1155(
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256 _tokenId,
        uint256 _amount
    ) external virtual onlyCallByCounterpart nonReentrant {
        require(_l1Token != address(0), "token address cannot be 0");
        require(_l1Token == tokenMapping[_l2Token], "l2 token mismatch");

        IMorphERC1155(_l2Token).mint(_to, _tokenId, _amount, "");

        emit FinalizeDepositERC1155(_l1Token, _l2Token, _from, _to, _tokenId, _amount);
    }

    /// @inheritdoc IL2ERC1155Gateway
    function finalizeBatchDepositERC1155(
        address _l1Token,
        address _l2Token,
        address _from,
        address _to,
        uint256[] calldata _tokenIds,
        uint256[] calldata _amounts
    ) external virtual onlyCallByCounterpart nonReentrant {
        require(_l1Token != address(0), "token address cannot be 0");
        require(_l1Token == tokenMapping[_l2Token], "l2 token mismatch");

        IMorphERC1155(_l2Token).batchMint(_to, _tokenIds, _amounts, "");

        emit FinalizeBatchDepositERC1155(_l1Token, _l2Token, _from, _to, _tokenIds, _amounts);
    }

Tool used

Manual Review

Recommendation

Before minting, check if the recipient address _to is a contract and whether it implements the IERC1155Receiver interface. This can prevent transaction reversion due to incompatible recipient contracts.

Ideally, in the future, a system should be implemented to check the Merkle tree and recover the ERC1155 tokens if the message fails on L2.