draft-AccountECDSA.sol 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.20;
  3. import {PackedUserOperation} from "../interfaces/draft-IERC4337.sol";
  4. import {ERC4337Utils} from "../account/utils/draft-ERC4337Utils.sol";
  5. import {ERC721Holder} from "../token/ERC721/utils/ERC721Holder.sol";
  6. // import {ERC1155HolderLean, IERC1155Receiver} from "../token/ERC1155/utils/ERC1155HolderLean.sol";
  7. import {ERC1155Holder, IERC1155Receiver} from "../token/ERC1155/utils/ERC1155Holder.sol";
  8. import {ERC165} from "../utils/introspection/ERC165.sol";
  9. import {IERC165} from "../utils/introspection/IERC165.sol";
  10. import {ECDSA} from "../utils/cryptography/ECDSA.sol";
  11. import {MessageHashUtils} from "../utils/cryptography/MessageHashUtils.sol";
  12. import {AccountBase} from "./draft-AccountBase.sol";
  13. import {ERC7739Signer, EIP712} from "../utils/cryptography/draft-ERC7739Signer.sol";
  14. import {Initializable} from "../proxy/utils/Initializable.sol";
  15. /**
  16. * @dev Account implementation using {ECDSA} signatures and {ERC7739Signer} for replay protection.
  17. *
  18. * An {_initializeSigner} function is provided to set the account's signer address. Doing so it's
  19. * easier for a factory, whose likely to use initializable clones of this contract.
  20. *
  21. * IMPORTANT: Avoiding to call {_initializeSigner} either during construction (if used standalone)
  22. * or during initialization (if used as a clone) may leave the account unusable.
  23. */
  24. abstract contract AccountECDSA is ERC165, ERC721Holder, ERC1155Holder, ERC7739Signer, AccountBase {
  25. using MessageHashUtils for bytes32;
  26. /**
  27. * @dev The {signer} is already initialized.
  28. */
  29. error AccountECDSAUninitializedSigner(address signer);
  30. address private _signer;
  31. /**
  32. * @dev Initializes the account with the address of the native signer. This function is called only once.
  33. */
  34. function _initializeSigner(address signerAddr) internal {
  35. if (_signer != address(0)) revert AccountECDSAUninitializedSigner(signerAddr);
  36. _signer = signerAddr;
  37. }
  38. /**
  39. * @dev Return the account's signer address.
  40. */
  41. function signer() public view virtual returns (address) {
  42. return _signer;
  43. }
  44. /**
  45. * @dev Returns the ERC-191 signed `userOpHash` hashed with keccak256 using `personal_sign`.
  46. */
  47. function _userOpSignedHash(
  48. PackedUserOperation calldata /* userOp */,
  49. bytes32 userOpHash
  50. ) internal view virtual override returns (bytes32) {
  51. return userOpHash.toEthSignedMessageHash();
  52. }
  53. /**
  54. * @dev Internal version of {validateUserOp} that relies on {_validateSignature}.
  55. *
  56. * The `userOpSignedHash` is the digest from {_userOpSignedHash}.
  57. *
  58. * NOTE: To override the signature functionality, try overriding {_validateSignature} instead.
  59. */
  60. function _validateUserOp(
  61. PackedUserOperation calldata userOp,
  62. bytes32 userOpSignedHash
  63. ) internal view virtual override returns (uint256) {
  64. return
  65. _isValidSignature(userOpSignedHash, userOp.signature)
  66. ? ERC4337Utils.SIG_VALIDATION_SUCCESS
  67. : ERC4337Utils.SIG_VALIDATION_FAILED;
  68. }
  69. /**
  70. * @dev Validates the signature using the account's signer.
  71. *
  72. * This function provides a nested EIP-712 hash. Developers must override only this
  73. * function to ensure no raw message signing is possible.
  74. */
  75. function _validateSignature(
  76. bytes32 nestedEIP712Hash,
  77. bytes calldata signature
  78. ) internal view virtual override returns (bool) {
  79. (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(nestedEIP712Hash, signature);
  80. return signer() == recovered && err == ECDSA.RecoverError.NoError;
  81. }
  82. /// @inheritdoc ERC165
  83. function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, ERC1155Holder) returns (bool) {
  84. return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
  85. }
  86. }