Skip to content

Commit e447c4e

Browse files
committed
ECDSA verifiers: use eip-191
1 parent 3ed7afe commit e447c4e

7 files changed

Lines changed: 17 additions & 11 deletions

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ All contracts are deployed deterministically with the following addresses.
1212
| ---------------------------- | -------------------------------------------- |
1313
| Keystore | `0x69C9F626b5Bd934C0F9806346682eD407FB978d3` |
1414
| KeystoreAccountFactory | `0x625cF8EDec3f68d48D3aA385F356524B04760BE8` |
15-
| UserOpECDSAVerifier | `0x294CD71960eed5AEa11DbbFa5D3c8eA4A1c1CE0F` |
16-
| UserOpMultiSigVerifier | `0x1dBadE1E34706f83598ae9acFC63B7F4f928146E` |
15+
| UserOpECDSAVerifier | `0x52949503fF5c34caEa4FC98F0723ebD0c300f232` |
16+
| UserOpMultiSigVerifier | `0x0ad936Ee17E2d1c5038A038151Da7c5F963384b8` |
1717
| UserOpWebAuthnVerifier | `0xE19620169A26aEbC4Fe229A073639da6b009bF1a` |
18-
| UserOpWebAuthnCosignVerifier | `0x7CD0D83C0c33AAC9cef88c75F3EDec80F4175252` |
18+
| UserOpWebAuthnCosignVerifier | `0x939C10DCdA11A73eCCc563340aBE3d257859dC6d` |
1919

2020
## Usage
2121

src/verifier/UserOpECDSAVerifier.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ contract UserOpECDSAVerifier is IVerifier, OnlyKeystore {
3838
signature = userOp.signature;
3939
}
4040

41-
return address(bytes20(config)) == ECDSA.recover(message, signature)
41+
return address(bytes20(config)) == ECDSA.recover(ECDSA.toEthSignedMessageHash(message), signature)
4242
? SIG_VALIDATION_SUCCESS
4343
: SIG_VALIDATION_FAILED;
4444
}

src/verifier/UserOpMultiSigVerifier.sol

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ contract UserOpMultiSigVerifier is IVerifier, OnlyKeystore {
7272
SignerData memory sd = signatures[i];
7373

7474
// Note: we need to ensure gas usage is consistent during simulation with dummy signers.
75-
!seen[sd.index] && owners[sd.index] == ECDSA.recover(message, sd.signature) ? valid++ : invalid++;
75+
!seen[sd.index] && owners[sd.index] == _ecdsaRecover(message, sd.signature) ? valid++ : invalid++;
7676
seen[sd.index] = true;
7777
}
7878

@@ -94,4 +94,8 @@ contract UserOpMultiSigVerifier is IVerifier, OnlyKeystore {
9494
require(owners[i] > owners[i - 1], OwnersUnsortedOrHasDuplicates());
9595
}
9696
}
97+
98+
function _ecdsaRecover(bytes32 message, bytes memory signature) internal view returns (address) {
99+
return ECDSA.recover(ECDSA.toEthSignedMessageHash(message), signature);
100+
}
97101
}

src/verifier/UserOpWebAuthnCosignVerifier.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ contract UserOpWebAuthnCosignVerifier is IVerifier, OnlyKeystore {
6363

6464
// Note: always run verification for both signatures in order to calculate accurate gas
6565
// estimates during simulation with dummy signers.
66-
bool cosignValid = cosigner == ECDSA.recover(message, ecdsaSignature);
66+
bool cosignValid = cosigner == ECDSA.recover(ECDSA.toEthSignedMessageHash(message), ecdsaSignature);
6767
bool webauthnValid = WebAuthn.verify(abi.encode(message), true, auth, x, y);
6868
return (cosignValid && webauthnValid) ? SIG_VALIDATION_SUCCESS : SIG_VALIDATION_FAILED;
6969
}

test/verifier/UserOpECDSAVerifier.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ contract UserOpECDSAVerifierTest is Test {
1919
function testFuzz_validateData(bool withUserOp) public {
2020
(address signer, uint256 signerPK) = makeAddrAndKey("signer");
2121
bytes32 message = keccak256("Signed by signer");
22-
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPK, message);
22+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPK, ECDSA.toEthSignedMessageHash(message));
2323

2424
bytes memory data = abi.encodePacked(r, s, v);
2525
if (withUserOp) {
@@ -35,7 +35,7 @@ contract UserOpECDSAVerifierTest is Test {
3535
function testFuzz_validateDataValidationFailed(bool withUserOp, address config) public {
3636
(, uint256 signerPK) = makeAddrAndKey("signer");
3737
bytes32 message = keccak256("Signed by signer");
38-
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPK, message);
38+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPK, ECDSA.toEthSignedMessageHash(message));
3939

4040
bytes memory data = abi.encodePacked(r, s, v);
4141
if (withUserOp) {

test/verifier/UserOpMultiSigVerifier.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ contract UserOpMultiSigVerifierTest is Test {
210210

211211
Signer[] memory signers = _createSigners(1);
212212
bytes32 message = keccak256("Signed by signer");
213-
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[0].pk, message);
213+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[0].pk, ECDSA.toEthSignedMessageHash(message));
214214
bytes memory signature = abi.encodePacked(r, s, v);
215215

216216
uint16 count = uint16(type(uint8).max) + excess;
@@ -307,7 +307,7 @@ contract UserOpMultiSigVerifierTest is Test {
307307
UserOpMultiSigVerifier.SignerData[] memory sd = new UserOpMultiSigVerifier.SignerData[](threshold);
308308
for (uint8 i = 0; i < threshold; i++) {
309309
uint16 index = uint16(i) + offset;
310-
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[index].pk, message);
310+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[index].pk, ECDSA.toEthSignedMessageHash(message));
311311
sd[i] = UserOpMultiSigVerifier.SignerData({
312312
// Note: index will overflow back to 0 after max uint8.
313313
// This is ok since an InvalidNumberOfOwners() error is expected.

test/verifier/UserOpWebAuthnCosignVerifier.t.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {SIG_VALIDATION_FAILED, SIG_VALIDATION_SUCCESS} from "account-abstraction
77
import {PackedUserOperation} from "account-abstraction/interfaces/PackedUserOperation.sol";
88
import {Test} from "forge-std/Test.sol";
99
import {Base64} from "solady/utils/Base64.sol";
10+
import {ECDSA} from "solady/utils/ECDSA.sol";
1011
import {LibString} from "solady/utils/LibString.sol";
1112
import {P256} from "solady/utils/P256.sol";
1213
import {WebAuthn} from "solady/utils/WebAuthn.sol";
@@ -116,7 +117,8 @@ contract UserOpWebAuthnCosignVerifierTest is Test {
116117
pure
117118
returns (bytes memory signature)
118119
{
119-
(uint8 cosignerV, bytes32 cosignerR, bytes32 cosignerS) = vm.sign(cosignerPrivateKey, message);
120+
(uint8 cosignerV, bytes32 cosignerR, bytes32 cosignerS) =
121+
vm.sign(cosignerPrivateKey, ECDSA.toEthSignedMessageHash(message));
120122

121123
string memory clientDataJSON =
122124
clientDataJSONPre.concat(Base64.encode(abi.encode(message), true, true)).concat(clientDataJSONPost);

0 commit comments

Comments
 (0)