Skip to content

Instantly share code, notes, and snippets.

@Theo6890
Last active December 15, 2022 09:52
Show Gist options
  • Save Theo6890/938beafe9890406bcb65163340c3fb48 to your computer and use it in GitHub Desktop.
Save Theo6890/938beafe9890406bcb65163340c3fb48 to your computer and use it in GitHub Desktop.
Sign message with etherjs using following ethereum format signature EIP-1271. If your signature contains complex data follow the EIP-712 to structure your signature & hash: this will allow end users to see the data they sign instead of an incomprehensible bytes32. For safe signatures follow these recommendations https://swcregistry.io/docs/SWC-121
const { ethers } = require('ethers');
/**
* @notice Path to where your .env file is. If the .env is at the root of your project,
* you can simply write `require('dotenv').config()`
*/
require('dotenv').config({ path: '../../.env' });
async function main() {
// instanciation can also be done using a private key
const wallet = new ethers.Wallet.fromMnemonic(process.env.SEED);
// by default the address at index 0 is used
walletAddr = await wallet.getAddress();
console.log('walletAddr: ', walletAddr);
/// @dev in solidity this will be written: `bytes memory rawEncodedMsg = abi.encode(param1, param2, ...)`
const rawEncodedMsg = ethers.utils.defaultAbiCoder.encode(
['uint256', 'uint256', 'address', 'address', 'uint256', 'uint256'],
[
parseInt(process.env.ID),
ethers.BigNumber.from(process.env.AMOUNT),
process.env.FROM,
process.env.TO,
parseInt(process.env.TIMESTAMP),
parseInt(process.env.CHAIN_ID),
]
);
/**
* @dev Create the hash of the original message.
* In solidity this will be written: `bytes32 hash = keccak256(rawEncodedMsg)`
*/
const encodedMessage = ethers.utils.keccak256(rawEncodedMsg);
/**
* @dev If only a bytes32 is needed we can encode the message in one line (like below),
* using: `ethers.utils.solidityKeccak256`
*/
console.log('raw encoded msg: ', rawEncodedMsg);
console.log('encoded msg: ', encodedMessage);
/**
* @dev Equivalent of OpenZeppelin: ECDSA.toEthSignedMessageHash(bytes memory s), which is:
* `keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));`
*/
let ethSignedMessageHash = ethers.utils.solidityKeccak256(
['string', 'string', 'bytes'],
[
'\x19Ethereum Signed Message:\n',
ethers.utils.hexDataLength(rawEncodedMsg).toString(),
rawEncodedMsg,
]
);
console.log('ethSignedMessageHash: ', ethSignedMessageHash);
// etherjs specific format requirements for signature
let messageHashBytes = ethers.utils.arrayify(rawEncodedMsg);
/// @dev equivalent of: ethereum.request({method: 'personal_sign', params: [walletAddr, messageHash]})
let signature = await wallet.signMessage(messageHashBytes);
console.log('signature: ', signature);
///@dev Pass r,s & v in Rewards contract
console.log('v: ', ethers.utils.splitSignature(signature).v);
console.log('r: ', ethers.utils.splitSignature(signature).r);
console.log('s: ', ethers.utils.splitSignature(signature).s);
}
main().then(console.log).catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment