Advertisement
Guest User

TestToken

a guest
Nov 12th, 2019
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.03 KB | None | 0 0
  1. /**
  2. *Submitted for verification at Etherscan.io on 2019-07-31
  3. */
  4.  
  5. // File: contracts\open-zeppelin-contracts\token\ERC777\IERC777.sol
  6.  
  7. pragma solidity ^0.5.0;
  8.  
  9. /**
  10. * @dev Interface of the ERC777Token standard as defined in the EIP.
  11. *
  12. * This contract uses the
  13. * [ERC1820 registry standard](https://eips.ethereum.org/EIPS/eip-1820) to let
  14. * token holders and recipients react to token movements by using setting implementers
  15. * for the associated interfaces in said registry. See `IERC1820Registry` and
  16. * `ERC1820Implementer`.
  17. */
  18. interface IERC777 {
  19. /**
  20. * @dev Returns the name of the token.
  21. */
  22. function name() external view returns (string memory);
  23.  
  24. /**
  25. * @dev Returns the symbol of the token, usually a shorter version of the
  26. * name.
  27. */
  28. function symbol() external view returns (string memory);
  29.  
  30. /**
  31. * @dev Returns the smallest part of the token that is not divisible. This
  32. * means all token operations (creation, movement and destruction) must have
  33. * amounts that are a multiple of this number.
  34. *
  35. * For most token contracts, this value will equal 1.
  36. */
  37. function granularity() external view returns (uint256);
  38.  
  39. /**
  40. * @dev Returns the amount of tokens in existence.
  41. */
  42. function totalSupply() external view returns (uint256);
  43.  
  44. /**
  45. * @dev Returns the amount of tokens owned by an account (`owner`).
  46. */
  47. function balanceOf(address owner) external view returns (uint256);
  48.  
  49. /**
  50. * @dev Moves `amount` tokens from the caller's account to `recipient`.
  51. *
  52. * If send or receive hooks are registered for the caller and `recipient`,
  53. * the corresponding functions will be called with `data` and empty
  54. * `operatorData`. See `IERC777Sender` and `IERC777Recipient`.
  55. *
  56. * Emits a `Sent` event.
  57. *
  58. * Requirements
  59. *
  60. * - the caller must have at least `amount` tokens.
  61. * - `recipient` cannot be the zero address.
  62. * - if `recipient` is a contract, it must implement the `tokensReceived`
  63. * interface.
  64. */
  65. function send(address recipient, uint256 amount, bytes calldata data) external;
  66.  
  67. /**
  68. * @dev Destroys `amount` tokens from the caller's account, reducing the
  69. * total supply.
  70. *
  71. * If a send hook is registered for the caller, the corresponding function
  72. * will be called with `data` and empty `operatorData`. See `IERC777Sender`.
  73. *
  74. * Emits a `Burned` event.
  75. *
  76. * Requirements
  77. *
  78. * - the caller must have at least `amount` tokens.
  79. */
  80. function burn(uint256 amount, bytes calldata data) external;
  81.  
  82. /**
  83. * @dev Returns true if an account is an operator of `tokenHolder`.
  84. * Operators can send and burn tokens on behalf of their owners. All
  85. * accounts are their own operator.
  86. *
  87. * See `operatorSend` and `operatorBurn`.
  88. */
  89. function isOperatorFor(address operator, address tokenHolder) external view returns (bool);
  90.  
  91. /**
  92. * @dev Make an account an operator of the caller.
  93. *
  94. * See `isOperatorFor`.
  95. *
  96. * Emits an `AuthorizedOperator` event.
  97. *
  98. * Requirements
  99. *
  100. * - `operator` cannot be calling address.
  101. */
  102. function authorizeOperator(address operator) external;
  103.  
  104. /**
  105. * @dev Make an account an operator of the caller.
  106. *
  107. * See `isOperatorFor` and `defaultOperators`.
  108. *
  109. * Emits a `RevokedOperator` event.
  110. *
  111. * Requirements
  112. *
  113. * - `operator` cannot be calling address.
  114. */
  115. function revokeOperator(address operator) external;
  116.  
  117. /**
  118. * @dev Returns the list of default operators. These accounts are operators
  119. * for all token holders, even if `authorizeOperator` was never called on
  120. * them.
  121. *
  122. * This list is immutable, but individual holders may revoke these via
  123. * `revokeOperator`, in which case `isOperatorFor` will return false.
  124. */
  125. function defaultOperators() external view returns (address[] memory);
  126.  
  127. /**
  128. * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
  129. * be an operator of `sender`.
  130. *
  131. * If send or receive hooks are registered for `sender` and `recipient`,
  132. * the corresponding functions will be called with `data` and
  133. * `operatorData`. See `IERC777Sender` and `IERC777Recipient`.
  134. *
  135. * Emits a `Sent` event.
  136. *
  137. * Requirements
  138. *
  139. * - `sender` cannot be the zero address.
  140. * - `sender` must have at least `amount` tokens.
  141. * - the caller must be an operator for `sender`.
  142. * - `recipient` cannot be the zero address.
  143. * - if `recipient` is a contract, it must implement the `tokensReceived`
  144. * interface.
  145. */
  146. function operatorSend(
  147. address sender,
  148. address recipient,
  149. uint256 amount,
  150. bytes calldata data,
  151. bytes calldata operatorData
  152. ) external;
  153.  
  154. /**
  155. * @dev Destoys `amount` tokens from `account`, reducing the total supply.
  156. * The caller must be an operator of `account`.
  157. *
  158. * If a send hook is registered for `account`, the corresponding function
  159. * will be called with `data` and `operatorData`. See `IERC777Sender`.
  160. *
  161. * Emits a `Burned` event.
  162. *
  163. * Requirements
  164. *
  165. * - `account` cannot be the zero address.
  166. * - `account` must have at least `amount` tokens.
  167. * - the caller must be an operator for `account`.
  168. */
  169. function operatorBurn(
  170. address account,
  171. uint256 amount,
  172. bytes calldata data,
  173. bytes calldata operatorData
  174. ) external;
  175.  
  176. event Sent(
  177. address indexed operator,
  178. address indexed from,
  179. address indexed to,
  180. uint256 amount,
  181. bytes data,
  182. bytes operatorData
  183. );
  184.  
  185. event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
  186.  
  187. event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
  188.  
  189. event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
  190.  
  191. event RevokedOperator(address indexed operator, address indexed tokenHolder);
  192. }
  193.  
  194. // File: contracts\open-zeppelin-contracts\token\ERC777\IERC777Recipient.sol
  195.  
  196. pragma solidity ^0.5.0;
  197.  
  198. /**
  199. * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
  200. *
  201. * Accounts can be notified of `IERC777` tokens being sent to them by having a
  202. * contract implement this interface (contract holders can be their own
  203. * implementer) and registering it on the
  204. * [ERC1820 global registry](https://eips.ethereum.org/EIPS/eip-1820).
  205. *
  206. * See `IERC1820Registry` and `ERC1820Implementer`.
  207. */
  208. interface IERC777Recipient {
  209. /**
  210. * @dev Called by an `IERC777` token contract whenever tokens are being
  211. * moved or created into a registered account (`to`). The type of operation
  212. * is conveyed by `from` being the zero address or not.
  213. *
  214. * This call occurs _after_ the token contract's state is updated, so
  215. * `IERC777.balanceOf`, etc., can be used to query the post-operation state.
  216. *
  217. * This function may revert to prevent the operation from being executed.
  218. */
  219. function tokensReceived(
  220. address operator,
  221. address from,
  222. address to,
  223. uint256 amount,
  224. bytes calldata userData,
  225. bytes calldata operatorData
  226. ) external;
  227. }
  228.  
  229. // File: contracts\open-zeppelin-contracts\token\ERC777\IERC777Sender.sol
  230.  
  231. pragma solidity ^0.5.0;
  232.  
  233. /**
  234. * @dev Interface of the ERC777TokensSender standard as defined in the EIP.
  235. *
  236. * `IERC777` Token holders can be notified of operations performed on their
  237. * tokens by having a contract implement this interface (contract holders can be
  238. * their own implementer) and registering it on the
  239. * [ERC1820 global registry](https://eips.ethereum.org/EIPS/eip-1820).
  240. *
  241. * See `IERC1820Registry` and `ERC1820Implementer`.
  242. */
  243. interface IERC777Sender {
  244. /**
  245. * @dev Called by an `IERC777` token contract whenever a registered holder's
  246. * (`from`) tokens are about to be moved or destroyed. The type of operation
  247. * is conveyed by `to` being the zero address or not.
  248. *
  249. * This call occurs _before_ the token contract's state is updated, so
  250. * `IERC777.balanceOf`, etc., can be used to query the pre-operation state.
  251. *
  252. * This function may revert to prevent the operation from being executed.
  253. */
  254. function tokensToSend(
  255. address operator,
  256. address from,
  257. address to,
  258. uint256 amount,
  259. bytes calldata userData,
  260. bytes calldata operatorData
  261. ) external;
  262. }
  263.  
  264. // File: contracts\open-zeppelin-contracts\token\ERC20\IERC20.sol
  265.  
  266. pragma solidity ^0.5.0;
  267.  
  268. /**
  269. * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
  270. * the optional functions; to access them see `ERC20Detailed`.
  271. */
  272. interface IERC20 {
  273. /**
  274. * @dev Returns the amount of tokens in existence.
  275. */
  276. function totalSupply() external view returns (uint256);
  277.  
  278. /**
  279. * @dev Returns the amount of tokens owned by `account`.
  280. */
  281. function balanceOf(address account) external view returns (uint256);
  282.  
  283. /**
  284. * @dev Moves `amount` tokens from the caller's account to `recipient`.
  285. *
  286. * Returns a boolean value indicating whether the operation succeeded.
  287. *
  288. * Emits a `Transfer` event.
  289. */
  290. function transfer(address recipient, uint256 amount) external returns (bool);
  291.  
  292. /**
  293. * @dev Returns the remaining number of tokens that `spender` will be
  294. * allowed to spend on behalf of `owner` through `transferFrom`. This is
  295. * zero by default.
  296. *
  297. * This value changes when `approve` or `transferFrom` are called.
  298. */
  299. function allowance(address owner, address spender) external view returns (uint256);
  300.  
  301. /**
  302. * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
  303. *
  304. * Returns a boolean value indicating whether the operation succeeded.
  305. *
  306. * > Beware that changing an allowance with this method brings the risk
  307. * that someone may use both the old and the new allowance by unfortunate
  308. * transaction ordering. One possible solution to mitigate this race
  309. * condition is to first reduce the spender's allowance to 0 and set the
  310. * desired value afterwards:
  311. * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
  312. *
  313. * Emits an `Approval` event.
  314. */
  315. function approve(address spender, uint256 amount) external returns (bool);
  316.  
  317. /**
  318. * @dev Moves `amount` tokens from `sender` to `recipient` using the
  319. * allowance mechanism. `amount` is then deducted from the caller's
  320. * allowance.
  321. *
  322. * Returns a boolean value indicating whether the operation succeeded.
  323. *
  324. * Emits a `Transfer` event.
  325. */
  326. function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
  327.  
  328. /**
  329. * @dev Emitted when `value` tokens are moved from one account (`from`) to
  330. * another (`to`).
  331. *
  332. * Note that `value` may be zero.
  333. */
  334. event Transfer(address indexed from, address indexed to, uint256 value);
  335.  
  336. /**
  337. * @dev Emitted when the allowance of a `spender` for an `owner` is set by
  338. * a call to `approve`. `value` is the new allowance.
  339. */
  340. event Approval(address indexed owner, address indexed spender, uint256 value);
  341. }
  342.  
  343. // File: contracts\open-zeppelin-contracts\math\SafeMath.sol
  344.  
  345. pragma solidity ^0.5.0;
  346.  
  347. /**
  348. * @dev Wrappers over Solidity's arithmetic operations with added overflow
  349. * checks.
  350. *
  351. * Arithmetic operations in Solidity wrap on overflow. This can easily result
  352. * in bugs, because programmers usually assume that an overflow raises an
  353. * error, which is the standard behavior in high level programming languages.
  354. * `SafeMath` restores this intuition by reverting the transaction when an
  355. * operation overflows.
  356. *
  357. * Using this library instead of the unchecked operations eliminates an entire
  358. * class of bugs, so it's recommended to use it always.
  359. */
  360. library SafeMath {
  361. /**
  362. * @dev Returns the addition of two unsigned integers, reverting on
  363. * overflow.
  364. *
  365. * Counterpart to Solidity's `+` operator.
  366. *
  367. * Requirements:
  368. * - Addition cannot overflow.
  369. */
  370. function add(uint256 a, uint256 b) internal pure returns (uint256) {
  371. uint256 c = a + b;
  372. require(c >= a, "SafeMath: addition overflow");
  373.  
  374. return c;
  375. }
  376.  
  377. /**
  378. * @dev Returns the subtraction of two unsigned integers, reverting on
  379. * overflow (when the result is negative).
  380. *
  381. * Counterpart to Solidity's `-` operator.
  382. *
  383. * Requirements:
  384. * - Subtraction cannot overflow.
  385. */
  386. function sub(uint256 a, uint256 b) internal pure returns (uint256) {
  387. require(b <= a, "SafeMath: subtraction overflow");
  388. uint256 c = a - b;
  389.  
  390. return c;
  391. }
  392.  
  393. /**
  394. * @dev Returns the multiplication of two unsigned integers, reverting on
  395. * overflow.
  396. *
  397. * Counterpart to Solidity's `*` operator.
  398. *
  399. * Requirements:
  400. * - Multiplication cannot overflow.
  401. */
  402. function mul(uint256 a, uint256 b) internal pure returns (uint256) {
  403. // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
  404. // benefit is lost if 'b' is also tested.
  405. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
  406. if (a == 0) {
  407. return 0;
  408. }
  409.  
  410. uint256 c = a * b;
  411. require(c / a == b, "SafeMath: multiplication overflow");
  412.  
  413. return c;
  414. }
  415.  
  416. /**
  417. * @dev Returns the integer division of two unsigned integers. Reverts on
  418. * division by zero. The result is rounded towards zero.
  419. *
  420. * Counterpart to Solidity's `/` operator. Note: this function uses a
  421. * `revert` opcode (which leaves remaining gas untouched) while Solidity
  422. * uses an invalid opcode to revert (consuming all remaining gas).
  423. *
  424. * Requirements:
  425. * - The divisor cannot be zero.
  426. */
  427. function div(uint256 a, uint256 b) internal pure returns (uint256) {
  428. // Solidity only automatically asserts when dividing by 0
  429. require(b > 0, "SafeMath: division by zero");
  430. uint256 c = a / b;
  431. // assert(a == b * c + a % b); // There is no case in which this doesn't hold
  432.  
  433. return c;
  434. }
  435.  
  436. /**
  437. * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
  438. * Reverts when dividing by zero.
  439. *
  440. * Counterpart to Solidity's `%` operator. This function uses a `revert`
  441. * opcode (which leaves remaining gas untouched) while Solidity uses an
  442. * invalid opcode to revert (consuming all remaining gas).
  443. *
  444. * Requirements:
  445. * - The divisor cannot be zero.
  446. */
  447. function mod(uint256 a, uint256 b) internal pure returns (uint256) {
  448. require(b != 0, "SafeMath: modulo by zero");
  449. return a % b;
  450. }
  451. }
  452.  
  453. // File: contracts\open-zeppelin-contracts\utils\Address.sol
  454.  
  455. pragma solidity ^0.5.0;
  456.  
  457. /**
  458. * @dev Collection of functions related to the address type
  459. */
  460. library Address {
  461. /**
  462. * @dev Returns true if `account` is a contract.
  463. *
  464. * This test is non-exhaustive, and there may be false-negatives: during the
  465. * execution of a contract's constructor, its address will be reported as
  466. * not containing a contract.
  467. *
  468. * > It is unsafe to assume that an address for which this function returns
  469. * false is an externally-owned account (EOA) and not a contract.
  470. */
  471. function isContract(address account) internal view returns (bool) {
  472. // This method relies in extcodesize, which returns 0 for contracts in
  473. // construction, since the code is only stored at the end of the
  474. // constructor execution.
  475.  
  476. // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
  477. // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
  478. // for accounts without code, i.e. `keccak256('')`
  479. bytes32 codehash;
  480. bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
  481. // solhint-disable-next-line no-inline-assembly
  482. assembly { codehash := extcodehash(account) }
  483. return (codehash != 0x0 && codehash != accountHash);
  484. }
  485.  
  486. /**
  487. * @dev Converts an `address` into `address payable`. Note that this is
  488. * simply a type cast: the actual underlying value is not changed.
  489. */
  490. function toPayable(address account) internal pure returns (address payable) {
  491. return address(uint160(account));
  492. }
  493. }
  494.  
  495. // File: contracts\open-zeppelin-contracts\introspection\IERC1820Registry.sol
  496.  
  497. pragma solidity ^0.5.0;
  498.  
  499. /**
  500. * @dev Interface of the global ERC1820 Registry, as defined in the
  501. * [EIP](https://eips.ethereum.org/EIPS/eip-1820). Accounts may register
  502. * implementers for interfaces in this registry, as well as query support.
  503. *
  504. * Implementers may be shared by multiple accounts, and can also implement more
  505. * than a single interface for each account. Contracts can implement interfaces
  506. * for themselves, but externally-owned accounts (EOA) must delegate this to a
  507. * contract.
  508. *
  509. * `IERC165` interfaces can also be queried via the registry.
  510. *
  511. * For an in-depth explanation and source code analysis, see the EIP text.
  512. */
  513. interface IERC1820Registry {
  514. /**
  515. * @dev Sets `newManager` as the manager for `account`. A manager of an
  516. * account is able to set interface implementers for it.
  517. *
  518. * By default, each account is its own manager. Passing a value of `0x0` in
  519. * `newManager` will reset the manager to this initial state.
  520. *
  521. * Emits a `ManagerChanged` event.
  522. *
  523. * Requirements:
  524. *
  525. * - the caller must be the current manager for `account`.
  526. */
  527. function setManager(address account, address newManager) external;
  528.  
  529. /**
  530. * @dev Returns the manager for `account`.
  531. *
  532. * See `setManager`.
  533. */
  534. function getManager(address account) external view returns (address);
  535.  
  536. /**
  537. * @dev Sets the `implementer` contract as `account`'s implementer for
  538. * `interfaceHash`.
  539. *
  540. * `account` being the zero address is an alias for the caller's address.
  541. * The zero address can also be used in `implementer` to remove an old one.
  542. *
  543. * See `interfaceHash` to learn how these are created.
  544. *
  545. * Emits an `InterfaceImplementerSet` event.
  546. *
  547. * Requirements:
  548. *
  549. * - the caller must be the current manager for `account`.
  550. * - `interfaceHash` must not be an `IERC165` interface id (i.e. it must not
  551. * end in 28 zeroes).
  552. * - `implementer` must implement `IERC1820Implementer` and return true when
  553. * queried for support, unless `implementer` is the caller. See
  554. * `IERC1820Implementer.canImplementInterfaceForAddress`.
  555. */
  556. function setInterfaceImplementer(address account, bytes32 interfaceHash, address implementer) external;
  557.  
  558. /**
  559. * @dev Returns the implementer of `interfaceHash` for `account`. If no such
  560. * implementer is registered, returns the zero address.
  561. *
  562. * If `interfaceHash` is an `IERC165` interface id (i.e. it ends with 28
  563. * zeroes), `account` will be queried for support of it.
  564. *
  565. * `account` being the zero address is an alias for the caller's address.
  566. */
  567. function getInterfaceImplementer(address account, bytes32 interfaceHash) external view returns (address);
  568.  
  569. /**
  570. * @dev Returns the interface hash for an `interfaceName`, as defined in the
  571. * corresponding
  572. * [section of the EIP](https://eips.ethereum.org/EIPS/eip-1820#interface-name).
  573. */
  574. function interfaceHash(string calldata interfaceName) external pure returns (bytes32);
  575.  
  576. /**
  577. * @notice Updates the cache with whether the contract implements an ERC165 interface or not.
  578. * @param account Address of the contract for which to update the cache.
  579. * @param interfaceId ERC165 interface for which to update the cache.
  580. */
  581. function updateERC165Cache(address account, bytes4 interfaceId) external;
  582.  
  583. /**
  584. * @notice Checks whether a contract implements an ERC165 interface or not.
  585. * If the result is not cached a direct lookup on the contract address is performed.
  586. * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
  587. * 'updateERC165Cache' with the contract address.
  588. * @param account Address of the contract to check.
  589. * @param interfaceId ERC165 interface to check.
  590. * @return True if `account.address()` implements `interfaceId`, false otherwise.
  591. */
  592. function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);
  593.  
  594. /**
  595. * @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
  596. * @param account Address of the contract to check.
  597. * @param interfaceId ERC165 interface to check.
  598. * @return True if `account.address()` implements `interfaceId`, false otherwise.
  599. */
  600. function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
  601.  
  602. event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
  603.  
  604. event ManagerChanged(address indexed account, address indexed newManager);
  605. }
  606.  
  607. // File: contracts\open-zeppelin-contracts\token\ERC777\ERC777.sol
  608.  
  609. pragma solidity ^0.5.0;
  610.  
  611.  
  612. /**
  613. * @dev Implementation of the `IERC777` interface.
  614. *
  615. * This implementation is agnostic to the way tokens are created. This means
  616. * that a supply mechanism has to be added in a derived contract using `_mint`.
  617. *
  618. * Support for ERC20 is included in this contract, as specified by the EIP: both
  619. * the ERC777 and ERC20 interfaces can be safely used when interacting with it.
  620. * Both `IERC777.Sent` and `IERC20.Transfer` events are emitted on token
  621. * movements.
  622. *
  623. * Additionally, the `granularity` value is hard-coded to `1`, meaning that there
  624. * are no special restrictions in the amount of tokens that created, moved, or
  625. * destroyed. This makes integration with ERC20 applications seamless.
  626. */
  627. contract ERC777 is IERC777, IERC20 {
  628. using SafeMath for uint256;
  629. using Address for address;
  630.  
  631. IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
  632.  
  633. mapping(address => uint256) private _balances;
  634.  
  635. uint256 private _totalSupply;
  636.  
  637. string private _name;
  638. string private _symbol;
  639.  
  640. // We inline the result of the following hashes because Solidity doesn't resolve them at compile time.
  641. // See https://github.com/ethereum/solidity/issues/4024
  642.  
  643. // keccak256("ERC777TokensSender")
  644. bytes32 constant private TOKENS_SENDER_INTERFACE_HASH =
  645. 0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895;
  646.  
  647. // keccak256("ERC777TokensRecipient")
  648. bytes32 constant private TOKENS_RECIPIENT_INTERFACE_HASH =
  649. 0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b;
  650.  
  651. // This isn't ever read from - it's only used to respond to the defaultOperators query.
  652. address[] private _defaultOperatorsArray;
  653.  
  654. // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
  655. mapping(address => bool) private _defaultOperators;
  656.  
  657. // For each account, a mapping of its operators and revoked default operators.
  658. mapping(address => mapping(address => bool)) private _operators;
  659. mapping(address => mapping(address => bool)) private _revokedDefaultOperators;
  660.  
  661. // ERC20-allowances
  662. mapping (address => mapping (address => uint256)) private _allowances;
  663.  
  664. /**
  665. * @dev `defaultOperators` may be an empty array.
  666. */
  667. constructor(
  668. string memory name,
  669. string memory symbol,
  670. address[] memory defaultOperators
  671. ) public {
  672. _name = name;
  673. _symbol = symbol;
  674.  
  675. _defaultOperatorsArray = defaultOperators;
  676. for (uint256 i = 0; i < _defaultOperatorsArray.length; i++) {
  677. _defaultOperators[_defaultOperatorsArray[i]] = true;
  678. }
  679.  
  680. // register interfaces
  681. _erc1820.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
  682. _erc1820.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
  683. }
  684.  
  685. /**
  686. * @dev See `IERC777.name`.
  687. */
  688. function name() public view returns (string memory) {
  689. return _name;
  690. }
  691.  
  692. /**
  693. * @dev See `IERC777.symbol`.
  694. */
  695. function symbol() public view returns (string memory) {
  696. return _symbol;
  697. }
  698.  
  699. /**
  700. * @dev See `ERC20Detailed.decimals`.
  701. *
  702. * Always returns 18, as per the
  703. * [ERC777 EIP](https://eips.ethereum.org/EIPS/eip-777#backward-compatibility).
  704. */
  705. function decimals() public pure returns (uint8) {
  706. return 18;
  707. }
  708.  
  709. /**
  710. * @dev See `IERC777.granularity`.
  711. *
  712. * This implementation always returns `1`.
  713. */
  714. function granularity() public view returns (uint256) {
  715. return 1;
  716. }
  717.  
  718. /**
  719. * @dev See `IERC777.totalSupply`.
  720. */
  721. function totalSupply() public view returns (uint256) {
  722. return _totalSupply;
  723. }
  724.  
  725. /**
  726. * @dev Returns the amount of tokens owned by an account (`tokenHolder`).
  727. */
  728. function balanceOf(address tokenHolder) public view returns (uint256) {
  729. return _balances[tokenHolder];
  730. }
  731.  
  732. /**
  733. * @dev See `IERC777.send`.
  734. *
  735. * Also emits a `Transfer` event for ERC20 compatibility.
  736. */
  737. function send(address recipient, uint256 amount, bytes calldata data) external {
  738. _send(msg.sender, msg.sender, recipient, amount, data, "", true);
  739. }
  740.  
  741. /**
  742. * @dev See `IERC20.transfer`.
  743. *
  744. * Unlike `send`, `recipient` is _not_ required to implement the `tokensReceived`
  745. * interface if it is a contract.
  746. *
  747. * Also emits a `Sent` event.
  748. */
  749. function transfer(address recipient, uint256 amount) external returns (bool) {
  750. require(recipient != address(0), "ERC777: transfer to the zero address");
  751.  
  752. address from = msg.sender;
  753.  
  754. _callTokensToSend(from, from, recipient, amount, "", "");
  755.  
  756. _move(from, from, recipient, amount, "", "");
  757.  
  758. _callTokensReceived(from, from, recipient, amount, "", "", false);
  759.  
  760. return true;
  761. }
  762.  
  763. /**
  764. * @dev See `IERC777.burn`.
  765. *
  766. * Also emits a `Transfer` event for ERC20 compatibility.
  767. */
  768. function burn(uint256 amount, bytes calldata data) external {
  769. _burn(msg.sender, msg.sender, amount, data, "");
  770. }
  771.  
  772. /**
  773. * @dev See `IERC777.isOperatorFor`.
  774. */
  775. function isOperatorFor(
  776. address operator,
  777. address tokenHolder
  778. ) public view returns (bool) {
  779. return operator == tokenHolder ||
  780. (_defaultOperators[operator] && !_revokedDefaultOperators[tokenHolder][operator]) ||
  781. _operators[tokenHolder][operator];
  782. }
  783.  
  784. /**
  785. * @dev See `IERC777.authorizeOperator`.
  786. */
  787. function authorizeOperator(address operator) external {
  788. require(msg.sender != operator, "ERC777: authorizing self as operator");
  789.  
  790. if (_defaultOperators[operator]) {
  791. delete _revokedDefaultOperators[msg.sender][operator];
  792. } else {
  793. _operators[msg.sender][operator] = true;
  794. }
  795.  
  796. emit AuthorizedOperator(operator, msg.sender);
  797. }
  798.  
  799. /**
  800. * @dev See `IERC777.revokeOperator`.
  801. */
  802. function revokeOperator(address operator) external {
  803. require(operator != msg.sender, "ERC777: revoking self as operator");
  804.  
  805. if (_defaultOperators[operator]) {
  806. _revokedDefaultOperators[msg.sender][operator] = true;
  807. } else {
  808. delete _operators[msg.sender][operator];
  809. }
  810.  
  811. emit RevokedOperator(operator, msg.sender);
  812. }
  813.  
  814. /**
  815. * @dev See `IERC777.defaultOperators`.
  816. */
  817. function defaultOperators() public view returns (address[] memory) {
  818. return _defaultOperatorsArray;
  819. }
  820.  
  821. /**
  822. * @dev See `IERC777.operatorSend`.
  823. *
  824. * Emits `Sent` and `Transfer` events.
  825. */
  826. function operatorSend(
  827. address sender,
  828. address recipient,
  829. uint256 amount,
  830. bytes calldata data,
  831. bytes calldata operatorData
  832. )
  833. external
  834. {
  835. require(isOperatorFor(msg.sender, sender), "ERC777: caller is not an operator for holder");
  836. _send(msg.sender, sender, recipient, amount, data, operatorData, true);
  837. }
  838.  
  839. /**
  840. * @dev See `IERC777.operatorBurn`.
  841. *
  842. * Emits `Burned` and `Transfer` events.
  843. */
  844. function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external {
  845. require(isOperatorFor(msg.sender, account), "ERC777: caller is not an operator for holder");
  846. _burn(msg.sender, account, amount, data, operatorData);
  847. }
  848.  
  849. /**
  850. * @dev See `IERC20.allowance`.
  851. *
  852. * Note that operator and allowance concepts are orthogonal: operators may
  853. * not have allowance, and accounts with allowance may not be operators
  854. * themselves.
  855. */
  856. function allowance(address holder, address spender) public view returns (uint256) {
  857. return _allowances[holder][spender];
  858. }
  859.  
  860. /**
  861. * @dev See `IERC20.approve`.
  862. *
  863. * Note that accounts cannot have allowance issued by their operators.
  864. */
  865. function approve(address spender, uint256 value) external returns (bool) {
  866. address holder = msg.sender;
  867. _approve(holder, spender, value);
  868. return true;
  869. }
  870.  
  871. /**
  872. * @dev See `IERC20.transferFrom`.
  873. *
  874. * Note that operator and allowance concepts are orthogonal: operators cannot
  875. * call `transferFrom` (unless they have allowance), and accounts with
  876. * allowance cannot call `operatorSend` (unless they are operators).
  877. *
  878. * Emits `Sent`, `Transfer` and `Approval` events.
  879. */
  880. function transferFrom(address holder, address recipient, uint256 amount) external returns (bool) {
  881. require(recipient != address(0), "ERC777: transfer to the zero address");
  882. require(holder != address(0), "ERC777: transfer from the zero address");
  883.  
  884. address spender = msg.sender;
  885.  
  886. _callTokensToSend(spender, holder, recipient, amount, "", "");
  887.  
  888. _move(spender, holder, recipient, amount, "", "");
  889. _approve(holder, spender, _allowances[holder][spender].sub(amount));
  890.  
  891. _callTokensReceived(spender, holder, recipient, amount, "", "", false);
  892.  
  893. return true;
  894. }
  895.  
  896. /**
  897. * @dev Creates `amount` tokens and assigns them to `account`, increasing
  898. * the total supply.
  899. *
  900. * If a send hook is registered for `account`, the corresponding function
  901. * will be called with `operator`, `data` and `operatorData`.
  902. *
  903. * See `IERC777Sender` and `IERC777Recipient`.
  904. *
  905. * Emits `Minted` and `Transfer` events.
  906. *
  907. * Requirements
  908. *
  909. * - `account` cannot be the zero address.
  910. * - if `account` is a contract, it must implement the `tokensReceived`
  911. * interface.
  912. */
  913. function _mint(
  914. address operator,
  915. address account,
  916. uint256 amount,
  917. bytes memory userData,
  918. bytes memory operatorData
  919. )
  920. internal
  921. {
  922. require(account != address(0), "ERC777: mint to the zero address");
  923.  
  924. // Update state variables
  925. _totalSupply = _totalSupply.add(amount);
  926. _balances[account] = _balances[account].add(amount);
  927.  
  928. _callTokensReceived(operator, address(0), account, amount, userData, operatorData, true);
  929.  
  930. emit Minted(operator, account, amount, userData, operatorData);
  931. emit Transfer(address(0), account, amount);
  932. }
  933.  
  934. /**
  935. * @dev Send tokens
  936. * @param operator address operator requesting the transfer
  937. * @param from address token holder address
  938. * @param to address recipient address
  939. * @param amount uint256 amount of tokens to transfer
  940. * @param userData bytes extra information provided by the token holder (if any)
  941. * @param operatorData bytes extra information provided by the operator (if any)
  942. * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
  943. */
  944. function _send(
  945. address operator,
  946. address from,
  947. address to,
  948. uint256 amount,
  949. bytes memory userData,
  950. bytes memory operatorData,
  951. bool requireReceptionAck
  952. )
  953. private
  954. {
  955. require(from != address(0), "ERC777: send from the zero address");
  956. require(to != address(0), "ERC777: send to the zero address");
  957.  
  958. _callTokensToSend(operator, from, to, amount, userData, operatorData);
  959.  
  960. _move(operator, from, to, amount, userData, operatorData);
  961.  
  962. _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck);
  963. }
  964.  
  965. /**
  966. * @dev Burn tokens
  967. * @param operator address operator requesting the operation
  968. * @param from address token holder address
  969. * @param amount uint256 amount of tokens to burn
  970. * @param data bytes extra information provided by the token holder
  971. * @param operatorData bytes extra information provided by the operator (if any)
  972. */
  973. function _burn(
  974. address operator,
  975. address from,
  976. uint256 amount,
  977. bytes memory data,
  978. bytes memory operatorData
  979. )
  980. private
  981. {
  982. require(from != address(0), "ERC777: burn from the zero address");
  983.  
  984. _callTokensToSend(operator, from, address(0), amount, data, operatorData);
  985.  
  986. // Update state variables
  987. _totalSupply = _totalSupply.sub(amount);
  988. _balances[from] = _balances[from].sub(amount);
  989.  
  990. emit Burned(operator, from, amount, data, operatorData);
  991. emit Transfer(from, address(0), amount);
  992. }
  993.  
  994. function _move(
  995. address operator,
  996. address from,
  997. address to,
  998. uint256 amount,
  999. bytes memory userData,
  1000. bytes memory operatorData
  1001. )
  1002. private
  1003. {
  1004. _balances[from] = _balances[from].sub(amount);
  1005. _balances[to] = _balances[to].add(amount);
  1006.  
  1007. emit Sent(operator, from, to, amount, userData, operatorData);
  1008. emit Transfer(from, to, amount);
  1009. }
  1010.  
  1011. function _approve(address holder, address spender, uint256 value) private {
  1012. // TODO: restore this require statement if this function becomes internal, or is called at a new callsite. It is
  1013. // currently unnecessary.
  1014. //require(holder != address(0), "ERC777: approve from the zero address");
  1015. require(spender != address(0), "ERC777: approve to the zero address");
  1016.  
  1017. _allowances[holder][spender] = value;
  1018. emit Approval(holder, spender, value);
  1019. }
  1020.  
  1021. /**
  1022. * @dev Call from.tokensToSend() if the interface is registered
  1023. * @param operator address operator requesting the transfer
  1024. * @param from address token holder address
  1025. * @param to address recipient address
  1026. * @param amount uint256 amount of tokens to transfer
  1027. * @param userData bytes extra information provided by the token holder (if any)
  1028. * @param operatorData bytes extra information provided by the operator (if any)
  1029. */
  1030. function _callTokensToSend(
  1031. address operator,
  1032. address from,
  1033. address to,
  1034. uint256 amount,
  1035. bytes memory userData,
  1036. bytes memory operatorData
  1037. )
  1038. private
  1039. {
  1040. address implementer = _erc1820.getInterfaceImplementer(from, TOKENS_SENDER_INTERFACE_HASH);
  1041. if (implementer != address(0)) {
  1042. IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData);
  1043. }
  1044. }
  1045.  
  1046. /**
  1047. * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but
  1048. * tokensReceived() was not registered for the recipient
  1049. * @param operator address operator requesting the transfer
  1050. * @param from address token holder address
  1051. * @param to address recipient address
  1052. * @param amount uint256 amount of tokens to transfer
  1053. * @param userData bytes extra information provided by the token holder (if any)
  1054. * @param operatorData bytes extra information provided by the operator (if any)
  1055. * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient
  1056. */
  1057. function _callTokensReceived(
  1058. address operator,
  1059. address from,
  1060. address to,
  1061. uint256 amount,
  1062. bytes memory userData,
  1063. bytes memory operatorData,
  1064. bool requireReceptionAck
  1065. )
  1066. private
  1067. {
  1068. address implementer = _erc1820.getInterfaceImplementer(to, TOKENS_RECIPIENT_INTERFACE_HASH);
  1069. if (implementer != address(0)) {
  1070. IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData);
  1071. } else if (requireReceptionAck) {
  1072. require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient");
  1073. }
  1074. }
  1075. }
  1076.  
  1077. // File: contracts\ERC777\TestToken.sol
  1078.  
  1079. pragma solidity ^0.5.0;
  1080.  
  1081.  
  1082. contract TestToken is ERC777 {
  1083.  
  1084. constructor(
  1085. string memory name,
  1086. string memory symbol,
  1087. address[] memory defaultOperators,
  1088. uint256 totalSupply
  1089. )
  1090. public payable
  1091. ERC777(name, symbol, defaultOperators)
  1092. {
  1093. // mint new tokens to address that deploys contract
  1094. _mint(msg.sender, msg.sender, totalSupply, "", "");
  1095. }
  1096. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement