ethereum / solidity

Solidity, the Smart Contract Programming Language
https://soliditylang.org
GNU General Public License v3.0
23.29k stars 5.77k forks source link

Optimizer failed to remove statement always true #14472

Open hpumengzhao opened 1 year ago

hpumengzhao commented 1 year ago

Description

For the following contract

pragma solidity ^0.8.0;

contract ComplexProgram {
    uint256 public globalVariable;
    struct MyStruct {
        uint256 value;
        bool flag;
    }
    function complexFunction() public view{
            MyStruct memory myStruct;
            myStruct.flag = true;
            uint256 x = 1;
            require(globalVariable != 0, "Global variable cannot be zero");
            assert(myStruct.flag == true);//failed to optimize
            assert(x == 1);
    }
}

The IR optimizer failed to remove assert(myStruct.flag == true);. But if i move the statement to the before of require(globalVariable != 0, "Global variable cannot be zero");. It can be optimized.

pragma solidity ^0.8.0;

contract ComplexProgram {
    uint256 public globalVariable;
    struct MyStruct {
        uint256 value;
        bool flag;
    }
    function complexFunction() public view{
            MyStruct memory myStruct;
            myStruct.flag = true;
            uint256 x = 1;
            assert(myStruct.flag == true);//can be optimized
            require(globalVariable != 0, "Global variable cannot be zero");
            assert(x == 1);
    }
}

Environment

gkirat commented 1 year ago

@hpumengzhao The reason why you aren't able to go ahead with code is because of the require statement, You see that in your require statement it is necessary to assign global variable a non zero number because initially in solidity the default value of uint data type is "0".

So this can be solved by 4 ways

1. Assign value to globalVariable inside function before the require statement so when the function runs it assigns the value to state variable "globalVariable" and then read require statement


/ / SPDX-License-Identifier: MIT
 pragma solidity ^0.8.0;

contract ComplexProgram {
    uint256 public globalVariable;
    struct MyStruct {
        uint256 value;
        bool flag;
    }

    function complexFunction1() public {
        MyStruct memory myStruct;
        myStruct.flag = true;
        uint256 x = 1;

        // Set globalVariable to a non-zero value before the require statement
        globalVariable = 1; // Or any other non-zero number

        // Perform assertions
        assert(myStruct.flag == true);
        require(globalVariable != 0, "Global variable cannot be zero");
        assert(x == 1);
    }
}

2.Assign the value of globalVariable by passing the value in the argument of the function

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ComplexProgram {

    uint256 public globalVariable;
    struct MyStruct {
        uint256 value;
        bool flag;
    }

    function complexFunction2(uint number) public {
        MyStruct memory myStruct;
        myStruct.flag = true;
        uint256 x = 1;

        // Set globalVariable to the value passed as an argument
        globalVariable = number;

        // Perform assertions
        assert(myStruct.flag == true);
        require(globalVariable != 0, "Global variable cannot be zero");
        assert(x == 1);
    }
}

3.By initially assigning the value to the globalVariable

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ComplexProgram {
    uint256 public globalVariable = 1; // Or any other non-zero number
    struct MyStruct {
        uint256 value;
        bool flag;
    }

    function complexFunction3() public view {
        MyStruct memory myStruct;
        myStruct.flag = true;
        uint256 x = 1;

        // Perform assertions
        assert(myStruct.flag == true);
        require(globalVariable != 0, "Global variable cannot be zero");
        assert(x == 1);
    }
}

4. Or just by removing the require statement from the code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ComplexProgram {
    uint256 public globalVariable;
    struct MyStruct {
        uint256 value;
        bool flag;
    }

    function complexFunction4() public pure {
        MyStruct memory myStruct;
        myStruct.flag = true;
        uint256 x = 1;

        // Perform assertions without the require statement
        assert(myStruct.flag == true);
        assert(x == 1);
    }
}