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?