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

Unable to load Solidity contract using compile_standard function due to error Second argument needs to be a buffer #42

Open
ltfschoen opened this issue Dec 30, 2017 · 1 comment

Comments

@ltfschoen
Copy link

  • py-solc Version: 2.1.0 (shown when running pip list)
  • solc Version: 0.4.18+commit.9cf6e910.Emscripten.clang (shown when running solc --version)
  • Python Version: 3.6.4rc1 (shown when running python --version)
  • OS: osx - macOS 10.12.6

What was wrong?

I used PyEnv to install and switch to the latest Python version 3.6.4rc1 https://github.com/pyenv/pyenv. I then installed the following Python packages:

pyenv install 3.6.4rc1
pyenv versions
pyenv global 3.6.4rc1
python -m pip install py-solc==2.1.0
python -m solc.install v0.4.18
python -m pip install web3==4.0.0b5 
python -m pip install ethereum==2.1.5
python scripts/main.py

I then created and executed a Python file i.e. main.py with python main.py:
main.py

import solc
from solc import compile_files
compiled_sol = compile_files(["FixedSupplyToken.sol"])

Note that the Solidity file I am using is in my repo here https://github.com/ltfschoen/geth-node/blob/master/contracts/FixedSupplyToken.sol, and it compiles successfully with solc v0.4.18, as I've done so in MIST and deployed it to a Private Network previously already.

I'm trying to replicate using Web3.py and py-solc the same functionality that worked when I used Web3.js and solc-js here: https://github.com/ltfschoen/geth-node/blob/master/scripts/main.js

In the file I use py-solc to compile Solidity source code from a file using the function compile_files, but I get a full output error in Bash terminal as follows:

$ python main.py 
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    compiled_sol = compile_files(["FixedSupplyToken.sol"])
  File "/Users/Ls/.pyenv/versions/3.6.4rc1/lib/python3.6/site-packages/solc/main.py", line 133, in compile_files
    stdoutdata, stderrdata, command, proc = solc_wrapper(**compiler_kwargs)
  File "/Users/Ls/.pyenv/versions/3.6.4rc1/lib/python3.6/site-packages/solc/utils/string.py", line 85, in inner
    return force_obj_to_text(fn(*args, **kwargs))
  File "/Users/Ls/.pyenv/versions/3.6.4rc1/lib/python3.6/site-packages/solc/wrapper.py", line 165, in solc_wrapper
    stderr_data=stderrdata,
solc.exceptions.SolcError: An error occurred during execution
> command: `solc --combined-json abi,asm,ast,bin,bin-runtime,clone-bin,devdoc,interface,opcodes,userdoc FixedSupplyToken.sol`
> return code: `1`
> stderr:

> stdout:
Invalid option selected, must specify either --bin or --abi

I then looked closer at the Py-Solc documentation here: https://github.com/ethereum/py-solc#standard-json-compilation, and changed my code to use the same syntax as the second example under the heading "Standard JSON Compilation":
main.py

import solc
from solc import compile_standard
compiled_sol = compile_standard({
  'language': 'Solidity',
  'sources': {'FixedSupplyToken.sol': 'urls': ["./contracts/FixedSupplyToken.sol"]},
}, allow_paths="./contracts/")

But when I run this it gives another error in the Bash terminal, which is because the example is missing a { just before 'urls':

$ python main.py 
  File "main.py", line 5
    'sources': {'FixedSupplyToken.sol': 'urls': ["FixedSupplyToken.sol"]},
                                              ^
SyntaxError: invalid syntax

So I added the missing {, and I used a JSON Validator to make sure the argument was valid json format:

main.py

import solc
from solc import compile_standard
compiled_sol = compile_standard({
  "language": "Solidity",
  "sources": {
    "FixedSupplyToken.sol": {
      "urls": ["file:///Users/Ls/code/blockchain/geth-node/contracts/FixedSupplyToken.sol"]
    }
  }
}, allow_paths="file:///Users/Ls/code/blockchain/geth-node/contracts/")

But then it gave me error:

$ python main.py 
Traceback (most recent call last):
  File "main.py", line 10, in <module>
    }, allow_paths="./contracts/")
  File "/Users/Ls/.pyenv/versions/3.6.4rc1/lib/python3.6/site-packages/solc/main.py", line 161, in compile_standard
    **kwargs
  File "/Users/Ls/.pyenv/versions/3.6.4rc1/lib/python3.6/site-packages/solc/utils/string.py", line 85, in inner
    return force_obj_to_text(fn(*args, **kwargs))
  File "/Users/Ls/.pyenv/versions/3.6.4rc1/lib/python3.6/site-packages/solc/wrapper.py", line 165, in solc_wrapper
    stderr_data=stderrdata,
