I'm trying to call a smart contract on Base L2 that has an ecrecover function, but when I sign a message and pass it my r,s,v values (contract accepts 4 params, all uint256, presumably hashedmessage, r, s, v), it never returns my address? I'm using ethers and the code below, am I doing something wrong?
const ethers = require('ethers');
async function main(message) {
const provider = new ethers.providers.JsonRpcProvider('https://goerli.base.org');
const wallet = new ethers.Wallet('private-key', provider);
console.log('Signing wallet address:', wallet.address);
const contractAddress = 'addr';
const messageHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(message));
const signature = await wallet.signMessage(ethers.utils.arrayify(messageHash));
const sig = ethers.utils.splitSignature(signature);
const functionSelector = 'functionname';
const arg0 = messageHash.slice(2);
const arg1 = ethers.utils.hexZeroPad(ethers.utils.hexlify(sig.v), 32).slice(2);
const arg2 = sig.r.slice(2);
const arg3 = sig.s.slice(2);
const data = functionSelector + arg0 + arg1 + arg2 + arg3;
const rawTransaction = {
to: contractAddress,
value: ethers.utils.parseEther("0"),
gasPrice: ethers.utils.parseUnits("1", "gwei"),
gasLimit: ethers.utils.hexlify(1000000),
nonce: await wallet.getTransactionCount(),
data: '0x' + data,
chainId: 84531 // Base Testnet Chain ID
};
const signedTransaction = await wallet.signTransaction(rawTransaction);
try {
const txResponse = await provider.sendTransaction(signedTransaction);
console.log('Transaction sent:', txResponse.hash);
const receipt = await txResponse.wait();
console.log('Transaction confirmed:', receipt.transactionHash);
} catch (error) {
console.error('Error:', error);
}
}
main('Hello World');
Contract decompiled code:
def unknown7e392050(uint256 _param1, uint256 _param2, uint256 _param3, uint256 _param4) payable:
require calldata.size - 4 >=′ 128
require _param1 == _param1
require _param2 == uint8(_param2)
require _param3 == _param3
require _param4 == _param4
signer = erecover(_param1, _param2 << 248, _param3, _param4) # precompiled
if not erecover.result:
revert with ext_call.return_data[0 len return_data.size]
log 0xe1f54da2: _param1, addr(signer)
if addr(signer) != caller:
revert with 0, 'Signer must be the message sender'
return 5