sign.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. const { web3 } = require('@openzeppelin/test-environment');
  2. function toEthSignedMessageHash (messageHex) {
  3. const messageBuffer = Buffer.from(messageHex.substring(2), 'hex');
  4. const prefix = Buffer.from(`\u0019Ethereum Signed Message:\n${messageBuffer.length}`);
  5. return web3.utils.sha3(Buffer.concat([prefix, messageBuffer]));
  6. }
  7. function fixSignature (signature) {
  8. // in geth its always 27/28, in ganache its 0/1. Change to 27/28 to prevent
  9. // signature malleability if version is 0/1
  10. // see https://github.com/ethereum/go-ethereum/blob/v1.8.23/internal/ethapi/api.go#L465
  11. let v = parseInt(signature.slice(130, 132), 16);
  12. if (v < 27) {
  13. v += 27;
  14. }
  15. const vHex = v.toString(16);
  16. return signature.slice(0, 130) + vHex;
  17. }
  18. // signs message in node (ganache auto-applies "Ethereum Signed Message" prefix)
  19. async function signMessage (signer, messageHex = '0x') {
  20. return fixSignature(await web3.eth.sign(messageHex, signer));
  21. };
  22. /**
  23. * Create a signer between a contract and a signer for a voucher of method, args, and redeemer
  24. * Note that `method` is the web3 method, not the truffle-contract method
  25. * @param contract TruffleContract
  26. * @param signer address
  27. * @param redeemer address
  28. * @param methodName string
  29. * @param methodArgs any[]
  30. */
  31. const getSignFor = (contract, signer) => (redeemer, methodName, methodArgs = []) => {
  32. const parts = [
  33. contract.address,
  34. redeemer,
  35. ];
  36. const REAL_SIGNATURE_SIZE = 2 * 65; // 65 bytes in hexadecimal string legnth
  37. const PADDED_SIGNATURE_SIZE = 2 * 96; // 96 bytes in hexadecimal string length
  38. const DUMMY_SIGNATURE = `0x${web3.utils.padLeft('', REAL_SIGNATURE_SIZE)}`;
  39. // if we have a method, add it to the parts that we're signing
  40. if (methodName) {
  41. if (methodArgs.length > 0) {
  42. parts.push(
  43. contract.contract.methods[methodName](...methodArgs.concat([DUMMY_SIGNATURE])).encodeABI()
  44. .slice(0, -1 * PADDED_SIGNATURE_SIZE)
  45. );
  46. } else {
  47. const abi = contract.abi.find(abi => abi.name === methodName);
  48. parts.push(abi.signature);
  49. }
  50. }
  51. // return the signature of the "Ethereum Signed Message" hash of the hash of `parts`
  52. const messageHex = web3.utils.soliditySha3(...parts);
  53. return signMessage(signer, messageHex);
  54. };
  55. module.exports = {
  56. signMessage,
  57. toEthSignedMessageHash,
  58. fixSignature,
  59. getSignFor,
  60. };