add unit tests

pull/1782/head
alpharush 2 years ago
parent c9fa73b216
commit bfe38cfd79
  1. 17
      tests/unit/core/test_arithmetic.py
  2. 60
      tests/unit/core/test_code_comments.py
  3. 106
      tests/unit/core/test_constant_folding.py
  4. 43
      tests/unit/core/test_contract_declaration.py
  5. 29
      tests/unit/core/test_data/arithmetic_usage/test.sol
  6. 88
      tests/unit/core/test_data/complex_func.sol
  7. 14
      tests/unit/core/test_data/constant_folding/constant_folding_binop.sol
  8. 9
      tests/unit/core/test_data/constant_folding/constant_folding_rational.sol
  9. 7
      tests/unit/core/test_data/constant_folding/constant_folding_unary.sol
  10. 5
      tests/unit/core/test_data/contract_declaration/abstract.sol
  11. 5
      tests/unit/core/test_data/contract_declaration/implicit_abstract.sol
  12. 13
      tests/unit/core/test_data/contract_declaration/private_variable.sol
  13. 7
      tests/unit/core/test_data/custom_comments/contract_comment.sol
  14. 16
      tests/unit/core/test_data/custom_comments/upgrade.sol
  15. 27
      tests/unit/core/test_data/deprecated_calls.sol
  16. 130
      tests/unit/core/test_data/function_declaration/test_function.sol
  17. 36
      tests/unit/core/test_data/function_declaration/test_function_reentrant.sol
  18. 100
      tests/unit/core/test_data/inheritance_graph.sol
  19. 22
      tests/unit/core/test_data/source_mapping.sol
  20. 19
      tests/unit/core/test_data/src_mapping/ReferencesUserDefinedAliases.sol
  21. 19
      tests/unit/core/test_data/src_mapping/ReferencesUserDefinedTypesCasting.sol
  22. 35
      tests/unit/core/test_data/src_mapping/inheritance.sol
  23. 1
      tests/unit/core/test_data/storage_layout/StorageLayout.abi
  24. 1
      tests/unit/core/test_data/storage_layout/StorageLayout.bin
  25. 576
      tests/unit/core/test_data/storage_layout/TEST_storage_layout.json
  26. 74
      tests/unit/core/test_data/storage_layout/storage_layout-0.8.10.sol
  27. 18
      tests/unit/core/test_data/taint_mapping.sol
  28. 27
      tests/unit/core/test_data/using_for/using-for-3-0.8.0.sol
  29. 25
      tests/unit/core/test_data/using_for/using-for-4-0.8.0.sol
  30. 14
      tests/unit/core/test_data/using_for/using-for-alias-contract-0.8.0.sol
  31. 11
      tests/unit/core/test_data/using_for/using-for-alias-dep1.sol
  32. 9
      tests/unit/core/test_data/using_for/using-for-alias-dep2.sol
  33. 15
      tests/unit/core/test_data/using_for/using-for-alias-top-level-0.8.0.sol
  34. 14
      tests/unit/core/test_data/using_for/using-for-in-library-0.8.0.sol
  35. 2
      tests/unit/core/test_data/using_for/using_for_global_collision/src/MyTypeA.sol
  36. 4
      tests/unit/core/test_data/using_for/using_for_global_collision/src/MyTypeA/Casting.sol
  37. 5
      tests/unit/core/test_data/using_for/using_for_global_collision/src/MyTypeA/Math.sol
  38. 6
      tests/unit/core/test_data/using_for/using_for_global_collision/src/MyTypeA/Type.sol
  39. 2
      tests/unit/core/test_data/using_for/using_for_global_collision/src/MyTypeB.sol
  40. 4
      tests/unit/core/test_data/using_for/using_for_global_collision/src/MyTypeB/Casting.sol
  41. 6
      tests/unit/core/test_data/using_for/using_for_global_collision/src/MyTypeB/Math.sol
  42. 6
      tests/unit/core/test_data/using_for/using_for_global_collision/src/MyTypeB/Type.sol
  43. 7
      tests/unit/core/test_data/using_for/using_for_global_collision/src/Test.sol
  44. 305
      tests/unit/core/test_function_declaration.py
  45. 127
      tests/unit/core/test_source_mapping.py
  46. 36
      tests/unit/core/test_storage_layout.py
  47. 95
      tests/unit/core/test_using_for.py
  48. 17
      tests/unit/slithir/test_data/operation_reads.sol
  49. 52
      tests/unit/slithir/test_data/ternary_expressions.sol
  50. 54
      tests/unit/slithir/test_operation_reads.py
  51. 1078
      tests/unit/slithir/test_ssa_generation.py
  52. 43
      tests/unit/slithir/test_ternary_expressions.py
  53. 64
      tests/unit/utils/test_data/functions_ids.sol
  54. 12
      tests/unit/utils/test_data/type_helpers.sol
  55. 64
      tests/unit/utils/test_functions_ids.py
  56. 13
      tests/unit/utils/test_type_helpers.py

@ -0,0 +1,17 @@
from pathlib import Path
from solc_select import solc_select
from slither import Slither
from slither.utils.arithmetic import unchecked_arithemtic_usage
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" / "arithmetic_usage"
def test_arithmetic_usage() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(Path(TEST_DATA_DIR, "test.sol").as_posix())
assert {
f.source_mapping.content_hash for f in unchecked_arithemtic_usage(slither.contracts[0])
} == {"2b4bc73cf59d486dd9043e840b5028b679354dd9", "e4ecd4d0fda7e762d29aceb8425f2c5d4d0bf962"}

@ -0,0 +1,60 @@
from pathlib import Path
from solc_select import solc_select
from slither import Slither
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
CUSTOM_COMMENTS_TEST_DATA_DIR = Path(TEST_DATA_DIR, "custom_comments")
def test_upgradeable_comments() -> None:
solc_select.switch_global_version("0.8.10", always_install=True)
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "upgrade.sol").as_posix())
compilation_unit = slither.compilation_units[0]
proxy = compilation_unit.get_contract_from_name("Proxy")[0]
assert proxy.is_upgradeable_proxy
v0 = compilation_unit.get_contract_from_name("V0")[0]
assert v0.is_upgradeable
print(v0.upgradeable_version)
assert v0.upgradeable_version == "version-0"
v1 = compilation_unit.get_contract_from_name("V1")[0]
assert v0.is_upgradeable
assert v1.upgradeable_version == "version_1"
def test_contract_comments() -> None:
comments = " @title Test Contract\n @dev Test comment"
solc_select.switch_global_version("0.8.10", always_install=True)
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "contract_comment.sol").as_posix())
compilation_unit = slither.compilation_units[0]
contract = compilation_unit.get_contract_from_name("A")[0]
assert contract.comments == comments
# Old solc versions have a different parsing of comments
# the initial space (after *) is also not kept on every line
comments = "@title Test Contract\n@dev Test comment"
solc_select.switch_global_version("0.5.16", always_install=True)
slither = Slither(Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "contract_comment.sol").as_posix())
compilation_unit = slither.compilation_units[0]
contract = compilation_unit.get_contract_from_name("A")[0]
assert contract.comments == comments
# Test with legacy AST
comments = "@title Test Contract\n@dev Test comment"
solc_select.switch_global_version("0.5.16", always_install=True)
slither = Slither(
Path(CUSTOM_COMMENTS_TEST_DATA_DIR, "contract_comment.sol").as_posix(),
solc_force_legacy_json=True,
)
compilation_unit = slither.compilation_units[0]
contract = compilation_unit.get_contract_from_name("A")[0]
assert contract.comments == comments

