无法以大数字作为参数从 web3 调用合约函数

Posted

技术标签:

【中文标题】无法以大数字作为参数从 web3 调用合约函数【英文标题】:Unable to call contract function from web3 with big number as parameter 【发布时间】:2020-09-29 18:33:24 【问题描述】:

您好,我正在尝试调用需要 unit256 参数的合同的自定义函数。

我用这个值作为参数从 web3 调用这个函数:10000000000000000000(10 有 18 个零) 一旦这个调用被 web3 击中,我就会遇到以下 Big number 错误:

错误:溢出(fault="overflow", operation="BigNumber.from", value=10000000000000000000, code=NUMERIC_FAULT, version=bignumber/5.0.0-beta.138)

有人知道原因吗?

这是我正在调用的合约的功能:

function lock(
    address tokenAddress,
    uint256 amount
)

这里是 web3 代码 sn-p:

Contract.methods.lock(0x57AA33D53351eA4BF00C6F10c816B3037E268b7a, 10000000000000000000,
        ).send(
            from: accounts[0],
            gasLimit: 500000,
            value: 0
        );

我尝试了相同的功能,但金额较小,它可以工作,例如1(有 18 个零)

【问题讨论】:

【参考方案1】:

我尝试将参数作为字符串发送,它成功了。

发布此答案,因此可能对某人有所帮助。

【讨论】:

我在运行华夫饼测试时遇到了这个错误:expect(await vrfContract.getHardcodedUintNumber()).to.be.equal(18446205110165755834005948204546580960626098221936403173208959885300094367089);,我对答案有点困惑,因为我认为(并认为)它暗示:“将 uint256 作为字符串返回函数”,即使在我的情况下,它应该返回一个 uint256。但是,将预期的数字放在双引号中解析(作为字符串):expect(await vrfContract.getHardcodedUintNumber()).to.be.equal("18446205110165755834005948204546580960626098221936403173208959885300094367089");【参考方案2】:

我在 Truffle UnitTest 中使用 BigInt

it('should return correct balances when transfer', async () => 
    const receiver = accounts[2];
    const balanceOfOwner = await contractInstance.balanceOf.call(owner);
    assert.equal(balanceOfOwner, totalSupply * 10 ** decimals, 'Total balance');

    const sendAmount = 69 * 10 ** decimals;
    await contractInstance.transfer(receiver, BigInt(sendAmount), 
      from: owner,
    );

    const balanceOfReceiver = await contractInstance.balanceOf.call(receiver);
    assert.equal(balanceOfReceiver, sendAmount, 'Received sendAmount');
    assert.equal(
      await contractInstance.balanceOf.call(owner),
      balanceOfOwner - sendAmount,
      'Decreased to'
    );
  );

【讨论】:

【参考方案3】:

原因可以在ethers包的文档中找到:

为什么我不能只使用数字? 许多人在处理以太坊时遇到的第一个问题是数字的概念。大多数常见货币的细分粒度很小。例如,一美元只有 100 美分。但是,一个以太币中有 1018 个wei。 javascript 使用 IEEE 754 双精度二进制浮点数来表示数值。结果,在9,007,199,254,740,991之后的整数集中有空洞;这对以太坊来说是有问题的,因为它只有大约 0.009 以太(以 wei 为单位),这意味着任何超过该值的值都将开始出现舍入错误。 (...) 为了解决这个问题,所有数字(可能很大)都作为大数字进行存储和操作。

【讨论】:

以上是关于无法以大数字作为参数从 web3 调用合约函数的主要内容,如果未能解决你的问题,请参考以下文章

web3 从合约调用的函数不起作用

使用 web3 js 调用智能合约函数

从 web3js 调用 Factory 合约的子函数

使用 Web3 从 Solidity 调用函数

如何在 REMIX(Solidity IDE)中从 web3 调用带有参数的构造函数

再深刻理解下web3.js中estimateGas如何计算智能合约消耗的gas量