Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid solc compilation : is it a correct error message? #1611

Open
sunbeomso opened this issue Feb 5, 2020 · 7 comments
Open

Invalid solc compilation : is it a correct error message? #1611

sunbeomso opened this issue Feb 5, 2020 · 7 comments
Assignees

Comments

@sunbeomso
Copy link

OS / Environment

Host OS: Ubuntu 18.04.2

Manticore version

0.3.3 (from docker image)

Python version

3.6.9 (from docker image)

Summary of the problem

Manticore reports Invalid solc compilation, none of the solc versions provided worked, although contracts can be actually compiled by the provided solcs.

Step to reproduce the behavior

Let test.sol be a contract from:
https://etherscan.io/address/0x580c1e3caca14826976b5820947f7ad486ac174d#code

My command was:

sudo docker exec CONTAINER manticore /tmp/test.sol --contract BitcoinAgileToken --core.timeout 1800 --solc-solcs-bin solc-0.4.25 --core.mprocessing single --core.procs 1 --exclude delegatecall,reentrancy,reentrancy-adv,env-instr,ext-call-leak,suicidal,uninitialized-memory,uninitialized-storage,unused-return

Again, I checked that this contract can be compiled with solc 0.4.25.

Expected behavior

If contracts can be compilable by some solcs, then they should be successfully analyzed by Manticore with those solcs.

Actual behavior

Although the contract above can be compiled with solc 0.4.25, Manticore produces a message Invalid solc compilation, none of the solc versions provided worked.

However, if I provided an option --solc-solcs-bin solc-0.4.16 (after installing solc-0.4.16), Manticore successfully works.

Any relevant logs

