Argent
  • Build with Argent
  • Argent Wallets
    • Argent X
      • Adding Custom RPCs
      • Network Switcher for Dapps
      • Verify signature of undeployed account
      • WalletAccount
    • Argent Mobile
      • Argent Mobile for your web app
      • Argent Mobile for your react native app
    • Web Wallet
      • Set up guide
      • Web Wallet UX
      • API reference
      • Key Management
    • Argent Multisig
      • How multisig works
      • Create a multisig
        • With Argent signer
        • With Ledger signer
      • Join a multisig
        • With Argent signer
        • With Ledger signer
      • Replace a multisig signer
      • Airgap
    • Telegram wallet (DEPRECATED)
  • TOOLS
    • 🎨STARKNETKIT
    • ✨Invisible SDK
      • Implementation
      • Other useful endpoints
      • Types and interfaces
      • Gas abstraction
  • Example Dapps
    • StarknetKit + Session keys Demo dapp
  • AA Use Cases
    • Session Keys
      • Implement session keys
      • Session keys with outside execution
      • Demo App
      • FAQ
      • Types
    • Paymasters
    • Verifying signatures and cosigners
      • Identifying a smart account onchain
    • Multicalls
    • Outside Execution
    • Deploy accounts on behalf of users
  • Optimize your Dapp
    • Dappland
    • Known dapps
    • Transaction reviews
    • Brand your token
  • Other Products
    • Argent Card
    • Spoks
    • Perkz
    • Argent Vault on Ethereum L1
  • SUPPORT & RESSOURCES
    • Contracts and audits
    • Get in touch
Powered by GitBook
On this page
  • Signing
  • Verifying signatures
  • Guardians and co-signers
  • Verifying multi-signatures

Was this helpful?

  1. AA Use Cases

Verifying signatures and cosigners

Providing multi-signature verification support for dApps

PreviousPaymastersNextIdentifying a smart account onchain

Last updated 2 months ago

Was this helpful?

A good example can be found in this repo:

Signing

All the different Starknet libs give you the ability to sign messages from an account. Let's take or for example.

Most of the time, you will try to make your users sign a typed data message.

With starknet.js, you would do something like this:

const account = new Account(provider, address, pk);
const typedData: TypedData = {
    // your typed data
}
const sig = await account.signMessage(typedData);

With starknet-react's hook, it will look like that:

// declare hook
const { signTypedDataAsync } = useSignTypedData({
    // your typedData
})
// use hook
const doSomething = async () => {
    // rest of the code
    const signature = await signTypedDataAsync({
        // your typedData
    })
    // do something with sig
}

Verifying signatures

On-chain verification method 1 - Calling the contract

Argent account signatures can be verified by calling the isValidSignature or is_valid_signature method of the account contract:

const contractAccount = new Contract(abi, accountAddress, provider);
const msgHash = typedData.getMessageHash(data, accountAddress);
await contractAccount.isValidSignature(msgHash, [signature.r, signature.s])

Be aware that most of Argent's accounts will return more that one signature that should all be verified. See below.

Signature r and s are the the 4th and 5th member of the sig array so signature[3] and signature[4] .

On-chain verification method 2 - with Typed data

Most of the time, you will get your users to sign a typed data message following the SNIP-12 standard. There is an easy way to verify such a signature.

const provider = new RpcProvider({
  nodeUrl: rpcUrl
});
const isValidSig = await provider.verifyMessageInStarknet(
      typedData, // typed data json your user signed
      signature, // raw user sig, no need to filter r and s
      account // user address
    );

This method also accepts message hash instead of the full json.

Guardians and co-signers

A guardian is a trusted party, added by the user, that acts as a cosigner/co-validator for the user's account when carrying out typical wallet operations or for recovery purposes.

For most of Argent's products e.g Argent Mobile, Web Wallet, Smart Accounts in Argent X etc, the guardian is usually Argent's backend.

In the next section, let's take a look at how you can verify multi-signatures for accounts with an active guardian.

Verifying multi-signatures

From a dApp's end, explicit support has to be provided for verifying multi-signatures, or account owners with guardians will be unable to sign transactions.

The signature is verified by calling the isValidSignature or is_valid_signature() method. If the user has a guardian, the signature returned by the wallet will be longer and include more data.

0: number of signers (i.e. 2 in this example)

1: type of signer 1

2: pubkey 1

3: r1

4: s1

5: type of signer 2 (guardian)

6: pubkey 2 (guardian)

7: r2 (guardian)

8: s2 (guardian)

const contractAccount = new Contract(abi, accountAddress, provider);
const msgHash = typedData.getMessageHash(data, accountAddress);
await contractAccount.isValidSignature(msgHash, [signature1.r, signature1.s, signature2.r, signature2.s])

Different Starknet accounts or wallets might return different signatures. Only the signature verification with isValidSignature should be sent as a payload

You'll notice that a signature is an array of several numbers. If the account is a standard account, then the sig length will be 5 and if it's a smart-account, it will be 9 (because you have both the account and the guardian signatures). The members of the sig array are explained .

There are several ways of verifying a signature, on-chain or off-chain. Most of the time, you will use one of the on-chain methods. The starknet.js doc has an example of .

off-chain signatures
starknet.js
starknet-react
SNIP-12
off-chain verification
below