ERC777SenderRecipientMockUpgradeable.sol 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "../token/ERC777/IERC777Upgradeable.sol";
  4. import "../token/ERC777/IERC777SenderUpgradeable.sol";
  5. import "../token/ERC777/IERC777RecipientUpgradeable.sol";
  6. import "../utils/ContextUpgradeable.sol";
  7. import "../utils/introspection/IERC1820RegistryUpgradeable.sol";
  8. import "../utils/introspection/ERC1820ImplementerUpgradeable.sol";
  9. import "../proxy/utils/Initializable.sol";
  10. contract ERC777SenderRecipientMockUpgradeable is Initializable, ContextUpgradeable, IERC777SenderUpgradeable, IERC777RecipientUpgradeable, ERC1820ImplementerUpgradeable {
  11. function __ERC777SenderRecipientMock_init() internal onlyInitializing {
  12. __ERC777SenderRecipientMock_init_unchained();
  13. }
  14. function __ERC777SenderRecipientMock_init_unchained() internal onlyInitializing {
  15. _erc1820 = IERC1820RegistryUpgradeable(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
  16. }
  17. event TokensToSendCalled(
  18. address operator,
  19. address from,
  20. address to,
  21. uint256 amount,
  22. bytes data,
  23. bytes operatorData,
  24. address token,
  25. uint256 fromBalance,
  26. uint256 toBalance
  27. );
  28. event TokensReceivedCalled(
  29. address operator,
  30. address from,
  31. address to,
  32. uint256 amount,
  33. bytes data,
  34. bytes operatorData,
  35. address token,
  36. uint256 fromBalance,
  37. uint256 toBalance
  38. );
  39. // Emitted in ERC777Mock. Here for easier decoding
  40. event BeforeTokenTransfer();
  41. bool private _shouldRevertSend;
  42. bool private _shouldRevertReceive;
  43. IERC1820RegistryUpgradeable private _erc1820;
  44. bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
  45. bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
  46. function tokensToSend(
  47. address operator,
  48. address from,
  49. address to,
  50. uint256 amount,
  51. bytes calldata userData,
  52. bytes calldata operatorData
  53. ) external override {
  54. if (_shouldRevertSend) {
  55. revert();
  56. }
  57. IERC777Upgradeable token = IERC777Upgradeable(_msgSender());
  58. uint256 fromBalance = token.balanceOf(from);
  59. // when called due to burn, to will be the zero address, which will have a balance of 0
  60. uint256 toBalance = token.balanceOf(to);
  61. emit TokensToSendCalled(
  62. operator,
  63. from,
  64. to,
  65. amount,
  66. userData,
  67. operatorData,
  68. address(token),
  69. fromBalance,
  70. toBalance
  71. );
  72. }
  73. function tokensReceived(
  74. address operator,
  75. address from,
  76. address to,
  77. uint256 amount,
  78. bytes calldata userData,
  79. bytes calldata operatorData
  80. ) external override {
  81. if (_shouldRevertReceive) {
  82. revert();
  83. }
  84. IERC777Upgradeable token = IERC777Upgradeable(_msgSender());
  85. uint256 fromBalance = token.balanceOf(from);
  86. // when called due to burn, to will be the zero address, which will have a balance of 0
  87. uint256 toBalance = token.balanceOf(to);
  88. emit TokensReceivedCalled(
  89. operator,
  90. from,
  91. to,
  92. amount,
  93. userData,
  94. operatorData,
  95. address(token),
  96. fromBalance,
  97. toBalance
  98. );
  99. }
  100. function senderFor(address account) public {
  101. _registerInterfaceForAddress(_TOKENS_SENDER_INTERFACE_HASH, account);
  102. address self = address(this);
  103. if (account == self) {
  104. registerSender(self);
  105. }
  106. }
  107. function registerSender(address sender) public {
  108. _erc1820.setInterfaceImplementer(address(this), _TOKENS_SENDER_INTERFACE_HASH, sender);
  109. }
  110. function recipientFor(address account) public {
  111. _registerInterfaceForAddress(_TOKENS_RECIPIENT_INTERFACE_HASH, account);
  112. address self = address(this);
  113. if (account == self) {
  114. registerRecipient(self);
  115. }
  116. }
  117. function registerRecipient(address recipient) public {
  118. _erc1820.setInterfaceImplementer(address(this), _TOKENS_RECIPIENT_INTERFACE_HASH, recipient);
  119. }
  120. function setShouldRevertSend(bool shouldRevert) public {
  121. _shouldRevertSend = shouldRevert;
  122. }
  123. function setShouldRevertReceive(bool shouldRevert) public {
  124. _shouldRevertReceive = shouldRevert;
  125. }
  126. function send(
  127. IERC777Upgradeable token,
  128. address to,
  129. uint256 amount,
  130. bytes memory data
  131. ) public {
  132. // This is 777's send function, not the Solidity send function
  133. token.send(to, amount, data); // solhint-disable-line check-send-result
  134. }
  135. function burn(
  136. IERC777Upgradeable token,
  137. uint256 amount,
  138. bytes memory data
  139. ) public {
  140. token.burn(amount, data);
  141. }
  142. /**
  143. * This empty reserved space is put in place to allow future versions to add new
  144. * variables without shifting down storage in the inheritance chain.
  145. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
  146. */
  147. uint256[49] private __gap;
  148. }