Exception on Echidna printer, 'TypeConversion' object has no attribute 'value'
Describe the issue:
When running Echidna with the command:
echidna ./ --config test/echidna-fuzzer/config.yaml --contract Fuzzer
I encounter the following warning:
WARNING: Running slither failed. Echidna will continue, however fuzzing will likely be less effective.
However, running Slither independently with: slither . succeeds and outputs:
INFO:Slither:. analyzed (113 contracts with 100 detectors), 493 result(s) found
Similarly, running slither --print echidna --json - . also succeeds without errors:
{"success": true, "error": null, "results": {"printers": ....}}
Could you help identify why Echidna fails to run Slither, despite Slither working independently? Are there specific logs or debugging steps I can use to diagnose this issue?
Code example to reproduce the issue:
.
Version:
echidna --version
Echidna 2.2.6
slither --version
0.11.3
Relevant log output:
Hi! Can you post your echidna config? in particular, do you have anything added to cryticArgs or solcArgs?
Can you also confirm if the following works and prints 0 at the end? If you have anything added to cryticArgs, add it to both the crytic-compile and slither commands.
crytic-compile --solc-disable-warnings --export-format solc ./
slither --ignore-compile --print echidna --json - ./
echo $?
my echidna config:
# Config wiki: https://github.com/crytic/echidna/wiki/Config
testMode: "assertion"
testLimit: 999999999999999999 # unlimited
deployer: "0x10000"
I did the test with these commands:
crytic-compile --solc-disable-warnings --export-format solc ./
slither --ignore-compile --print echidna --json - ./
echo $?
they both returns the status code 0
What does your project look like? What compilation framework are you using?
Can you confirm if a simpler project works on your setup? For example
mkdir ~/example
cd ~/example
forge init
echidna ./ --test-mode assertion
If it does not, can you post the log of that?
The "Running slither failed" error message roughly translates to "slither exited with non-zero code" so you should consider why that might be and what differences there might be with your attempts on the shell (e.g. maybe you have somehow a different PATH set up, or your shell aliases slither to something else, and that's why it appears to work manually)
https://github.com/crytic/echidna/blob/master/lib/Echidna/SourceAnalysis/Slither.hs#L176-L181
@elopez It appears that the slither analysis in the echidna test fails due to an assertion in the contract:
assert(IERC20(WETH).balanceOf(address(player1)) <= 2.0001 ether);
However, when the assertion is separated into two steps:
uint256 balance = IERC20(WETH).balanceOf(address(player1));
assert( balance <= 2.0001 ether );
The slither test in echidna passes successfully.
Btw, the slither command slither --ignore-compile --print echidna --json - ./ works correctly in both scenarios.
hm, interesting. Can you prepare a small testcase that shows the issue to try and debug this further?
@elopez sure. You can use this test case:
mkdir ~/example
cd ~/example
forge init
pragma solidity ^0.8.13;
contract Counter {
uint256 public number;
function setNumber(uint256 newNumber) public {
number = newNumber;
}
function increment() public {
number++;
}
function assertEthBalance() public {
uint256 balance = address(0x2c39Ca299b4A1Af7eAE50Fb2B6A18dBb0Ec65E1b).balance;
assert(balance == 0);
// the slither on echidna will fail if the below assertion is enabled.
// assert(address(0x2c39Ca299b4A1Af7eAE50Fb2B6A18dBb0Ec65E1b).balance == 0);
}
}
Thanks, I can reproduce the failure locally with Slither. I'll move the issue to the Slither repo so it can be addressed there, as it is not a problem on the Echidna side.
$ slither --print echidna .
'forge clean' running (wd: /private/tmp/ddd)
'forge config --json' running
'forge build --build-info --skip */test/** */script/** --force' running (wd: /private/tmp/ddd)
Traceback (most recent call last):
File "/opt/homebrew/bin/slither", line 8, in <module>
sys.exit(main())
~~~~^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/__main__.py", line 776, in main
main_impl(all_detector_classes=detectors, all_printer_classes=printers)
~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/__main__.py", line 882, in main_impl
) = process_all(filename, args, detector_classes, printer_classes)
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/__main__.py", line 107, in process_all
) = process_single(compilation, args, detector_classes, printer_classes)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/__main__.py", line 87, in process_single
return _process(slither, detector_classes, printer_classes)
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/__main__.py", line 143, in _process
printer_results = slither.run_printers()
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/slither.py", line 302, in run_printers
return [p.output(self._crytic_compile.target).data for p in self._printers]
~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/printers/guidance/echidna.py", line 454, in output
(cst_used, cst_used_in_binary) = _extract_constants(contracts)
~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/printers/guidance/echidna.py", line 285, in _extract_constants
_extract_constants_from_irs(
~~~~~~~~~~~~~~~~~~~~~~~~~~~^
function.all_slithir_operations(),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<2 lines>...
context_explored,
^^^^^^^^^^^^^^^^^
)
^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/printers/guidance/echidna.py", line 245, in _extract_constants_from_irs
_extract_constant_from_binary(ir, all_cst_used, all_cst_used_in_binary)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/printers/guidance/echidna.py", line 231, in _extract_constant_from_binary
cst = ConstantFolding(ir.expression, type_).result()
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/visitors/expression/constants_folding.py", line 60, in __init__
super().__init__(expression)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/visitors/expression/expression.py", line 59, in __init__
self._visit_expression(self.expression)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/visitors/expression/expression.py", line 76, in _visit_expression
visitor(expression)
~~~~~~~^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/visitors/expression/expression.py", line 87, in _visit_binary_operation
self._visit_expression(expression.expression_left)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/visitors/expression/expression.py", line 78, in _visit_expression
self._post_visit(expression)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/visitors/expression/expression.py", line 276, in _post_visit
self._post_member_access(expression)
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
File "/opt/homebrew/Cellar/slither-analyzer/0.11.3/libexec/lib/python3.13/site-packages/slither/visitors/expression/constants_folding.py", line 360, in _post_member_access
isinstance(expression.expression.value, Contract)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'TypeConversion' object has no attribute 'value'