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

AttributeError: 'NoneType' object has no attribute 'is_analyzed' #123

Closed
BlinkyStitt opened this issue Jan 7, 2019 · 12 comments
Closed

Comments

@BlinkyStitt
Copy link

$ slither .
ERROR:root:Error in .
ERROR:root:Traceback (most recent call last):
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 241, in main_impl
    (results, number_contracts) = process_truffle(filename, args, detector_classes, printer_classes)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 81, in process_truffle
    return process_files(filenames, args, detector_classes, printer_classes)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 91, in process_files
    slither = Slither(all_contracts, args.solc, args.disable_solc_warnings, args.solc_args)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/slither.py", line 41, in __init__
    self._analyze_contracts()
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 179, in _analyze_contracts
    self._analyze_all_enums(contracts_to_be_analyzed)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 213, in _analyze_all_enums
    all_father_analyzed = all(father.is_analyzed for father in contract.inheritance)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 213, in <genexpr>
    all_father_analyzed = all(father.is_analyzed for father in contract.inheritance)
AttributeError: 'NoneType' object has no attribute 'is_analyzed'

I created the contract json in a very non-standard way, so I'm sure that is at the heart of the issue. It is probably missing a section since I only include the abi, ast, and bytecode. What else does slither need?

@montyly
Copy link
Member

montyly commented Jan 8, 2019

The issue is that the json you manually created is missing a part of the code.

If you look at the inheritance of GasToken2:

        "linearizedBaseContracts": [
          536,
          722
        ],
  • 536 is the id of GasToken2
  • 722 is the id of Rlp, but the its definition is not present in the json

Slither needs access to all the source code to work, so you need to add the definition of Rlp.
If you compile both contracts separately, the id generated may differ (the AST of Rlp can give an id different than 722), so you will need to manually update them.

Out of curiosity, is there a particular reason from crafting the json manually?

@BlinkyStitt
Copy link
Author

BlinkyStitt commented Jan 8, 2019 via email

@BlinkyStitt
Copy link
Author

BlinkyStitt commented Jan 8, 2019

So that error was happening with the output from this solc command:

solc-0.4.25 \
    --allow-paths "${gastoken_contract_dir}" \
    --optimize \
    --output-dir "${build_dir}/gastoken" \
    --abi --ast-compact-json --bin \
    "=${gastoken_contract_dir}/" \
    "${gastoken_contract_dir}/GST2_ETH.sol"

I think compact is missing some things that are needed though and I added rlp.sol to the command.

solc-0.4.25 \
    --allow-paths "${gastoken_contract_dir}" \
    --optimize \
    --output-dir "${build_dir}/gastoken" \
    --abi --ast-json --bin \
    "=${gastoken_contract_dir}/" \
    "${gastoken_contract_dir}/"{GST2_ETH,rlp}.sol

Then I prepend the bin output with "0x" and rename it to *.truffle-bin.

Truffle is building it with this config:


    external: {
      command: "./scripts/build-external.sh",
      targets: [
        {
          properties: {
            contractName: "GasToken2",
          },
          fileProperties: {
            abi: "build/gastoken/GasToken2.abi",
            ast: "build/gastoken/GST2_ETH.sol_json.ast",
            bytecode: "build/gastoken/GasToken2.truffle-bin",
          },
        },
        // TODO: more contracts. gastoken/rlp?
      ],
    },

But now I get this error:

ERROR:root:Error in .
ERROR:root:Traceback (most recent call last):
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 241, in main_impl
    (results, number_contracts) = process_truffle(filename, args, detector_classes, printer_classes)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 81, in process_truffle
    return process_files(filenames, args, detector_classes, printer_classes)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 91, in process_files
    slither = Slither(all_contracts, args.solc, args.disable_solc_warnings, args.solc_args)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/slither.py", line 32, in __init__
    self._parse_contracts_from_loaded_json(c, path)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 69, in _parse_contracts_from_loaded_json
    if data_loaded[self.get_key()] == 'root':
KeyError: 'nodeType'

