Hi @Sarah,
Regards setInterfaceImplementer, this needs to be called by the externally owned account, otherwise the externally owned account needs to call setManager to set the contract as the manager.
Apologies, I was missing a step, that I have added above.
Contract needs to also implement canImplementInterfaceForAddress (e.g. inherit from ERC1820Implementer)
I have added a Simple777Sender to my example:
Simple777Sender.sol
pragma solidity ^0.5.0;
import "@openzeppelin/contracts/token/ERC777/IERC777.sol";
import "@openzeppelin/contracts/introspection/IERC1820Registry.sol";
import "@openzeppelin/contracts/introspection/ERC1820Implementer.sol";
import "@openzeppelin/contracts/token/ERC777/IERC777Sender.sol";
contract Simple777Sender is IERC777Sender, ERC1820Implementer {
bytes32 constant public TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
event DoneStuff(address operator, address from, address to, uint256 amount, bytes userData, bytes operatorData);
function senderFor(address account) public {
_registerInterfaceForAddress(TOKENS_SENDER_INTERFACE_HASH, account);
}
function tokensToSend(
address operator,
address from,
address to,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external {
// do stuff
emit DoneStuff(operator, from, to, amount, userData, operatorData);
}
}
Simple777Sender.test.js
const { singletons, BN, expectEvent } = require('openzeppelin-test-helpers');
const Simple777Token = artifacts.require('Simple777Token');
const Simple777Sender = artifacts.require('Simple777Sender');
contract('Simple777Sender', function ([_, registryFunder, creator, holder, recipient]) {
const data = web3.utils.sha3('777TestData');
beforeEach(async function () {
this.erc1820 = await singletons.ERC1820Registry(registryFunder);
this.token = await Simple777Token.new({ from: creator });
const amount = new BN(10000);
await this.token.send(holder, amount, data, { from: creator });
this.sender = await Simple777Sender.new({ from: creator });
});
it('sends from an externally-owned account', async function () {
const amount = new BN(1000);
const tokensSenderInterfaceHash = await this.sender.TOKENS_SENDER_INTERFACE_HASH();
await this.sender.senderFor(holder);
await this.erc1820.setInterfaceImplementer(holder, tokensSenderInterfaceHash, this.sender.address, { from: holder });
const receipt = await this.token.send(recipient, amount, data, { from: holder });
await expectEvent.inTransaction(receipt.tx, Simple777Sender, 'DoneStuff', { from: holder, to: recipient, amount: amount, userData: data, operatorData: null });
const recipientBalance = await this.token.balanceOf(recipient);
recipientBalance.should.be.bignumber.equal(amount);
});
});