@ -0,0 +1,106 @@
from pathlib import Path
from slither import Slither
from slither.visitors.expression.constants_folding import ConstantFolding
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
CONSTANT_FOLDING_TEST_ROOT = Path(TEST_DATA_DIR, "constant_folding")
def test_constant_folding_unary():
file = Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_unary.sol").as_posix()
Slither(file)
def test_constant_folding_rational():
s = Slither(Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_rational.sol").as_posix())
contract = s.get_contract_from_name("C")[0]
variable_a = contract.get_state_variable_from_name("a")
assert str(variable_a.type) == "uint256"
assert str(ConstantFolding(variable_a.expression, "uint256").result()) == "10"
variable_b = contract.get_state_variable_from_name("b")
assert str(variable_b.type) == "int128"
assert str(ConstantFolding(variable_b.expression, "int128").result()) == "2"
variable_c = contract.get_state_variable_from_name("c")
assert str(variable_c.type) == "int64"
assert str(ConstantFolding(variable_c.expression, "int64").result()) == "3"
variable_d = contract.get_state_variable_from_name("d")
assert str(variable_d.type) == "int256"
assert str(ConstantFolding(variable_d.expression, "int256").result()) == "1500"
variable_e = contract.get_state_variable_from_name("e")
assert str(variable_e.type) == "uint256"
assert (
str(ConstantFolding(variable_e.expression, "uint256").result())
== "57896044618658097711785492504343953926634992332820282019728792003956564819968"
)
variable_f = contract.get_state_variable_from_name("f")
assert str(variable_f.type) == "uint256"
assert (
str(ConstantFolding(variable_f.expression, "uint256").result())
== "115792089237316195423570985008687907853269984665640564039457584007913129639935"
)
variable_g = contract.get_state_variable_from_name("g")
assert str(variable_g.type) == "int64"
assert str(ConstantFolding(variable_g.expression, "int64").result()) == "-7"
def test_constant_folding_binary_expressions():
sl = Slither(Path(CONSTANT_FOLDING_TEST_ROOT, "constant_folding_binop.sol").as_posix())
contract = sl.get_contract_from_name("BinOp")[0]
variable_a = contract.get_state_variable_from_name("a")
assert str(variable_a.type) == "uint256"
assert str(ConstantFolding(variable_a.expression, "uint256").result()) == "0"
variable_b = contract.get_state_variable_from_name("b")
assert str(variable_b.type) == "uint256"
assert str(ConstantFolding(variable_b.expression, "uint256").result()) == "3"
variable_c = contract.get_state_variable_from_name("c")
assert str(variable_c.type) == "uint256"
assert str(ConstantFolding(variable_c.expression, "uint256").result()) == "3"
variable_d = contract.get_state_variable_from_name("d")
assert str(variable_d.type) == "bool"
assert str(ConstantFolding(variable_d.expression, "bool").result()) == "False"
variable_e = contract.get_state_variable_from_name("e")
assert str(variable_e.type) == "bool"
assert str(ConstantFolding(variable_e.expression, "bool").result()) == "False"
variable_f = contract.get_state_variable_from_name("f")
assert str(variable_f.type) == "bool"
assert str(ConstantFolding(variable_f.expression, "bool").result()) == "True"
variable_g = contract.get_state_variable_from_name("g")
assert str(variable_g.type) == "bool"
assert str(ConstantFolding(variable_g.expression, "bool").result()) == "False"
variable_h = contract.get_state_variable_from_name("h")
assert str(variable_h.type) == "bool"
assert str(ConstantFolding(variable_h.expression, "bool").result()) == "False"
variable_i = contract.get_state_variable_from_name("i")
assert str(variable_i.type) == "bool"
assert str(ConstantFolding(variable_i.expression, "bool").result()) == "True"
variable_j = contract.get_state_variable_from_name("j")
assert str(variable_j.type) == "bool"
assert str(ConstantFolding(variable_j.expression, "bool").result()) == "False"
variable_k = contract.get_state_variable_from_name("k")
assert str(variable_k.type) == "bool"
assert str(ConstantFolding(variable_k.expression, "bool").result()) == "True"
variable_l = contract.get_state_variable_from_name("l")
assert str(variable_l.type) == "uint256"
assert (
str(ConstantFolding(variable_l.expression, "uint256").result())
== "115792089237316195423570985008687907853269984665640564039457584007913129639935"
)

@ -0,0 +1,43 @@
import inspect
from pathlib import Path
import pytest
from crytic_compile import CryticCompile
from crytic_compile.platform.solc_standard_json import SolcStandardJson
from solc_select import solc_select
from slither import Slither
from slither.core.variables.state_variable import StateVariable
from slither.detectors import all_detectors
from slither.detectors.abstract_detector import AbstractDetector
from slither.slithir.operations import InternalCall, LibraryCall
from slither.utils.arithmetic import unchecked_arithemtic_usage
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
CONTRACT_DECL_TEST_ROOT = Path(TEST_DATA_DIR, "contract_declaration")
def test_abstract_contract() -> None:
solc_select.switch_global_version("0.8.0", always_install=True)
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "abstract.sol").as_posix())
assert not slither.contracts[0].is_fully_implemented
solc_select.switch_global_version("0.5.0", always_install=True)
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "implicit_abstract.sol").as_posix())
assert not slither.contracts[0].is_fully_implemented
slither = Slither(
Path(CONTRACT_DECL_TEST_ROOT, "implicit_abstract.sol").as_posix(),
solc_force_legacy_json=True,
)
assert not slither.contracts[0].is_fully_implemented
def test_private_variable() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(Path(CONTRACT_DECL_TEST_ROOT, "private_variable.sol").as_posix())
contract_c = slither.get_contract_from_name("C")[0]
f = contract_c.functions[0]
var_read = f.variables_read[0]
assert isinstance(var_read, StateVariable)
assert str(var_read.contract) == "B"

@ -0,0 +1,29 @@
function protected(uint a, uint b) returns(uint){
return (a + b) * (a + b);
}
function not_protected_asm(uint a, uint b) returns(uint){
uint c;
assembly{
c := mul(add(a,b), add(a,b))
}
return c;
}
function not_protected_unchecked(uint a, uint b) returns(uint){
uint c;
unchecked{
return (a + b) * (a + b);
}
}
contract A{
function f(uint a, uint b) public{
protected(a,b);
not_protected_asm(a, b);
not_protected_unchecked(a, b);
}
}

@ -0,0 +1,88 @@
pragma solidity ^0.4.24;
contract Complex {
int numberOfSides = 7;
string shape;
uint i0 = 0;
uint i1 = 0;
uint i2 = 0;
uint i3 = 0;
uint i4 = 0;
uint i5 = 0;
uint i6 = 0;
uint i7 = 0;
uint i8 = 0;
uint i9 = 0;
uint i10 = 0;
function computeShape() external {
if (numberOfSides <= 2) {
shape = "Cant be a shape!";
} else if (numberOfSides == 3) {
shape = "Triangle";
} else if (numberOfSides == 4) {
shape = "Square";
} else if (numberOfSides == 5) {
shape = "Pentagon";
} else if (numberOfSides == 6) {
shape = "Hexagon";
} else if (numberOfSides == 7) {
shape = "Heptagon";
} else if (numberOfSides == 8) {
shape = "Octagon";
} else if (numberOfSides == 9) {
shape = "Nonagon";
} else if (numberOfSides == 10) {
shape = "Decagon";
} else if (numberOfSides == 11) {
shape = "Hendecagon";
} else {
shape = "Your shape is more than 11 sides.";
}
}
function complexExternalWrites() external {
Increment test1 = new Increment();
test1.increaseBy1();
test1.increaseBy1();
test1.increaseBy1();
test1.increaseBy1();
test1.increaseBy1();
Increment test2 = new Increment();
test2.increaseBy1();
address test3 = new Increment();
test3.call(bytes4(keccak256("increaseBy2()")));
address test4 = new Increment();
test4.call(bytes4(keccak256("increaseBy2()")));
}
function complexStateVars() external {
i0 = 1;
i1 = 1;
i2 = 1;
i3 = 1;
i4 = 1;
i5 = 1;
i6 = 1;
i7 = 1;
i8 = 1;
i9 = 1;
i10 = 1;
}
}
contract Increment {
uint i = 0;
function increaseBy1() public {
i += 1;
}
function increaseBy2() public {
i += 2;
}
}

@ -0,0 +1,14 @@
contract BinOp {
uint a = 1 & 2;
uint b = 1 ^ 2;
uint c = 1 | 2;
bool d = 2 < 1;
bool e = 1 > 2;
bool f = 1 <= 2;
bool g = 1 >= 2;
bool h = 1 == 2;
bool i = 1 != 2;
bool j = true && false;
bool k = true || false;
uint l = uint(1) - uint(2);
}

@ -0,0 +1,9 @@
contract C {
uint256 constant a = 2.5 + 7 + 0.5;
int128 b = 6 / 3.0;
int64 constant c = 5 * 0.5 + 0.5;
int256 d = 1e3 + 5E2;
uint256 e = 2 ** 255;
uint256 f = 115792089237316195423570985008687907853269984665640564039457584_007_913_129_639_935;
int64 constant g = -7.0;
}

@ -0,0 +1,7 @@
contract C {
int8 constant a = -7;
function f() public pure {
uint[-a] memory x;
x[0] = 2;
}
}

@ -0,0 +1,5 @@
pragma solidity ^0.8.0;
abstract contract ExplicitAbstract{
function f() virtual public;
}

@ -0,0 +1,5 @@
pragma solidity ^0.5.0;
contract ImplicitAbstract{
function f() public;
}

@ -0,0 +1,13 @@
contract A{
uint private v = 10;
}
contract B{
uint v = 20;
}
contract C is B, A{
function f() public view returns(uint) {
return v;
}
}

@ -0,0 +1,7 @@
/**
* @title Test Contract
* @dev Test comment
*/
contract A{
}

@ -0,0 +1,16 @@
/// @custom:security isDelegatecallProxy
contract Proxy{
}
/// @custom:security isUpgradeable
/// @custom:version name=version-0
contract V0{
}
/// @custom:security isUpgradeable
/// @custom:version name=version_1
contract V1{
}

@ -0,0 +1,27 @@
contract ContractWithDeprecatedReferences {
bytes32 globalBlockHash = block.blockhash(0);
// Deprecated: Change constant -> view
function functionWithDeprecatedThrow() public constant {
// Deprecated: Change msg.gas -> gasleft()
if(msg.gas == msg.value) {
// Deprecated: Change throw -> revert()
throw;
}
}
// Deprecated: Change constant -> view
function functionWithDeprecatedReferences() public constant {
// Deprecated: Change sha3() -> keccak256()
bytes32 sha3Result = sha3("test deprecated sha3 usage");
// Deprecated: Change block.blockhash() -> blockhash()
bytes32 blockHashResult = block.blockhash(0);
// Deprecated: Change callcode() -> delegatecall()
address(this).callcode();
// Deprecated: Change suicide() -> selfdestruct()
suicide(address(0));
}
}

@ -0,0 +1,130 @@
pragma solidity ^0.6.12;
// solidity source used by tests/test_function.py.
// tests/test_function.py tests that the functions below get translated into correct
// `slither.core.declarations.Function` objects or its subclasses
// and that these objects behave correctly.
contract TestFunction {
bool entered = false;
bytes32 public info;
function external_payable(uint _a) external payable returns (uint) {
return 1;
}
function public_reenter() public {
msg.sender.call("");
}
function public_payable_reenter_send(bool _b) public payable {
msg.sender.call{value: 1}("");
}
function external_send(uint8 _c) external {
require(!entered);
entered = true;
msg.sender.call{value: 1}("");
}
function internal_assembly(bytes calldata _d) internal returns (uint) {
uint256 chain;
assembly {
chain := chainid()
}
return chain;
}
fallback() external {
}
receive() external payable {
}
constructor(address payable _e) public payable {
}
function private_view() private view returns (bool) {
return entered;
}
function public_pure() public pure returns (bool) {
return true;
}
}
contract TestFunctionCanSendEth {
function send_direct() internal {
address(1).send(1);
}
function transfer_direct() internal {
address(1).transfer(1);
}
function call_direct() internal {
address(1).call{value: 1}("");
}
function highlevel_call_direct() internal {
TestFunctionCanSendEthOther(address(5)).i_am_payable{value: 1}();
}
function send_via_internal() public {
send_direct();
}
function transfer_via_internal() public {
transfer_direct();
}
function call_via_internal() public {
call_direct();
}
function highlevel_call_via_internal() public {
highlevel_call_direct();
}
function send_via_external() public {
TestFunctionCanSendEthOther(address(5)).send_direct();
}
function transfer_via_external() public {
TestFunctionCanSendEthOther(address(5)).transfer_direct();
}
function call_via_external() public {
TestFunctionCanSendEthOther(address(5)).call_direct();
}
function highlevel_call_via_external() public {
TestFunctionCanSendEthOther(address(5)).highlevel_call_direct();
}
}
contract TestFunctionCanSendEthOther {
function i_am_payable() external payable {
}
function send_direct() external {
address(1).send(1);
}
function transfer_direct() external {
address(1).transfer(1);
}
function call_direct() external {
address(1).call{value: 1}("");
}
function highlevel_call_direct() external {
TestFunctionCanSendEthOther(address(5)).i_am_payable{value: 1}();
}
}

@ -0,0 +1,36 @@
contract TestReentrant{
modifier nonReentrant(){
_;
}
function is_reentrant() public{
internal_and_could_be_reentrant();
internal_and_reentrant();
}
function is_non_reentrant() nonReentrant() public{
internal_and_could_be_reentrant();
internal_and_not_reentrant2();
}
function internal_and_not_reentrant() nonReentrant() internal{
}
function internal_and_not_reentrant2() internal{
}
// Called by a protected and unprotected function
function internal_and_could_be_reentrant() internal{
}
// Called by a protected and unprotected function
function internal_and_reentrant() internal{
}
}

@ -0,0 +1,100 @@
contract TestContractVar {
}
contract A {
uint public public_var = 1;
uint internal private_var = 1;
TestContractVar public public_contract;
TestContractVar internal private_contract;
uint public shadowed_public_var = 1;
uint internal shadowed_private_var = 1;
TestContractVar public shadowed_public_contract;
TestContractVar internal shadowed_private_contract;
function getValue() public pure returns (uint) {
return 0;
}
function notRedefined() public returns (uint) {
return getValue();
}
modifier testModifier {
assert(true);
_;
}
function testFunction() testModifier public returns (uint) {
return 0;
}
}
contract B is A {
// This function overshadows A directly, and overshadows C indirectly (via 'G'->'D')
function getValue() public pure returns (uint) {
return 1;
}
}
contract Good is A, B {
}
contract C is A {
// This function overshadows A directly, and overshadows B indirectly (via 'G')
function getValue() public pure returns (uint) {
return super.getValue() + 1;
}
}
contract D is B {
// This should overshadow A's definitions.
uint public shadowed_public_var = 2;
uint internal shadowed_private_var = 2;
TestContractVar public shadowed_public_contract;
TestContractVar internal shadowed_private_contract;
}
contract E {
// Variables cannot indirectly shadow, so this should not be counted.
uint public public_var = 2;
uint internal private_var = 2;
TestContractVar public public_contract;
TestContractVar internal private_contract;
// This should overshadow A's definition indirectly (via 'G').
modifier testModifier {
assert(false);
_;
}
}
contract F is B {
// This should overshadow A's definitions.
uint public shadowed_public_var = 2;
uint internal shadowed_private_var = 2;
TestContractVar public shadowed_public_contract;
TestContractVar internal shadowed_private_contract;
// This should overshadow B's definition directly, as well as B's and C's indirectly (via 'G')
// (graph only outputs directly if both, so B direct and C indirect should be reported).
function getValue() public pure returns (uint) {
return 1;
}
// This should indirectly shadow definition in A directly, and E indirectly (via 'G')
modifier testModifier {
assert(false);
_;
}
}
contract G is B, C, D, E, F {
// This should overshadow definitions in A, D, and F
uint public shadowed_public_var = 3;
uint internal shadowed_private_var = 3;
TestContractVar public shadowed_public_contract;
// This contract's multiple inheritance chain should cause indirect shadowing (c3 linearization shadowing).
}

@ -0,0 +1,22 @@
contract A{
// ëëëëëëëëëëëëë
address unused;
address unused2;
//
address unused3;
address unused4;
//
address used;
}

@ -0,0 +1,19 @@
pragma solidity 0.8.16;
type aliasTopLevel is uint;
contract C
{
type aliasContractLevel is uint;
}
contract Test
{
aliasTopLevel a;
C.aliasContractLevel b;
}
function f(aliasTopLevel, C.aliasContractLevel)
{
}

@ -0,0 +1,19 @@
pragma solidity 0.8.16;
interface A
{
function a() external;
}
contract C
{
function g(address _address) private
{
A(_address).a();
}
}
function f(address _address)
{
A(_address).a();
}

@ -0,0 +1,35 @@
contract A{
function f() public virtual {
}
function test() public {
f();
}
}
contract B is A{
function f() public override {
}
}
contract C is A{
function f() public override {
}
function test2() public {
f();
}
}
contract D is A{
}

@ -0,0 +1 @@
[{"inputs":[],"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"}]

File diff suppressed because one or more lines are too long

