How do you recover the sender of a signed transaction? #1267
Unanswered
marcellobardus
asked this question in
Q&A
Replies: 2 comments 4 replies
-
You are close, but keep in mind the transaction hash includes the signature, so it cannot be what is signed (you can't put the signature inside the hash to sign ;)). You need the transaction pre-image, which is what you get by serializing the transaction without the signature. Here is an example from some random transaction I just pulled off the network now. I've included lots of extra debugging information and console.log statements so you can see what is happening. :) (async function() {
// Example test case; I just plucked the most recent hash I saw on etherscan
const provider = ethers.getDefaultProvider();
const hash = "0x2769fa79d3a55fdb003461ad8b86bc2a85e6f28ecf9f64c3246a30677fbff35d";
const expectedFrom = "0xDA86793f4aa24C0716b657eeD899a73b9a12F937";
const tx = await provider.getTransaction(hash);
console.log(tx);
const baseTx = {
to: tx.to,
nonce: tx.nonce,
data: tx.data,
value: tx.value,
gasLimit: tx.gasLimit,
gasPrice: tx.gasPrice,
chainId: tx.chainId,
}
const sig = {
r: tx.r,
s: tx.s,
v: tx.v
};
///////////////////
// Here is what you need to do:
// serializeTransaction(tx [ , signature ])
// - If signature is unspecified, you get an unsigned tx
const unsignedTx = ethers.utils.serializeTransaction(baseTx);
console.log("Unsigned Tx:", unsignedTx);
// Unsigned Tx: 0xf86a818f851d1a94a20082becf94066798d9ef0833ccc719076dab77199ecbd178b080b844095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018080
// Get the transaction pre-image
const preimage = ethers.utils.keccak256(unsignedTx);
console.log("Preimage:", preimage);
// Preimage: 0x8342181a4b3dd526c10ac9d25b85bd896245199e386af170f6d7649b00174b3a
// ecrecover based on the signature and the **preimage**
const from = ethers.utils.recoverAddress(preimage, sig);
console.log({ from, expectedFrom });
// {
// from: '0xDA86793f4aa24C0716b657eeD899a73b9a12F937',
// expectedFrom: '0xDA86793f4aa24C0716b657eeD899a73b9a12F937'
// }
///////////////////
// As a note, here is how you would get the transaction hash:
const signedTx = ethers.utils.serializeTransaction(baseTx, sig);
console.log("Signed Tx:", signedTx);
// Signed Tx: 0xf8aa818f851d1a94a20082becf94066798d9ef0833ccc719076dab77199ecbd178b080b844095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff25a007cca508ee0c29e9e3402ef74bb611b8d8532d4682ac04f21fbf21171244208ba02cf161165f71d0de343f31a4666c29a2c804d3f18d8a7a276b8fb7d72477e1a8
const hashedSignedTransaction = ethers.utils.keccak256(signedTx);
console.log("Hash:", hashedSignedTransaction);
// Hash: 0x2769fa79d3a55fdb003461ad8b86bc2a85e6f28ecf9f64c3246a30677fbff35d
})(); Does that help? |
Beta Was this translation helpful? Give feedback.
1 reply
-
(moving to discussions) |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
When interacting with contracts Ethers includes
{ r, s, v }
in the transaction object.ex.
const tx = await erc20.connect(signer).approve(contractBAddress, MaxUint256.toString())
.Background.
I'm signing a transaction as shown above, then I serialize it using
serializeTransaction
previously resolving it's properties withresolveProperties
. Then I recover the signer address usingconst recovered = recoverAddress(tx.hash, { tx.v, tx.r, tx.s })
Problem.
Sadly the recovered address does not match the signer address.
I tried to do the same in a contract code below:
I'm getting the same result, I checked if maybe the transaction hash is not correct but it's the same as in the
tx
object.I was wondering that it may be an issue related to hardhat netid
31337
which may affect thev
param of the signature.But it's not a reproduced it on ganache and I'm getting the same effect.
Thanks in advance.
Beta Was this translation helpful? Give feedback.
All reactions