24

Does solidity supports power operations like 2^3 = 8 or should I perform multiple multiplications? Should i include a math library? I don't find anything in the official doc. Thanks

4

3 Answers 3

32

you need only to use **.

the following function calulate A to the power of B.

function power(uint256 A, uint256 B) public returns (uint256){ 
        return A**B;
     }
4

** is the operator you are looking for. 2**3 = 8.

But be paranoid when using it - it is very easy to overflow.

For example... in the case of 255 to the second power... the answer you probably want is 65025. However, if you used a uint8, then what are you actually getting is 65025 mod (2^8), or, 1.

For example:

uint8 a = 255;
uint8 b = 2;
uint8 c = a**b;

results in c being equal to 1.

Even the following does you no good. Since a and b are both uint8s, the result is a uint8 with the "feature" of a mod 2^8, before being cast to a uint256.

uint256 d = a**b;

Once again, d would equal 1.

The following gets you the right answer, but only because a and b are so small.

uint256 e = uint256(a)**uint256(b);

e equals 65025.

A sophisticated approach to make sure you are safe is here...

https://stackoverflow.com/questions/199333/how-to-detect-integer-overflow

A simpler rule of thumb: if you take a number that's 255 or less, to the power of 32 or less, you should be okay.

Remember that (a^b)^c equals a^(b*c).

So taking the max uint8, 255...

255^255
< 256^255
= (2^8)^255
= 2^(8x255)
= 2^(2040)

which is clearly more bits than a "tiny" uint256 can hold (2^256 - 1)...

255 ^ 32
< 256 ^ 32
= (2^8)^32
= 2^(8*32)
= 2^256
= one less than the maximum value of a uint256
1
  • I think that ** is safe to use to in Solidity 0.8 and above. The compiler checks for overflows now. Commented Mar 11, 2021 at 10:41
1

Here's a SafeMath based implementation of the power function in solidity using a recursive exponentiation by squaring approach:

function pow(uint n, uint e) public pure returns (uint) {
    
    if (e == 0) {
        return 1;
    } else if (e == 1) {
        return n;
    } else {
        uint p = pow(n, e.div(2));
        p = p.mul(p);
        if (e.mod(2) == 1) {
            p = p.mul(n);
        }
        return p;
    }
}
3
  • What's the advantage of using this over the vanilla ** operator? (Besides overflow safety in Solidity 0.7 and below) Commented Mar 11, 2021 at 10:45
  • AFAIC it's only advantage is overflow safety. If you're dealing with smaller inputs that don't overflow or if you don't care about the consequences of an overflow in your calculations, you can stick with the vanilla operator for better performance Commented Mar 11, 2021 at 11:48
  • Cool, thanks for confirming. I am using Solidity 0.8 so I don't care about overflows. Commented Mar 11, 2021 at 11:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.