SignatureChecker.sol 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (utils/cryptography/SignatureChecker.sol)
  3. pragma solidity ^0.8.0;
  4. import "./ECDSA.sol";
  5. import "../Address.sol";
  6. import "../../interfaces/IERC1271.sol";
  7. /**
  8. * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
  9. * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
  10. * Argent and Gnosis Safe.
  11. *
  12. * _Available since v4.1._
  13. */
  14. library SignatureChecker {
  15. /**
  16. * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
  17. * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
  18. *
  19. * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
  20. * change through time. It could return true at block N and false at block N+1 (or the opposite).
  21. */
  22. function isValidSignatureNow(
  23. address signer,
  24. bytes32 hash,
  25. bytes memory signature
  26. ) internal view returns (bool) {
  27. (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
  28. if (error == ECDSA.RecoverError.NoError && recovered == signer) {
  29. return true;
  30. }
  31. (bool success, bytes memory result) = signer.staticcall(
  32. abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
  33. );
  34. return (success &&
  35. result.length == 32 &&
  36. abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
  37. }
  38. }