I feel like I am making this more complex than it should be. What's the right way to build the json for slither to parse?

@montyly
Copy link
Member

montyly commented Jan 8, 2019

Could you share the code that your are trying to analyze?

I am not sure to understand why you need a manual json editing.

If your project is a truffle project, running slither . on top of the truffle directory will be enough. I would recommend deleting the build directory before running slither, in case you have manually edited files in it.

@BlinkyStitt
Copy link
Author

BlinkyStitt commented Jan 8, 2019

My project is a truffle project. The problem is that I'm also including other projects (just https://github.com/projectchicago/gastoken for now) that aren't truffle projects and I need to build them for my test blockchain, too. It's likely that this is an issue with truffle's external compiler step or my use of it.

I'm not manually editing JSON. Truffle is doing that part. I'm just passing output from solc to truffle like I thought I was supposed to. I'm able to deploy the contract, so I know that part of solc/truffle output is correct.

More detail here: trufflesuite/truffle#1607

@montyly
Copy link
Member

montyly commented Jan 8, 2019

I see!

I am not entirely sure about the error:

  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 69, in _parse_contracts_from_loaded_json
    if data_loaded[self.get_key()] == 'root':
KeyError: 'nodeType'

Is it possible that the generated json mixes the solc compact ast format with the legacy one? If it folows only the compact ast format, each node should have a nodeType item (and so data_loaded should have it too)

If you have a minimal codebase that produces the same error, I can try to reproduce it

@BlinkyStitt
Copy link
Author

Oh, so we do want --ast-compact-json and not --ast-json. I'll put it back to that and see what happens. If that doesn't work, I'll push my repo to GitHub so you can take a look.

Thanks for the help!

@BlinkyStitt
Copy link
Author

Oh right. Switching to --ast-compact-json brings back the originally reported error.

# yarn slither .
yarn run v1.12.3
$ slither .
INFO:Slither:truffle compile running...
INFO:Slither:Building external contracts...
Clearing old builds...
Building gastoken...
Success building external contracts
Writing artifacts to ./build/contracts

Compiling ./contracts/Bank.sol...
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/MultipleActions.sol...
Compiling ./contracts/interface/IGastoken2.sol...
Compiling ./contracts/lib/ERC20SafeTransfer.sol...
Compiling ./contracts/test/TestERC20s.sol...
Compiling openzeppelin-solidity/contracts/access/Roles.sol...
Compiling openzeppelin-solidity/contracts/access/roles/PauserRole.sol...
Compiling openzeppelin-solidity/contracts/access/roles/WhitelistAdminRole.sol...
Compiling openzeppelin-solidity/contracts/access/roles/WhitelistedRole.sol...
Compiling openzeppelin-solidity/contracts/lifecycle/Pausable.sol...
Compiling openzeppelin-solidity/contracts/math/Math.sol...
Compiling openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling openzeppelin-solidity/contracts/ownership/Ownable.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/IERC20.sol...
Compiling openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol...
Writing artifacts to ./build/contracts


ERROR:Slither:/usr/src/app/external/gastoken/contract/GST2_ETH.sol:162:13: Warning: Return value of low-level calls not used.
            mk_contract_address(this, i).call();
            ^---------------------------------^

ERROR:root:Error in .
ERROR:root:Traceback (most recent call last):
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 241, in main_impl
    (results, number_contracts) = process_truffle(filename, args, detector_classes, printer_classes)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 81, in process_truffle
    return process_files(filenames, args, detector_classes, printer_classes)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/__main__.py", line 91, in process_files
    slither = Slither(all_contracts, args.solc, args.disable_solc_warnings, args.solc_args)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/slither.py", line 41, in __init__
    self._analyze_contracts()
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 179, in _analyze_contracts
    self._analyze_all_enums(contracts_to_be_analyzed)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 213, in _analyze_all_enums
    all_father_analyzed = all(father.is_analyzed for father in contract.inheritance)
  File "/root/.local/venvs/slither-analyzer/lib/python3.6/site-packages/slither/solc_parsing/slitherSolc.py", line 213, in <genexpr>
    all_father_analyzed = all(father.is_analyzed for father in contract.inheritance)
AttributeError: 'NoneType' object has no attribute 'is_analyzed'

error Command failed with exit code 255.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

@montyly
Copy link
Member

montyly commented Jan 8, 2019

Could you check that all the ids in the linearizedBaseContracts items of the json refer to a ContractDefinition node id?

@BlinkyStitt
Copy link
Author

I'm pretty new to this, but I think the definition for rlp is missing. I guess adding rlp.sol to the end of my solc command isn't enough.

https://gist.github.com/WyseNynja/e76a61f1564650ba34a037648d5fcc60

@montyly
Copy link
Member

montyly commented Jan 8, 2019

I am able to have slither working, but its a bit tricky:

  • In an empty directory, run touch truffle.js and create a subdirectory build/contracts
  • Copy GasToken2.json file to build/contracts
  • Extract the json from rlp.sol: solc-0.4.25 rlp.sol --ast-compact-json > rlp.json
  • Edit rlp.json:
    • Change the id of the contract to 722, (it should be at lines 11, 36, and 39)
    • Add an extra } at the end of the file
    • Replace the header
JSON AST (compact format):


======= ../rlp.sol =======

by

{
"sourcePath":"rlp.sol",
  • Copy rlp.json to build/contracts
  • Run slither .

Truffle should generate the rlp.json file automatically, but maybe it does not as you provide an extra compilation step (and you use two different compiler versions)

@BlinkyStitt
Copy link
Author

BlinkyStitt commented Jan 8, 2019

That is certainly trickier than I was hoping for. Your directions pointed me to a typo that got what I have working though! A bad copy/paste had me using the same ast file for both GST2 and rlp.

./scripts/build-external.sh

#!/bin/bash -eu
echo "Building external contracts..."

# TODO: only run if they are outdated

script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

root_dir="$(realpath "${script_dir}/../")"

build_dir="${root_dir}/build"

external_dir="${root_dir}/external"

# clearing old builds
# TODO: move to a temp dir instead?
echo "Clearing old builds..."
rm -rf "${build_dir}"
mkdir -p "${build_dir}"

# gastoken
echo "Building gastoken..."
gastoken_contract_dir="${external_dir}/gastoken/contract"
solc-0.4.25 \
    --allow-paths "${gastoken_contract_dir}" \
    --optimize \
    --output-dir "${build_dir}/gastoken" \
    --abi --ast-compact-json --bin \
    "=${gastoken_contract_dir}/" \
    "${gastoken_contract_dir}/"{GST2_ETH,rlp}.sol

for bin in "${build_dir}/"*"/"*.bin; do
    bin_dir=$(dirname -- "$bin")
    filename=$(basename -- "$bin")
    filename="${filename%.*}"

    # bin output needs to be prefixed with 0x for truffle to like it
    (echo -n "0x"; cat "$bin") > "${bin_dir}/${filename}.truffle-bin"
done

echo "Success building external contracts"

truffle-config.js

module.exports = {
  ...
  compilers: {
    external: {
      command: "./scripts/build-external.sh",
      targets: [
        {
          properties: {
            contractName: "GasToken2",
          },
          fileProperties: {
            abi: "build/gastoken/GasToken2.abi",
            ast: "build/gastoken/GST2_ETH.sol_json.ast",
            bytecode: "build/gastoken/GasToken2.truffle-bin",
          },
        },
        {
          properties: {
            contractName: "rlp",
          },
          fileProperties: {
            abi: "build/gastoken/rlp.abi",
            ast: "build/gastoken/rlp.sol_json.ast",
            bytecode: "build/gastoken/rlp.truffle-bin",
          },
        },
      ],
    },
...
$ yarn slither .
...
INFO:Slither:. analyzed (19 contracts), 75 result(s) found

I have a feeling that my truffle-config.js is going to get pretty long if I have to do this for all the upstream projects. Luckily 0x has a very helpful migrate script that I can use instead of manually compiling like I'm doing for gastoken.

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