@ -0,0 +1,576 @@
{
"packedUint": {
"name": "packedUint",
"type_string": "uint248",
"slot": 0,
"size": 248,
"offset": 0,
"value": 1,
"elems": {}
},
"packedBool": {
"name": "packedBool",
"type_string": "bool",
"slot": 0,
"size": 8,
"offset": 248,
"value": true,
"elems": {}
},
"_packedStruct": {
"name": "_packedStruct",
"type_string": "StorageLayout.PackedStruct",
"slot": 1,
"size": 256,
"offset": 0,
"value": "0000000000000000000000000000000000000000000000000000000000000101",
"elems": {
"b": {
"name": "_packedStruct.b",
"type_string": "bool",
"slot": 1,
"size": 8,
"offset": 0,
"value": true,
"elems": {}
},
"a": {
"name": "_packedStruct.a",
"type_string": "uint248",
"slot": 1,
"size": 248,
"offset": 8,
"value": 1,
"elems": {}
}
}
},
"mappingPackedStruct": {
"name": "mappingPackedStruct",
"type_string": "mapping(uint256 => StorageLayout.PackedStruct)",
"slot": 2,
"size": 256,
"offset": 0,
"value": 0,
"elems": {}
},
"deepMappingPackedStruct": {
"name": "deepMappingPackedStruct",
"type_string": "mapping(address => mapping(uint256 => StorageLayout.PackedStruct))",
"slot": 3,
"size": 256,
"offset": 0,
"value": 0,
"elems": {}
},
"deepMappingElementaryTypes": {
"name": "deepMappingElementaryTypes",
"type_string": "mapping(address => mapping(uint256 => bool))",
"slot": 4,
"size": 256,
"offset": 0,
"value": 0,
"elems": {}
},
"mappingDynamicArrayOfStructs": {
"name": "mappingDynamicArrayOfStructs",
"type_string": "mapping(address => StorageLayout.PackedStruct[])",
"slot": 5,
"size": 256,
"offset": 0,
"value": 0,
"elems": {}
},
"_address": {
"name": "_address",
"type_string": "address",
"slot": 6,
"size": 160,
"offset": 0,
"value": "0xae17D2dD99e07CA3bF2571CCAcEAA9e2Aefc2Dc6",
"elems": {}
},
"_string": {
"name": "_string",
"type_string": "string",
"slot": 7,
"size": 256,
"offset": 0,
"value": "slither-read-storage",
"elems": {}
},
"packedUint8": {
"name": "packedUint8",
"type_string": "uint8",
"slot": 8,
"size": 8,
"offset": 0,
"value": 8,
"elems": {}
},
"packedBytes": {
"name": "packedBytes",
"type_string": "bytes8",
"slot": 8,
"size": 64,
"offset": 8,
"value": "6161616161616161",
"elems": {}
},
"_enumA": {
"name": "_enumA",
"type_string": "StorageLayout.Enum",
"slot": 8,
"size": 8,
"offset": 72,
"value": "00",
"elems": {}
},
"_enumB": {
"name": "_enumB",
"type_string": "StorageLayout.Enum",
"slot": 8,
"size": 8,
"offset": 80,
"value": "01",
"elems": {}
},
"_enumC": {
"name": "_enumC",
"type_string": "StorageLayout.Enum",
"slot": 8,
"size": 8,
"offset": 88,
"value": "02",
"elems": {}
},
"fixedArray": {
"name": "fixedArray",
"type_string": "uint256[3]",
"slot": 9,
"size": 768,
"offset": 0,
"value": 1,
"elems": {
"0": {
"name": "fixedArray[0]",
"type_string": "uint256",
"slot": 9,
"size": 256,
"offset": 0,
"value": 1,
"elems": {}
},
"1": {
"name": "fixedArray[1]",
"type_string": "uint256",
"slot": 10,
"size": 256,
"offset": 0,
"value": 2,
"elems": {}
},
"2": {
"name": "fixedArray[2]",
"type_string": "uint256",
"slot": 11,
"size": 256,
"offset": 0,
"value": 3,
"elems": {}
}
}
},
"dynamicArrayOfFixedArrays": {
"name": "dynamicArrayOfFixedArrays",
"type_string": "uint256[3][]",
"slot": 12,
"size": 256,
"offset": 0,
"value": 2,
"elems": {
"0": {
"name": "dynamicArrayOfFixedArrays[0]",
"type_string": "uint256",
"slot": 101051993584849178915136821395265346177868384823507754984078593667947067386055,
"size": 256,
"offset": 0,
"value": 1,
"elems": {
"0": {
"name": "dynamicArrayOfFixedArrays[0]",
"type_string": "uint256",
"slot": 101051993584849178915136821395265346177868384823507754984078593667947067386055,
"size": 256,
"offset": 0,
"value": 1,
"elems": {}
},
"1": {
"name": "dynamicArrayOfFixedArrays[0]",
"type_string": "uint256",
"slot": 101051993584849178915136821395265346177868384823507754984078593667947067386056,
"size": 256,
"offset": 0,
"value": 2,
"elems": {}
},
"2": {
"name": "dynamicArrayOfFixedArrays[0]",
"type_string": "uint256",
"slot": 101051993584849178915136821395265346177868384823507754984078593667947067386057,
"size": 256,
"offset": 0,
"value": 3,
"elems": {}
}
}
},
"1": {
"name": "dynamicArrayOfFixedArrays[1]",
"type_string": "uint256",
"slot": 101051993584849178915136821395265346177868384823507754984078593667947067386058,
"size": 256,
"offset": 0,
"value": 4,
"elems": {
"0": {
"name": "dynamicArrayOfFixedArrays[1]",
"type_string": "uint256",
"slot": 101051993584849178915136821395265346177868384823507754984078593667947067386058,
"size": 256,
"offset": 0,
"value": 4,
"elems": {}
},
"1": {
"name": "dynamicArrayOfFixedArrays[1]",
"type_string": "uint256",
"slot": 101051993584849178915136821395265346177868384823507754984078593667947067386059,
"size": 256,
"offset": 0,
"value": 5,
"elems": {}
},
"2": {
"name": "dynamicArrayOfFixedArrays[1]",
"type_string": "uint256",
"slot": 101051993584849178915136821395265346177868384823507754984078593667947067386060,
"size": 256,
"offset": 0,
"value": 6,
"elems": {}
}
}
}
}
},
"fixedArrayofDynamicArrays": {
"name": "fixedArrayofDynamicArrays",
"type_string": "uint256[][3]",
"slot": 13,
"size": 768,
"offset": 0,
"value": 1,
"elems": {
"0": {
"name": "fixedArrayofDynamicArrays[0]",
"type_string": "uint256",
"slot": 13,
"size": 256,
"offset": 0,
"value": 1,
"elems": {
"0": {
"name": "fixedArrayofDynamicArrays[0]",
"type_string": "uint256",
"slot": 97569884605916225051403212656556507955018248777258318895762758024193532305077,
"size": 256,
"offset": 0,
"value": 7,
"elems": {}
}
}
},
"1": {
"name": "fixedArrayofDynamicArrays[1]",
"type_string": "uint256",
"slot": 14,
"size": 256,
"offset": 0,
"value": 2,
"elems": {
"0": {
"name": "fixedArrayofDynamicArrays[1]",
"type_string": "uint256",
"slot": 84800337471693920904250232874319843718400766719524250287777680170677855896573,
"size": 256,
"offset": 0,
"value": 8,
"elems": {}
},
"1": {
"name": "fixedArrayofDynamicArrays[1]",
"type_string": "uint256",
"slot": 84800337471693920904250232874319843718400766719524250287777680170677855896574,
"size": 256,
"offset": 0,
"value": 9,
"elems": {}
}
}
},
"2": {
"name": "fixedArrayofDynamicArrays[2]",
"type_string": "uint256",
"slot": 15,
"size": 256,
"offset": 0,
"value": 3,
"elems": {
"0": {
"name": "fixedArrayofDynamicArrays[2]",
"type_string": "uint256",
"slot": 63806209331542711802848847270949280092855778197726125910674179583545433573378,
"size": 256,
"offset": 0,
"value": 10,
"elems": {}
},
"1": {
"name": "fixedArrayofDynamicArrays[2]",
"type_string": "uint256",
"slot": 63806209331542711802848847270949280092855778197726125910674179583545433573379,
"size": 256,
"offset": 0,
"value": 11,
"elems": {}
},
"2": {
"name": "fixedArrayofDynamicArrays[2]",
"type_string": "uint256",
"slot": 63806209331542711802848847270949280092855778197726125910674179583545433573380,
"size": 256,
"offset": 0,
"value": 12,
"elems": {}
}
}
}
}
},
"multidimensionalArray": {
"name": "multidimensionalArray",
"type_string": "uint256[][]",
"slot": 16,
"size": 256,
"offset": 0,
"value": 3,
"elems": {
"0": {
"name": "multidimensionalArray[0]",
"type_string": "uint256",
"slot": 12396694973890998440467380340983585058878106250672390494374587083972727727730,
"size": 256,
"offset": 0,
"value": 1,
"elems": {
"0": {
"name": "multidimensionalArray[0]",
"type_string": "uint256",
"slot": 93856215500098298973000561543003607329881518401177956003908346942307446808932,
"size": 256,
"offset": 0,
"value": 13,
"elems": {}
}
}
},
"1": {
"name": "multidimensionalArray[1]",
"type_string": "uint256",
"slot": 12396694973890998440467380340983585058878106250672390494374587083972727727731,
"size": 256,
"offset": 0,
"value": 2,
"elems": {
"0": {
"name": "multidimensionalArray[1]",
"type_string": "uint256",
"slot": 48332168562525185806884758054388614910060623018875025120987491603435926351511,
"size": 256,
"offset": 0,
"value": 14,
"elems": {}
},
"1": {
"name": "multidimensionalArray[1]",
"type_string": "uint256",
"slot": 48332168562525185806884758054388614910060623018875025120987491603435926351512,
"size": 256,
"offset": 0,
"value": 15,
"elems": {}
}
}
},
"2": {
"name": "multidimensionalArray[2]",
"type_string": "uint256",
"slot": 12396694973890998440467380340983585058878106250672390494374587083972727727732,
"size": 256,
"offset": 0,
"value": 3,
"elems": {
"0": {
"name": "multidimensionalArray[2]",
"type_string": "uint256",
"slot": 69037578548663760355678879060995014288537668748590083357305779656188235687653,
"size": 256,
"offset": 0,
"value": 16,
"elems": {}
},
"1": {
"name": "multidimensionalArray[2]",
"type_string": "uint256",
"slot": 69037578548663760355678879060995014288537668748590083357305779656188235687654,
"size": 256,
"offset": 0,
"value": 17,
"elems": {}
},
"2": {
"name": "multidimensionalArray[2]",
"type_string": "uint256",
"slot": 69037578548663760355678879060995014288537668748590083357305779656188235687655,
"size": 256,
"offset": 0,
"value": 18,
"elems": {}
}
}
}
}
},
"dynamicArrayOfStructs": {
"name": "dynamicArrayOfStructs",
"type_string": "StorageLayout.PackedStruct[]",
"slot": 17,
"size": 256,
"offset": 0,
"value": "0000000000000000000000000000000000000000000000000000000000000002",
"elems": {
"0": {
"b": {
"name": "dynamicArrayOfStructs[0]",
"type_string": "bool",
"slot": 22581645139872629890233439717971975110198959689450188087151966948260709403752,
"size": 8,
"offset": 0,
"value": true,
"elems": {}
},
"a": {
"name": "dynamicArrayOfStructs[0]",
"type_string": "uint248",
"slot": 22581645139872629890233439717971975110198959689450188087151966948260709403752,
"size": 248,
"offset": 8,
"value": 1,
"elems": {}
}
},
"1": {
"b": {
"name": "dynamicArrayOfStructs[1]",
"type_string": "bool",
"slot": 22581645139872629890233439717971975110198959689450188087151966948260709403753,
"size": 8,
"offset": 0,
"value": false,
"elems": {}
},
"a": {
"name": "dynamicArrayOfStructs[1]",
"type_string": "uint248",
"slot": 22581645139872629890233439717971975110198959689450188087151966948260709403753,
"size": 248,
"offset": 8,
"value": 10,
"elems": {}
}
}
}
},
"fixedArrayOfStructs": {
"name": "fixedArrayOfStructs",
"type_string": "StorageLayout.PackedStruct[3]",
"slot": 18,
"size": 768,
"offset": 0,
"value": "0000000000000000000000000000000000000000000000000000000000000101",
"elems": {
"0": {
"b": {
"name": "fixedArrayOfStructs[0]",
"type_string": "bool",
"slot": 18,
"size": 8,
"offset": 0,
"value": true,
"elems": {}
},
"a": {
"name": "fixedArrayOfStructs[0]",
"type_string": "uint248",
"slot": 18,
"size": 248,
"offset": 8,
"value": 1,
"elems": {}
}
},
"1": {
"b": {
"name": "fixedArrayOfStructs[1]",
"type_string": "bool",
"slot": 19,
"size": 8,
"offset": 0,
"value": false,
"elems": {}
},
"a": {
"name": "fixedArrayOfStructs[1]",
"type_string": "uint248",
"slot": 19,
"size": 248,
"offset": 8,
"value": 10,
"elems": {}
}
},
"2": {
"b": {
"name": "fixedArrayOfStructs[2]",
"type_string": "bool",
"slot": 20,
"size": 8,
"offset": 0,
"value": false,
"elems": {}
},
"a": {
"name": "fixedArrayOfStructs[2]",
"type_string": "uint248",
"slot": 20,
"size": 248,
"offset": 8,
"value": 0,
"elems": {}
}
}
}
}
}

