draft-ERC7821.sol 2.6 KB

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