ERC777.sol 17 KB

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