@ -0,0 +1,74 @@
// overwrite abi and bin:
// solc tests/storage-layout/storage_layout-0.8.10.sol --abi --bin -o tests/storage-layout --overwrite
contract StorageLayout {
uint248 packedUint = 1;
bool packedBool = true;
struct PackedStruct {
bool b;
uint248 a;
}
PackedStruct _packedStruct = PackedStruct(packedBool, packedUint);
mapping (uint => PackedStruct) mappingPackedStruct;
mapping (address => mapping (uint => PackedStruct)) deepMappingPackedStruct;
mapping (address => mapping (uint => bool)) deepMappingElementaryTypes;
mapping (address => PackedStruct[]) mappingDynamicArrayOfStructs;
address _address;
string _string = "slither-read-storage";
uint8 packedUint8 = 8;
bytes8 packedBytes = "aaaaaaaa";
enum Enum {
a,
b,
c
}
Enum _enumA = Enum.a;
Enum _enumB = Enum.b;
Enum _enumC = Enum.c;
uint256[3] fixedArray;
uint256[3][] dynamicArrayOfFixedArrays;
uint[][3] fixedArrayofDynamicArrays;
uint[][] multidimensionalArray;
PackedStruct[] dynamicArrayOfStructs;
PackedStruct[3] fixedArrayOfStructs;
function store() external {
require(_address == address(0));
_address = msg.sender;
mappingPackedStruct[packedUint] = _packedStruct;
deepMappingPackedStruct[_address][packedUint] = _packedStruct;
deepMappingElementaryTypes[_address][1] = true;
deepMappingElementaryTypes[_address][2] = true;
fixedArray = [1, 2, 3];
dynamicArrayOfFixedArrays.push(fixedArray);
dynamicArrayOfFixedArrays.push([4, 5, 6]);
fixedArrayofDynamicArrays[0].push(7);
fixedArrayofDynamicArrays[1].push(8);
fixedArrayofDynamicArrays[1].push(9);
fixedArrayofDynamicArrays[2].push(10);
fixedArrayofDynamicArrays[2].push(11);
fixedArrayofDynamicArrays[2].push(12);
multidimensionalArray.push([13]);
multidimensionalArray.push([14, 15]);
multidimensionalArray.push([16, 17, 18]);
dynamicArrayOfStructs.push(_packedStruct);
dynamicArrayOfStructs.push(PackedStruct(false, 10));
fixedArrayOfStructs[0] = _packedStruct;
fixedArrayOfStructs[1] = PackedStruct(false, 10);
mappingDynamicArrayOfStructs[_address].push(dynamicArrayOfStructs[0]);
mappingDynamicArrayOfStructs[_address].push(dynamicArrayOfStructs[1]);
}
}

@ -0,0 +1,18 @@
contract Test{
mapping(uint => mapping(uint => address)) authorized_destination;
address destination;
function init(){
authorized_destination[0][0] = msg.sender;
}
function setup(uint idx){
destination = authorized_destination[0][0];
}
function withdraw(){
destination.transfer(this.balance);
}
}

@ -0,0 +1,27 @@
using {a} for Data;
struct Data { mapping(uint => bool) flags; }
function a(Data storage self, uint value, uint value2) returns(bool){
return false;
}
library Lib {
function a(Data storage self, uint value) public
view
returns (bool)
{
return true;
}
}
contract C {
using Lib for Data;
Data knownValues;
function libCall(uint value) public {
require(knownValues.a(value));
}
}

@ -0,0 +1,25 @@
using {f} for St;
struct St { uint field; }
function f(St storage self, uint8 v) view returns(uint){
return 0;
}
library Lib {
function f(St storage self, uint256 v) public view returns (uint) {
return 1;
}
}
contract C {
using Lib for St;
St st;
function libCall(uint16 v) public view returns(uint){
return st.f(v); // return 1
}
}

@ -0,0 +1,14 @@
import "./using-for-alias-dep1.sol";
contract C {
using {T3.a, T3.Lib.b} for uint256;
function topLevel(uint256 value) public {
value.a();
}
function libCall(uint256 value) public {
value.b();
}
}

@ -0,0 +1,11 @@
import "./using-for-alias-dep2.sol" as T3;
function b(uint256 value) returns(bool) {
return true;
}
library Lib {
function a(uint256 value) public returns(bool) {
return true;
}
}

@ -0,0 +1,9 @@
function a(uint256 value) returns(bool) {
return true;
}
library Lib {
function b(uint256 value) public returns(bool) {
return true;
}
}

@ -0,0 +1,15 @@
import "./using-for-alias-dep1.sol";
using {T3.a, T3.Lib.b} for uint256;
contract C {
function topLevel(uint256 value) public {
value.a();
}
function libCall(uint256 value) public {
value.b();
}
}

@ -0,0 +1,14 @@
library A {
using B for uint256;
function a(uint256 v) public view returns (uint) {
return v.b();
}
}
library B {
function b(uint256 v) public view returns (uint) {
return 1;
}
}

@ -0,0 +1,2 @@
import "./MyTypeA/Type.sol";
import "./MyTypeA/Math.sol";

@ -0,0 +1,4 @@
import "./Type.sol";
function unwrap(MyTypeA a) pure returns (int256) {
return MyTypeA.unwrap(a);
}

@ -0,0 +1,5 @@
import "./Type.sol";
function mul(MyTypeA a, MyTypeA b) pure returns (MyTypeA) {
return MyTypeA.wrap(MyTypeA.unwrap(a) * MyTypeA.unwrap(b));
}

@ -0,0 +1,6 @@
import "./Casting.sol" as C;
import "./Math.sol" as M;
type MyTypeA is int256;
using {M.mul, C.unwrap} for MyTypeA global;

@ -0,0 +1,2 @@
import "./MyTypeB/Type.sol";
import "./MyTypeB/Math.sol";

@ -0,0 +1,4 @@
import "./Type.sol";
function unwrap(MyTypeB a) pure returns (uint256) {
return MyTypeB.unwrap(a);
}

@ -0,0 +1,6 @@
import "./Type.sol";
function mul(MyTypeB a, MyTypeB b) pure returns (MyTypeB) {
return MyTypeB.wrap(MyTypeB.unwrap(a) * MyTypeB.unwrap(b));
}

@ -0,0 +1,6 @@
import "./Casting.sol" as C;
import "./Math.sol" as M;
type MyTypeB is uint256;
using {M.mul, C.unwrap} for MyTypeB global;

@ -0,0 +1,7 @@
import "./MyTypeB.sol";
contract UsingForGlobalTopLevelCollision {
function mulAndUnwrap(MyTypeB x, MyTypeB y) external pure returns (uint256 z) {
z = x.mul(y).unwrap();
}
}

