Solidity

比較智能合約中的數字時出錯(大數字)

  • January 20, 2021

我無法理解我們什麼時候需要將數字轉換為 bigNumbers 才能斷言相等。在某些情況下,我錯誤地錯過了將整數變數轉換為 bigNumber 並且它們沒有錯誤地工作。有人可以對同一件事提出更多的看法嗎?

Javascript 沒有 256 位數字類型。BN 庫以自己的內部格式將它們表示為對象。你從許多乙太坊函式中得到一個 256 位的數字,這些數字總是以 BN 形式返回。

一旦你習慣了它,它就沒有什麼奇怪的了。只需將所有內容都轉換為 BN,使用 BN 進行數學運算,並在需要可讀結果時使用字元串。請記住,JS 並不是唯一不能處理這些高精度數字的系統,例如數據庫可能是個問題。

2 ^ 256 = 10 ^ 77

這有效:

let value = "1234567890123456789012345678901234567890 ..." // good

…但這不是,因為 2 ^ 64 是 10 ^ 20,所以它太大了。這就是國陣可以提供的幫助。

let value = 1234567890123456789012345678901234567890 ... // fail

BN 具有用於.add.sub.mul等的方法(很多!),因為 JS 無法處理這些大數字,所以將所有內容轉換為 BN 並使用 BN 方法執行您的算術運算。他們希望所有論點都是 BN。它們是無損的並且始終有效。

如果您的測試使用低精度數字,您可能會得到誤導性的結果和似乎有效的東西,但您會在生產中遇到問題。這是混亂的根源,所以我建議不要這樣做。JS 可能會非常努力,只是截斷低位來給出答案,但不一定答案。啊。不要依賴 JS 類型和正常表達式來處理進出乙太坊的數據。考慮一個命名約定,如myValueBN.

let xBN = web3.utils.toBN("1234567890123456789012345678901234567890");
let yBN = web3.utils.toBN("1");
let nextBN = xBN.add(yBN);
// show me a base-10 interpretation of "next"
console.log(nextBN.toString(10)); // "1234567890123456789012345678901234567891"

當然,在實踐中你會從一個函式中得到你的數字,比如說……

let resultBN = await myContract.getSomething(); // is BN if value is a uint256

然後你可以去:

let twoBN = web3.utils.toBN("2");
let halfBN = resultBN.div(twoBN); // this is nearly lossless even if there are many digits
console.log(halfBN.toString(10));

作為對遇到此問題的其他人的警告。我說“幾乎”無損,因為除法是一種特殊情況。我們正在處理整數,因此舍入/截斷是不可避免的。BN 有一個.mod函式,因此您可以計算餘數併計算餘數。

希望能幫助到你。

引用自:https://ethereum.stackexchange.com/questions/92533