Skip to content

AssertionError in resolve_remapping_and_renaming when analyzing contract with import aliasing #3019

Description

@Aniket-Engg

Description

Slither fails with an AssertionError when analyzing Solidity code that imports files using import aliasing (specifically the Chainlink KeeperCompatibleInterface.sol pattern).

Environment

  • Slither version: 0.11.5
  • Python version: 3.11
  • Operating system: macOS (Darwin 22.3.0)
  • Solidity compiler: 0.8.34
  • Framework: Foundry

Steps to Reproduce

  1. Create a Foundry project with the following structure:

foundry.toml:

[profile.default]
src = "src"
out = "out"
libs = ["lib"]

remappings.txt:

  @chainlink/=lib/chainlink-evm/

src/KeepersCounter.sol:

  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  import "@chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol";

  contract KeepersCounter is KeeperCompatibleInterface {
      uint256 public counter;
      uint256 public immutable interval;
      uint256 public lastTimeStamp;

      constructor(uint256 updateInterval) {
          interval = updateInterval;
          lastTimeStamp = block.timestamp;
          counter = 0;
      }

      function checkUpkeep(bytes calldata) external view override returns (bool upkeepNeeded, bytes memory) {
          upkeepNeeded = (block.timestamp - lastTimeStamp) > interval;
      }

      function performUpkeep(bytes calldata) external override {
          if ((block.timestamp - lastTimeStamp) > interval) {
              lastTimeStamp = block.timestamp;
              counter = counter + 1;
          }
      }
  }

lib/chainlink-evm/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol:

  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "./AutomationCompatibleInterface.sol";

  lib/chainlink-evm/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol:
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  interface AutomationCompatibleInterface {
      function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData);
      function performUpkeep(bytes calldata performData) external;
  }
  1. Run: forge build (this succeeds)
  2. Run: slither .

Expected Behavior

Slither should successfully analyze the contract.

Actual Behavior

Slither fails with:

Traceback (most recent call last):
File "/opt/homebrew/bin/slither", line 8, in
sys.exit(main())
^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/slither/main.py", line 760, in main
main_impl(all_detector_classes=detectors, all_printer_classes=printers)
File "/opt/homebrew/lib/python3.11/site-packages/slither/main.py", line 865, in main_impl
) = process_all(filename, args, detector_classes, printer_classes)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/slither/main.py", line 106, in process_all
) = process_single(compilation, args, detector_classes, printer_classes)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/slither/main.py", line 79, in process_single
slither = Slither(target, ast_format=ast, **vars(args))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/slither/slither.py", line 197, in init
self._init_parsing_and_analyses(kwargs.get("skip_analyze", False))
File "/opt/homebrew/lib/python3.11/site-packages/slither/slither.py", line 206, in _init_parsing_and_analyses
raise e
File "/opt/homebrew/lib/python3.11/site-packages/slither/slither.py", line 202, in _init_parsing_and_analyses
parser.parse_contracts()
File "/opt/homebrew/lib/python3.11/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 502, in parse_contracts
target = resolve_remapping_and_renaming(contract_parser, i)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 488, in resolve_remapping_and_renaming
assert target, f"Contract {contract_name} not found"
AssertionError: Contract KeeperCompatibleInterface not found


Trying slither with --ignore-compile and running forge build --ast before hand throws these errors:

  File "/opt/homebrew/lib/python3.11/site-packages/crytic_compile/crytic_compile.py", line 211, in __init__
    self._compile(**kwargs)
  File "/opt/homebrew/lib/python3.11/site-packages/crytic_compile/crytic_compile.py", line 633, in _compile
    self._platform.compile(self, **kwargs)
  File "/opt/homebrew/lib/python3.11/site-packages/crytic_compile/platform/foundry.py", line 102, in compile
    hardhat_like_parsing(
  File "/opt/homebrew/lib/python3.11/site-packages/crytic_compile/platform/hardhat.py", line 72, in hardhat_like_parsing
    targets_json = loaded_json["output"]
                   ~~~~~~~~~~~^^^^^^^^^^
KeyError: 'output'

Root Cause

The issue occurs in slither_compilation_unit_solc.py:488 in the resolve_remapping_and_renaming function. The file KeeperCompatibleInterface.sol uses the pattern:

import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "./AutomationCompatibleInterface.sol";

This creates an alias/re-export where KeeperCompatibleInterface is not actually defined as a contract in the file, but is aliased from AutomationCompatibleInterface. Slither's contract resolver cannot find
KeeperCompatibleInterface as an actual contract definition and fails.

Additional Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions