在智能合约中传输哈希验证

时间:2019-01-15 22:12:47

标签: ethereum solidity web3js

我有一个合同,代表地址持有令牌,并在提供已签名的转移哈希值时将其转移。

合同看起来像这样

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

这可行,但是我必须同时使用ethersweb3-utils软件包来实现此目的。

如何用soliditySha3版本替换ethers函数?

我看了soliditySha3的实现,看起来很复杂。

问题是web3js似乎没有在我的函数中创建messageHashBytes的函数。所以我都坚持。并不是很糟糕,但是减少库的数量会很好。

1 个答案:

答案 0 :(得分:0)

如果可以使用web3.js进行所有操作,那么应该可以使用以下方法:

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