metamask-mobile icon indicating copy to clipboard operation
metamask-mobile copied to clipboard

[Bug]: Unexpected characters in signature message

Open Garchbold opened this issue 1 year ago • 0 comments

Describe the bug

When trying to deposit at https://bag.win, the site triggers a metatransaction, but the metamask signature is displaying concerning unfamiliar characters.

Expected behavior

It should show a regular metamask signature.

Screenshots/Recordings

image (61)

img_0559

Steps to reproduce

  1. Go to https://bag.win
  2. Connect Wallet
  3. Sign the message
  4. Go to Balance
  5. Try to deposit USDT

Error messages or log output

No response

Version

11.7.5

Build type

None

Device

Apple iPhone 13 Pro Max

Operating system

iOS

Additional context

Source Code:

function executeMetaTransactionWithSignature(
  userAddress: string,
  signature: string,
  tokenContract: Contract,
  functionSignature: string,
  gasLimit?: number,
) {
  return new Promise(async (resolve, reject) => {
    logger.log('User address:', userAddress);
    logger.log('Signature:', signature);
    logger.log('Token contract:', tokenContract);
    logger.log('Function signature:', functionSignature);

    try {      
      if (!signature)
        throw new Error("Signature failed."); 

      let { r, s, v } = getSignatureParameters(signature);

      let tx = await tokenContract.executeMetaTransaction(
        userAddress,
        functionSignature,
        r,
        s,
        v,
        (gasLimit ? {gasLimit: gasLimit} : {})
      );

      logger.log('Transaction hash:', tx.hash);
      await tx.wait(1);
      logger.log('Transaction successfully confirmed');
      resolve(tx.hash);
    } catch (error: any) {
      logger.log('Execute Meta-Transactions failed:', error);
      reject(false);
    }
  });
}



const getSignatureParameters = (signature: string) => {
  if (!ethers.utils.isHexString(signature)) {
    throw new Error(
      'Given value "'.concat(signature, '" is not a valid hex string.')
    );
  }
  const r = signature.slice(0, 66);
  const s = '0x'.concat(signature.slice(66, 130));
  let vString = '0x'.concat(signature.slice(130, 132));
  let v = ethers.BigNumber.from(vString).toNumber();
  if (![27, 28].includes(v)) v += 27;
  return {
    r: r,
    s: s,
    v: v,
  };
};


function executeMetaTransaction(i: number, functionSignature: any, contractInstance: any, userAddress: string, web3Default: Web3, domainData: any = null) {
  return new Promise(async (resolve, reject) => {
    let domainType = {};
    if (domainData === null) {
      domainData = arrayDomainData[i];
      domainType = arrayDomainType[i];
    } else {
      domainType = domainTypeToken;
    }

    console.log('Execute Biconomy PoS meta-transaction: ' + i);
    console.log('Function signature: ' + functionSignature);
    console.log('User address: ' + userAddress);
    console.log('Verify contract: ' + domainData.verifyingContract);

    try {
      // console.log('contract instance...');
      // console.log(contractInstance);

      console.log('nonce: ')
      let nonce = await contractInstance.methods.getNonce(userAddress).call();
      console.log('noncex: ', nonce)

      let message: any = {};
      message.nonce = parseInt(nonce);
      message.from = userAddress;
      message.functionSignature = functionSignature;

      const dataToSign = JSON.stringify({
        types: {
          EIP712Domain: domainType,
          MetaTransaction: metaTransactionType
        },
        domain: domainData,
        primaryType: 'MetaTransaction',
        message: message
      });

      console.log('Domain data: ', Object.keys(domainData));
      console.log('Web3Provider Info: ', Object.keys(web3Default), web3Default.eth, web3Default.eth.currentProvider);

      if(web3Default.eth.currentProvider) {
        const provider: any = web3Default.eth.currentProvider;

        console.log(provider);

        const signedResponse = await provider.sendAsync(
          {
            jsonrpc: '2.0',
            id: 999999999999,
            method: 'eth_signTypedData_v4',
            params: [userAddress, dataToSign],
            fromAddress: userAddress
          },

          async (error: any, response: any) => {
            executeMetaTx(response, dataToSign, functionSignature, contractInstance, userAddress, web3Default, resolve, reject);
          }
        );
        console.log('Signed Response: ', signedResponse);
        if (signedResponse) executeMetaTx(signedResponse, dataToSign, functionSignature, contractInstance, userAddress, web3Default, resolve, reject);
      }
    } catch (error) {
      console.log('Execute Meta-Transactions failed: ', error);
      reject(false);
    }
  });
}

async function executeMetaTx(signedResponse: any, dataToSign: string, functionSignature: any, contractInstance: any, userAddress: string, web3Default: Web3, resolve: any, reject: any) {
  try {
    let { r, s, v } = getSignatureParameters(signedResponse && signedResponse.hasOwnProperty('result') ? signedResponse.result : signedResponse);

    const recovered = sigUtil.recoverTypedSignature_v4({
      data: JSON.parse(dataToSign),
      sig: signedResponse.hasOwnProperty('result') ? signedResponse.result : signedResponse
    });
    console.log('User signature: ' + signedResponse.hasOwnProperty('result') ? signedResponse.result : signedResponse);
    console.log('Recovered address: ' + recovered);
    console.log('r: ' + r);
    console.log('s: ' + s);
    console.log('v: ' + v);
    const ret = await contractInstance.methods.executeMetaTransaction(userAddress, functionSignature, r, s, v).send({
      from: userAddress
    });

    console.log('Execute Meta-Transactions done');
    console.log(ret);
    resolve(ret.transactionHash);
  } catch (error) {
    console.log('Execute Meta-Transactions failed: ', error);
    reject(false);
  }
}

Severity

No response

Garchbold avatar Feb 21 '24 19:02 Garchbold