Solidity

一元運算符 - 不能應用於 uint256 類型

  • May 4, 2021

我試圖編譯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);

請注意,僅當您使用檢​​查算法時,這才比其他解決方案更快。

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