foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.09k stars 1.67k forks source link

Foundry treats only 0x01 as true, instead of all non-zero values #4067

Closed lmanini closed 1 year ago

lmanini commented 1 year ago

Component

Forge, Chisel

Have you ensured that all of these are up to date?

What version of Foundry are you on?

forge 0.2.0 (2ff9902 2023-01-11T00:10:20.160113215Z)

What command(s) is the bug in?

forge test

Operating System

Linux

Describe the bug

When returning a boolean in yul, the underlying VM treats only 0x01 as a true value instead of all non zero values, which is different behaviour from that shown by Remix IDE.

Following is an image showing how 0x02 is treated as false. The same getBool() function, when called on Remix with value = 2 returns true

image

DaniPopes commented 1 year ago

It's not that the returned value isn't interpreted as true, it's that the instructions, automatically generated by Solidity, that check the return value expect either a 0 or a 1, and reverts on all other values. If you enable traces you can see that the function returns the value correctly but it reverts after that, and not with the "assert" revert message.

You'd have to try this snippet on Remix:

pragma solidity ^0.8.0;

contract Bools {
    function getBool(uint256 x) external pure returns (bool) {
        assembly {
            mstore(0x00, x)
            return(0x00, 0x20)
        }
    }

    function getBoolExt(uint256 x) external view returns(bool) {
        return this.getBool(x);
    }
}

If you call getBoolExt(x), which will create a new EVM call context, with any value other than 0 or 1 it will revert with no message, AKA "Reason: EVMError: Revert"

if you call getBool(x) from outside the EVM (remix call button) it will not revert because the part that reverts is the return value check

rakita commented 1 year ago

So solidity is strict and "bool" must be 0 or 1 or it will revert if it is not, and this check is not done in pure functions but the outside of it. fun times

lmanini commented 1 year ago

thank you for the explainer @DaniPopes - didn't know the return value check was so restrictive. although, such a restrictive check doesn't seem very logical to me..