ERC777.sol 18 KB

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