How to best override private function _doSafeTransferAcceptanceCheck in ERC1155?

Hi all,

I’m trying to inherit the ERC1155 base contract as provided by OZ. Specifically, I’m overriding safeTransferFrom. I’m trying to mimic the original implementation as closely as possible, including teh call to _doSafeTransferAcceptanceCheck, however, because that function is private, I can’t call it.

What’s the best solution to getting around this problem? I can’t override it as it’s a private function (as far as I know).

I’m between two options, though I feel like there’s probably a better one I hadn’t considered.

  1. Reimplementing the doSafeTransferAcceptanceCheck under a new name
  2. Reimplementing the entire contract and adding my functions (rather than inheriting)

I certainly want this functionality in the end so removing the function call entirely seems like a bad idea.

:computer: Environment

N/A

:memo:Details

:1234: Code to reproduce

    /**
     * @dev See {IERC1155-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public virtual override {
        require(to != address(0), "ERC1155: transfer to the zero address");
        require(
            from == _msgSender() ||
                isApprovedForAll(from, _msgSender())
            "ERC1155: caller is not owner, token holder, or pod manager"
        );

        // Imagine some unique implementation here

        address operator = _msgSender();

        _balances[id][from] = _balances[id][from].sub(
            amount,
            "ERC1155: insufficient balance for transfer"
        );
        _balances[id][to] = _balances[id][to].add(amount);

        emit TransferSingle(operator, from, to, id, amount);

        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
    }

    function _doSafeTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) private override {
        if (to.isContract()) {
            try
                IERC1155Receiver(to).onERC1155Received(
                    operator,
                    from,
                    id,
                    amount,
                    data
                )
            returns (bytes4 response) {
                if (
                    response != IERC1155Receiver(to).onERC1155Received.selector
                ) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non ERC1155Receiver implementer");
            }
        }
    }
1 Like

Just like what you said above, _doSafeTransferAcceptanceCheck is a private function, so you can not rewrite it, what you can do is to rewrite the function safeTransferFrom, so then you can do whatever you want to do.

1 Like

Hi @willKim19,

You could look at using the hook _beforeTokenTransfer, see Using Hooks. If you can’t do what you want to do using hooks, then you should do as @Skyge recommended.