@ -0,0 +1,305 @@
"""
tests for `slither.core.declarations.Function`.
tests that `tests/test_function.sol` gets translated into correct
`slither.core.declarations.Function` objects or its subclasses
and that these objects behave correctly.
"""
from pathlib import Path
from solc_select import solc_select
from slither import Slither
from slither.core.declarations.function import FunctionType
from slither.core.solidity_types.elementary_type import ElementaryType
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
FUNC_DELC_TEST_ROOT = Path(TEST_DATA_DIR, "function_declaration")
def test_functions():
# pylint: disable=too-many-statements
solc_select.switch_global_version("0.6.12", always_install=True)
file = Path(FUNC_DELC_TEST_ROOT, "test_function.sol").as_posix()
slither = Slither(file)
functions = slither.get_contract_from_name("TestFunction")[0].available_functions_as_dict()
f = functions["external_payable(uint256)"]
assert f.name == "external_payable"
assert f.full_name == "external_payable(uint256)"
assert f.canonical_name == "TestFunction.external_payable(uint256)"
assert f.solidity_signature == "external_payable(uint256)"
assert f.signature_str == "external_payable(uint256) returns(uint256)"
assert f.function_type == FunctionType.NORMAL
assert f.contains_assembly is False
assert f.can_reenter() is False
assert f.can_send_eth() is False
assert f.is_constructor is False
assert f.is_fallback is False
assert f.is_receive is False
assert f.payable is True
assert f.visibility == "external"
assert f.view is False
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is False
assert f.parameters[0].name == "_a"
assert f.parameters[0].type == ElementaryType("uint256")
assert f.return_type[0] == ElementaryType("uint256")
f = functions["public_reenter()"]
assert f.name == "public_reenter"
assert f.full_name == "public_reenter()"
assert f.canonical_name == "TestFunction.public_reenter()"
assert f.solidity_signature == "public_reenter()"
assert f.signature_str == "public_reenter() returns()"
assert f.function_type == FunctionType.NORMAL
assert f.contains_assembly is False
assert f.can_reenter() is True
assert f.can_send_eth() is False
assert f.is_constructor is False
assert f.is_fallback is False
assert f.is_receive is False
assert f.payable is False
assert f.visibility == "public"
assert f.view is False
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is False
assert f.parameters == []
assert f.return_type is None
f = functions["public_payable_reenter_send(bool)"]
assert f.name == "public_payable_reenter_send"
assert f.full_name == "public_payable_reenter_send(bool)"
assert f.canonical_name == "TestFunction.public_payable_reenter_send(bool)"
assert f.solidity_signature == "public_payable_reenter_send(bool)"
assert f.signature_str == "public_payable_reenter_send(bool) returns()"
assert f.function_type == FunctionType.NORMAL
assert f.contains_assembly is False
assert f.can_reenter() is True
assert f.can_send_eth() is True
assert f.is_constructor is False
assert f.is_fallback is False
assert f.is_receive is False
assert f.payable is True
assert f.visibility == "public"
assert f.view is False
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is False
assert f.parameters[0].name == "_b"
assert f.parameters[0].type == ElementaryType("bool")
assert f.return_type is None
f = functions["external_send(uint8)"]
assert f.name == "external_send"
assert f.full_name == "external_send(uint8)"
assert f.canonical_name == "TestFunction.external_send(uint8)"
assert f.solidity_signature == "external_send(uint8)"
assert f.signature_str == "external_send(uint8) returns()"
assert f.function_type == FunctionType.NORMAL
assert f.contains_assembly is False
assert f.can_reenter() is True
assert f.can_send_eth() is True
assert f.is_constructor is False
assert f.is_fallback is False
assert f.is_receive is False
assert f.payable is False
assert f.visibility == "external"
assert f.view is False
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is False
assert f.parameters[0].name == "_c"
assert f.parameters[0].type == ElementaryType("uint8")
assert f.return_type is None
f = functions["internal_assembly(bytes)"]
assert f.name == "internal_assembly"
assert f.full_name == "internal_assembly(bytes)"
assert f.canonical_name == "TestFunction.internal_assembly(bytes)"
assert f.solidity_signature == "internal_assembly(bytes)"
assert f.signature_str == "internal_assembly(bytes) returns(uint256)"
assert f.function_type == FunctionType.NORMAL
assert f.contains_assembly is True
assert f.can_reenter() is False
assert f.can_send_eth() is False
assert f.is_constructor is False
assert f.is_fallback is False
assert f.is_receive is False
assert f.payable is False
assert f.visibility == "internal"
assert f.view is False
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is False
assert f.parameters[0].name == "_d"
assert f.parameters[0].type == ElementaryType("bytes")
assert f.return_type[0] == ElementaryType("uint256")
f = functions["fallback()"]
assert f.name == "fallback"
assert f.full_name == "fallback()"
assert f.canonical_name == "TestFunction.fallback()"
assert f.solidity_signature == "fallback()"
assert f.signature_str == "fallback() returns()"
assert f.function_type == FunctionType.FALLBACK
assert f.contains_assembly is False
assert f.can_reenter() is False
assert f.can_send_eth() is False
assert f.is_constructor is False
assert f.is_fallback is True
assert f.is_receive is False
assert f.payable is False
assert f.visibility == "external"
assert f.view is False
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is True
assert f.parameters == []
assert f.return_type is None
f = functions["receive()"]
assert f.name == "receive"
assert f.full_name == "receive()"
assert f.canonical_name == "TestFunction.receive()"
assert f.solidity_signature == "receive()"
assert f.signature_str == "receive() returns()"
assert f.function_type == FunctionType.RECEIVE
assert f.contains_assembly is False
assert f.can_reenter() is False
assert f.can_send_eth() is False
assert f.is_constructor is False
assert f.is_fallback is False
assert f.is_receive is True
assert f.payable is True
assert f.visibility == "external"
assert f.view is False
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is True
assert f.parameters == []
assert f.return_type is None
f = functions["constructor(address)"]
assert f.name == "constructor"
assert f.full_name == "constructor(address)"
assert f.canonical_name == "TestFunction.constructor(address)"
assert f.solidity_signature == "constructor(address)"
assert f.signature_str == "constructor(address) returns()"
assert f.function_type == FunctionType.CONSTRUCTOR
assert f.contains_assembly is False
assert f.can_reenter() is False
assert f.can_send_eth() is False
assert f.is_constructor
assert f.is_fallback is False
assert f.is_receive is False
assert f.payable is True
assert f.visibility == "public"
assert f.view is False
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is True
assert f.parameters[0].name == "_e"
assert f.parameters[0].type == ElementaryType("address")
assert f.return_type is None
f = functions["private_view()"]
assert f.name == "private_view"
assert f.full_name == "private_view()"
assert f.canonical_name == "TestFunction.private_view()"
assert f.solidity_signature == "private_view()"
assert f.signature_str == "private_view() returns(bool)"
assert f.function_type == FunctionType.NORMAL
assert f.contains_assembly is False
assert f.can_reenter() is False
assert f.can_send_eth() is False
assert f.is_constructor is False
assert f.is_fallback is False
assert f.is_receive is False
assert f.payable is False
assert f.visibility == "private"
assert f.view is True
assert f.pure is False
assert f.is_implemented is True
assert f.is_empty is False
assert f.parameters == []
assert f.return_type[0] == ElementaryType("bool")
f = functions["public_pure()"]
assert f.name == "public_pure"
assert f.full_name == "public_pure()"
assert f.canonical_name == "TestFunction.public_pure()"
assert f.solidity_signature == "public_pure()"
assert f.signature_str == "public_pure() returns(bool)"
assert f.function_type == FunctionType.NORMAL
assert f.contains_assembly is False
assert f.can_reenter() is False
assert f.can_send_eth() is False
assert f.is_constructor is False
assert f.is_fallback is False
assert f.is_receive is False
assert f.payable is False
assert f.visibility == "public"
assert f.view is True
assert f.pure is True
assert f.is_implemented is True
assert f.is_empty is False
assert f.parameters == []
assert f.return_type[0] == ElementaryType("bool")
def test_function_can_send_eth():
solc_select.switch_global_version("0.6.12", always_install=True)
file = Path(FUNC_DELC_TEST_ROOT, "test_function.sol").as_posix()
slither = Slither(file)
compilation_unit = slither.compilation_units[0]
functions = compilation_unit.get_contract_from_name("TestFunctionCanSendEth")[
0
].available_functions_as_dict()
assert functions["send_direct()"].can_send_eth() is True
assert functions["transfer_direct()"].can_send_eth() is True
assert functions["call_direct()"].can_send_eth() is True
assert functions["highlevel_call_direct()"].can_send_eth() is True
assert functions["send_via_internal()"].can_send_eth() is True
assert functions["transfer_via_internal()"].can_send_eth() is True
assert functions["call_via_internal()"].can_send_eth() is True
assert functions["highlevel_call_via_internal()"].can_send_eth() is True
assert functions["send_via_external()"].can_send_eth() is False
assert functions["transfer_via_external()"].can_send_eth() is False
assert functions["call_via_external()"].can_send_eth() is False
assert functions["highlevel_call_via_external()"].can_send_eth() is False
def test_reentrant():
solc_select.switch_global_version("0.8.10", always_install=True)
file = Path(FUNC_DELC_TEST_ROOT, "test_function_reentrant.sol").as_posix()
slither = Slither(file)
compilation_unit = slither.compilation_units[0]
functions = compilation_unit.get_contract_from_name("TestReentrant")[
0
].available_functions_as_dict()
assert functions["is_reentrant()"].is_reentrant
assert not functions["is_non_reentrant()"].is_reentrant
assert not functions["internal_and_not_reentrant()"].is_reentrant
assert not functions["internal_and_not_reentrant2()"].is_reentrant
assert functions["internal_and_could_be_reentrant()"].is_reentrant
assert functions["internal_and_reentrant()"].is_reentrant
def test_public_variable() -> None:
solc_select.switch_global_version("0.6.12", always_install=True)
file = Path(FUNC_DELC_TEST_ROOT, "test_function.sol").as_posix()
slither = Slither(file)
contracts = slither.get_contract_from_name("TestFunction")
assert len(contracts) == 1
contract = contracts[0]
var = contract.get_state_variable_from_name("info")
assert var
assert var.solidity_signature == "info()"
assert var.signature_str == "info() returns(bytes32)"
assert var.visibility == "public"
assert var.type == ElementaryType("bytes32")

