Skip to content

Unexpected implicit casting in Solidity's exponential operator #1738

@o0ragman0o

Description

@o0ragman0o

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions