[Feature Request]: Printer to report all external calls in a contract
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
Do you have a format in mind? Most of the printers are tables but we can also show the source code context
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