@ -0,0 +1,127 @@
from pathlib import Path
from solc_select import solc_select
from slither import Slither
from slither.core.declarations import Function
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
SRC_MAPPING_TEST_ROOT = Path(TEST_DATA_DIR, "src_mapping")
def test_source_mapping():
solc_select.switch_global_version("0.6.12", always_install=True)
file = Path(SRC_MAPPING_TEST_ROOT, "inheritance.sol").as_posix()
slither = Slither(file)
# Check if A.f() is at the offset 27
functions = slither.offset_to_objects(file, 27)
print(functions)
assert len(functions) == 1
function = functions.pop()
assert isinstance(function, Function)
assert function.canonical_name == "A.f()"
# Only one definition for A.f()
assert {(x.start, x.end) for x in slither.offset_to_definitions(file, 27)} == {(26, 28)}
# Only one reference for A.f(), in A.test()
assert {(x.start, x.end) for x in slither.offset_to_references(file, 27)} == {(92, 93)}
# Only one implementation for A.f(), in A.test()
assert {(x.start, x.end) for x in slither.offset_to_implementations(file, 27)} == {(17, 53)}
# Check if C.f() is at the offset 203
functions = slither.offset_to_objects(file, 203)
assert len(functions) == 1
function = functions.pop()
assert isinstance(function, Function)
assert function.canonical_name == "C.f()"
# Only one definition for C.f()
assert {(x.start, x.end) for x in slither.offset_to_definitions(file, 203)} == {(202, 204)}
# Two references for C.f(), in A.test() and C.test2()
assert {(x.start, x.end) for x in slither.offset_to_references(file, 203)} == {
(270, 271),
(92, 93),
}
# Only one implementation for A.f(), in A.test()
assert {(x.start, x.end) for x in slither.offset_to_implementations(file, 203)} == {(193, 230)}
# Offset 93 is the call to f() in A.test()
# This can lead to three differents functions, depending on the current contract's context
functions = slither.offset_to_objects(file, 93)
print(functions)
assert len(functions) == 3
for function in functions:
assert isinstance(function, Function)
assert function.canonical_name in ["A.f()", "B.f()", "C.f()"]
# There are three definitions possible (in A, B or C)
assert {(x.start, x.end) for x in slither.offset_to_definitions(file, 93)} == {
(26, 28),
(202, 204),
(138, 140),
}
# There are two references possible (in A.test() or C.test2() )
assert {(x.start, x.end) for x in slither.offset_to_references(file, 93)} == {
(92, 93),
(270, 271),
}
# There are three implementations possible (in A, B or C)
assert {(x.start, x.end) for x in slither.offset_to_implementations(file, 93)} == {
(17, 53),
(193, 230),
(129, 166),
}
def _sort_references_lines(refs: list) -> list:
return sorted([ref.lines[0] for ref in refs])
def _test_references_user_defined_aliases():
"""
Tests if references are filled correctly for user defined aliases (declared using "type [...] is [...]" statement).
"""
solc_select.switch_global_version("0.8.16", always_install=True)
file = Path(SRC_MAPPING_TEST_ROOT, "ReferencesUserDefinedAliases.sol").as_posix()
slither = Slither(file)
alias_top_level = slither.compilation_units[0].user_defined_value_types["aliasTopLevel"]
assert len(alias_top_level.references) == 2
lines = _sort_references_lines(alias_top_level.references)
assert lines == [12, 16]
alias_contract_level = (
slither.compilation_units[0]
.contracts[0]
.file_scope.user_defined_types["C.aliasContractLevel"]
)
assert len(alias_contract_level.references) == 2
lines = _sort_references_lines(alias_contract_level.references)
assert lines == [13, 16]
def _test_references_user_defined_types_when_casting():
"""
Tests if references are filled correctly for user defined types in case of casting.
"""
solc_select.switch_global_version("0.8.16", always_install=True)
file = Path(SRC_MAPPING_TEST_ROOT, "ReferencesUserDefinedTypesCasting.sol").as_posix()
slither = Slither(file)
contracts = slither.compilation_units[0].contracts
a = contracts[0] if contracts[0].is_interface else contracts[1]
assert len(a.references) == 2
lines = _sort_references_lines(a.references)
assert lines == [12, 18]
def test_references():
"""
Tests if references list is filled correctly in the following cases:
- user defined aliases (declared using "type [...] is [...]" statement)
- user defined types in case of casting (TypeConversion expressions)
"""
_test_references_user_defined_aliases()
_test_references_user_defined_types_when_casting()

@ -0,0 +1,36 @@
import json
from pathlib import Path
from subprocess import PIPE, Popen
from solc_select import solc_select
from slither import Slither
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
STORAGE_TEST_ROOT = Path(TEST_DATA_DIR, "storage_layout")
def test_storage_layout():
# the storage layout has not yet changed between solidity versions so we will test with one version of the compiler
solc_select.switch_global_version("0.8.10", always_install=True)
test_item = Path(STORAGE_TEST_ROOT, "storage_layout-0.8.10.sol").as_posix()
sl = Slither(test_item, solc_force_legacy_json=False, disallow_partial=True)
with Popen(["solc", test_item, "--storage-layout"], stdout=PIPE) as process:
for line in process.stdout: # parse solc output
if '{"storage":[{' in line.decode("utf-8"): # find the storage layout
layout = iter(json.loads(line)["storage"])
while True:
try:
for contract in sl.contracts:
curr_var = next(layout)
var_name = curr_var["label"]
sl_name = contract.variables_as_dict[var_name]
slot, offset = contract.compilation_unit.storage_layout_of(
contract, sl_name
)
assert slot == int(curr_var["slot"])
assert offset == int(curr_var["offset"])
except StopIteration:
break
except KeyError as e:
print(f"not found {e} ")

@ -0,0 +1,95 @@
from pathlib import Path
from crytic_compile import CryticCompile
from crytic_compile.platform.solc_standard_json import SolcStandardJson
from solc_select import solc_select
from slither import Slither
from slither.slithir.operations import InternalCall, LibraryCall
from tests.utils import _run_all_detectors
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
USING_FOR_TEST_DATA_DIR = Path(TEST_DATA_DIR, "using_for")
def test_using_for_global_collision() -> None:
solc_select.switch_global_version("0.8.18", always_install=True)
standard_json = SolcStandardJson()
for source_file in Path(USING_FOR_TEST_DATA_DIR, "using_for_global_collision").rglob("*.sol"):
standard_json.add_source_file(Path(source_file).as_posix())
compilation = CryticCompile(standard_json)
sl = Slither(compilation)
_run_all_detectors(sl)
def test_using_for_top_level_same_name() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(Path(USING_FOR_TEST_DATA_DIR, "using-for-3-0.8.0.sol").as_posix())
contract_c = slither.get_contract_from_name("C")[0]
libCall = contract_c.get_function_from_full_name("libCall(uint256)")
for ir in libCall.all_slithir_operations():
if isinstance(ir, LibraryCall) and ir.destination == "Lib" and ir.function_name == "a":
return
assert False
def test_using_for_top_level_implicit_conversion() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(Path(USING_FOR_TEST_DATA_DIR, "using-for-4-0.8.0.sol").as_posix())
contract_c = slither.get_contract_from_name("C")[0]
libCall = contract_c.get_function_from_full_name("libCall(uint16)")
for ir in libCall.all_slithir_operations():
if isinstance(ir, LibraryCall) and ir.destination == "Lib" and ir.function_name == "f":
return
assert False
def test_using_for_alias_top_level() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(
Path(USING_FOR_TEST_DATA_DIR, "using-for-alias-top-level-0.8.0.sol").as_posix()
)
contract_c = slither.get_contract_from_name("C")[0]
libCall = contract_c.get_function_from_full_name("libCall(uint256)")
ok = False
for ir in libCall.all_slithir_operations():
if isinstance(ir, LibraryCall) and ir.destination == "Lib" and ir.function_name == "b":
ok = True
if not ok:
assert False
topLevelCall = contract_c.get_function_from_full_name("topLevel(uint256)")
for ir in topLevelCall.all_slithir_operations():
if isinstance(ir, InternalCall) and ir.function_name == "a":
return
assert False
def test_using_for_alias_contract() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(
Path(USING_FOR_TEST_DATA_DIR, "using-for-alias-contract-0.8.0.sol").as_posix()
)
contract_c = slither.get_contract_from_name("C")[0]
libCall = contract_c.get_function_from_full_name("libCall(uint256)")
ok = False
for ir in libCall.all_slithir_operations():
if isinstance(ir, LibraryCall) and ir.destination == "Lib" and ir.function_name == "b":
ok = True
if not ok:
assert False
topLevelCall = contract_c.get_function_from_full_name("topLevel(uint256)")
for ir in topLevelCall.all_slithir_operations():
if isinstance(ir, InternalCall) and ir.function_name == "a":
return
assert False
def test_using_for_in_library() -> None:
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(Path(USING_FOR_TEST_DATA_DIR, "using-for-in-library-0.8.0.sol").as_posix())
contract_c = slither.get_contract_from_name("A")[0]
libCall = contract_c.get_function_from_full_name("a(uint256)")
for ir in libCall.all_slithir_operations():
if isinstance(ir, LibraryCall) and ir.destination == "B" and ir.function_name == "b":
return
assert False

@ -0,0 +1,17 @@
contract Placeholder {
constructor() payable {}
}
contract NewContract {
bytes32 internal constant state_variable_read = bytes32(0);
function readAllStateVariables() external {
new Placeholder{salt: state_variable_read} ();
}
function readAllLocalVariables() external {
bytes32 local_variable_read = bytes32(0);
new Placeholder{salt: local_variable_read} ();
}
}

@ -0,0 +1,52 @@
interface Test {
function test() external payable returns (uint);
function testTuple() external payable returns (uint, uint);
}
contract C {
// TODO
// 1) support variable declarations
//uint min = 1 > 0 ? 1 : 2;
// 2) suppory ternary index range access
// function e(bool cond, bytes calldata x) external {
// bytes memory a = x[cond ? 1 : 2 :];
// }
function a(uint a, uint b) external {
(uint min, uint max) = a < b ? (a, b) : (b, a);
}
function b( address a, address b) external {
(address tokenA, address tokenB) = a < b ? (a, b) : (b, a);
}
bytes char;
function c(bytes memory strAddress, uint i, uint padding, uint length) external {
char[0] = strAddress[i < padding + 2 ? i : 42 + i - length];
}
function d(bool cond, bytes calldata x) external {
bytes1 a = x[cond ? 1 : 2];
}
function e(address one, address two) public {
uint x = Test(one).test{value: msg.sender == two ? 1 : 2, gas: true ? 2 : gasleft()}();
}
// Parenthetical expression
function f(address one, address two) public {
uint x = Test(one).test{value: msg.sender == two ? 1 : 2, gas: true ? (1 == 1 ? 1 : 2) : gasleft()}();
}
// Unused tuple variable
function g(address one) public {
(, uint x) = Test(one).testTuple();
}
uint[] myIntegers;
function _h(uint c) internal returns(uint) {
return c;
}
function h(bool cond, uint a, uint b) public {
uint d = _h(
myIntegers[cond ? a : b]
);
}
}

