передача хеш-проверки в смарт-контракт - PullRequest
0 голосов
/ 16 января 2019

У меня есть контракт, который содержит токены от имени адресов и передает их, когда предоставляется подписанный хэш перевода.

Контракт выглядит так

pragma solidity ^0.5.0;

import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";

contract Settlement is Ownable {
    using SafeMath for uint256;

    struct Withdrawal {
        uint256 amount;
        address token;
        uint256 timestamp;
    }

    // token => (holder => balance)
    mapping(address => mapping(address => uint256)) public tokenBalances;
    mapping(address => Withdrawal) withdrawals;

    function transferInto(address recipient, uint256 amount, address token) public {
        //get the tokens
        IERC20(token).transferFrom(msg.sender, address(this), amount);
        //increase the token balance in the payment contract
        tokenBalances[token][recipient] = tokenBalances[token][recipient].add(amount);
    }

    string constant private prefix = "\u0019Ethereum Signed Message:\n32";
    function transfer(address to, uint256 amount, address token, uint8 v, bytes32 r, bytes32 s)
    public {
        bytes32 paramHash = keccak256(abi.encodePacked(to, amount, token));
        address signer = ecrecover(keccak256(abi.encodePacked(prefix, paramHash)), v, r, s);
        //SafeMath ensures that the signer has enough tokens in their payment account
        tokenBalances[token][signer] = tokenBalances[token][signer].sub(amount);

        IERC20(token).transfer(to, amount);
    }

}

и я написал функцию для создания подписи, которая передается функции transfer контракта:

const ethers = require('ethers')
const BigNumber = require('bignumber.js')
const utils = require('web3-utils')

// the purpose of this function is to be able to create BN from exponent numbers like '2e22' they must be formatted as string in this case
const toBN = (num) => utils.toBN(new BigNumber(num).toString(10))

async function signTransfer(recipient, amount, tokenAddress, privateKey){
  const wallet = new ethers.Wallet(privateKey)
  const txMsg = utils.soliditySha3(recipient, toBN(amount), tokenAddress)
  const messageHashBytes = ethers.utils.arrayify(txMsg)
  const flatSig = await wallet.signMessage(messageHashBytes)
  const sig = ethers.utils.splitSignature(flatSig)

  return {
    ...sig,
    hash: messageHashBytes
  }
}

module.exports = signTransfer

это работает, но мне пришлось использовать оба пакета ethers и web3-utils для реализации этого.

как заменить функцию soliditySha3 версией ethers?

Я посмотрел на реализацию soliditySha3, и она выглядит очень сложной.

Дело в том, что web3js, похоже, не имеет функции для создания messageHashBytes в моей функции. Так что я застрял с обоими. Это неплохо, но было бы неплохо сократить количество библиотек.

1 Ответ

0 голосов
/ 16 января 2019

Если у вас все в порядке, просто используйте web3.js для всего, что-то вроде этого должно работать:

function signTransfer(recipient, amount, tokenAddress, privateKey) {
  return web3.eth.accounts.sign(
    web3.utils.soliditySha3(recipient, toBN(amount), tokenAddress),
    privateKey);
}
...