Skip to content

Commit 05f4095

Browse files
committed
fix: solve wrong response for account.verifyMessage
1 parent a074bde commit 05f4095

File tree

5 files changed

+88
-24
lines changed

5 files changed

+88
-24
lines changed

__tests__/account.test.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Contract,
55
DeclareDeployUDCResponse,
66
Provider,
7+
SignatureVerifResult,
78
TransactionType,
89
cairo,
910
constants,
@@ -397,7 +398,7 @@ describe('deploy and test Wallet', () => {
397398
expect(toBigInt(response.number as string).toString()).toStrictEqual('57');
398399
});
399400

400-
test('sign and verify offchain message fail', async () => {
401+
test('sign and verify EIP712 message fail', async () => {
401402
const signature = await account.signMessage(typedDataExample);
402403
const [r, s] = stark.formatSignature(signature);
403404

@@ -408,12 +409,32 @@ describe('deploy and test Wallet', () => {
408409

409410
if (!signature2) return;
410411

411-
expect(await account.verifyMessage(typedDataExample, signature2)).toBe(false);
412+
const verifMessageResponse: SignatureVerifResult = await account.verifyMessage(
413+
typedDataExample,
414+
signature2
415+
);
416+
expect(verifMessageResponse.isVerificationProcessed).toBe(true);
417+
expect(verifMessageResponse.isSignatureValid).toBe(false);
418+
419+
const wrongAccount = new Account(provider, '0x037891', '0x026789', undefined, TEST_TX_VERSION); // non existing account
420+
const verifMessageResponse2: SignatureVerifResult = await wrongAccount.verifyMessage(
421+
typedDataExample,
422+
signature2
423+
);
424+
expect(verifMessageResponse2.isVerificationProcessed).toBe(false);
425+
expect(verifMessageResponse2.error?.message).toContain(
426+
'Signature verification request is rejected by the network.'
427+
);
412428
});
413429

414-
test('sign and verify offchain message', async () => {
430+
test('sign and verify message', async () => {
415431
const signature = await account.signMessage(typedDataExample);
416-
expect(await account.verifyMessage(typedDataExample, signature)).toBe(true);
432+
const verifMessageResponse: SignatureVerifResult = await account.verifyMessage(
433+
typedDataExample,
434+
signature
435+
);
436+
expect(verifMessageResponse.isVerificationProcessed).toBe(true);
437+
expect(verifMessageResponse.isSignatureValid).toBe(true);
417438
});
418439

419440
describe('Contract interaction with Account', () => {

src/account/default.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
Nonce,
3333
ProviderOptions,
3434
Signature,
35+
SignatureVerifResult,
3536
SimulateTransactionDetails,
3637
SimulateTransactionResponse,
3738
TransactionType,
@@ -573,23 +574,59 @@ export class Account extends Provider implements AccountInterface {
573574
return getMessageHash(typedData, this.address);
574575
}
575576

576-
public async verifyMessageHash(hash: BigNumberish, signature: Signature): Promise<boolean> {
577+
public async verifyMessageHash(
578+
hash: BigNumberish,
579+
signature: Signature
580+
): Promise<SignatureVerifResult> {
577581
try {
578-
await this.callContract({
582+
const resp = await this.callContract({
579583
contractAddress: this.address,
580584
entrypoint: 'isValidSignature',
581585
calldata: CallData.compile({
582586
hash: toBigInt(hash).toString(),
583587
signature: formatSignature(signature),
584588
}),
585589
});
586-
return true;
587-
} catch {
588-
return false;
590+
// console.log('verifySign=', resp);
591+
if (BigInt(resp.result[0]) === 0n) {
592+
// OpenZeppelin 0.8.0 invalid signature
593+
return {
594+
isVerificationProcessed: true,
595+
isSignatureValid: false,
596+
} as SignatureVerifResult;
597+
}
598+
// OpenZeppelin 0.8.0, ArgentX 0.3.0 & Braavos Cairo 0 valid signature
599+
return {
600+
isVerificationProcessed: true,
601+
isSignatureValid: true,
602+
} as SignatureVerifResult;
603+
} catch (err) {
604+
// console.log('verifySign error=', err);
605+
if ((err as Error).message.includes('argent/invalid-signature')) {
606+
// ArgentX 0.3.0 invalid signature
607+
return {
608+
isVerificationProcessed: true,
609+
isSignatureValid: false,
610+
} as SignatureVerifResult;
611+
}
612+
if ((err as Error).message.includes('is invalid, with respect to the public key')) {
613+
// Braavos Cairo 0 invalid signature
614+
return {
615+
isVerificationProcessed: true,
616+
isSignatureValid: false,
617+
} as SignatureVerifResult;
618+
}
619+
return {
620+
isVerificationProcessed: false,
621+
error: new Error('Signature verification request is rejected by the network.'),
622+
} as SignatureVerifResult;
589623
}
590624
}
591625

592-
public async verifyMessage(typedData: TypedData, signature: Signature): Promise<boolean> {
626+
public async verifyMessage(
627+
typedData: TypedData,
628+
signature: Signature
629+
): Promise<SignatureVerifResult> {
593630
const hash = await this.hashMessage(typedData);
594631
return this.verifyMessageHash(hash, signature);
595632
}

src/account/interface.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
MultiDeployContractResponse,
2626
Nonce,
2727
Signature,
28+
SignatureVerifResult,
2829
SimulateTransactionDetails,
2930
SimulateTransactionResponse,
3031
TypedData,
@@ -356,7 +357,10 @@ export abstract class AccountInterface extends ProviderInterface {
356357
* @returns true if the signature is valid, false otherwise
357358
* @throws {Error} if the JSON object is not a valid JSON or the signature is not a valid signature
358359
*/
359-
public abstract verifyMessage(typedData: TypedData, signature: Signature): Promise<boolean>;
360+
public abstract verifyMessage(
361+
typedData: TypedData,
362+
signature: Signature
363+
): Promise<SignatureVerifResult>;
360364

361365
/**
362366
* Verify a signature of a given hash
@@ -367,7 +371,10 @@ export abstract class AccountInterface extends ProviderInterface {
367371
* @returns true if the signature is valid, false otherwise
368372
* @throws {Error} if the signature is not a valid signature
369373
*/
370-
public abstract verifyMessageHash(hash: BigNumberish, signature: Signature): Promise<boolean>;
374+
public abstract verifyMessageHash(
375+
hash: BigNumberish,
376+
signature: Signature
377+
): Promise<SignatureVerifResult>;
371378

372379
/**
373380
* Gets the nonce of the account with respect to a specific block

src/types/lib/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import { CompiledContract, CompiledSierraCasm, ContractClass } from './contract'
77
export type WeierstrassSignatureType = weierstrass.SignatureType;
88
export type ArraySignatureType = string[];
99
export type Signature = ArraySignatureType | WeierstrassSignatureType;
10+
export type SignatureVerifResult = {
11+
isVerificationProcessed: boolean;
12+
isSignatureValid?: boolean;
13+
error?: Error;
14+
};
1015

1116
export type BigNumberish = string | number | bigint;
1217

www/docs/guides/signature.md

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -174,17 +174,11 @@ const signature2 = await account.signMessage(typedDataValidate) as WeierstrassSi
174174
On the receiver side, you receive the JSON, the signature, and the account address. To verify the message:
175175

176176
```typescript
177-
const compiledAccount = json.parse(fs.readFileSync("./compiledContracts/Account_0_5_1.json").toString("ascii"));
178-
const contractAccount = new Contract(compiledAccount.abi, accountAddress, provider);
179-
180-
const msgHash5 = typedData.getMessageHash(typedDataValidate, accountAddress);
181-
// The call of isValidSignature will generate an error if not valid
182-
let result5: boolean;
183-
try {
184-
await contractAccount.isValidSignature(msgHash5, [signature2.r, signature2.s]);
185-
result5 = true;
186-
} catch {
187-
result5 = false;
177+
const myAccount = new Account(provider, accountAddress, "0x0123"); // fake private key
178+
const result = await myAccount.verifyMessage(typedMessage, signature);
179+
if (result.isVerificationProcessed) {
180+
console.log("Result (boolean) =", result.isSignatureValid);
181+
} else {
182+
console.log("verification failed :", result.error);
188183
}
189-
console.log("Result5 (boolean) =", result5);
190184
```

0 commit comments

Comments
 (0)