2020-02-05 08:35:22,090: [752] m.main:^[[34mINFO:^[[0m Registered plugins: DetectManipulableBalance, <class 'manticore.ethereum.plugins.KeepOnlyIfStorageChanges'>, DetectIntegerOverflow, DetectInvalid
2020-02-05 08:35:22,090: [752] m.main:^[[34mINFO:^[[0m Beginning analysis
2020-02-05 08:35:22,092: [752] m.e.manticore:^[[34mINFO:^[[0m Starting symbolic create contract
2020-02-05 08:35:22,101: [752] m.e.manticore:^[[31mERROR:^[[0m Errors : Invalid solc compilation, none of the solc versions provided worked
. Solidity failed to generate bytecode for your contract. Check if all the abstract functions are implemented.
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/manticore/ethereum/manticore.py", line 282, in _compile_through_crytic_compile
    crytic_compile = CryticCompile(filename, **crytic_compile_args)
  File "/usr/local/lib/python3.6/dist-packages/crytic_compile/crytic_compile.py", line 142, in __init__
    self._compile(target, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/crytic_compile/crytic_compile.py", line 915, in _compile
    self._platform.compile(self, target, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/crytic_compile/platform/solc.py", line 66, in compile
    working_dir=solc_working_dir,
  File "/usr/local/lib/python3.6/dist-packages/crytic_compile/platform/solc.py", line 365, in _run_solcs_path
    "Invalid solc compilation, none of the solc versions provided worked"
crytic_compile.platform.exceptions.InvalidCompilation: Invalid solc compilation, none of the solc versions provided worked

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/manticore", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.6/dist-packages/manticore/__main__.py", line 42, in main
    ethereum_main(args, logger)
  File "/usr/local/lib/python3.6/dist-packages/manticore/ethereum/cli.py", line 119, in ethereum_main
    compile_args=vars(args),  # FIXME
  File "/usr/local/lib/python3.6/dist-packages/manticore/ethereum/manticore.py", line 1008, in multi_tx_analysis
    compile_args=compile_args,
  File "/usr/local/lib/python3.6/dist-packages/manticore/ethereum/manticore.py", line 566, in solidity_create_contract
    source_code, contract_name_i, libraries=deps, crytic_compile_args=compile_args
  File "/usr/local/lib/python3.6/dist-packages/manticore/ethereum/manticore.py", line 350, in _compile
    source_code, contract_name, libraries, crytic_compile_args
  File "/usr/local/lib/python3.6/dist-packages/manticore/ethereum/manticore.py", line 319, in _compile_through_crytic_compile
    f"Errors : {e}\n. Solidity failed to generate bytecode for your contract. Check if all the abstract functions are implemented. "
manticore.exceptions.EthereumError: Errors : Invalid solc compilation, none of the solc versions provided worked
. Solidity failed to generate bytecode for your contract. Check if all the abstract functions are implemented.
@montyly
Copy link
Member

montyly commented Feb 19, 2020

Hi @sunbeomso, thank you for reporting this issue.

Can you confirm that solc-0.4.25 is a binary in the PATH? What happens if you run

solc-0.4.25 /tmp/test.sol

@montyly montyly self-assigned this Feb 19, 2020
@sunbeomso
Copy link
Author

Hi @montyly ,

  1. sudo docker exec CONTAINER_NAME solc-0.4.25 --version outputs:
solc, the solidity compiler commandline interface
Version: 0.4.25+commit.59dbf8f1.Linux.g++
  1. sudo docker exec CONTAINER_NAME solc-0.4.25 /tmp/test.sol outputs several warning messages but no error messages:
/tmp/test.sol:6:5: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
    function owned() public {
    ^ (Relevant source part starts here and spans across multiple lines).
/tmp/test.sol:45:5: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
    function TokenERC20() public {
    ^ (Relevant source part starts here and spans across multiple lines).
/tmp/test.sol:20:28: Warning: Functions in interfaces should be declared external.
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }
                           ^-----------------------------------------------------------------------------------------------^
/tmp/test.sol:68:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(_from, _to, _value);
        ^--------------------------^
/tmp/test.sol:145:9: Warning: Invoking events without "emit" prefix is deprecated.
        Burn(msg.sender, _value);
        ^----------------------^
/tmp/test.sol:163:9: Warning: Invoking events without "emit" prefix is deprecated.
        Burn(_from, _value);
        ^-----------------^
/tmp/test.sol:191:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(_from, _to, _value);
        ^--------------------------^
/tmp/test.sol:200:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(0, this, mintedAmount);
        ^-----------------------------^
/tmp/test.sol:201:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(this, target, mintedAmount);
        ^----------------------------------^
/tmp/test.sol:209:9: Warning: Invoking events without "emit" prefix is deprecated.
        FrozenFunds(target, freeze);
        ^-------------------------^
/tmp/test.sol:229:17: Warning: Using contract member "balance" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).balance" instead.
        require(this.balance >= amount * sellPrice);      // checks if the contract has enough ether to buy

Finally, I remark that, for this contract, I resolved the issue by providing an options with different solcs:

--solc-solcs-bin solc-0.4.26,solc-0.4.25,solc-0.4.24,solc-0.4.23,solc-0.4.21,solc-0.4.20,solc-0.4.19,solc-0.4.18,solc-0.4.17,solc-0.4.16,solc-0.4.11

However, I still encountered the similar situations for a few other contracts.

My point is that the produced warning message seems not correct in that the contracts can be compiled with the provided solcs.

@montyly
Copy link
Member

montyly commented Feb 20, 2020

Thanks for the details @sunbeomso.

Most likely it's an issue with crytic-compile, the library that handles solc compilation.

I can't reproduce the issue locally, could you share how the container was created? If you can't share the container, could you try the following commands:

$ sudo docker exec CONTAINER_NAME manticore test.sol --solc solc-0.4.25 --contract BitcoinAgileToken
$ sudo docker exec CONTAINER_NAME crytic-compile --version
$ sudo docker exec CONTAINER_NAME crytic-compile test.sol --solc solc-0.4.25
$ sudo docker exec CONTAINER_NAME crytic-compile test.sol --solc-solcs-bin solc-0.4.25

@sunbeomso
Copy link
Author

@montyly

[1] sudo docker exec CONTAINER_NAME manticore //tmp/test.sol --solc solc-0.4.25 --contract BitcoinAgileToken

With the command above, Manticore successfully begins analysis without error messages.

[2] $ sudo docker exec CONTAINER_NAME crytic-compile --version outputs 0.1.6.

[3, 4] Both commands (sudo docker exec CONTAINER_NAME crytic-compile //tmp/test.sol --solc solc-0.4.25 and sudo docker exec CONTAINER_NAME crytic-compile //tmp/test.sol --solc solc-0.4.25) outputs the same following warning messages:

INFO:CryticCompile:Compilation warnings/errors on //tmp/test.sol:
//tmp/test.sol:6:5: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
    function owned() public {
    ^ (Relevant source part starts here and spans across multiple lines).
//tmp/test.sol:45:5: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
    function TokenERC20() public {
    ^ (Relevant source part starts here and spans across multiple lines).
tmp/test.sol:6:5: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
    function owned() public {
    ^ (Relevant source part starts here and spans across multiple lines).
tmp/test.sol:45:5: Warning: Defining constructors as functions with the same name as the contract is deprecated. Use "constructor(...) { ... }" instead.
    function TokenERC20() public {
    ^ (Relevant source part starts here and spans across multiple lines).
//tmp/test.sol:20:28: Warning: Functions in interfaces should be declared external.
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }
                           ^-----------------------------------------------------------------------------------------------^
//tmp/test.sol:68:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(_from, _to, _value);
        ^--------------------------^
//tmp/test.sol:145:9: Warning: Invoking events without "emit" prefix is deprecated.
        Burn(msg.sender, _value);
        ^----------------------^
//tmp/test.sol:163:9: Warning: Invoking events without "emit" prefix is deprecated.
        Burn(_from, _value);
        ^-----------------^
//tmp/test.sol:191:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(_from, _to, _value);
        ^--------------------------^
//tmp/test.sol:200:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(0, this, mintedAmount);
        ^-----------------------------^
//tmp/test.sol:201:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(this, target, mintedAmount);
        ^----------------------------------^
//tmp/test.sol:209:9: Warning: Invoking events without "emit" prefix is deprecated.
        FrozenFunds(target, freeze);
        ^-------------------------^
//tmp/test.sol:229:17: Warning: Using contract member "balance" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).balance" instead.
        require(this.balance >= amount * sellPrice);      // checks if the contract has enough ether to buy
                ^----------^
tmp/test.sol:20:28: Warning: Functions in interfaces should be declared external.
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }
                           ^-----------------------------------------------------------------------------------------------^
tmp/test.sol:68:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(_from, _to, _value);
        ^--------------------------^
tmp/test.sol:145:9: Warning: Invoking events without "emit" prefix is deprecated.
        Burn(msg.sender, _value);
        ^----------------------^
tmp/test.sol:163:9: Warning: Invoking events without "emit" prefix is deprecated.
        Burn(_from, _value);
        ^-----------------^
tmp/test.sol:191:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(_from, _to, _value);
        ^--------------------------^
tmp/test.sol:200:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(0, this, mintedAmount);
        ^-----------------------------^
tmp/test.sol:201:9: Warning: Invoking events without "emit" prefix is deprecated.
        Transfer(this, target, mintedAmount);
        ^----------------------------------^
tmp/test.sol:209:9: Warning: Invoking events without "emit" prefix is deprecated.
        FrozenFunds(target, freeze);
        ^-------------------------^
tmp/test.sol:229:17: Warning: Using contract member "balance" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).balance" instead.
        require(this.balance >= amount * sellPrice);      // checks if the contract has enough ether to buy
                ^----------^

@sunbeomso
Copy link
Author

sunbeomso commented Feb 20, 2020

@montyly

I can't reproduce the issue locally, could you share how the container was created?

I created the container as follows (which seems there is no unusual part for me):

  1. sudo docker create --entrypoint=/bin/bash --name CONTAINER -it trailofbits/manticore:0.3.3

  2. sudo docker start CONTAINER

  3. Copy solc v. 0.4.25 from my local to the container (assume my solc v 0.4.25 is located in /usr/local/bin/solc_0.4.25):

sudo docker cp /usr/local/bin/solc_0.4.25 CONTAINER:/usr/bin/solc-0.4.25
  1. Run manticore after copying test.sol (which is mentioned above) from my local to the container:
sudo docker cp test.sol CONTAINER:/tmp/test.sol

sudo docker exec CONTAINER manticore /tmp/test.sol --contract BitcoinAgileToken --core.timeout 1800 --solc-solcs-bin solc-0.4.25 --core.mprocessing single --core.procs 1 --exclude delegatecall,reentrancy,reentrancy-adv,env-instr,ext-call-leak,suicidal,uninitialized-memory,uninitialized-storage,unused-return

@sunbeomso
Copy link
Author

@montyly

I can't reproduce the issue locally,

Could you try my steps described above?

I have just tried again my steps above without any modifications, and I double-checked that I still encounter the error message Invalid solc compilation.

Of course, sudo docker exec CONTAINER solc-0.4.25 /tmp/test.sol outputs warning messages but no error messages.

@sunbeomso
Copy link
Author

sunbeomso commented Aug 10, 2020

@montyly Hi, could you tell me about the progress of this issue?

With the latest Manticore (v.0.3.4), I still encounter problems (Manticore produces Invalid solc compilation messages for contracts that can be compiled with provided solcs).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants