如何在交易中包含大数 >=1e21

How to include large numbers in transactions >=1e21

我正在 Rinkeby 测试网上测试 ERC20 代币。

我正在发送 transfer 1e23 个单位的交易。 web3 的回复说

我尝试使用 Javascript toString 方法将金额转换为字符串。 并用 web3.utils.toHex().

转换

两个 return 错误

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 以合理的数字开头,则使用大数字库将其转换为大数字。 Web3 内部使用 bn.js as its bignumber library so for full compatibility you should also use the same but 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');