I am using ethers to get a signed request. I have a signature for the address 0x518171C334AD3adc1cF990A884D67963201B675F.

It is, c4b71f516c36468022d61b0e22016c6bc69bc2c99666fb7e63e3d04841c82ff53d5c687ebe43b290d03caa6766e8e957192faa6b360f4102b536c54c3318304f1b.

When I use ethers.js, to serialize my transaction with my signature I get a transaction which is something like 0xf86a808477359400825208943e245df5a4de41e65cecd1f98b96ca06c3d319f087470de4df8200008029a0c4b71f516c36468022d61b0e22016c6bc69bc2c99666fb7e63e3d04841c82ff5a03d5c687ebe43b290d03caa6766e8e957192faa6b360f4102b536c54c3318304f

As it is an ECDSA signature, it keeps on changing every time I generate it. And every time I try to decode the serialized transaction I get a different from address.

This means that there must be something wrong in how I am using the function. This is the code I am working with, with one of the signatures that I have generated (mentioned above)

const { utils } = require('ethers');
const bn = require('bignumber.js');
const { serializeTransaction, parseEther } = utils;
const tx2 = require('ethereumjs-tx');
async function serialize1() {
        const wei = parseEther('0.02');
        const gasPrice = '0x' + (2000000000).toString(16);
        const tx = {
                gasPrice: gasPrice,
                gasLimit: 21000,
                to: '0x3e245df5a4de41e65cecd1f98b96ca06c3d319f0',
                value: wei,
                nonce: 0,
                data: '',
                chainId: 3,
        const serializedTransaction = await serializeTransaction(tx);
        const signature = 'c4b71f516c36468022d61b0e22016c6bc69bc2c99666fb7e63e3d04841c82ff53d5c687ebe43b290d03caa6766e8e957192faa6b360f4102b536c54c3318304f1b';
        const signedSerialized = await serializeTransaction(tx, Buffer.from(signature, 'hex'));


When I decode this transaction, I get

  "nonce": 0,
  "gasPrice": 2000000000,
  "gasLimit": 21000,
  "to": "0x3e245df5a4de41e65cecd1f98b96ca06c3d319f0",
  "value": 20000000000000000,
  "data": "",
  "from": "0x0d67ffdd9b1d8858582d903bf0093e22b9da682e",
  "r": "c4b71f516c36468022d61b0e22016c6bc69bc2c99666fb7e63e3d04841c82ff5",
  "v": "29",
  "s": "3d5c687ebe43b290d03caa6766e8e957192faa6b360f4102b536c54c3318304f"

Which is clearly not the from address I want. Am I using the serialize function in the correct way? Is the encoding that I am sending the signature in correct? Any other way I can use this signature? Any other package? Any help will be greatly appreciated!!!


You don't sign a request with a signature, you sign a transaction. You cannot generate generic signatures to be associated to transactions later on, you need to have access the complete object you want to sign - the raw transaction in your case - before the process works correctly.

Each library and wallet has its own signing implementation. With ethers.js in particular, you can use the Signer object to sign a transaction. From the ethers.js official documentation:

signer.signTransaction( transactionRequest ) ⇒ Promise< string< DataHexString > >

Returns a Promise which resolves to the signed transaction of the transactionRequest. This method does not populate any missing fields.

Sub-classes must implement this, however they may throw if signing a transaction is not supported, which is common for security reasons in many clients.

Signer usually refers to an external wallet - i.e MetaMask - not controlled by your ÐApp.

If instead you control the wallet with your app - so not a ÐApp anymore ;) - below some examples of signing transactions and messages with ethers.js and a wallet. You can find them inside the Wallet official documentation also:

// Create a wallet instance from a mnemonic...
mnemonic = "announce room limb pattern dry unit scale effort smooth jazz weasel alcohol"
walletMnemonic = Wallet.fromMnemonic(mnemonic)

// ...or from a private key
walletPrivateKey = new Wallet(walletMnemonic.privateKey)

walletMnemonic.address === walletPrivateKey.address
// true

// The address as a Promise per the Signer API
// { Promise: '0x71CB05EE1b1F506fF321Da3dac38f25c0c9ce6E1' }

// A Wallet address is also available synchronously
// '0x71CB05EE1b1F506fF321Da3dac38f25c0c9ce6E1'

// The internal cryptographic components
// '0x1da6847600b0ee25e9ad9a52abbd786dd2502fa4005dd5af9310b7cc7a3b25db'
// '0x04b9e72dfd423bcf95b3801ac93f4392be5ff22143f9980eb78b3a860c4843bfd04829ae61cdba4b3b1978ac5fc64f5cc2f4350e35a108a9c9a92a81200a60cd64'

// The wallet mnemonic
// {
//   locale: 'en',
//   path: 'm/44\'/60\'/0\'/0/0',
//   phrase: 'announce room limb pattern dry unit scale effort smooth jazz weasel alcohol'
// }

// Note: A wallet created with a private key does not
//       have a mnemonic (the derivation prevents it)
// null

// Signing a message
walletMnemonic.signMessage("Hello World")
// { Promise: '0x14280e5885a19f60e536de50097e96e3738c7acae4e9e62d67272d794b8127d31c03d9cd59781d4ee31fb4e1b893bd9b020ec67dfa65cfb51e2bdadbb1de26d91c' }

tx = {
  to: "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
  value: utils.parseEther("1.0")

// Signing a transaction
// { Promise: '0xf865808080948ba1f109551bd432803012645ac136ddd64dba72880de0b6b3a7640000801ca0918e294306d177ab7bd664f5e141436563854ebe0a3e523b9690b4922bbb52b8a01181612cec9c431c4257a79b8c9f0c980a2c49bb5a0e6ac52949163eeb565dfc' }

// The connect method returns a new instance of the
// Wallet connected to a provider
wallet = walletMnemonic.connect(provider)

// Querying the network
// { Promise: { BigNumber: "42" } }
// { Promise: 0 }

// Sending ether

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.