ERC777SenderRecipientMock.sol 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "../../token/ERC777/IERC777.sol";
  4. import "../../token/ERC777/IERC777Sender.sol";
  5. import "../../token/ERC777/IERC777Recipient.sol";
  6. import "../../utils/Context.sol";
  7. import "../../utils/introspection/IERC1820Registry.sol";
  8. import "../../utils/introspection/ERC1820Implementer.sol";
  9. contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient, ERC1820Implementer {
  10. event TokensToSendCalled(
  11. address operator,
  12. address from,
  13. address to,
  14. uint256 amount,
  15. bytes data,
  16. bytes operatorData,
  17. address token,
  18. uint256 fromBalance,
  19. uint256 toBalance
  20. );
  21. event TokensReceivedCalled(
  22. address operator,
  23. address from,
  24. address to,
  25. uint256 amount,
  26. bytes data,
  27. bytes operatorData,
  28. address token,
  29. uint256 fromBalance,
  30. uint256 toBalance
  31. );
  32. // Emitted in ERC777Mock. Here for easier decoding
  33. event BeforeTokenTransfer();
  34. bool private _shouldRevertSend;
  35. bool private _shouldRevertReceive;
  36. IERC1820Registry private _erc1820 = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
  37. bytes32 private constant _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender");
  38. bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient");
  39. function tokensToSend(
  40. address operator,
  41. address from,
  42. address to,
  43. uint256 amount,
  44. bytes calldata userData,
  45. bytes calldata operatorData
  46. ) external override {
  47. if (_shouldRevertSend) {
  48. revert();
  49. }
  50. IERC777 token = IERC777(_msgSender());
  51. uint256 fromBalance = token.balanceOf(from);
  52. // when called due to burn, to will be the zero address, which will have a balance of 0
  53. uint256 toBalance = token.balanceOf(to);
  54. emit TokensToSendCalled(
  55. operator,
  56. from,
  57. to,
  58. amount,
  59. userData,
  60. operatorData,
  61. address(token),
  62. fromBalance,
  63. toBalance
  64. );
  65. }
  66. function tokensReceived(
  67. address operator,
  68. address from,
  69. address to,
  70. uint256 amount,
  71. bytes calldata userData,
  72. bytes calldata operatorData
  73. ) external override {
  74. if (_shouldRevertReceive) {
  75. revert();
  76. }
  77. IERC777 token = IERC777(_msgSender());
  78. uint256 fromBalance = token.balanceOf(from);
  79. // when called due to burn, to will be the zero address, which will have a balance of 0
  80. uint256 toBalance = token.balanceOf(to);
  81. emit TokensReceivedCalled(
  82. operator,
  83. from,
  84. to,
  85. amount,
  86. userData,
  87. operatorData,
  88. address(token),
  89. fromBalance,
  90. toBalance
  91. );
  92. }
  93. function senderFor(address account) public {
  94. _registerInterfaceForAddress(_TOKENS_SENDER_INTERFACE_HASH, account);
  95. address self = address(this);
  96. if (account == self) {
  97. registerSender(self);
  98. }
  99. }
  100. function registerSender(address sender) public {
  101. _erc1820.setInterfaceImplementer(address(this), _TOKENS_SENDER_INTERFACE_HASH, sender);
  102. }
  103. function recipientFor(address account) public {
  104. _registerInterfaceForAddress(_TOKENS_RECIPIENT_INTERFACE_HASH, account);
  105. address self = address(this);
  106. if (account == self) {
  107. registerRecipient(self);
  108. }
  109. }
  110. function registerRecipient(address recipient) public {
  111. _erc1820.setInterfaceImplementer(address(this), _TOKENS_RECIPIENT_INTERFACE_HASH, recipient);
  112. }
  113. function setShouldRevertSend(bool shouldRevert) public {
  114. _shouldRevertSend = shouldRevert;
  115. }
  116. function setShouldRevertReceive(bool shouldRevert) public {
  117. _shouldRevertReceive = shouldRevert;
  118. }
  119. function send(IERC777 token, address to, uint256 amount, bytes memory data) public {
  120. // This is 777's send function, not the Solidity send function
  121. token.send(to, amount, data); // solhint-disable-line check-send-result
  122. }
  123. function burn(IERC777 token, uint256 amount, bytes memory data) public {
  124. token.burn(amount, data);
  125. }
  126. }