Skip to content

Commit eae626d

Browse files
mssassiiThegaram
authored andcommitted
ci: add Slither static-analysis (#103)
Co-authored-by: Péter Garamvölgyi <[email protected]>
1 parent 4e66294 commit eae626d

File tree

13 files changed

+105
-4
lines changed

13 files changed

+105
-4
lines changed

.github/workflows/contracts.yml

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,59 @@ jobs:
138138
run: npx hardhat compile
139139

140140
- name: Run hardhat tests
141-
run: npx hardhat test
141+
run: npx hardhat test
142+
143+
slither:
144+
if: github.event.pull_request.draft == false
145+
needs: foundry
146+
runs-on: ubuntu-latest
147+
permissions:
148+
statuses: write
149+
security-events: write
150+
151+
steps:
152+
- uses: actions/checkout@v4
153+
with:
154+
submodules: recursive
155+
persist-credentials: false
156+
157+
- uses: actions/setup-node@v4
158+
with:
159+
node-version: '18'
160+
161+
- run: yarn install --frozen-lockfile
162+
163+
- uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1.4.0
164+
with:
165+
version: nightly
166+
167+
- name: Build contracts
168+
run: forge build --build-info --out out --evm-version cancun
169+
170+
- uses: actions/setup-python@v5
171+
with:
172+
python-version: '3.11'
173+
174+
- run: |
175+
python -m pip install --upgrade pip
176+
pip install slither-analyzer==0.11.3
177+
178+
- name: Run Slither (High severity gate)
179+
run: |
180+
slither . \
181+
--filter-paths "src/test/*|src/mocks/*|scripts/*|node_modules" \
182+
--foundry-out-directory out \
183+
--exclude-dependencies \
184+
--exclude-medium \
185+
--exclude-low \
186+
--exclude-informational \
187+
--fail-high \
188+
--json slither-report.json \
189+
--markdown-root slither-report.md
190+
191+
- uses: actions/upload-artifact@v4
192+
with:
193+
name: slither-static-analysis
194+
path: |
195+
slither-report.json
196+
slither-report.md

src/L1/L1ScrollMessenger.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
203203
require(_from != xDomainMessageSender, "Invalid message sender");
204204

205205
xDomainMessageSender = _from;
206+
// xDomainMessageSender serves as reentrancy guard (notInExecution modifier).
207+
// slither-disable-next-line reentrancy-eth
206208
(bool success, ) = _to.call{value: _value}(_message);
207209
// reset value to refund gas.
208210
xDomainMessageSender = ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER;
@@ -316,6 +318,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
316318
// @note If the list is very long, the message may never be dropped.
317319
while (true) {
318320
// If the `_lastIndex` is from `messageQueueV2`, it will revert in `messageQueueV1.dropCrossDomainMessage`.
321+
// call to messageQueueV1 is safe.
322+
// slither-disable-next-line reentrancy-no-eth
319323
IL1MessageQueueV1(messageQueueV1).dropCrossDomainMessage(_lastIndex);
320324
_lastIndex = prevReplayIndex[_lastIndex];
321325
if (_lastIndex == 0) break;
@@ -328,6 +332,8 @@ contract L1ScrollMessenger is ScrollMessengerBase, IL1ScrollMessenger {
328332

329333
// set execution context
330334
xDomainMessageSender = ScrollConstants.DROP_XDOMAIN_MESSAGE_SENDER;
335+
// xDomainMessageSender serves as reentrancy guard (notInExecution modifier).
336+
// slither-disable-next-line reentrancy-eth
331337
IMessageDropCallback(_from).onDropMessage{value: _value}(_message);
332338
// clear execution context
333339
xDomainMessageSender = ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER;

src/L1/gateways/L1ETHGateway.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ contract L1ETHGateway is ScrollGatewayBase, IL1ETHGateway, IMessageDropCallback
9090

9191
// @note can possible trigger reentrant call to messenger,
9292
// but it seems not a big problem.
93+
// no reentrancy risk (nonReentrant modifier).
94+
// slither-disable-next-line arbitrary-send-eth
9395
(bool _success, ) = _to.call{value: _amount}("");
9496
require(_success, "ETH transfer failed");
9597

@@ -108,6 +110,8 @@ contract L1ETHGateway is ScrollGatewayBase, IL1ETHGateway, IMessageDropCallback
108110

109111
require(_amount == msg.value, "msg.value mismatch");
110112

113+
// no reentrancy risk (nonReentrant modifier).
114+
// slither-disable-next-line arbitrary-send-eth
111115
(bool _success, ) = _receiver.call{value: _amount}("");
112116
require(_success, "ETH transfer failed");
113117

src/L1/gateways/L1GatewayRouter.sol

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,19 @@ contract L1GatewayRouter is OwnableUpgradeable, IL1GatewayRouter {
104104
*****************************/
105105

106106
/// @inheritdoc IL1GatewayRouter
107-
/// @dev All the gateways should have reentrancy guard to prevent potential attack though this function.
107+
/// @dev All the gateways should have reentrancy guard to prevent potential attack through this function.
108108
function requestERC20(
109109
address _sender,
110110
address _token,
111111
uint256 _amount
112112
) external onlyInContext returns (uint256) {
113113
address _caller = _msgSender();
114114
uint256 _balance = IERC20Upgradeable(_token).balanceOf(_caller);
115+
116+
// only whitelisted caller allowed (onlyInContext modifier).
117+
// slither-disable-next-line arbitrary-send-erc20
115118
IERC20Upgradeable(_token).safeTransferFrom(_sender, _caller, _amount);
119+
116120
_amount = IERC20Upgradeable(_token).balanceOf(_caller) - _balance;
117121
return _amount;
118122
}
@@ -157,6 +161,8 @@ contract L1GatewayRouter is OwnableUpgradeable, IL1GatewayRouter {
157161
// encode msg.sender with _data
158162
bytes memory _routerData = abi.encode(_msgSender(), _data);
159163

164+
// gatewayInContext serves as reentrancy guard (onlyNotInContext modifier).
165+
// slither-disable-next-line reentrancy-eth
160166
IL1ERC20Gateway(_gateway).depositERC20AndCall{value: msg.value}(_token, _to, _amount, _routerData, _gasLimit);
161167

162168
// leave deposit context

src/L1/gateways/L1WETHGateway.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ contract L1WETHGateway is L1ERC20Gateway {
102102
require(_l2Token == l2WETH, "l2 token not WETH");
103103
require(_amount == msg.value, "msg.value mismatch");
104104

105+
// deposit to WETH token is safe.
106+
// slither-disable-next-line arbitrary-send-eth
105107
IWETH(_l1Token).deposit{value: _amount}();
106108
}
107109

@@ -114,6 +116,8 @@ contract L1WETHGateway is L1ERC20Gateway {
114116
require(_token == WETH, "token not WETH");
115117
require(_amount == msg.value, "msg.value mismatch");
116118

119+
// deposit to WETH token is safe.
120+
// slither-disable-next-line arbitrary-send-eth
117121
IWETH(_token).deposit{value: _amount}();
118122
}
119123

src/L2/L2ScrollMessenger.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ contract L2ScrollMessenger is ScrollMessengerBase, IL2ScrollMessenger {
156156

157157
xDomainMessageSender = _from;
158158
// solhint-disable-next-line avoid-low-level-calls
159+
// no reentrancy risk, only alias(l1ScrollMessenger) can call relayMessage.
160+
// slither-disable-next-line reentrancy-eth
159161
(bool success, ) = _to.call{value: _value}(_message);
160162
// reset value to refund gas.
161163
xDomainMessageSender = ScrollConstants.DEFAULT_XDOMAIN_MESSAGE_SENDER;

src/L2/gateways/L2ETHGateway.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ contract L2ETHGateway is ScrollGatewayBase, IL2ETHGateway {
8686
require(msg.value == _amount, "msg.value mismatch");
8787

8888
// solhint-disable-next-line avoid-low-level-calls
89+
// no reentrancy risk.
90+
// slither-disable-next-line arbitrary-send-eth
8991
(bool _success, ) = _to.call{value: _amount}("");
9092
require(_success, "ETH transfer failed");
9193

src/L2/gateways/L2WETHGateway.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ contract L2WETHGateway is L2ERC20Gateway {
110110
require(_l2Token == WETH, "l2 token not WETH");
111111
require(_amount == msg.value, "msg.value mismatch");
112112

113+
// deposit to WETH token is safe.
114+
// slither-disable-next-line arbitrary-send-eth
113115
IWETH(_l2Token).deposit{value: _amount}();
114116
IERC20Upgradeable(_l2Token).safeTransfer(_to, _amount);
115117

src/L2/predeploys/L2TxFeeVault.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ contract L2TxFeeVault is OwnableBase {
119119

120120
emit Withdrawal(_value, recipient, msg.sender);
121121

122-
// no fee provided
122+
// @note no fee provided
123+
// transfer to messenger is safe.
124+
// slither-disable-next-line arbitrary-send-eth
123125
IL2ScrollMessenger(messenger).sendMessage{value: _value}(
124126
recipient,
125127
_value,

src/L2/predeploys/WrappedEther.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ contract WrappedEther is ERC20Permit {
3939

4040
_burn(_sender, wad);
4141

42+
// no reentrancy risk (checks-effects-interactions).
43+
// slither-disable-next-line arbitrary-send-eth
4244
(bool success, ) = _sender.call{value: wad}("");
4345
require(success, "withdraw ETH failed");
4446

0 commit comments

Comments
 (0)