Summary
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:
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:
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.
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
Best Answer
In Javascript, the maximum safe integer is 2^53-1.
So you should generally avoid using numbers like 100000000000000000000.
For example, in your code, you should change this:
To this:
In addition to that, the usage of
toNumber()
is also unsafe, as you have noticed yourself.When you call from the off-chain an on-chain function which returns
uint256
, you get aBigNumber
object. If this object represents a number smaller thanNumber.MAX_SAFE_INTEGER
, then it is safe to usetoNumber()
on it. But since you do not know that for sure, you should avoid usingtoNumber()
.Also, please note that it is better to use
toFixed()
thantoString()
, because the latter may return the scientific notation of the number (e.g.1+e18
), which may give you unexpected problems when you later use it in other contexts.