У меня есть контракт, который содержит токены от имени адресов и передает их, когда предоставляется подписанный хэш перевода.
Контракт выглядит так
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
в моей функции. Так что я застрял с обоими. Это неплохо, но было бы неплохо сократить количество библиотек.