web3 / web3.js

Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.
https://web3js.org/
Other
19.4k stars 4.97k forks source link

fault="overflow", operation="toNumber", value="100000000000000000", code=NUMERIC_FAULT, version=bignumber/5.0.12 #4004

Closed VexyCats closed 3 years ago

VexyCats commented 3 years ago

Expected behavior

Making a web3.js call to a contract that returns a struct of data like this:

  amount_of_tokens_left   uint256 :  5
  total_in_series   uint256 :  5
  starting_id   uint256 :  1
  price   uint256 :  100000000000000000
  creator   address :  0x000000000000000000....000
  url   string :  metadata/1/51

Should return the values properly. If price is under 1 ETH in gwei, it works, but as soon as its over 1 ETH - it overflows.

Actual behavior

The call errors out with:

overflow (fault="overflow", operation="toNumber", value="100000000000000000", code=NUMERIC_FAULT, version=bignumber/5.0.12)
    at Logger.makeError (index.ts:205)
    at Logger.throwError (index.ts:217)
    at throwFault (bignumber.ts:348)
    at BigNumber.toNumber (bignumber.ts:188)
    at array.js:60

Steps to reproduce the behavior

Call a contract that returns a uint256 inside a struct that is over 10000000000000000 as the uint256

   return await contractInstance.methods[methodName](...params)
      .call()
      .then((res) => {
        return res;
      });

Environment

"web3": "^1.2.11"

GregTheGreek commented 3 years ago

Please use the latest version of web3.js!

tambu22 commented 3 years ago

I have the same issue, with version "web3": "^1.3.5"

I'm trying to call a router contract function getAmountOut:

Function ABI:

{
    inputs: [
      { internalType: "uint256", name: "amountIn", type: "uint256" },
      { internalType: "address[]", name: "path", type: "address[]" },
    ],
    name: "getAmountsOut",
    outputs: [
      { internalType: "uint256[]", name: "amounts", type: "uint256[]" },
    ],
    stateMutability: "view",
    type: "function",
  }

In some coins with extremely low value i get the overflow error:

Error: overflow (fault="overflow", operation="toNumber", value="3963877391197344453575983046348115674221700746820753546331534351508065746944", code=NUMERIC_FAULT, version=bignumber/5.1.0)
    at Logger.makeError (/home/nico/Documents/bsc/node_modules/@ethersproject/logger/lib/index.js:180:21)
    at Logger.throwError (/home/nico/Documents/bsc/node_modules/@ethersproject/logger/lib/index.js:189:20)
    at throwFault (/home/nico/Documents/bsc/node_modules/@ethersproject/bignumber/lib/bignumber.js:305:19)
    at BigNumber.toNumber (/home/nico/Documents/bsc/node_modules/@ethersproject/bignumber/lib/bignumber.js:153:13)
    at /home/nico/Documents/bsc/node_modules/@ethersproject/abi/lib/coders/array.js:90:60
    at Array.forEach (<anonymous>)
    at Object.unpack (/home/nico/Documents/bsc/node_modules/@ethersproject/abi/lib/coders/array.js:85:12)
    at TupleCoder.decode (/home/nico/Documents/bsc/node_modules/@ethersproject/abi/lib/coders/tuple.js:39:49)
    at AbiCoder.decode (/home/nico/Documents/bsc/node_modules/@ethersproject/abi/lib/abi-coder.js:93:22)
    at ABICoder.decodeParametersWith (/home/nico/Documents/bsc/node_modules/web3-eth-abi/lib/index.js:304:30)
    at ABICoder.decodeParameters (/home/nico/Documents/bsc/node_modules/web3-eth-abi/lib/index.js:285:17)
    at Contract._decodeMethodReturn (/home/nico/Documents/bsc/node_modules/web3-eth-contract/lib/index.js:470:22)
    at Method.outputFormatter (/home/nico/Documents/bsc/node_modules/web3-eth-contract/lib/index.js:760:42)
    at Method.formatOutput (/home/nico/Documents/bsc/node_modules/web3-core-method/lib/index.js:147:54)
    at sendTxCallback (/home/nico/Documents/bsc/node_modules/web3-core-method/lib/index.js:523:33)
    at /home/nico/Documents/bsc/node_modules/web3-core-requestmanager/lib/index.js:308:9
    at XMLHttpRequest.request.onreadystatechange (/home/nico/Documents/bsc/node_modules/web3-providers-http/lib/index.js:98:13)
    at XMLHttpRequestEventTarget.dispatchEvent (/home/nico/Documents/bsc/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:22)
    at XMLHttpRequest._setReadyState (/home/nico/Documents/bsc/node_modules/xhr2-cookies/dist/xml-http-request.js:208:14)
    at XMLHttpRequest._onHttpResponseEnd (/home/nico/Documents/bsc/node_modules/xhr2-cookies/dist/xml-http-request.js:318:14)
    at IncomingMessage.<anonymous> (/home/nico/Documents/bsc/node_modules/xhr2-cookies/dist/xml-http-request.js:289:61)
    at IncomingMessage.emit (events.js:215:7)
    at endReadableNT (_stream_readable.js:1183:12)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) {
  reason: 'overflow',
  code: 'NUMERIC_FAULT',
  fault: 'overflow',
  operation: 'toNumber',
  value: '3963877391197344453575983046348115674221700746820753546331534351508065746944'
}

My code:

try {
    priceArray = await router.methods.getAmountsOut(1000000000, path).call({});
  } catch (error) {
    await eventLog(error, CONSTANTS.ERRORS.FETCHING_PRICES);
    return undefined;
  }

To reproduce: npm i web3

const Web3 = require("web3");
const web3 = new Web3("https://bsc-dataseed1.binance.org:443");
const ABIRouter = [
  {
    inputs: [
      { internalType: "uint256", name: "amountIn", type: "uint256" },
      { internalType: "address[]", name: "path", type: "address[]" },
    ],
    name: "getAmountsOut",
    outputs: [
      { internalType: "uint256[]", name: "amounts", type: "uint256[]" },
    ],
    stateMutability: "view",
    type: "function",
  },
];
const router = new web3.eth.Contract(
  ABIRouter,
  "0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F"
);
const path = [
  "0x81e4d494b85a24a58a6ba45c9b418b32a4e039de",
  "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
  "0xe9e7cea3dedca5984780bafc599bd69add087d56",
];

const test = async () => {
  try {
    console.log(router.methods);
    priceArray = await router.methods.getAmountsOut(1000000000, path).call({});
    console.log(priceArray[2].toString()); //if works prints the big number
  } catch (error) {
    console.log(error); //print the erro
    return undefined;
  }
};

test();

Edit: I've already tried supplying the function with the number in string, web.BN, BigNumber and Hex

jacastro commented 3 years ago

I am having the same problem for a few days with last version of web3.

tambu22 commented 3 years ago

Duplicated issue? #3897

GregTheGreek commented 3 years ago

Bignumbers have been a bit of a bottleneck for us, we are working on this. Thank you for pointing this out.

ktpm489 commented 3 years ago

Because data format when return the result ( normal get symbol() function return string type but some contract return bytes32) .You should handle for each type. Please see attach code .I handle to get symbol data for normal and unnormal contract:

async function getTokenNameBalance (contractAddress, address) { return new Promise(async (resolve, reject) => { const minABI = [{ constant: true, inputs: [], name: 'name', outputs: [{ name: '', type: 'string' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [{ name: 'spender', type: 'address' }, { name: 'value', type: 'uint256' }], name: 'approve', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: true, inputs: [{ name: 'value', type: 'uint256' }], name: 'estimateFee', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'totalSupply', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'issuer', outputs: [{ name: '', type: 'address' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [{ name: 'from', type: 'address' }, { name: 'to', type: 'address' }, { name: 'value', type: 'uint256' }], name: 'transferFrom', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: true, inputs: [], name: 'minFee', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'decimals', outputs: [{ name: '', type: 'uint8' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [{ name: 'value', type: 'uint256' }], name: 'setMinFee', outputs: [], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: false, inputs: [{ name: 'to', type: 'address' }, { name: 'value', type: 'uint256' }], name: 'mint', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: false, inputs: [{ name: 'value', type: 'uint256' }], name: 'burn', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: true, inputs: [{ name: 'owner', type: 'address' }], name: 'balanceOf', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'symbol', outputs: [{ name: '', type: 'string' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [{ name: 'account', type: 'address' }], name: 'addMinter', outputs: [], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: false, inputs: [], name: 'renounceMinter', outputs: [], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: false, inputs: [{ name: 'to', type: 'address' }, { name: 'value', type: 'uint256' }], name: 'transfer', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: true, inputs: [{ name: 'account', type: 'address' }], name: 'isMinter', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [{ name: 'owner', type: 'address' }, { name: 'spender', type: 'address' }], name: 'allowance', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { inputs: [], payable: false, stateMutability: 'nonpayable', type: 'constructor' }, { anonymous: false, inputs: [{ indexed: true, name: 'account', type: 'address' }], name: 'MinterAdded', type: 'event' }, { anonymous: false, inputs: [{ indexed: true, name: 'account', type: 'address' }], name: 'MinterRemoved', type: 'event' }, { anonymous: false, inputs: [{ indexed: true, name: 'from', type: 'address' }, { indexed: true, name: 'to', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }], name: 'Transfer', type: 'event' }, { anonymous: false, inputs: [{ indexed: true, name: 'owner', type: 'address' }, { indexed: true, name: 'spender', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }], name: 'Approval', type: 'event' }, { anonymous: false, inputs: [{ indexed: true, name: 'from', type: 'address' }, { indexed: true, name: 'to', type: 'address' }, { indexed: true, name: 'issuer', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }], name: 'Fee', type: 'event' }] const contract = new web3.eth.Contract(minABI, contractAddress) contract.methods.name().call().then(name => { contract.methods.symbol().call().then(symbol => { contract.methods.balanceOf(address).call().then(balance => { contract.methods.decimals().call().then(decimal => { resolve({ name: name, symbol: symbol, balance: balance, decimal }) }).catch((e) => { resolve({ name: '', symbol, balance: balance, decimal: 18 }) }) }).catch(err => { // console.log('e1', err) reject(err) }) }).catch(err => { // console.log('e2', err) reject(err) }) }).catch(err => { // console.log('e', err) reject(err) })

}).catch(function (error) {
    return new Promise(async (resolve, reject) => {
        const minABI = [{ constant: true, inputs: [], name: 'name', outputs: [{ name: '', type: 'bytes32' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [{ name: 'spender', type: 'address' }, { name: 'value', type: 'uint256' }], name: 'approve', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: true, inputs: [{ name: 'value', type: 'uint256' }], name: 'estimateFee', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'totalSupply', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'issuer', outputs: [{ name: '', type: 'address' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [{ name: 'from', type: 'address' }, { name: 'to', type: 'address' }, { name: 'value', type: 'uint256' }], name: 'transferFrom', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: true, inputs: [], name: 'minFee', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'decimals', outputs: [{ name: '', type: 'uint8' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [{ name: 'value', type: 'uint256' }], name: 'setMinFee', outputs: [], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: false, inputs: [{ name: 'to', type: 'address' }, { name: 'value', type: 'uint256' }], name: 'mint', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: false, inputs: [{ name: 'value', type: 'uint256' }], name: 'burn', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: true, inputs: [{ name: 'owner', type: 'address' }], name: 'balanceOf', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'symbol', outputs: [{ name: '', type: 'bytes32' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [{ name: 'account', type: 'address' }], name: 'addMinter', outputs: [], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: false, inputs: [], name: 'renounceMinter', outputs: [], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: false, inputs: [{ name: 'to', type: 'address' }, { name: 'value', type: 'uint256' }], name: 'transfer', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'nonpayable', type: 'function' }, { constant: true, inputs: [{ name: 'account', type: 'address' }], name: 'isMinter', outputs: [{ name: '', type: 'bool' }], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [{ name: 'owner', type: 'address' }, { name: 'spender', type: 'address' }], name: 'allowance', outputs: [{ name: '', type: 'uint256' }], payable: false, stateMutability: 'view', type: 'function' }, { inputs: [], payable: false, stateMutability: 'nonpayable', type: 'constructor' }, { anonymous: false, inputs: [{ indexed: true, name: 'account', type: 'address' }], name: 'MinterAdded', type: 'event' }, { anonymous: false, inputs: [{ indexed: true, name: 'account', type: 'address' }], name: 'MinterRemoved', type: 'event' }, { anonymous: false, inputs: [{ indexed: true, name: 'from', type: 'address' }, { indexed: true, name: 'to', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }], name: 'Transfer', type: 'event' }, { anonymous: false, inputs: [{ indexed: true, name: 'owner', type: 'address' }, { indexed: true, name: 'spender', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }], name: 'Approval', type: 'event' }, { anonymous: false, inputs: [{ indexed: true, name: 'from', type: 'address' }, { indexed: true, name: 'to', type: 'address' }, { indexed: true, name: 'issuer', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }], name: 'Fee', type: 'event' }]
        const contract = new web3.eth.Contract(minABI, contractAddress)
        contract.methods.name().call().then(name => {
            contract.methods.symbol().call().then(symbol => {
                contract.methods.balanceOf(address).call().then(balance => {
                    contract.methods.decimals().call().then(decimal => {
                        let nameFormat = web3.utils.toAscii(name).split('\u0000')[0]
                        let symbolFormat = web3.utils.toAscii(symbol).split('\u0000')[0]
                        resolve({ name: nameFormat ? nameFormat : symbolFormat, symbol: symbolFormat, balance: balance, decimal })
                    }).catch((e) => {
                        resolve({ name: '', symbol, balance: balance, decimal: 18 })
                    })
                }).catch(err => {
                    // console.log('e', err)
                    reject(err)
                })
            }).catch(err => {
                // console.log('e', err)
                reject(err)
            })
        }).catch(err => {
            // console.log('e', err)
            reject(err)
        })
    })
})

}

github-actions[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions. If you believe this was a mistake, please comment.

fzn0x commented 2 years ago

This is still an issue