From f22eee883b7416c316a42a6fb7010ba02da468b1 Mon Sep 17 00:00:00 2001 From: Sidnym Ladrut Date: Wed, 29 Jan 2025 21:43:01 +0000 Subject: [PATCH] Add legacy EIP-1271 support (i.e. 'isValidSigner(bytes,bytes)') --- src/AccountV3.sol | 24 ++++++++++++++++++++++++ src/abstract/Signatory.sol | 21 +++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/AccountV3.sol b/src/AccountV3.sol index 9522cc3..e4fa198 100644 --- a/src/AccountV3.sol +++ b/src/AccountV3.sol @@ -216,6 +216,30 @@ contract AccountV3 is return _isValidSigner(signer, ""); } + /** + * Determines if a given data and signature are valid for this account + * @param data Data payload of signed data + * @param signature ECDSA signature or encoded contract signature (v=0) + */ + function _isValidSignature(bytes calldata data, bytes calldata signature) + internal + view + virtual + override(Signatory) + returns (bool) + { + bytes32 hash = keccak256(data); + bytes32 digest; + // Adds EIP-191 signature prefix to hashed data + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ea736bd45bd844d7968a64c5707d97710fe1c077/contracts/utils/cryptography/MessageHashUtils.sol#L30 + assembly ("memory-safe") { + mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of hash + mstore(0x1c, hash) // 0x1c (28) is the length of the prefix + digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) + } + return _isValidSignature(digest, signature); + } + /** * @notice Returns whether a given account is authorized to execute transactions on behalf of * this account diff --git a/src/abstract/Signatory.sol b/src/abstract/Signatory.sol index bcd5705..0cf5d51 100644 --- a/src/abstract/Signatory.sol +++ b/src/abstract/Signatory.sol @@ -28,4 +28,25 @@ abstract contract Signatory is IERC1271 { view virtual returns (bool); + + /** + * @dev See {IERC1721-isValidSignature} + */ + function isValidSignature(bytes calldata data, bytes calldata signature) + external + view + returns (bytes4 magicValue) + { + if (_isValidSignature(data, signature)) { + return bytes4(keccak256(bytes("isValidSignature(bytes,bytes)"))); + } + + return bytes4(0); + } + + function _isValidSignature(bytes calldata data, bytes calldata signature) + internal + view + virtual + returns (bool); }