You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
At Halborn we were testing slither with some client contracts and encountered the following issue.
Of course, those are anonymized contracts but are able to reproduce the issue well.
The problem seems to occur when two contracts import other two different ones with the same alias (in this case Errors) and one inherit from another. Another example that comes to mind, could be for example, if two different Math libraries are imported as Math.
It doesn't stop the execution of slither, but it is indeed not able to generate the IR for the mentioned cases.
Debbuging the issue
Our working contracts are:
import {
AccessControlErrors as Errors
} from "../errors/ParentContractErrors.sol";
contract ParentContract {
function functionWithAccessControlErrors1(uint256 a, uint256 b) external pure returns (uint256) {
if (a == b) {
revert Errors.AccessControlErrors1();
}
return a + b;
}
function functionWithAccessControlErrors2(uint256 a, uint256 b) external pure returns (uint256) {
if (a < b) {
revert Errors.AccessControlErrors2();
}
return a - b;
}
import {
ParentContract
} from "./ParentContract.sol";
import {
MainErrors as Errors
} from "./../errors/MainErrors.sol";
contract MainContract is ParentContract {
function functionWithMainError1(uint256 a, uint256 b) external pure returns (uint256) {
if (a == b) {
revert Errors.MainError1();
}
return a + b;
}
function functionWithMainError2(uint256 a, uint256 b) external pure returns (uint256) {
if (a < b) {
revert Errors.MainError2();
}
return a - b;
}
function functionWithMainError3(uint256 a, uint256 b) external pure returns (uint256) {
if (b == 0) {
revert Errors.MainError3();
}
return a * b;
}
}
Analyzing and debbuging the code, the issue seems to be in the find_variable.py file and find_variable function, especifically in the following lines of code:
Indeed if we see what is happening with a acouple of prints, like this:
For call Errors.functionWithAccessControlErrors1 and Errors.functionWithAccessControlErrors1, we obtain the following output:
And return the parsed expression as MainErrors.AccessControlErrors1() and MainErrors.AccessControlErrors2(). Those errors do not exist for that contract, through it fails to generate the IR.
Proposed solution
In order to correctly check where to fix the issue, we can print the underlaying function being call in the find variable contract like this:
We can see that there seem to be no mention to AccessControlErrors2(), just to the ParentContract's functions. So we cannot really check there if the final function (AccessControlErrors1 or AccessControlErrors2) function is declared in the var_name contract in this part.
However, if we debug the expression parsing file, at the parse_expression function, we can see that it goes to the Identifier branch in order to call find_variable and printing the expression:
We see there that it is indeed, identifying there the correct library. So a way to solve the issue, could be, after finding the variable, if the variable is a contract and the typeString value is algo a contract, change the var to the contract at the expression, like this:
pattern = r'\b(\w+)\s*\)'
type_string = expression["typeDescriptions"]["typeString"]
type_string_name = re.search(pattern, type_string)
if type_string_name:
found_contract = type_string_name.group(1)
all_contracts_dict = {c.name: c for c in caller_context.compilation_unit.contracts}
if str(var) in all_contracts_dict.keys() and found_contract in all_contracts_dict.keys():
if str(var) != found_contract:
var = all_contracts_dict[found_contract]
ERROR:ContractSolcParsing:Impossible to generate IR for MainContract.functionWithAccessControlErrors1 (contracts/core/ParentContract.sol#13-18):
'NoneType' object has no attribute 'parameters'
ERROR:ContractSolcParsing:Impossible to generate IR for MainContract.functionWithAccessControlErrors2 (contracts/core/ParentContract.sol#20-25):
'NoneType' object has no attribute 'parameters'
The text was updated successfully, but these errors were encountered:
@MarHalborn Would you upgrade to the latest slither version as the latest release fixed many issues related to aliased imports? Let us know if it is still not working please
@0xalpharush I tested with the last version on the master branch of slither and encontoured the issue (it says latest commit was last month, I downloaded it last week )
0xalpharush
changed the title
[Bug-Candidate]: ERROR:ContractSolcParsing when using same alias for import
[Bug]: ERROR:ContractSolcParsing when using same alias for import
May 10, 2024
Describe the issue:
Hello,
At Halborn we were testing slither with some client contracts and encountered the following issue.
Of course, those are anonymized contracts but are able to reproduce the issue well.
The problem seems to occur when two contracts import other two different ones with the same alias (in this case Errors) and one inherit from another. Another example that comes to mind, could be for example, if two different Math libraries are imported as Math.
It doesn't stop the execution of slither, but it is indeed not able to generate the IR for the mentioned cases.
Debbuging the issue
Our working contracts are:
Analyzing and debbuging the code, the issue seems to be in the find_variable.py file and find_variable function, especifically in the following lines of code:
Indeed if we see what is happening with a acouple of prints, like this:
For call Errors.functionWithAccessControlErrors1 and Errors.functionWithAccessControlErrors1, we obtain the following output:
Which, makes this section evaluate to true:
And return the parsed expression as MainErrors.AccessControlErrors1() and MainErrors.AccessControlErrors2(). Those errors do not exist for that contract, through it fails to generate the IR.
Proposed solution
In order to correctly check where to fix the issue, we can print the underlaying function being call in the find variable contract like this:
That returns, for the second one, for example:
We can see that there seem to be no mention to AccessControlErrors2(), just to the ParentContract's functions. So we cannot really check there if the final function (AccessControlErrors1 or AccessControlErrors2) function is declared in the var_name contract in this part.
However, if we debug the expression parsing file, at the parse_expression function, we can see that it goes to the Identifier branch in order to call find_variable and printing the expression:
It returns the following:
We see there that it is indeed, identifying there the correct library. So a way to solve the issue, could be, after finding the variable, if the variable is a contract and the typeString value is algo a contract, change the var to the contract at the expression, like this:
Of course, could be other solutions.
We have implemented this at: https://github.com/halbornlabs/slither and will do a pull request.
Code example to reproduce the issue:
https://github.com/MarHalborn/slither-inheritance-issue.git
Version:
0.10.0
Relevant log output:
The text was updated successfully, but these errors were encountered: