draft-ERC7821.sol 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.20;
  3. import {ERC7579Utils, Mode, CallType, ExecType, ModeSelector} from "../utils/draft-ERC7579Utils.sol";
  4. import {IERC7821} from "../../interfaces/draft-IERC7821.sol";
  5. import {Account} from "../Account.sol";
  6. /**
  7. * @dev Minimal batch executor following ERC-7821.
  8. *
  9. * Only supports supports single batch mode (`0x01000000000000000000`). Does not support optional "opData".
  10. *
  11. * @custom:stateless
  12. */
  13. abstract contract ERC7821 is IERC7821 {
  14. using ERC7579Utils for *;
  15. error UnsupportedExecutionMode();
  16. /**
  17. * @dev Executes the calls in `executionData` with no optional `opData` support.
  18. *
  19. * NOTE: Access to this function is controlled by {_erc7821AuthorizedExecutor}. Changing access permissions, for
  20. * example to approve calls by the ERC-4337 entrypoint, should be implemented by overriding it.
  21. *
  22. * Reverts and bubbles up error if any call fails.
  23. */
  24. function execute(bytes32 mode, bytes calldata executionData) public payable virtual {
  25. if (!_erc7821AuthorizedExecutor(msg.sender, mode, executionData))
  26. revert Account.AccountUnauthorized(msg.sender);
  27. if (!supportsExecutionMode(mode)) revert UnsupportedExecutionMode();
  28. executionData.execBatch(ERC7579Utils.EXECTYPE_DEFAULT);
  29. }
  30. /// @inheritdoc IERC7821
  31. function supportsExecutionMode(bytes32 mode) public view virtual returns (bool result) {
  32. (CallType callType, ExecType execType, ModeSelector modeSelector, ) = Mode.wrap(mode).decodeMode();
  33. return
  34. callType == ERC7579Utils.CALLTYPE_BATCH &&
  35. execType == ERC7579Utils.EXECTYPE_DEFAULT &&
  36. modeSelector == ModeSelector.wrap(0x00000000);
  37. }
  38. /**
  39. * @dev Access control mechanism for the {execute} function.
  40. * By default, only the contract itself is allowed to execute.
  41. *
  42. * Override this function to implement custom access control, for example to allow the
  43. * ERC-4337 entrypoint to execute.
  44. *
  45. * ```solidity
  46. * function _erc7821AuthorizedExecutor(
  47. * address caller,
  48. * bytes32 mode,
  49. * bytes calldata executionData
  50. * ) internal view virtual override returns (bool) {
  51. * return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
  52. * }
  53. * ```
  54. */
  55. function _erc7821AuthorizedExecutor(
  56. address caller,
  57. bytes32 /* mode */,
  58. bytes calldata /* executionData */
  59. ) internal view virtual returns (bool) {
  60. return caller == address(this);
  61. }
  62. }