Bug

Solidity 的指數運算符中的意外隱式轉換

  • March 6, 2017

在調查 ERC20 中不正確的代幣獎勵錯誤時,發現關於指數運算符的鑄造存在明顯的不一致a**b。特別是,輸出轉換為 typeb而不是 type a

因此,當計算定義的小數位指數時10**exp,輸出被截斷為 8 位,給出的答案是而不是。exp``uint8 exp = 3``232``1000

如果基數被定義為uint8更長類型的指數,例如uint,編譯器將拋出一個隱式轉換錯誤,表明輸出應該是基數類型而不是指數。

這似乎不受非複合參數的影響,這些參數無論如何都轉換為 32 位插槽。

contract PowerOfTest {
   // Returns 232
   uint8 public placesA = 3;
   uint public EXP_A = 10**placesA;

   // Returns 1000
   uint public placesB = 3;
   uint public EXP_B = 10**placesB;

   // Returns 1000
   uint8 public placesC = 3;
   uint public EXP_C = 10**uint(placesC);

   // Type uint256 is not implicity convertable to expected type uint 8
   // uint public EXP_D = 3;
   // uint8 public placesD = 10**EXP_D;

   // Returns 1000 for `pow(10, 3)`
   function pow(uint base, uint8 exponent) returns(uint)
   {
       return base**exponent;
   }

   // Returns 232 for `pow(10, 3)`
   function pow2() returns(uint)
   {
       uint8 EXP_D = 3;
       return 10**EXP_D;
   }
}

來自@chriseth 回應提出的 GH 問題…

Solidity 中任何二元運算符的結果類型(也承認 ** 作為非交換運算符應區別對待)是一種可以適合兩種參數類型的類型。表達式 a**b 的結果始終是 a 和 b 的“較大”類型。請注意,將表達式結果分配給的變數類型不會影響表達式本身的類型。

作為一種解決方案,我建議使用 uint(10)**placesA 並且只要 ** 運算符的基數是常量,編譯器就應該添加一個警告。

…常量一旦遇到非常數,就會假定它們適合的最小類型。

進一步閱讀文字的數學和類型轉換。

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