@ -0,0 +1,54 @@
from pathlib import Path
from collections import namedtuple
from slither import Slither
from slither.slithir.operations import Operation, NewContract
from solc_select import solc_select
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
def check_num_local_vars_read(function, slithir_op: Operation, num_reads_expected: int):
for node in function.nodes:
for operation in node.irs:
if isinstance(operation, slithir_op):
assert len(operation.read) == num_reads_expected
assert len(node.local_variables_read) == num_reads_expected
def check_num_states_vars_read(function, slithir_op: Operation, num_reads_expected: int):
for node in function.nodes:
for operation in node.irs:
if isinstance(operation, slithir_op):
assert len(operation.read) == num_reads_expected
assert len(node.state_variables_read) == num_reads_expected
OperationTest = namedtuple("OperationTest", "contract_name slithir_op")
OPERATION_TEST = [OperationTest("NewContract", NewContract)]
def test_operation_reads() -> None:
"""
Every slithir operation has its own contract and reads all local and state variables in readAllLocalVariables and readAllStateVariables, respectively.
"""
solc_select.switch_global_version("0.8.15", always_install=True)
slither = Slither(Path(TEST_DATA_DIR, "operation_reads.sol").as_posix())
for op_test in OPERATION_TEST:
print(op_test)
available = slither.get_contract_from_name(op_test.contract_name)
assert len(available) == 1
target = available[0]
num_state_variables = len(target.state_variables_ordered)
state_function = target.get_function_from_signature("readAllStateVariables()")
check_num_states_vars_read(state_function, op_test.slithir_op, num_state_variables)
local_function = target.get_function_from_signature("readAllLocalVariables()")
num_local_vars = len(local_function.local_variables)
check_num_local_vars_read(local_function, op_test.slithir_op, num_local_vars)
if __name__ == "__main__":
test_operation_reads()

File diff suppressed because it is too large Load Diff

@ -0,0 +1,43 @@
from pathlib import Path
from solc_select import solc_select
from slither import Slither
from slither.core.cfg.node import NodeType
from slither.slithir.operations import Assignment
from slither.core.expressions import AssignmentOperation, TupleExpression
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
# pylint: disable=too-many-nested-blocks
def test_ternary_conversions() -> None:
"""This tests that true and false sons define the same number of variables that the father node declares"""
solc_select.switch_global_version("0.8.0", always_install=True)
slither = Slither(Path(TEST_DATA_DIR, "ternary_expressions.sol").as_posix())
for contract in slither.contracts:
for function in contract.functions:
vars_declared = 0
vars_assigned = 0
for node in function.nodes:
if node.type in [NodeType.IF, NodeType.IFLOOP]:
# Iterate over true and false son
for inner_node in node.sons:
# Count all variables declared
expression = inner_node.expression
if isinstance(expression, AssignmentOperation):
var_expr = expression.expression_left
# Only tuples declare more than one var
if isinstance(var_expr, TupleExpression):
vars_declared += len(var_expr.expressions)
else:
vars_declared += 1
for ir in inner_node.irs:
# Count all variables defined
if isinstance(ir, Assignment):
vars_assigned += 1
assert vars_declared == vars_assigned
if __name__ == "__main__":
test_ternary_conversions()

@ -0,0 +1,64 @@
pragma experimental ABIEncoderV2;
contract Contract{}
contract C{
mapping(uint => address)[] public arrayOfMappings;
mapping(uint => address[]) public normalMappingArrayField;
enum State{a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35,a36,a37,a38,a39,a40,a41,a42,a43,a44,a45,a46,a47,a48,a49,a50,a51,a52,a53,a54,a55,a56,a57,a58,a59,a60,a61,a62,a63,a64,a65,a66,a67,a68,a69,a70,a71,a72,a73,a74,a75,a76,a77,a78,a79,a80,a81,a82,a83,a84,a85,a86,a87,a88,a89,a90,a91,a92,a93,a94,a95,a96,a97,a98,a99,a100,a101,a102,a103,a104,a105,a106,a107,a108,a109,a110,a111,a112,a113,a114,a115,a116,a117,a118,a119,a120,a121,a122,a123,a124,a125,a126,a127,a128,a129,a130,a131,a132,a133,a134,a135,a136,a137,a138,a139,a140,a141,a142,a143,a144,a145,a146,a147,a148,a149,a150,a151,a152,a153,a154,a155,a156,a157,a158,a159,a160,a161,a162,a163,a164,a165,a166,a167,a168,a169,a170,a171,a172,a173,a174,a175,a176,a177,a178,a179,a180,a181,a182,a183,a184,a185,a186,a187,a188,a189,a190,a191,a192,a193,a194,a195,a196,a197,a198,a199,a200,a201,a202,a203,a204,a205,a206,a207,a208,a209,a210,a211,a212,a213,a214,a215,a216,a217,a218,a219,a220,a221,a222,a223,a224,a225,a226,a227,a228,a229,a230,a231,a232,a233,a234,a235,a236,a237,a238,a239,a240,a241,a242,a243,a244,a245,a246,a247,a248,a249,a250,a251,a252,a253,a254,a255,a256}
mapping(State => uint) public stateMap;
mapping(Contract => uint) public contractMap;
uint[][] public multiDimensionalArray;
struct Simple {
uint a;
uint b;
mapping(uint => uint) c;
uint[] d;
function(uint) external returns (uint) e;
}
Simple public simple;
struct Inner {
uint a;
uint b;
}
struct Outer {
Inner inner;
uint c;
}
Outer public outer;
struct A {
Inner inner;
uint a;
}
struct B {
uint a;
Inner inner;
}
A public a;
A[] public a_array;
mapping(address => B[]) public b_mapping_of_array;
function function_with_struct(A memory a) public{}
function function_with_array(A[] memory array, B memory b) public {}
struct AnotherStruct{
B b;
A[] a;
}
mapping(address => AnotherStruct[][]) public mapping_of_double_array_of_struct;
}

@ -0,0 +1,12 @@
contract A{
struct St{
St[] a;
uint b;
}
function f(St memory s) internal{
f(s);
}
}

@ -0,0 +1,64 @@
from pathlib import Path
from solc_select import solc_select
from slither import Slither
# % solc functions_ids.sol --hashes
# ======= functions_ids.sol:C =======
# Function signatures:
# 0dbe671f: a()
# 4a1f689d: a_array(uint256)
# 98fc2aa5: arrayOfMappings(uint256,uint256)
# 4ea7a557: b_mapping_of_array(address,uint256)
# 3c0af344: contractMap(address)
# 20969954: function_with_array(((uint256,uint256),uint256)[],(uint256,(uint256,uint256)))
# 1c039831: function_with_struct(((uint256,uint256),uint256))
# 37e66bae: mapping_of_double_array_of_struct(address,uint256,uint256)
# f29872a8: multiDimensionalArray(uint256,uint256)
# 9539e3c8: normalMappingArrayField(uint256,uint256)
# 87c3dbb6: outer()
# df201a46: simple()
# 5a20851f: stateMap(uint16)
# {"contracts":{"functions_ids.sol:C":{"hashes":{"a()":"0dbe671f","a_array(uint256)":"4a1f689d","arrayOfMappings(uint256,uint256)":"98fc2aa5","b_mapping_of_array(address,uint256)":"4ea7a557","contractMap(address)":"3c0af344","function_with_array(((uint256,uint256),uint256)[],(uint256,(uint256,uint256)))":"20969954","function_with_struct(((uint256,uint256),uint256))":"1c039831","mapping_of_double_array_of_struct(address,uint256,uint256)":"37e66bae","multiDimensionalArray(uint256,uint256)":"f29872a8","normalMappingArrayField(uint256,uint256)":"9539e3c8","outer()":"87c3dbb6","simple()":"df201a46","stateMap(uint16)":"5a20851f"}},"functions_ids.sol:Contract":{"hashes":{}}},"version":"0.7.0+commit.9e61f92b.Darwin.appleclang"}
from slither.utils.function import get_function_id
signatures = {
"a()": "0dbe671f",
"a_array(uint256)": "4a1f689d",
"arrayOfMappings(uint256,uint256)": "98fc2aa5",
"b_mapping_of_array(address,uint256)": "4ea7a557",
"contractMap(address)": "3c0af344",
"function_with_array(((uint256,uint256),uint256)[],(uint256,(uint256,uint256)))": "20969954",
"function_with_struct(((uint256,uint256),uint256))": "1c039831",
"mapping_of_double_array_of_struct(address,uint256,uint256)": "37e66bae",
"multiDimensionalArray(uint256,uint256)": "f29872a8",
"normalMappingArrayField(uint256,uint256)": "9539e3c8",
"outer()": "87c3dbb6",
"simple()": "df201a46",
"stateMap(uint16)": "5a20851f",
}
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
def test_functions_ids() -> None:
solc_select.switch_global_version("0.7.0", always_install=True)
file = Path(TEST_DATA_DIR, "functions_ids.sol").as_posix()
sl = Slither(file)
contracts_c = sl.get_contract_from_name("C")
assert len(contracts_c) == 1
contract_c = contracts_c[0]
for sig, hashes in signatures.items():
func = contract_c.get_function_from_signature(sig)
if not func:
var_name = sig[: sig.find("(")]
var = contract_c.get_state_variable_from_name(var_name)
assert var
assert get_function_id(var.solidity_signature) == int(hashes, 16)
else:
assert get_function_id(func.solidity_signature) == int(hashes, 16)
if __name__ == "__main__":
test_functions_ids()

@ -0,0 +1,13 @@
from pathlib import Path
from solc_select import solc_select
from slither import Slither
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
def test_function_id_rec_structure() -> None:
solc_select.switch_global_version("0.8.0", always_install=True)
slither = Slither(Path(TEST_DATA_DIR, "type_helpers.sol").as_posix())
for compilation_unit in slither.compilation_units:
for function in compilation_unit.functions:
assert function.solidity_signature
Loading…
Cancel
Save