12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- const utils = require('ethereumjs-util');
- const { soliditySha3 } = require('web3-utils');
- const REAL_SIGNATURE_SIZE = 2 * 65; // 65 bytes in hexadecimal string legnth
- const PADDED_SIGNATURE_SIZE = 2 * 96; // 96 bytes in hexadecimal string length
- const DUMMY_SIGNATURE = `0x${web3.padLeft('', REAL_SIGNATURE_SIZE)}`;
- /**
- * Hash and add same prefix to the hash that ganache use.
- * @param {string} message the plaintext/ascii/original message
- * @return {string} the hash of the message, prefixed, and then hashed again
- */
- function hashMessage (message) {
- const messageHex = Buffer.from(utils.sha3(message).toString('hex'), 'hex');
- const prefix = utils.toBuffer('\u0019Ethereum Signed Message:\n' + messageHex.length.toString());
- return utils.bufferToHex(utils.sha3(Buffer.concat([prefix, messageHex])));
- }
- // signs message in node (auto-applies prefix)
- // message must be in hex already! will not be autoconverted!
- const signMessage = (signer, message = '') => {
- return web3.eth.sign(signer, message);
- };
- // @TODO - remove this when we migrate to web3-1.0.0
- const transformToFullName = function (json) {
- if (json.name.indexOf('(') !== -1) {
- return json.name;
- }
- const typeName = json.inputs.map(function (i) { return i.type; }).join();
- return json.name + '(' + typeName + ')';
- };
- /**
- * Create a signer between a contract and a signer for a voucher of method, args, and redeemer
- * Note that `method` is the web3 method, not the truffle-contract method
- * Well truffle is terrible, but luckily (?) so is web3 < 1.0, so we get to make our own method id
- * fetcher because the method on the contract isn't actually the SolidityFunction object ಠ_ಠ
- * @param contract TruffleContract
- * @param signer address
- * @param redeemer address
- * @param methodName string
- * @param methodArgs any[]
- */
- const getBouncerSigner = (contract, signer) => (redeemer, methodName, methodArgs = []) => {
- const parts = [
- contract.address,
- redeemer,
- ];
- // if we have a method, add it to the parts that we're signing
- if (methodName) {
- if (methodArgs.length > 0) {
- parts.push(
- contract.contract[methodName].getData(...methodArgs.concat([DUMMY_SIGNATURE])).slice(
- 0,
- -1 * PADDED_SIGNATURE_SIZE
- )
- );
- } else {
- const abi = contract.abi.find(abi => abi.name === methodName);
- const name = transformToFullName(abi);
- const signature = web3.sha3(name).slice(0, 10);
- parts.push(signature);
- }
- }
- // ^ substr to remove `0x` because in solidity the address is a set of byes, not a string `0xabcd`
- const hashOfMessage = soliditySha3(...parts);
- return signMessage(signer, hashOfMessage);
- };
- module.exports = {
- hashMessage,
- signMessage,
- getBouncerSigner,
- };
|