Solidity
一元運算符 - 不能應用於 uint256 類型
我試圖編譯mulDiv函式,它是uniswap-v3-core程式碼庫的一部分,但出現以下錯誤:
一元運算符 - 不能應用於 uint256 類型
這是它中斷的行:
uint256 twos = -denominator & denominator;
我使用的是 Solidity v0.8.3,而他們使用的是Solidity v0.7.6。
這似乎沒有在v0.8.0 重大更改中列出。如何在確保邏輯保持不變的同時使其在 v0.8 中工作?
一元運算符
-
否定給定的數字。更容易看出它對有符號整數的作用。如果我們使用int8
類型並且我們否定正數 10,我們會得到 -10。現在,無符號整數當然不能表示負數。Solidity在否定 uint8
x
(在 v0.7 及更低版本中)時所做的是返回type(uint8).max - x + 1
. 例如,否定 10 得到 246。我編寫的以下函式返回
true
所有可能的值x
:function checkNegativeUnary(uint8 x) external pure returns (bool result) { uint8 a = -x; uint8 b = type(uint8).max - x + 1; result = a == b; }
由於現在 Solidity v0.8 似乎禁止對無符號整數求反,所以要進行
mulDiv
編譯,我們應該denominator
像這樣重寫:uint256 twos = (type(uint256).max - denominator + 1) & denominator;
這不會溢出,因為
denominator
它永遠不會為 0,因為在函式前面進行了另一項檢查:// Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1);
更新
根據我在 CS SE 中開始的這個問答中的答案,我設法找到了一個更短的實現:如何找到給定整數的兩個除數的最大冪?:
uint256 twos = denominator & (~denominator + 1);
請注意,僅當您使用檢查算法時,這才比其他解決方案更快。