4

While investigating an incorrect token award bug in an ERC20, it's come to light that there is an apparent inconsistency in casting with regard to the exponential operator a**b. In particular, the output casts to type b rather than type a.

So when calculating a decimal place exponent 10**exp where exp is defined uint8 exp = 3 the output is truncated to 8 bit giving the answer of 232 rather than 1000.

If the base is definded as uint8 and exponent of longer type, e.g.uint, the compiler will throw an implicit conversion error which indicates the output should be of type base and not exponent.

This doesn't seem to be affected by non-compound parameters which are all cast to 32bit slots anyway.

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;
    }
}
2

From @chriseth responding to the GH issue raised...

The result type of any binary operator in Solidity (also admitting that ** as a non-commutative operator should be treated differently) is a type that can fit both argument types. The result of the expression a**b is always the "larger" type of a and b. Note that the type of the variable the result of the expression is assigned to does not influence the type of the expression itself.

As a solution, I would suggest to use uint(10)**placesA and the compiler should add a warning whenever the base of a ** operator is a constant.

... constants assume the smallest type they fit into as soon as they hit a non-constant.

Further reading on the maths and type casting of literals.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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