Web3js – How to Pass Numbers Greater Than 9007199254740991 to Smart Contracts

bignumberweb3js

When I try to call function check() with a number greater than 9007199254740991 I get an error:

Error encoding arguments: Error: Assertion failed

contract C {
     function rateCheck(uint rate){
          if(rate % 10 finney != 0 || rate == 0){
             throw;
          }
     }
}

Question:
What's the best workaround?

Best Answer

Summary

  • 10 finney is equals to 0.01 ethers or 10000000000000000 wei. Refer to http://ether.fund/tool/converter.
  • The native units in geth, solidity and the web3 interface is in wei.
  • Floating point numbers are currently unsupported.
  • Your code is trying to perform that following conditional check

    if (rate % 10000000000000000 != 0 || rate == 0)
    
  • The condition will fail if rate = 999999999999999
  • The condition will pass if rate = "999999999999999000000000000000000".
  • You can also use web3.toWei("999999999999999", "ether")
  • You will have to double quote your long numbers so the JavaScript interpreter treats it as a BigNumber. See A note on big numbers in web3.js for further information.



Details

Your issue is not with the large number.

Following is the code to test whether the large number is causing the problem:

pragma solidity ^0.4.2;

contract Test {
    uint256 public rate;

    function setRate(uint256 _rate) {
        rate = _rate;
    }
}

Here is the Browser Solidity screen showing that your number will be accepted via the web browser commands:

enter image description here

And I tried interacting with the contract through the geth console command line:

> var testABI = [{"constant":true,"inputs":[],"name":"rate","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_rate","type":"uint256"}],"name":"setRate","outputs":[],"payable":false,"type":"function"}];
undefined
> var testAddress="0x0016e39f81fb2968fd3cd1c9a0cefcfc4400322c";
undefined
> var testInterface = web3.eth.contract(testABI).at(testAddress);
undefined
> testInterface.setRate(999999999999999, {from: eth.accounts[0], gas: 500000})
"0x6b337f89f71e4e6fd40675392804dedfb0038049e2c4f32cb13e088d94a1d352"
> testInterface.rate()
999999999999999

Following is the screenshot that demonstrates that the problem is likely to be around the % operator:

enter image description here

Following is the Browser Solidity screen showing that your function works correctly - provided you pass the right units. And because the number is large, I had to enclose it in double quotes so the JavaScript interpreter passes the number as a BigNumber.

enter image description here

Here is a check from the geth console command line:

> var testABI = [{"constant":false,"inputs":[{"name":"rate","type":"uint256"}],"name":"rateCheck","outputs":[],"payable":false,"type":"function"}];
undefined
> var testAddress="0x2df61b421b5a6c42ab31a666634301047639355d";
undefined
> var testInterface = web3.eth.contract(testABI).at(testAddress);
undefined
> testInterface.rateCheck(9007199254740991, {from: eth.accounts[0], gas: 500000})
"0xad9856272b9862df1b1a471b897b4ea1fe619174051a11fdf98516750bf7c5ed"
> eth.getTransactionReceipt("0xad9856272b9862df1b1a471b897b4ea1fe619174051a11fdf98516750bf7c5ed")
{
  blockHash: "0x2956aca46107b646611bf1b5c788ac08e60f7cd4c5672e4b319e39aaf43fb1c3",
  blockNumber: 17127,
  contractAddress: null,
  cumulativeGasUsed: 500000,
  from: "0x5ad21746717442a76089bde62720412f29aee414",
  gasUsed: 500000,
  logs: [],
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  root: "0x27a5aff06d0f622311982b12f33d15672cfc2d6627cf554c8f126c3e1e6f7431",
  to: "0x2df61b421b5a6c42ab31a666634301047639355d",
  transactionHash: "0xad9856272b9862df1b1a471b897b4ea1fe619174051a11fdf98516750bf7c5ed",
  transactionIndex: 0
}
// gasUsed == gas supplied - error was thrown
> testInterface.rateCheck(web3.toWei("9007199254740991", "ether"), {from: eth.accounts[0], gas: 500000})
"0x93b8b8c2d78d465ef97024f3dd81267c6cf2f9ae7680f6e4d137a05341d0329e"
> eth.getTransactionReceipt("0x93b8b8c2d78d465ef97024f3dd81267c6cf2f9ae7680f6e4d137a05341d0329e")
{
  blockHash: "0x2e26507caa37e947d07e3e419ad67a7b11430200d7ec5da16e03c35bc9220d27",
  blockNumber: 17139,
  contractAddress: null,
  cumulativeGasUsed: 22450,
  from: "0x5ad21746717442a76089bde62720412f29aee414",
  gasUsed: 22450,
  logs: [],
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  root: "0x52df9a3abec58e84fcf0b429fb008b011c7b17452f3908803d81cf2eb2f0fe8c",
  to: "0x2df61b421b5a6c42ab31a666634301047639355d",
  transactionHash: "0x93b8b8c2d78d465ef97024f3dd81267c6cf2f9ae7680f6e4d137a05341d0329e",
  transactionIndex: 0
}
// gasUsed != gas supplied - no error was thrown