1

I noticed that the following Solidity functions are not equivalent:

function a(int256 x) pure returns (uint256 result) {
    assembly {
        result := div(sub(0, x), x) 
    }
}

function b(int256 x) pure returns (uint256 result) {
    result = -x / x;
}

If we pass 8 as an input, we get two different results back:

a: 14474011154664524427946373126085988481658748083205070504932198000989141204991
b: -1

What gives? I would have expected the results to be the same.

1 Answer 1

1

The explanation has to do with the fact that Solidity (and the EVM) uses the two's complement system to store signed values.

In function a, sub(0, x) has this value (when x is 8):

115792089237316195423570985008687907853269984665640564039457584007913129639928

This number is actually -8 in two's complement. But a does not return -1, because the Yul instruction used is div, which cannot handle signed values.

To make the two functions equivalent, we could instead use the sdiv instruction:

function a(int256 x) pure returns (uint256 result) {
    assembly {
        result := sdiv(sub(0, x), x) 
    }
}

This will return -1 for both a and b.

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.