ERC777.sol 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "../../utils/Context.sol";
  4. import "./IERC777.sol";
  5. import "./IERC777Recipient.sol";
  6. import "./IERC777Sender.sol";
  7. import "../../token/ERC20/IERC20.sol";
  8. import "../../utils/Address.sol";
  9. import "../../introspection/IERC1820Registry.sol";
  10. /**
  11. * @dev Implementation of the {IERC777} interface.
  12. *
  13. * This implementation is agnostic to the way tokens are created. This means
  14. * that a supply mechanism has to be added in a derived contract using {_mint}.
  15. *
  16. * Support for ERC20 is included in this contract, as specified by the EIP: both
  17. * the ERC777 and ERC20 interfaces can be safely used when interacting with it.
  18. * Both {IERC777-Sent} and {IERC20-Transfer} events are emitted on token
  19. * movements.
  20. *
  21. * Additionally, the {IERC777-granularity} value is hard-coded to `1`, meaning that there
  22. * are no special restrictions in the amount of tokens that created, moved, or
  23. * destroyed. This makes integration with ERC20 applications seamless.
  24. */
  25. contract ERC777 is Context, IERC777, IERC20 {
  26. using Address for address;
  27. IERC1820Registry constant internal _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
  28. mapping(address => uint256) private _balances;
  29. uint256 private _totalSupply;
  30. string private _name;
  31. string private _symbol;
  32. // We inline the result of the following hashes because Solidity doesn't resolve them at compile time.
  33. // See https://github.com/ethereum/solidity/issues/4024.
  34. // keccak256("ERC777TokensSender")
  35. bytes32 constant private _TOKENS_SENDER_INTERFACE_HASH =
  36. 0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895;
  37. // keccak256("ERC777TokensRecipient")
  38. bytes32 constant private _TOKENS_RECIPIENT_INTERFACE_HASH =
  39. 0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b;
  40. // This isn't ever read from - it's only used to respond to the defaultOperators query.
  41. address[] private _defaultOperatorsArray;
  42. // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
  43. mapping(address => bool) private _defaultOperators;
  44. // For each account, a mapping of its operators and revoked default operators.
  45. mapping(address => mapping(address => bool)) private _operators;
  46. mapping(address => mapping(address => bool)) private _revokedDefaultOperators;
  47. // ERC20-allowances
  48. mapping (address => mapping (address => uint256)) private _allowances;
  49. /**
  50. * @dev `defaultOperators` may be an empty array.
  51. */
  52. constructor(
  53. string memory name_,
  54. string memory symbol_,
  55. address[] memory defaultOperators_
  56. ) {
  57. _name = name_;
  58. _symbol = symbol_;
  59. _defaultOperatorsArray = defaultOperators_;
  60. for (uint256 i = 0; i < _defaultOperatorsArray.length; i++) {
  61. _defaultOperators[_defaultOperatorsArray[i]] = true;
  62. }
  63. // register interfaces
  64. _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
  65. _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
  66. }
  67. /**
  68. * @dev See {IERC777-name}.
  69. */
  70. function name() public view virtual override returns (string memory) {
  71. return _name;
  72. }
  73. /**
  74. * @dev See {IERC777-symbol}.
  75. */
  76. function symbol() public view virtual override returns (string memory) {
  77. return _symbol;
  78. }
  79. /**
  80. * @dev See {ERC20-decimals}.
  81. *
  82. * Always returns 18, as per the
  83. * [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
  84. */
  85. function decimals() public pure virtual returns (uint8) {
  86. return 18;
  87. }
  88. /**
  89. * @dev See {IERC777-granularity}.
  90. *
  91. * This implementation always returns `1`.
  92. */
  93. function granularity() public view virtual override returns (uint256) {
  94. return 1;
  95. }
  96. /**
  97. * @dev See {IERC777-totalSupply}.
  98. */
  99. function totalSupply() public view virtual override(IERC20, IERC777) returns (uint256) {
  100. return _totalSupply;
  101. }
  102. /**
  103. * @dev Returns the amount of tokens owned by an account (`tokenHolder`).
  104. */
  105. function balanceOf(address tokenHolder) public view virtual override(IERC20, IERC777) returns (uint256) {
  106. return _balances[tokenHolder];
  107. }
  108. /**
  109. * @dev See {IERC777-send}.
  110. *
  111. * Also emits a {IERC20-Transfer} event for ERC20 compatibility.
  112. */
  113. function send(address recipient, uint256 amount, bytes memory data) public virtual override {
  114. _send(_msgSender(), recipient, amount, data, "", true);
  115. }
  116. /**
  117. * @dev See {IERC20-transfer}.
  118. *
  119. * Unlike `send`, `recipient` is _not_ required to implement the {IERC777Recipient}
  120. * interface if it is a contract.
  121. *
  122. * Also emits a {Sent} event.
  123. */
  124. function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
  125. require(recipient != address(0), "ERC777: transfer to the zero address");
  126. address from = _msgSender();
  127. _callTokensToSend(from, from, recipient, amount, "", "");
  128. _move(from, from, recipient, amount, "", "");
  129. _callTokensReceived(from, from, recipient, amount, "", "", false);
  130. return true;
  131. }
  132. /**
  133. * @dev See {IERC777-burn}.
  134. *
  135. * Also emits a {IERC20-Transfer} event for ERC20 compatibility.
  136. */
  137. function burn(uint256 amount, bytes memory data) public virtual override {
  138. _burn(_msgSender(), amount, data, "");
  139. }
  140. /**
  141. * @dev See {IERC777-isOperatorFor}.
  142. */
  143. function isOperatorFor(address operator, address tokenHolder) public view virtual override returns (bool) {
  144. return operator == tokenHolder ||
  145. (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
  146. _operators[tokenHolder][operator];
  147. }
  148. /**
  149. * @dev See {IERC777-authorizeOperator}.
  150. */
  151. function authorizeOperator(address operator) public virtual override {
  152. require(_msgSender() != operator, "ERC777: authorizing self as operator");
  153. if (_defaultOperators[operator]) {
  154. delete _revokedDefaultOperators[_msgSender()][operator];
  155. } else {
  156. _operators[_msgSender()][operator] = true;
  157. }
  158. emit AuthorizedOperator(operator, _msgSender());
  159. }
  160. /**
  161. * @dev See {IERC777-revokeOperator}.
  162. */
  163. function revokeOperator(address operator) public virtual override {
  164. require(operator != _msgSender(), "ERC777: revoking self as operator");
  165. if (_defaultOperators[operator]) {
  166. _revokedDefaultOperators[_msgSender()][operator] = true;
  167. } else {
  168. delete _operators[_msgSender()][operator];
  169. }
  170. emit RevokedOperator(operator, _msgSender());
  171. }
  172. /**
  173. * @dev See {IERC777-defaultOperators}.
  174. */
  175. function defaultOperators() public view virtual override returns (address[] memory) {
  176. return _defaultOperatorsArray;
  177. }
  178. /**
  179. * @dev See {IERC777-operatorSend}.
  180. *
  181. * Emits {Sent} and {IERC20-Transfer} events.
  182. */
  183. function operatorSend(
  184. address sender,
  185. address recipient,
  186. uint256 amount,
  187. bytes memory data,
  188. bytes memory operatorData
  189. )
  190. public
  191. virtual
  192. override
  193. {
  194. require(isOperatorFor(_msgSender(), sender), "ERC777: caller is not an operator for holder");
  195. _send(sender, recipient, amount, data, operatorData, true);
  196. }
  197. /**
  198. * @dev See {IERC777-operatorBurn}.
  199. *
  200. * Emits {Burned} and {IERC20-Transfer} events.
  201. */
  202. function operatorBurn(address account, uint256 amount, bytes memory data, bytes memory operatorData) public virtual override {
  203. require(isOperatorFor(_msgSender(), account), "ERC777: caller is not an operator for holder");
  204. _burn(account, amount, data, operatorData);
  205. }
  206. /**
  207. * @dev See {IERC20-allowance}.
  208. *
  209. * Note that operator and allowance concepts are orthogonal: operators may
  210. * not have allowance, and accounts with allowance may not be operators
  211. * themselves.
  212. */
  213. function allowance(address holder, address spender) public view virtual override returns (uint256) {
  214. return _allowances[holder][spender];
  215. }
  216. /**
  217. * @dev See {IERC20-approve}.
  218. *
  219. * Note that accounts cannot have allowance issued by their operators.
  220. */
  221. function approve(address spender, uint256 value) public virtual override returns (bool) {
  222. address holder = _msgSender();
  223. _approve(holder, spender, value);
  224. return true;
  225. }
  226. /**
  227. * @dev See {IERC20-transferFrom}.
  228. *
  229. * Note that operator and allowance concepts are orthogonal: operators cannot
  230. * call `transferFrom` (unless they have allowance), and accounts with
  231. * allowance cannot call `operatorSend` (unless they are operators).
  232. *
  233. * Emits {Sent}, {IERC20-Transfer} and {IERC20-Approval} events.
  234. */
  235. function transferFrom(address holder, address recipient, uint256 amount) public virtual override returns (bool) {
  236. require(recipient != address(0), "ERC777: transfer to the zero address");
  237. require(holder != address(0), "ERC777: transfer from the zero address");
  238. address spender = _msgSender();
  239. _callTokensToSend(spender, holder, recipient, amount, "", "");
  240. _move(spender, holder, recipient, amount, "", "");
  241. _approve(holder, spender, _allowances[holder][spender] - amount);
  242. _callTokensReceived(spender, holder, recipient, amount, "", "", false);
  243. return true;
  244. }
  245. /**
  246. * @dev Creates `amount` tokens and assigns them to `account`, increasing
  247. * the total supply.
  248. *
  249. * If a send hook is registered for `account`, the corresponding function
  250. * will be called with `operator`, `data` and `operatorData`.
  251. *
  252. * See {IERC777Sender} and {IERC777Recipient}.
  253. *
  254. * Emits {Minted} and {IERC20-Transfer} events.
  255. *
  256. * Requirements
  257. *
  258. * - `account` cannot be the zero address.
  259. * - if `account` is a contract, it must implement the {IERC777Recipient}
  260. * interface.
  261. */
  262. function _mint(
  263. address account,
  264. uint256 amount,
  265. bytes memory userData,
  266. bytes memory operatorData
  267. )
  268. internal
  269. virtual
  270. {
  271. require(account != address(0), "ERC777: mint to the zero address");
  272. address operator = _msgSender();
  273. _beforeTokenTransfer(operator, address(0), account, amount);
  274. // Update state variables
  275. _totalSupply = _totalSupply + amount;
  276. _balances[account] = _balances[account] + amount;
  277. _callTokensReceived(operator, address(0), account, amount, userData, operatorData, true);
  278. emit Minted(operator, account, amount, userData, operatorData);
  279. emit Transfer(address(0), account, amount);
  280. }
  281. /**
  282. * @dev Send tokens
  283. * @param from address token holder address
  284. * @param to address recipient address
  285. * @param amount uint256 amount of tokens to transfer
  286. * @param userData bytes extra information provided by the token holder (if any)
  287. * @param operatorData bytes extra information provided by the operator (if any)
  288. * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
  289. */
  290. function _send(
  291. address from,
  292. address to,
  293. uint256 amount,
  294. bytes memory userData,
  295. bytes memory operatorData,
  296. bool requireReceptionAck
  297. )
  298. internal
  299. virtual
  300. {
  301. require(from != address(0), "ERC777: send from the zero address");
  302. require(to != address(0), "ERC777: send to the zero address");
  303. address operator = _msgSender();
  304. _callTokensToSend(operator, from, to, amount, userData, operatorData);
  305. _move(operator, from, to, amount, userData, operatorData);
  306. _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);
  307. }
  308. /**
  309. * @dev Burn tokens
  310. * @param from address token holder address
  311. * @param amount uint256 amount of tokens to burn
  312. * @param data bytes extra information provided by the token holder
  313. * @param operatorData bytes extra information provided by the operator (if any)
  314. */
  315. function _burn(
  316. address from,
  317. uint256 amount,
  318. bytes memory data,
  319. bytes memory operatorData
  320. )
  321. internal
  322. virtual
  323. {
  324. require(from != address(0), "ERC777: burn from the zero address");
  325. address operator = _msgSender();
  326. _callTokensToSend(operator, from, address(0), amount, data, operatorData);
  327. _beforeTokenTransfer(operator, from, address(0), amount);
  328. // Update state variables
  329. _balances[from] = _balances[from] - amount;
  330. _totalSupply = _totalSupply - amount;
  331. emit Burned(operator, from, amount, data, operatorData);
  332. emit Transfer(from, address(0), amount);
  333. }
  334. function _move(
  335. address operator,
  336. address from,
  337. address to,
  338. uint256 amount,
  339. bytes memory userData,
  340. bytes memory operatorData
  341. )
  342. private
  343. {
  344. _beforeTokenTransfer(operator, from, to, amount);
  345. _balances[from] = _balances[from] - amount;
  346. _balances[to] = _balances[to] + amount;
  347. emit Sent(operator, from, to, amount, userData, operatorData);
  348. emit Transfer(from, to, amount);
  349. }
  350. /**
  351. * @dev See {ERC20-_approve}.
  352. *
  353. * Note that accounts cannot have allowance issued by their operators.
  354. */
  355. function _approve(address holder, address spender, uint256 value) internal {
  356. require(holder != address(0), "ERC777: approve from the zero address");
  357. require(spender != address(0), "ERC777: approve to the zero address");
  358. _allowances[holder][spender] = value;
  359. emit Approval(holder, spender, value);
  360. }
  361. /**
  362. * @dev Call from.tokensToSend() if the interface is registered
  363. * @param operator address operator requesting the transfer
  364. * @param from address token holder address
  365. * @param to address recipient address
  366. * @param amount uint256 amount of tokens to transfer
  367. * @param userData bytes extra information provided by the token holder (if any)
  368. * @param operatorData bytes extra information provided by the operator (if any)
  369. */
  370. function _callTokensToSend(
  371. address operator,
  372. address from,
  373. address to,
  374. uint256 amount,
  375. bytes memory userData,
  376. bytes memory operatorData
  377. )
  378. private
  379. {
  380. address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(from, _TOKENS_SENDER_INTERFACE_HASH);
  381. if (implementer != address(0)) {
  382. IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
  383. }
  384. }
  385. /**
  386. * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
  387. * tokensReceived() was not registered for the recipient
  388. * @param operator address operator requesting the transfer
  389. * @param from address token holder address
  390. * @param to address recipient address
  391. * @param amount uint256 amount of tokens to transfer
  392. * @param userData bytes extra information provided by the token holder (if any)
  393. * @param operatorData bytes extra information provided by the operator (if any)
  394. * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
  395. */
  396. function _callTokensReceived(
  397. address operator,
  398. address from,
  399. address to,
  400. uint256 amount,
  401. bytes memory userData,
  402. bytes memory operatorData,
  403. bool requireReceptionAck
  404. )
  405. private
  406. {
  407. address implementer = _ERC1820_REGISTRY.getInterfaceImplementer(to, _TOKENS_RECIPIENT_INTERFACE_HASH);
  408. if (implementer != address(0)) {
  409. IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
  410. } else if (requireReceptionAck) {
  411. require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
  412. }
  413. }
  414. /**
  415. * @dev Hook that is called before any token transfer. This includes
  416. * calls to {send}, {transfer}, {operatorSend}, minting and burning.
  417. *
  418. * Calling conditions:
  419. *
  420. * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
  421. * will be to transferred to `to`.
  422. * - when `from` is zero, `amount` tokens will be minted for `to`.
  423. * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
  424. * - `from` and `to` are never both zero.
  425. *
  426. * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
  427. */
  428. function _beforeTokenTransfer(address operator, address from, address to, uint256 amount) internal virtual { }
  429. }