我正在Rinkeby测试网上测试ERC20代币。
我正在发送 1e23 单位的transfer
交易。 web3 的回应说
我尝试使用Javascript toString方法将金额转换为字符串。 并用web3.utils.toHex()
转换.
两个返回错误
dat=token.methods.transfer(w3.utils.toHex(to),web3.utils.toHex(amount)).encodeABI()
/*
OR
dat=token.methods.transfer(w3.utils.toHex(to),web3.utils.toHex(amount)).encodeABI()
*/
w3.eth.sendTransaction({from:from,to:TOKEN_ADDRESS,data:dat,gas:gasLimit()},(err,txhash)=>{
if(err) throw err
console.log(txhash)
callback(txhash)
})
Uncaught Error: Please pass numbers as strings or BigNumber objects to avoid precision errors.
TLDR
使用内置的 util 函数将以太币转换为 wei:
var amount = web3.utils.toWei('1000000','ether');
旧答案如下:
从字面上看,只需遵循错误的建议即可。
to
数字最初应该是字符串类型,因为 javascript 中的数字类型太小而无法存储地址。
如果amount
以合理的数字开头,则使用大数库将其转换为 BigNumber。Web3 内部使用 bn.js 作为其大数库,因此为了完全兼容,您也应该使用相同的库,但根据我的经验,bignum 也是兼容的:
const BN = require('bn.js');
token.methods.transfer(new BN(to),new BN(amount)).encodeABI()
根据您的评论,您似乎正在尝试将1e+24
作为数字传递。问题是它太大了,无法在不损失精度的情况下放入双精度。Web3 拒绝使用该数字,因为它甚至在 web3 有机会处理它之前就已经失去了精度。解决方法是改用字符串:
var amount = '1000000000000000000000000';
token.methods.transfer(to,amount).encodeABI()
如果你真的不想键入 24 个零,你可以使用字符串操作:
var amount = '1' + '0'.repeat(24);
或者,如果这个金额真的是一百万以太币,最好使用内置的 util 函数来显示您的真实意思:
var amount = web3.utils.toWei('1000000','ether');
我知道这很旧,但我在使用 chai 进行一些坚固性测试时遇到了麻烦,我添加了以下评论:
/* global BigInt */
有了它,您可以使用大数字
const testValue = 2000000000000000000n;