solc.exceptions.SolcError: An error occurred during execution
        > command: `solc --allow-paths file:///Users/Ls/code/blockchain/geth-node/contracts/ --standard-json`
        > return code: `1`
        > stderr:

        > stdout:
        /Users/Ls/.nvm/versions/node/v8.7.0/lib/node_modules/solc/node_modules/graceful-fs/polyfills.js:144
        throw er
        ^

TypeError: Second argument needs to be a buffer
    at Object.fs.readSync (fs.js:682:18)
    at Object.readSync (/Users/Ls/.nvm/versions/node/v8.7.0/lib/node_modules/solc/node_modules/graceful-fs/polyfills.js:138:28)
    at Object.<anonymous> (/Users/Ls/.nvm/versions/node/v8.7.0/lib/node_modules/solc/solcjs:65:18)
    at Module._compile (module.js:624:30)
    at Object.Module._extensions..js (module.js:635:10)
    at Module.load (module.js:545:32)
    at tryModuleLoad (module.js:508:12)
    at Function.Module._load (module.js:500:3)
    at Function.Module.runMain (module.js:665:10)
    at startup (bootstrap_node.js:187:16)

So then I clicked the link that says "Solidity Documentation for Standard JSON input and ouptup format" (FYI, note the typo here in the word "output") http://solidity.readthedocs.io/en/develop/using-the-compiler.html#compiler-input-and-output-json-description, specifically the section http://solidity.readthedocs.io/en/develop/using-the-compiler.html#input-description.

It highlighted that that object we are passing to compile_standard is an Input JSON Description, which the compiler API expects to be in JSON format, and it outputs the compilation result in a JSON formatted output.

When looked more closely at the error, which says solc --allow-paths file:///Users/Ls/code/blockchain/geth-node/contracts/ --standard-json, it's clearly missing a JSON file as an input argument at the end.
Is this something that the compiler is supposed to automatically generate? A similar error was raised in the solc-js repo issues here ethereum/solc-js#126

I tried experimenting a bit more trying to find an alternative and found that I'm able to manually created ABI files in Bash terminal with the command: solc --abi FixedSupplyToken.sol --output-dir ./build, which generates the following in the ./build/ folder:

  • __FixedSupplyToken_sol_ERC20Interface.abi
  • __FixedSupplyToken_sol_FixedSupplyToken.abi

But I don't know how to load these generated ABI files into the variable contract_interface in main.py. Currently my code is contract_interface = compiled_sol['<stdin>:FixedSupplyToken'],

I then tried copying the JSON argument into a file called test.json.
test.json

{
  "language": "Solidity",
  "sources": {
    "FixedSupplyToken.sol": {
      "urls": ["file:///Users/Ls/code/blockchain/geth-node/contracts/FixedSupplyToken.sol"]
    }
  }
}

I then ran the following:

solc --standard-json test.json --output-dir ./build

But it just returned the following;

Empty input was read

So I don't even understand how to use the CLI.
Any help greatly appreciated
I've pushed my latest code here: https://github.com/ltfschoen/geth-node/blob/master/scripts/main.py

Cute Animal Picture

Python

@ltfschoen
Copy link
Author

I tried changing to the following in https://github.com/ltfschoen/geth-node/blob/master/scripts/main.py and passed additional arguments defined in https://github.com/ethereum/py-solc/blob/master/solc/wrapper.py to the compile_files function. I also modified https://github.com/ethereum/py-solc/blob/master/solc/wrapper.py, moving the conditional check for source_files after the conditional check for abi to try and get it to run
solc --output-dir ./ --allow-paths ./ --bin ./contracts/FixedSupplyToken.sol

Changes to https://github.com/ethereum/py-solc/blob/master/solc/wrapper.py

...
if abi:
    command.append('--abi')

if source_files is not None:
    # command.extend(source_files)
    command.append(source_files['sources']['FixedSupplyToken.sol']['urls'][0])  
...

Changes to https://github.com/ltfschoen/geth-node/blob/master/scripts/main.py

# Standard JSON Compilation - https://github.com/ethereum/py-solc#standard-json-compilation
compiled_sol = compile_files({
  "language": "Solidity",
  "sources": {
    "FixedSupplyToken.sol": {
      "urls": ["../contracts/FixedSupplyToken.sol"]
    }
  }
}, 
output_dir="./",
bin=True,
allow_paths="./")

But it just outputs binary files in the current directory instead of assigning to the variable

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

1 participant