slither icon indicating copy to clipboard operation
slither copied to clipboard

[Feature Request]: Printer to report all external calls in a contract

Open mds1 opened this issue 2 years ago • 2 comments

Describe the desired feature

It's valuable to have a list of all external calls for various reasons. A rough workaround for this is to run slither . --print function-summary and review the "External calls" column, but this currently has a bug (https://github.com/crytic/slither/issues/2073) and there's also a lot of noise in the output.

I'd like to see something like slither . --print external-call-summary that returns (1) a list of all external calls in a contract, and (2) the contract and method containing that external call.

For example:

contract A {
  IERC20 token;

  function foo() internal {
    token.balanceOf(address(this));
  }
}

contract B is A {
  function bar() public {
     foo()
  }
}

For this example the printer should report that B.bar() makes an external call of token.balanceOf(address(this)). If it can report the fact that the call is because of A.foo() that would be even better

mds1 avatar Aug 01 '23 22:08 mds1

Do you have a format in mind? Most of the printers are tables but we can also show the source code context

0xalpharush avatar Aug 01 '23 23:08 0xalpharush

Hmm, I'm a bit indifferent on the output format, but I do think having the full context is useful, since tracking inheritance paths manually to see where it's from can get tricky for large protocols that have a lot of inheritance, e.g. OZ governors where there's no choice but a lot of inheritance and overrides.

A table where the columns are something like contractName, inheritance path / stack trace, the external call, and path to line of code would be a good format. I'd probably default to this one since it's consistent with the other output formats.

I don't think showing the extra source code context is necessary as long as it's easy to find the specified line of source

Another idea is a tree view, optionally with line numbers if plausible

B.bar()
|-- A.foo() [B, L3] <-- the brackets indicate you can find this in contract B, line 3, alternatively can just link directly to the file here, e.g. src/B.sol#L3
      |--token.balanceOf(address(this)) [A, L5]

Another idea is a flat view which might scale better when there's large amounts of calls.

B.bar() -> A.foo() [B, L3] -> token.balanceOf(address(this)) [A, L5]

Linking to source inline would get messy with the latter, perhaps could be solved like this. Main benefit is this makes it easier to filter out the file paths if you don't want them

B.bar() -> A.foo() -> token.balanceOf(address(this))
              |             |-- src/A.sol#L5
              |-- src/B.sol#L3

Open to thoughts/other ideas here too, but my initial thoughts are that the table is the way to go

mds1 avatar Aug 01 '23 23:08 mds1