Beginner here, trying to implement an ERC777 token, recipient and sender. The code at the bottom stands for the token and the sender/receiver, respectively. I wrote them out as per this tutorial, but there must be something wrong because the following truffle console commands result in an error:
var accs = await web3.eth.getAccounts()
>> undefined
const [personA, personB] = accs
>> undefined
var token = await MyToken.new(10000, { from: personA })
>> undefined
token.balanceOf(personA)
>> BN: 10000
token.balanceOf(personB)
>> BN: 0
var clientA = await Client.new(token.address, { from: personA })
>> undefined
var clientB = await Client.new(token.address, { from: personB })
>> undefined
token.balanceOf(clientA)
>> BN: 0
token.balanceOf(clientB)
>> BN: 0
token.send(clientA.address, new BN(2500), web3.utils.sha3('whatever'), { from: personA })
>> undefined
token.balanceOf(personA)
>> BN: 7500
token.balanceOf(clientA.address)
>> BN: 2500
token.send(clientB.address, new BN(1000), web3.utils.sha3('whatever'), { from: clientA.address })
>> TXRejectedError: sender account not recognized
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
import "@openzeppelin/contracts/token/ERC777/ERC777.sol";
contract MyToken is ERC777 {
constructor(uint initialSupply)
ERC777("Token", "TKN", new address[](0)) {
_mint(msg.sender, initialSupply, "", "");
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
import "@openzeppelin/contracts/token/ERC777/IERC777.sol";
import "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol";
import "@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol";
import "@openzeppelin/contracts/utils/introspection/ERC1820Implementer.sol";
import "@openzeppelin/contracts/token/ERC777/IERC777Sender.sol";
contract Client is IERC777Recipient, IERC777Sender, ERC1820Implementer {
IERC777 private _token;
IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
bytes32 constant private TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
event TokensSent(
address operator,
address from,
address to,
uint256 amount,
bytes userData,
bytes operatorData
);
event TokensReceived(
address operator,
address from,
address to,
uint amount,
bytes userData,
bytes operatorData
);
constructor(address token_) {
_token = IERC777(token_);
_erc1820.setInterfaceImplementer(address(this), TOKENS_RECIPIENT_INTERFACE_HASH, address(this));
}
function senderFor(address account_) public {
_registerInterfaceForAddress(TOKENS_SENDER_INTERFACE_HASH, account_);
}
function tokensToSend(
address operator_,
address from_,
address to_,
uint amount_,
bytes calldata userData_,
bytes calldata operatorData_
) external {
emit TokensSent(
operator_,
from_,
to_,
amount_,
userData_,
operatorData_
);
}
function tokensReceived(
address operator_,
address from_,
address to_,
uint amount_,
bytes calldata userData_,
bytes calldata operatorData_
) external {
require(msg.sender == address(_token), "Client: invalid token");
emit TokensReceived(
operator_,
from_,
to_,
amount_,
userData_,
operatorData_
);
}
}