ERC777.sol 19 KB

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