solidity測試指令碼:小心js裡坑爹的數值計算
阿新 • • 發佈:2018-11-05
前天在除錯solidity程式碼時,發現一個極為詭異的行為:solidity中存數的數值,當使用web3取出的時候,數值是錯的——與solidity中的值對不上!
solidity中的程式碼大概是這樣的:
mapping (uint => uint) public data;
...
data[0] = 9901538745632159654;
data[data[0]] = 5901538745632159654;
...
測試指令碼是這樣的:
let begin= await MyContract.data(0);
let next = await MyContract. data(begin.toNumber());
console.log("next :", next.toNumber());
結果發現next的值一直是0,而不是正確的5901538745632159654!
當我將begin這樣打出來之後,一切都瞭然了:
console.log("begin toNumber:", begin.toNumber(), ", begin toString:", begin.toString());
輸出:
begin toNumber: 9901538745632160000, begin toString:9901538745632159654
在toNumber的過程中損失了精度!正確的測試程式碼應該這樣寫——避免使用toNumber:
let begin= await MyContract.data(0);
let next = await MyContract.data(begin);
console.log("next :", next.toString());
總結:
在需要nodejs與solidity有資料互動的時候,儘量避免使用toNumber,打日誌的時候使用toString,js傳引數給solidity的時候直接使用BigNumber,假如要在js中進行算數計算,應直接使用BigNumber的相關方法諸如plus進行算數計算。
後記:
之前solidity中使用的資料一直是比較整的,像這樣
data[0] = 1000000000000000000;
data[data[0]] = 3000000000000000000;
這樣的資料經過toNumber操作之後也是不會出問題的,只有零頭比較長的資料才會如此,就像9901538745632159654這種。