Update Cheatcode Printer

pull/2413/head
Alexis 8 months ago
parent 46d0cb13db
commit 7045cb82d8
No known key found for this signature in database
  1. 1
      slither/printers/all_printers.py
  2. 53
      slither/printers/summary/cheatcodes.py
  3. 66
      tests/e2e/printers/test_data/test_printer_cheatcode/README.md
  4. 14
      tests/e2e/printers/test_data/test_printer_cheatcode/src/Counter.sol
  5. 8
      tests/e2e/printers/test_data/test_printer_cheatcode/src/Vault.sol
  6. 36
      tests/e2e/printers/test_data/test_printer_cheatcode/test/Counter.t.sol
  7. 32
      tests/e2e/printers/test_data/test_printer_cheatcode/test/Vault.t.sol
  8. 15
      tests/e2e/printers/test_printers.py

@ -24,3 +24,4 @@ from .summary.when_not_paused import PrinterWhenNotPaused
from .summary.declaration import Declaration from .summary.declaration import Declaration
from .functions.dominator import Dominator from .functions.dominator import Dominator
from .summary.martin import Martin from .summary.martin import Martin
from .summary.cheatcodes import CheatcodePrinter

@ -4,6 +4,7 @@
This printer prints the usage of cheatcode in the code. This printer prints the usage of cheatcode in the code.
""" """
from slither.printers.abstract_printer import AbstractPrinter from slither.printers.abstract_printer import AbstractPrinter
from slither.slithir.operations import HighLevelCall
from slither.utils import output from slither.utils import output
@ -11,9 +12,59 @@ class CheatcodePrinter(AbstractPrinter):
ARGUMENT = "cheatcode" ARGUMENT = "cheatcode"
HELP = """""" HELP = """
Print the usage of (Foundry) cheatcodes in the code.
For the complete list of Cheatcodes, see https://book.getfoundry.sh/cheatcodes/
"""
WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#cheatcode" WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#cheatcode"
def output(self, filename: str) -> output.Output: def output(self, filename: str) -> output.Output:
info: str = ""
vm = self.slither.get_contract_from_name("Vm").pop()
for contract in self.slither.contracts_derived:
# Check that the IS_TEST variable is set. (Only works for Foundry)
is_test_var = contract.variables_as_dict.get("IS_TEST", None)
is_test = False
if is_test_var is not None:
try:
is_test = is_test_var.expression.value == "true"
except AttributeError:
pass pass
if not is_test:
continue
found_contract: bool = False
contract_info: str = ""
for func in contract.functions_declared:
function_info = f"\t{func}\n"
found_function: bool = False
for node in func.nodes:
for op in node.all_slithir_operations():
if (
isinstance(op, HighLevelCall)
and op.function.contract == vm
and op.function.visibility == "external"
):
found_function = True
function_info += (
f"\t\tL{node.source_mapping.lines}: {op.function.name}\n"
)
if found_function:
if found_contract is False:
contract_info = f"{contract} ({contract.source_mapping.filename.short})\n"
found_contract = True
contract_info += function_info
if found_contract:
info += contract_info
self.info(info)
res = output.Output(info)
return res

@ -1,66 +1,6 @@
## Foundry # Counter
**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
Foundry consists of:
- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.
## Documentation
https://book.getfoundry.sh/
## Usage
### Build
```shell
$ forge build
```
### Test
```shell
$ forge test
```
### Format
```shell
$ forge fmt
```
### Gas Snapshots
```shell
$ forge snapshot
```
### Anvil
```shell
$ anvil
```
### Deploy
```shell
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
```
### Cast
```shell
$ cast <subcommand>
```
### Help
Init using :
```shell ```shell
$ forge --help forge install foundry-rs/forge-std
$ anvil --help
$ cast --help
``` ```

@ -0,0 +1,14 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract Counter {
uint256 public number;
function setNumber(uint256 newNumber) public {
number = newNumber;
}
function increment() public {
number++;
}
}

@ -1,8 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract Vault {
constructor(){
}
}

@ -0,0 +1,36 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "../src/Counter.sol";
contract CounterTest is Test {
Counter public counter;
address public alice = address(0x42);
address public bob = address(0x43);
function difficulty(uint256 value) public {
// empty
}
function setUp() public {
counter = new Counter();
counter.setNumber(0);
vm.deal(alice, 1 ether);
vm.deal(bob, 2 ether);
difficulty(1);
}
function testIncrement() public {
vm.prank(alice);
counter.increment();
assertEq(counter.number(), 1);
vm.prank(bob);
counter.increment();
assertEq(counter.number(), 2);
}
}

@ -1,32 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
import "../src/Vault.sol";
contract VaultTest is Test {
Vault public vault;
address public alice = address(0x42);
function broadcast() pure public {}
function setUp() public {
vm.prank(alice);
vm.deal(alice, 1000 ether);
uint256 value = 123;
vm.warp(1641070800);
vm.roll(100);
vm.fee(25 gwei);
// Not a cheatcode
broadcast();
}
function test_deal() public {
}
}

@ -1,14 +1,15 @@
import re import re
import shutil import shutil
import pytest
from collections import Counter from collections import Counter
from pathlib import Path from pathlib import Path
import pytest
from crytic_compile import CryticCompile from crytic_compile import CryticCompile
from crytic_compile.platform.solc_standard_json import SolcStandardJson from crytic_compile.platform.solc_standard_json import SolcStandardJson
from slither import Slither from slither import Slither
from slither.printers.inheritance.inheritance_graph import PrinterInheritanceGraph from slither.printers.inheritance.inheritance_graph import PrinterInheritanceGraph
from slither.printers.summary.cheatcodes import CheatcodePrinter
TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"
@ -45,4 +46,14 @@ def test_inheritance_printer(solc_binary_path) -> None:
not foundry_available or not project_ready, reason="requires Foundry and project setup" not foundry_available or not project_ready, reason="requires Foundry and project setup"
) )
def test_printer_cheatcode(): def test_printer_cheatcode():
slither = Slither(Path(TEST_DATA_DIR, "test_printer_cheatcode").as_posix()) slither = Slither(
Path(TEST_DATA_DIR, "test_printer_cheatcode").as_posix(), foundry_compile_all=True
)
printer = CheatcodePrinter(slither=slither, logger=None)
output = printer.output("cheatcode.out")
assert (
output
== "CounterTest (test/Counter.t.sol)\n\tsetUp\n\t\tL[21]: deal\n\t\tL[22]: deal\n\ttestIncrement\n\t\tL[28]: prank\n\t\tL[30]: assertEq\n\t\tL[32]: prank\n\t\tL[34]: assertEq\n"
)

Loading…
Cancel
Save