0

In my Hardhat test, I can deploy the following:

  • ERC1820 contract via a Hardhat plugin
  • ERC777 contract
  • Staking contract to hold ERC777 tokens

Then I can mint some ERC777 tokens to an user:

await lpToken777.connect(owner).mint(user1Addr, userInitBalance);

But when I tried to mint some ERC777 tokens to my Staking contract

await rwToken777.connect(owner).mint(erc777StakingAddr, rwTokenTotalSupply);

That failed with the error message: "ERC777: token recipient contract has no implementer for ERC777TokensRecipient"

I found some explanation about that error:

https://docs.openzeppelin.com/contracts/4.x/erc777 : recipient contract has not registered itself as aware of the ERC777 protocol, so transfers to it are disabled to prevent tokens from being locked forever

https://docs.openzeppelin.com/contracts/4.x/api/utils#ERC1820Implementer IERC1820Registry.setInterfaceImplementer should then be called for the registration to be complete.

I traced that error back to OpenZeppelin's ERC777Upgradeable.sol, which the parent contract of my ERC777 contract:

    function _callTokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes memory userData,
        bytes memory operatorData,
        bool requireReceptionAck
    ) private {
        address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(to, _TOKENS_RECIPIENT_INTERFACE_HASH);
        if (implementer != address(0)) {
            IERC777RecipientUpgradeable(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
        } else if (requireReceptionAck) {
            require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
        }
    }

I see I need to deploy this _ERC1820_REGISTRY contract somehow, then register my Staking contract onto it... That sounds like a lot of extra work... Is there a much better way for me to do it? how can I deploy erc1820 with OpenZeppelin and register my staking contract?

1 Answer 1

1

To deploy an erc1820 or _ERC1820_REGISTRY contract, use this Hardhat plugin from https://www.npmjs.com/package/hardhat-erc1820:

Install it: yarn add hardhat-erc1820

Add this line in hardhat.config.ts: import "hardhat-erc1820";

Then that plugin will somehow deploy an _ERC1820_REGISTRY contract for you at the default address: 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24

Then we need to implement tokensReceived() function in our staking contract:

Copy code from ERC777SenderRecipientMock.sol https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/ERC777SenderRecipientMock.sol

    IERC1820RegistryUpgradeable internal constant _ERC1820_REGISTRY = IERC1820RegistryUpgradeable(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
    bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
    bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");

    function tokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external {
        ...
    }

    function tokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external {
        ...
    }

    function initialize() external initializer {
        __Ownable_init();
        __Pausable_init();

        // register interfaces
        // register our staking contract at _ERC1820_REGISTRY contract
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), _TOKENS_RECIPIENT_INTERFACE_HASH, address(this));
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), _TOKENS_SENDER_INTERFACE_HASH, address(this));
    }
2
  • Thank you for your answer. BTW, Where can I find these instruction? seems EIP or OpenZeppelin Docs or something though. Commented Nov 23, 2022 at 15:17
  • 1
    @reaverlover you can find these instructions in the ERC777SenderRecipientMock.sol in Openzeppelin's Github. Follow my link above
    – Russo
    Commented Nov 23, 2022 at 17:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.