There's a smart contract that I'm interacting with via ethers.js which has a function withdraw(uint8 v, bytes32 r, bytes32 s)
that withdraws funds stored in the contract to the caller's account and where the v
, r
, and s
arguments are ECDSA values which are used to verify the caller's address msg.sender
. How, using ethers.js, do I obtain these arguments to pass to this function? I have an ethers.js wallet object generated from the account's private key but don't know how to go from wallet
to v
, r
, and s
.
2 Answers
The v
, r
and s
params are parts of a signature after signing a message.
So first, you'll need to know what message you need to sign. Since it's verified in the contract, you should be able to find the desired message by inspecting the contract source code.
Then you can use the Ethers signMessage()
function (docs) to sign the message with your private key. You get a 65byte Raw Signature
(docs) as a result, which you can pass to the splitSignature()
function (docs) to get the v
, r
and s
params of the Signature
object (docs).

- 40,554
- 8
- 72
- 100
-
Thanks for your response though I'm not sure I understand entirely. To reiterate, I want to call `withdraw(v, r, s)` and to do that I need the `v`, `r`, and `s` arguments. As I understand your response, I need to create a transaction object `tx = { to: ..., data: ..., etc }` where `to` is the address of `contract.withdraw` and `data` are data about the `withdraw` function. Then, I call `signTransaction` and pass that result to `splitSignature` which yields `v`, `r`, and `s`. Then I can call `withdraw` via `await contract.withdraw(v, r, s)`. Is that correct and how do I create the `tx` object? – icosceles Jan 29 '22 at 01:27
-
Not `signTransaction` but `signMessage`... The message is unknown in this context. But because the contract performs some kind of validation such as `require(recover(message, v, r, s) == expectedSignerAddress);` (otherwise why would they ask for the signature if they didn't validate it?), you should be able to retrieve the expected message from the contract source code. – Petr Hejda Jan 29 '22 at 09:54
Looks like you want to use the ecrecover
function available in solidity. ecrecover
helps in recovering the address from the signature which consists of r,v,s
You can use ethereumjs-util
npm package which can be used in Node.js and in the browser with browserify.
import * as util from "ethereumjs-util";
const { v, r, s } = util.fromRpcSig(messageSignedByMetamask);
// then pass them contract code

- 35,338
- 10
- 157
- 202