Skip to content

Commit 8190a48

Browse files
authored
Merge pull request #2575 from crytic/dev-optimism-deprecation
Add Optimism deprecation detector
2 parents 0811cd6 + 6b503a9 commit 8190a48

File tree

6 files changed

+129
-0
lines changed

6 files changed

+129
-0
lines changed

slither/detectors/all_detectors.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,6 @@
9797
from .statements.tautological_compare import TautologicalCompare
9898
from .statements.return_bomb import ReturnBomb
9999
from .functions.out_of_order_retryable import OutOfOrderRetryable
100+
from .functions.optimism_deprecation import OptimismDeprecation
100101

101102
# from .statements.unused_import import UnusedImport
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
from typing import List
2+
3+
from slither.detectors.abstract_detector import (
4+
AbstractDetector,
5+
DetectorClassification,
6+
DETECTOR_INFO,
7+
)
8+
from slither.core.cfg.node import Node
9+
from slither.core.variables.variable import Variable
10+
from slither.core.expressions import TypeConversion, Literal
11+
from slither.utils.output import Output
12+
13+
14+
class OptimismDeprecation(AbstractDetector):
15+
16+
ARGUMENT = "optimism-deprecation"
17+
HELP = "Detect when deprecated Optimism predeploy or function is used."
18+
IMPACT = DetectorClassification.LOW
19+
CONFIDENCE = DetectorClassification.HIGH
20+
21+
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#optimism-deprecation"
22+
23+
WIKI_TITLE = "Optimism deprecated predeploy or function"
24+
WIKI_DESCRIPTION = "Detect when deprecated Optimism predeploy or function is used."
25+
26+
# region wiki_exploit_scenario
27+
WIKI_EXPLOIT_SCENARIO = """
28+
```solidity
29+
interface GasPriceOracle {
30+
function scalar() external view returns (uint256);
31+
}
32+
33+
contract Test {
34+
GasPriceOracle constant OPT_GAS = GasPriceOracle(0x420000000000000000000000000000000000000F);
35+
36+
function a() public {
37+
OPT_GAS.scalar();
38+
}
39+
}
40+
```
41+
The call to the `scalar` function of the Optimism GasPriceOracle predeploy always revert.
42+
"""
43+
# endregion wiki_exploit_scenario
44+
45+
WIKI_RECOMMENDATION = "Do not use the deprecated components."
46+
47+
def _detect(self) -> List[Output]:
48+
results = []
49+
50+
deprecated_predeploys = [
51+
"0x4200000000000000000000000000000000000000", # LegacyMessagePasser
52+
"0x4200000000000000000000000000000000000001", # L1MessageSender
53+
"0x4200000000000000000000000000000000000002", # DeployerWhitelist
54+
"0x4200000000000000000000000000000000000013", # L1BlockNumber
55+
]
56+
57+
for contract in self.compilation_unit.contracts_derived:
58+
use_deprecated: List[Node] = []
59+
60+
for _, ir in contract.all_high_level_calls:
61+
# To avoid FPs we assume predeploy contracts are always assigned to a constant and typecasted to an interface
62+
# and we check the target address of a high level call.
63+
if (
64+
isinstance(ir.destination, Variable)
65+
and isinstance(ir.destination.expression, TypeConversion)
66+
and isinstance(ir.destination.expression.expression, Literal)
67+
):
68+
if ir.destination.expression.expression.value in deprecated_predeploys:
69+
use_deprecated.append(ir.node)
70+
71+
if (
72+
ir.destination.expression.expression.value
73+
== "0x420000000000000000000000000000000000000F"
74+
and ir.function_name in ("overhead", "scalar", "getL1GasUsed")
75+
):
76+
use_deprecated.append(ir.node)
77+
# Sort so output is deterministic
78+
use_deprecated.sort(key=lambda x: (x.node_id, x.function.full_name))
79+
if len(use_deprecated) > 0:
80+
info: DETECTOR_INFO = [
81+
"A deprecated Optimism predeploy or function is used in the ",
82+
contract.name,
83+
" contract.\n",
84+
]
85+
86+
for node in use_deprecated:
87+
info.extend(["\t - ", node, "\n"])
88+
89+
res = self.generate_result(info)
90+
results.append(res)
91+
92+
return results
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
A deprecated Optimism predeploy or function is used in the Test contract.
2+
- OPT_GAS.scalar() (tests/e2e/detectors/test_data/optimism-deprecation/0.8.20/optimism_deprecation.sol#15)
3+
- L1_BLOCK_NUMBER.q() (tests/e2e/detectors/test_data/optimism-deprecation/0.8.20/optimism_deprecation.sol#19)
4+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
interface GasPriceOracle {
2+
function scalar() external view returns (uint256);
3+
function baseFee() external view returns (uint256);
4+
}
5+
6+
interface L1BlockNumber {
7+
function q() external view returns (uint256);
8+
}
9+
10+
contract Test {
11+
GasPriceOracle constant OPT_GAS = GasPriceOracle(0x420000000000000000000000000000000000000F);
12+
L1BlockNumber constant L1_BLOCK_NUMBER = L1BlockNumber(0x4200000000000000000000000000000000000013);
13+
14+
function bad() public {
15+
OPT_GAS.scalar();
16+
}
17+
18+
function bad2() public {
19+
L1_BLOCK_NUMBER.q();
20+
}
21+
22+
function good() public {
23+
OPT_GAS.baseFee();
24+
}
25+
26+
27+
}
Binary file not shown.

tests/e2e/detectors/test_detectors.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,6 +1714,11 @@ def id_test(test_item: Test):
17141714
"out_of_order_retryable.sol",
17151715
"0.8.20",
17161716
),
1717+
Test(
1718+
all_detectors.OptimismDeprecation,
1719+
"optimism_deprecation.sol",
1720+
"0.8.20",
1721+
),
17171722
# Test(
17181723
# all_detectors.UnusedImport,
17191724
# "ConstantContractLevelUsedInContractTest.sol",

0 commit comments

Comments
 (0)