-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslither-detectors.json
926 lines (926 loc) · 70.6 KB
/
slither-detectors.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
[
{
"index": 1,
"check": "abiencoderv2-array",
"title": "Storage abiencoderv2 array",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#storage-abiencoderv2-array",
"description": "`solc` versions `0.4.7`-`0.5.9` contain a [compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs) leading to incorrect ABI encoder usage.",
"exploit_scenario": "\n```solidity\ncontract A {\n uint[2][3] bad_arr = [[1, 2], [3, 4], [5, 6]];\n \n /* Array of arrays passed to abi.encode is vulnerable */\n function bad() public { \n bytes memory b = abi.encode(bad_arr);\n }\n}\n```\n`abi.encode(bad_arr)` in a call to `bad()` will incorrectly encode the array as `[[1, 2], [2, 3], [3, 4]]` and lead to unintended behavior.\n",
"recommendation": "Use a compiler >= `0.5.10`."
},
{
"index": 2,
"check": "arbitrary-send-erc20",
"title": "transferFrom uses arbitrary `from`",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom",
"description": "Detect when `msg.sender` is not used as `from` in transferFrom.",
"exploit_scenario": "\n```solidity\n function a(address from, address to, uint256 amount) public {\n erc20.transferFrom(from, to, am);\n }\n```\nAlice approves this contract to spend her ERC20 tokens. Bob can call `a` and specify Alice's address as the `from` parameter in `transferFrom`, allowing him to transfer Alice's tokens to himself.",
"recommendation": "\nUse `msg.sender` as `from` in transferFrom.\n"
},
{
"index": 3,
"check": "array-by-reference",
"title": "Modifying storage array by value",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#modifying-storage-array-by-value",
"description": "Detect arrays passed to a function that expects reference to a storage array",
"exploit_scenario": "\n```solidity\ncontract Memory {\n uint[1] public x; // storage\n\n function f() public {\n f1(x); // update x\n f2(x); // do not update x\n }\n\n function f1(uint[1] storage arr) internal { // by reference\n arr[0] = 1;\n }\n\n function f2(uint[1] arr) internal { // by value\n arr[0] = 2;\n }\n}\n```\n\nBob calls `f()`. Bob assumes that at the end of the call `x[0]` is 2, but it is 1.\nAs a result, Bob's usage of the contract is incorrect.",
"recommendation": "Ensure the correct usage of `memory` and `storage` in the function parameters. Make all the locations explicit."
},
{
"index": 4,
"check": "incorrect-shift",
"title": "The order of parameters in a shift instruction is incorrect.",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-shift-in-assembly",
"description": "Detect if the values in a shift operation are reversed",
"exploit_scenario": "\n```solidity\ncontract C {\n function f() internal returns (uint a) {\n assembly {\n a := shr(a, 8)\n }\n }\n}\n```\nThe shift statement will right-shift the constant 8 by `a` bits",
"recommendation": "Swap the order of parameters."
},
{
"index": 5,
"check": "multiple-constructors",
"title": "Multiple constructor schemes",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes",
"description": "Detect multiple constructor definitions in the same contract (using new and old schemes).",
"exploit_scenario": "\n```solidity\ncontract A {\n uint x;\n constructor() public {\n x = 0;\n }\n function A() public {\n x = 1;\n }\n \n function test() public returns(uint) {\n return x;\n }\n}\n```\nIn Solidity [0.4.22](https://github.com/ethereum/solidity/releases/tag/v0.4.23), a contract with both constructor schemes will compile. The first constructor will take precedence over the second, which may be unintended.",
"recommendation": "Only declare one constructor, preferably using the new scheme `constructor(...)` instead of `function <contractName>(...)`."
},
{
"index": 6,
"check": "name-reused",
"title": "Contract's name reused",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused",
"description": "If a codebase has two contracts the similar names, the compilation artifacts\nwill not contain one of the contracts with the duplicate name.",
"exploit_scenario": "\nBob's `truffle` codebase has two contracts named `ERC20`.\nWhen `truffle compile` runs, only one of the two contracts will generate artifacts in `build/contracts`.\nAs a result, the second contract cannot be analyzed.\n",
"recommendation": "Rename the contract."
},
{
"index": 7,
"check": "protected-vars",
"title": "Detected unprotected variables",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#protected-variables",
"description": "Detect unprotected variable that are marked protected",
"exploit_scenario": "\n```solidity\ncontract Buggy{\n\n /// @custom:security write-protection=\"onlyOwner()\"\n address owner;\n\n function set_protected() public onlyOwner(){\n owner = msg.sender;\n }\n\n function set_not_protected() public{\n owner = msg.sender;\n }\n} \n```\n`owner` must be always written by function using `onlyOwner` (`write-protection=\"onlyOwner()\"`), however anyone can call `set_not_protected`.\n",
"recommendation": "Add access controls to the vulnerable function"
},
{
"index": 8,
"check": "public-mappings-nested",
"title": "Public mappings with nested variables",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables",
"description": "Prior to Solidity 0.5, a public mapping with nested structures returned [incorrect values](https://github.com/ethereum/solidity/issues/5520).",
"exploit_scenario": "Bob interacts with a contract that has a public mapping with nested structures. The values returned by the mapping are incorrect, breaking Bob's usage",
"recommendation": "Do not use public mapping with nested structures."
},
{
"index": 9,
"check": "rtlo",
"title": "Right-To-Left-Override control character is used",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character",
"description": "An attacker can manipulate the logic of the contract by using a right-to-left-override character (`U+202E)`.",
"exploit_scenario": "\n```solidity\ncontract Token\n{\n\n address payable o; // owner\n mapping(address => uint) tokens;\n\n function withdraw() external returns(uint)\n {\n uint amount = tokens[msg.sender];\n address payable d = msg.sender;\n tokens[msg.sender] = 0;\n _withdraw(/*owner\u202e/*noitanitsed*/ d, o/*\u202d\n\t\t /*value */, amount);\n }\n\n function _withdraw(address payable fee_receiver, address payable destination, uint value) internal\n {\n\t\tfee_receiver.transfer(1);\n\t\tdestination.transfer(value);\n }\n}\n```\n\n`Token` uses the right-to-left-override character when calling `_withdraw`. As a result, the fee is incorrectly sent to `msg.sender`, and the token balance is sent to the owner.\n\n",
"recommendation": "Special control characters must not be allowed."
},
{
"index": 10,
"check": "shadowing-state",
"title": "State variables shadowing",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing",
"description": "Detection of state variables shadowed.",
"exploit_scenario": "\n```solidity\ncontract BaseContract{\n address owner;\n\n modifier isOwner(){\n require(owner == msg.sender);\n _;\n }\n\n}\n\ncontract DerivedContract is BaseContract{\n address owner;\n\n constructor(){\n owner = msg.sender;\n }\n\n function withdraw() isOwner() external{\n msg.sender.transfer(this.balance);\n }\n}\n```\n`owner` of `BaseContract` is never assigned and the modifier `isOwner` does not work.",
"recommendation": "Remove the state variable shadowing."
},
{
"index": 11,
"check": "suicidal",
"title": "Functions allowing anyone to destruct the contract",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal",
"description": "Unprotected call to a function executing `selfdestruct`/`suicide`.",
"exploit_scenario": "\n```solidity\ncontract Suicidal{\n function kill() public{\n selfdestruct(msg.sender);\n }\n}\n```\nBob calls `kill` and destructs the contract.",
"recommendation": "Protect access to all sensitive functions."
},
{
"index": 12,
"check": "uninitialized-state",
"title": "Uninitialized state variables",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables",
"description": "Uninitialized state variables.",
"exploit_scenario": "\n```solidity\ncontract Uninitialized{\n address destination;\n\n function transfer() payable public{\n destination.transfer(msg.value);\n }\n}\n```\nBob calls `transfer`. As a result, the Ether are sent to the address `0x0` and are lost.\n",
"recommendation": "\nInitialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability.\n"
},
{
"index": 13,
"check": "uninitialized-storage",
"title": "Uninitialized storage variables",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables",
"description": "An uninitialized storage variable will act as a reference to the first state variable, and can override a critical variable.",
"exploit_scenario": "\n```solidity\ncontract Uninitialized{\n address owner = msg.sender;\n\n struct St{\n uint a;\n }\n\n function func() {\n St st;\n st.a = 0x0;\n }\n}\n```\nBob calls `func`. As a result, `owner` is overridden to `0`.\n",
"recommendation": "Initialize all storage variables."
},
{
"index": 14,
"check": "unprotected-upgrade",
"title": "Unprotected upgradeable contract",
"impact": "High",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#unprotected-upgradeable-contract",
"description": "Detects logic contract that can be destructed.",
"exploit_scenario": "\n```solidity\ncontract Buggy is Initializable{\n address payable owner;\n\n function initialize() external initializer{\n require(owner == address(0));\n owner = msg.sender;\n }\n function kill() external{\n require(msg.sender == owner);\n selfdestruct(owner);\n }\n}\n```\nBuggy is an upgradeable contract. Anyone can call initialize on the logic contract, and destruct the contract.\n",
"recommendation": "Add a constructor to ensure `initialize` cannot be called on the logic contract."
},
{
"index": 15,
"check": "codex",
"title": "Use Codex to find vulnerabilities.",
"impact": "High",
"confidence": "Low",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#codex",
"description": "Use [codex](https://openai.com/blog/openai-codex/) to find vulnerabilities",
"exploit_scenario": "N/A",
"recommendation": "Review codex's message."
},
{
"index": 16,
"check": "arbitrary-send-erc20-permit",
"title": "transferFrom uses arbitrary from with permit",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom-used-with-permit",
"description": "Detect when `msg.sender` is not used as `from` in transferFrom and permit is used.",
"exploit_scenario": "\n```solidity\n function bad(address from, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s, address to) public {\n erc20.permit(from, address(this), value, deadline, v, r, s);\n erc20.transferFrom(from, to, value);\n }\n```\nIf an ERC20 token does not implement permit and has a fallback function e.g. WETH, transferFrom allows an attacker to transfer all tokens approved for this contract.",
"recommendation": "\nEnsure that the underlying ERC20 token correctly implements a permit function.\n"
},
{
"index": 17,
"check": "arbitrary-send-eth",
"title": "Functions that send Ether to arbitrary destinations",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations",
"description": "Unprotected call to a function sending Ether to an arbitrary address.",
"exploit_scenario": "\n```solidity\ncontract ArbitrarySendEth{\n address destination;\n function setDestination(){\n destination = msg.sender;\n }\n\n function withdraw() public{\n destination.transfer(this.balance);\n }\n}\n```\nBob calls `setDestination` and `withdraw`. As a result he withdraws the contract's balance.",
"recommendation": "Ensure that an arbitrary user cannot withdraw unauthorized funds."
},
{
"index": 18,
"check": "controlled-array-length",
"title": "Tainted array length assignment",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment",
"description": "Detects the direct assignment of an array's length.",
"exploit_scenario": "\n```solidity\ncontract A {\n\tuint[] testArray; // dynamic size array\n\n\tfunction f(uint usersCount) public {\n\t\t// ...\n\t\ttestArray.length = usersCount;\n\t\t// ...\n\t}\n\n\tfunction g(uint userIndex, uint val) public {\n\t\t// ...\n\t\ttestArray[userIndex] = val;\n\t\t// ...\n\t}\n}\n```\nContract storage/state-variables are indexed by a 256-bit integer.\nThe user can set the array length to `2**256-1` in order to index all storage slots. \nIn the example above, one could call the function `f` to set the array length, then call the function `g` to control any storage slot desired. \nNote that storage slots here are indexed via a hash of the indexers; nonetheless, all storage will still be accessible and could be controlled by the attacker.",
"recommendation": "Do not allow array lengths to be set directly set; instead, opt to add values as needed.\nOtherwise, thoroughly review the contract to ensure a user-controlled variable cannot reach an array length assignment."
},
{
"index": 19,
"check": "controlled-delegatecall",
"title": "Controlled delegatecall destination",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall",
"description": "`Delegatecall` or `callcode` to an address controlled by the user.",
"exploit_scenario": "\n```solidity\ncontract Delegatecall{\n function delegate(address to, bytes data){\n to.delegatecall(data);\n }\n}\n```\nBob calls `delegate` and delegates the execution to his malicious contract. As a result, Bob withdraws the funds of the contract and destructs it.",
"recommendation": "Avoid using `delegatecall`. Use only trusted destinations."
},
{
"index": 20,
"check": "delegatecall-loop",
"title": "Payable functions using `delegatecall` inside a loop",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop",
"description": "Detect the use of `delegatecall` inside a loop in a payable function.",
"exploit_scenario": "\n```solidity\ncontract DelegatecallInLoop{\n\n mapping (address => uint256) balances;\n\n function bad(address[] memory receivers) public payable {\n for (uint256 i = 0; i < receivers.length; i++) {\n address(this).delegatecall(abi.encodeWithSignature(\"addBalance(address)\", receivers[i]));\n }\n }\n\n function addBalance(address a) public payable {\n balances[a] += msg.value;\n } \n\n}\n```\nWhen calling `bad` the same `msg.value` amount will be accredited multiple times.",
"recommendation": "\nCarefully check that the function called by `delegatecall` is not payable/doesn't use `msg.value`.\n"
},
{
"index": 21,
"check": "msg-value-loop",
"title": "msg.value inside a loop",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop",
"description": "Detect the use of `msg.value` inside a loop.",
"exploit_scenario": "\n```solidity\ncontract MsgValueInLoop{\n\n mapping (address => uint256) balances;\n\n function bad(address[] memory receivers) public payable {\n for (uint256 i=0; i < receivers.length; i++) {\n balances[receivers[i]] += msg.value;\n }\n }\n\n}\n```\n",
"recommendation": "\nTrack msg.value through a local variable and decrease its amount on every iteration/usage.\n"
},
{
"index": 22,
"check": "reentrancy-eth",
"title": "Reentrancy vulnerabilities (theft of ethers)",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities",
"description": "\nDetection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).\nDo not report reentrancies that don't involve Ether (see `reentrancy-no-eth`)",
"exploit_scenario": "\n```solidity\n function withdrawBalance(){\n // send userBalance[msg.sender] Ether to msg.sender\n // if msg.sender is a contract, it will call its fallback function\n if( ! (msg.sender.call.value(userBalance[msg.sender])() ) ){\n throw;\n }\n userBalance[msg.sender] = 0;\n }\n```\n\nBob uses the re-entrancy bug to call `withdrawBalance` two times, and withdraw more than its initial deposit to the contract.",
"recommendation": "Apply the [`check-effects-interactions pattern`](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
},
{
"index": 23,
"check": "storage-array",
"title": "Signed storage integer array compiler bug",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array",
"description": "`solc` versions `0.4.7`-`0.5.9` contain [a compiler bug](https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs)\nleading to incorrect values in signed integer arrays.",
"exploit_scenario": "\n```solidity\ncontract A {\n\tint[3] ether_balances; // storage signed integer array\n\tfunction bad0() private {\n\t\t// ...\n\t\tether_balances = [-1, -1, -1];\n\t\t// ...\n\t}\n}\n```\n`bad0()` uses a (storage-allocated) signed integer array state variable to store the ether balances of three accounts. \n`-1` is supposed to indicate uninitialized values but the Solidity bug makes these as `1`, which could be exploited by the accounts.\n",
"recommendation": "Use a compiler version >= `0.5.10`."
},
{
"index": 24,
"check": "unchecked-transfer",
"title": "Unchecked tokens transfer",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer",
"description": "The return value of an external transfer/transferFrom call is not checked",
"exploit_scenario": "\n```solidity\ncontract Token {\n function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);\n}\ncontract MyBank{ \n mapping(address => uint) balances;\n Token token;\n function deposit(uint amount) public{\n token.transferFrom(msg.sender, address(this), amount);\n balances[msg.sender] += amount;\n }\n}\n```\nSeveral tokens do not revert in case of failure and return false. If one of these tokens is used in `MyBank`, `deposit` will not revert if the transfer fails, and an attacker can call `deposit` for free..",
"recommendation": "Use `SafeERC20`, or ensure that the transfer/transferFrom return value is checked."
},
{
"index": 25,
"check": "weak-prng",
"title": "Weak PRNG",
"impact": "High",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG",
"description": "Weak PRNG due to a modulo on `block.timestamp`, `now` or `blockhash`. These can be influenced by miners to some extent so they should be avoided.",
"exploit_scenario": "\n```solidity\ncontract Game {\n\n uint reward_determining_number;\n\n function guessing() external{\n reward_determining_number = uint256(block.blockhash(10000)) % 10;\n }\n}\n```\nEve is a miner. Eve calls `guessing` and re-orders the block containing the transaction. \nAs a result, Eve wins the game.",
"recommendation": "Do not use `block.timestamp`, `now` or `blockhash` as a source of randomness"
},
{
"index": 26,
"check": "domain-separator-collision",
"title": "Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision",
"description": "An ERC20 token has a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR(), causing unanticipated behavior for contracts using `permit` functionality.",
"exploit_scenario": "\n```solidity\ncontract Contract{\n function some_collisions() external() {}\n}\n```\n`some_collision` clashes with EIP-2612's DOMAIN_SEPARATOR() and will interfere with contract's using `permit`.",
"recommendation": "Remove or rename the function that collides with DOMAIN_SEPARATOR()."
},
{
"index": 27,
"check": "enum-conversion",
"title": "Detect dangerous enum conversion",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion",
"description": "Detect out-of-range `enum` conversion (`solc` < `0.4.5`).",
"exploit_scenario": "\n```solidity\n pragma solidity 0.4.2;\n contract Test{\n\n enum E{a}\n\n function bug(uint a) public returns(E){\n return E(a);\n }\n}\n```\nAttackers can trigger unexpected behaviour by calling `bug(1)`.",
"recommendation": "Use a recent compiler version. If `solc` <`0.4.5` is required, check the `enum` conversion range."
},
{
"index": 28,
"check": "erc20-interface",
"title": "Incorrect ERC20 interfaces",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface",
"description": "Incorrect return values for `ERC20` functions. A contract compiled with Solidity > 0.4.22 interacting with these functions will fail to execute them, as the return value is missing.",
"exploit_scenario": "\n```solidity\ncontract Token{\n function transfer(address to, uint value) external;\n //...\n}\n```\n`Token.transfer` does not return a boolean. Bob deploys the token. Alice creates a contract that interacts with it but assumes a correct `ERC20` interface implementation. Alice's contract is unable to interact with Bob's contract.",
"recommendation": "Set the appropriate return values and types for the defined `ERC20` functions."
},
{
"index": 29,
"check": "erc721-interface",
"title": "Incorrect ERC721 interfaces",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface",
"description": "Incorrect return values for `ERC721` functions. A contract compiled with solidity > 0.4.22 interacting with these functions will fail to execute them, as the return value is missing.",
"exploit_scenario": "\n```solidity\ncontract Token{\n function ownerOf(uint256 _tokenId) external view returns (bool);\n //...\n}\n```\n`Token.ownerOf` does not return an address like `ERC721` expects. Bob deploys the token. Alice creates a contract that interacts with it but assumes a correct `ERC721` interface implementation. Alice's contract is unable to interact with Bob's contract.",
"recommendation": "Set the appropriate return values and vtypes for the defined `ERC721` functions."
},
{
"index": 30,
"check": "incorrect-equality",
"title": "Dangerous strict equalities",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities",
"description": "Use of strict equalities that can be easily manipulated by an attacker.",
"exploit_scenario": "\n```solidity\ncontract Crowdsale{\n function fund_reached() public returns(bool){\n return this.balance == 100 ether;\n }\n```\n`Crowdsale` relies on `fund_reached` to know when to stop the sale of tokens.\n`Crowdsale` reaches 100 Ether. Bob sends 0.1 Ether. As a result, `fund_reached` is always false and the `crowdsale` never ends.",
"recommendation": "Don't use strict equality to determine if an account has enough Ether or tokens."
},
{
"index": 31,
"check": "locked-ether",
"title": "Contracts that lock ether",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether",
"description": "Contract with a `payable` function, but without a withdrawal capacity.",
"exploit_scenario": "\n```solidity\npragma solidity 0.4.24;\ncontract Locked{\n function receive() payable public{\n }\n}\n```\nEvery Ether sent to `Locked` will be lost.",
"recommendation": "Remove the payable attribute or add a withdraw function."
},
{
"index": 32,
"check": "mapping-deletion",
"title": "Deletion on mapping containing a structure",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure",
"description": "A deletion in a structure containing a mapping will not delete the mapping (see the [Solidity documentation](https://solidity.readthedocs.io/en/latest/types.html##delete)). The remaining data may be used to compromise the contract.",
"exploit_scenario": "\n```solidity\n struct BalancesStruct{\n address owner;\n mapping(address => uint) balances;\n }\n mapping(address => BalancesStruct) public stackBalance;\n\n function remove() internal{\n delete stackBalance[msg.sender];\n }\n```\n`remove` deletes an item of `stackBalance`.\nThe mapping `balances` is never deleted, so `remove` does not work as intended.",
"recommendation": "Use a lock mechanism instead of a deletion to disable structure containing a mapping."
},
{
"index": 33,
"check": "shadowing-abstract",
"title": "State variables shadowing from abstract contracts",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts",
"description": "Detection of state variables shadowed from abstract contracts.",
"exploit_scenario": "\n```solidity\ncontract BaseContract{\n address owner;\n}\n\ncontract DerivedContract is BaseContract{\n address owner;\n}\n```\n`owner` of `BaseContract` is shadowed in `DerivedContract`.",
"recommendation": "Remove the state variable shadowing."
},
{
"index": 34,
"check": "tautology",
"title": "Tautology or contradiction",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction",
"description": "Detects expressions that are tautologies or contradictions.",
"exploit_scenario": "\n```solidity\ncontract A {\n\tfunction f(uint x) public {\n\t\t// ...\n if (x >= 0) { // bad -- always true\n // ...\n }\n\t\t// ...\n\t}\n\n\tfunction g(uint8 y) public returns (bool) {\n\t\t// ...\n return (y < 512); // bad!\n\t\t// ...\n\t}\n}\n```\n`x` is a `uint256`, so `x >= 0` will be always true.\n`y` is a `uint8`, so `y <512` will be always true. \n",
"recommendation": "Fix the incorrect comparison by changing the value type or the comparison."
},
{
"index": 35,
"check": "write-after-write",
"title": "Unused write",
"impact": "Medium",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write",
"description": "Detects variables that are written but never read and written again.",
"exploit_scenario": "\n ```solidity\n contract Buggy{\n function my_func() external initializer{\n // ...\n a = b;\n a = c;\n // ..\n }\n }\n ```\n `a` is first asigned to `b`, and then to `c`. As a result the first write does nothing.",
"recommendation": "Fix or remove the writes."
},
{
"index": 36,
"check": "boolean-cst",
"title": "Misuse of Boolean constant",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant",
"description": "Detects the misuse of a Boolean constant.",
"exploit_scenario": "\n```solidity\ncontract A {\n\tfunction f(uint x) public {\n\t\t// ...\n if (false) { // bad!\n // ...\n }\n\t\t// ...\n\t}\n\n\tfunction g(bool b) public returns (bool) {\n\t\t// ...\n return (b || true); // bad!\n\t\t// ...\n\t}\n}\n```\nBoolean constants in code have only a few legitimate uses. \nOther uses (in complex expressions, as conditionals) indicate either an error or, most likely, the persistence of faulty code.",
"recommendation": "Verify and simplify the condition."
},
{
"index": 37,
"check": "constant-function-asm",
"title": "Constant functions using assembly code",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code",
"description": "\nFunctions declared as `constant`/`pure`/`view` using assembly code.\n\n`constant`/`pure`/`view` was not enforced prior to Solidity 0.5.\nStarting from Solidity 0.5, a call to a `constant`/`pure`/`view` function uses the `STATICCALL` opcode, which reverts in case of state modification.\n\nAs a result, a call to an [incorrectly labeled function may trap a contract compiled with Solidity 0.5](https://solidity.readthedocs.io/en/develop/050-breaking-changes.html#interoperability-with-older-contracts).",
"exploit_scenario": "\n```solidity\ncontract Constant{\n uint counter;\n function get() public view returns(uint){\n counter = counter +1;\n return counter\n }\n}\n```\n`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract that interacts with `Constant` in Solidity 0.5.0. \nAll the calls to `get` revert, breaking Bob's smart contract execution.",
"recommendation": "Ensure the attributes of contracts compiled prior to Solidity 0.5.0 are correct."
},
{
"index": 38,
"check": "constant-function-state",
"title": "Constant functions changing the state",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state",
"description": "\nFunctions declared as `constant`/`pure`/`view` change the state.\n\n`constant`/`pure`/`view` was not enforced prior to Solidity 0.5.\nStarting from Solidity 0.5, a call to a `constant`/`pure`/`view` function uses the `STATICCALL` opcode, which reverts in case of state modification.\n\nAs a result, a call to an [incorrectly labeled function may trap a contract compiled with Solidity 0.5](https://solidity.readthedocs.io/en/develop/050-breaking-changes.html#interoperability-with-older-contracts).",
"exploit_scenario": "\n```solidity\ncontract Constant{\n uint counter;\n function get() public view returns(uint){\n counter = counter +1;\n return counter\n }\n}\n```\n`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract that interacts with `Constant` in Solidity 0.5.0. \nAll the calls to `get` revert, breaking Bob's smart contract execution.",
"recommendation": "Ensure that attributes of contracts compiled prior to Solidity 0.5.0 are correct."
},
{
"index": 39,
"check": "divide-before-multiply",
"title": "Imprecise arithmetic operations order",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply",
"description": "Solidity's integer division truncates. Thus, performing division before multiplication can lead to precision loss.",
"exploit_scenario": "\n```solidity\ncontract A {\n\tfunction f(uint n) public {\n coins = (oldSupply / n) * interest;\n }\n}\n```\nIf `n` is greater than `oldSupply`, `coins` will be zero. For example, with `oldSupply = 5; n = 10, interest = 2`, coins will be zero. \nIf `(oldSupply * interest / n)` was used, `coins` would have been `1`. \nIn general, it's usually a good idea to re-arrange arithmetic to perform multiplication before division, unless the limit of a smaller type makes this dangerous.",
"recommendation": "Consider ordering multiplication before division."
},
{
"index": 40,
"check": "reentrancy-no-eth",
"title": "Reentrancy vulnerabilities (no theft of ethers)",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1",
"description": "\nDetection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).\nDo not report reentrancies that involve Ether (see `reentrancy-eth`).",
"exploit_scenario": "\n```solidity\n function bug(){\n require(not_called);\n if( ! (msg.sender.call() ) ){\n throw;\n }\n not_called = False;\n } \n```\n",
"recommendation": "Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
},
{
"index": 41,
"check": "reused-constructor",
"title": "Reused base constructor",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors",
"description": "Detects if the same base constructor is called with arguments from two different locations in the same inheritance hierarchy.",
"exploit_scenario": "\n```solidity\npragma solidity ^0.4.0;\n\ncontract A{\n uint num = 5;\n constructor(uint x) public{\n num += x;\n }\n}\n\ncontract B is A{\n constructor() A(2) public { /* ... */ }\n}\n\ncontract C is A {\n constructor() A(3) public { /* ... */ }\n}\n\ncontract D is B, C {\n constructor() public { /* ... */ }\n}\n\ncontract E is B {\n constructor() A(1) public { /* ... */ }\n}\n```\nThe constructor of `A` is called multiple times in `D` and `E`:\n- `D` inherits from `B` and `C`, both of which construct `A`.\n- `E` only inherits from `B`, but `B` and `E` construct `A`.\n.",
"recommendation": "Remove the duplicate constructor call."
},
{
"index": 42,
"check": "tx-origin",
"title": "Dangerous usage of `tx.origin`",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin",
"description": "`tx.origin`-based protection can be abused by a malicious contract if a legitimate user interacts with the malicious contract.",
"exploit_scenario": "\n```solidity\ncontract TxOrigin {\n address owner = msg.sender;\n\n function bug() {\n require(tx.origin == owner);\n }\n```\nBob is the owner of `TxOrigin`. Bob calls Eve's contract. Eve's contract calls `TxOrigin` and bypasses the `tx.origin` protection.",
"recommendation": "Do not use `tx.origin` for authorization."
},
{
"index": 43,
"check": "unchecked-lowlevel",
"title": "Unchecked low-level calls",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls",
"description": "The return value of a low-level call is not checked.",
"exploit_scenario": "\n```solidity\ncontract MyConc{\n function my_func(address payable dst) public payable{\n dst.call.value(msg.value)(\"\");\n }\n}\n```\nThe return value of the low-level call is not checked, so if the call fails, the Ether will be locked in the contract.\nIf the low level is used to prevent blocking operations, consider logging failed calls.\n ",
"recommendation": "Ensure that the return value of a low-level call is checked or logged."
},
{
"index": 44,
"check": "unchecked-send",
"title": "Unchecked send",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send",
"description": "The return value of a `send` is not checked.",
"exploit_scenario": "\n```solidity\ncontract MyConc{\n function my_func(address payable dst) public payable{\n dst.send(msg.value);\n }\n}\n```\nThe return value of `send` is not checked, so if the send fails, the Ether will be locked in the contract.\nIf `send` is used to prevent blocking operations, consider logging the failed `send`.\n ",
"recommendation": "Ensure that the return value of `send` is checked or logged."
},
{
"index": 45,
"check": "uninitialized-local",
"title": "Uninitialized local variables",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables",
"description": "Uninitialized local variables.",
"exploit_scenario": "\n```solidity\ncontract Uninitialized is Owner{\n function withdraw() payable public onlyOwner{\n address to;\n to.transfer(this.balance)\n }\n}\n```\nBob calls `transfer`. As a result, all Ether is sent to the address `0x0` and is lost.",
"recommendation": "Initialize all the variables. If a variable is meant to be initialized to zero, explicitly set it to zero to improve code readability."
},
{
"index": 46,
"check": "unused-return",
"title": "Unused return values",
"impact": "Medium",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return",
"description": "The return value of an external call is not stored in a local or state variable.",
"exploit_scenario": "\n```solidity\ncontract MyConc{\n using SafeMath for uint; \n function my_func(uint a, uint b) public{\n a.add(b);\n }\n}\n```\n`MyConc` calls `add` of `SafeMath`, but does not store the result in `a`. As a result, the computation has no effect.",
"recommendation": "Ensure that all the return values of the function calls are used."
},
{
"index": 47,
"check": "incorrect-modifier",
"title": "Modifiers that can return the default value",
"impact": "Low",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier",
"description": "If a modifier does not execute `_` or revert, the execution of the function will return the default value, which can be misleading for the caller.",
"exploit_scenario": "\n```solidity\n modidfier myModif(){\n if(..){\n _;\n }\n }\n function get() myModif returns(uint){\n\n }\n```\nIf the condition in `myModif` is false, the execution of `get()` will return 0.",
"recommendation": "All the paths in a modifier must execute `_` or revert."
},
{
"index": 48,
"check": "shadowing-builtin",
"title": "Built-in symbol shadowing",
"impact": "Low",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing",
"description": "Detection of shadowing built-in symbols using local variables, state variables, functions, modifiers, or events.",
"exploit_scenario": "\n```solidity\npragma solidity ^0.4.24;\n\ncontract Bug {\n uint now; // Overshadows current time stamp.\n\n function assert(bool condition) public {\n // Overshadows built-in symbol for providing assertions.\n }\n\n function get_next_expiration(uint earlier_time) private returns (uint) {\n return now + 259200; // References overshadowed timestamp.\n }\n}\n```\n`now` is defined as a state variable, and shadows with the built-in symbol `now`. The function `assert` overshadows the built-in `assert` function. Any use of either of these built-in symbols may lead to unexpected results.",
"recommendation": "Rename the local variables, state variables, functions, modifiers, and events that shadow a builtin symbol."
},
{
"index": 49,
"check": "shadowing-local",
"title": "Local variables shadowing",
"impact": "Low",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing",
"description": "Detection of shadowing using local variables.",
"exploit_scenario": "\n```solidity\npragma solidity ^0.4.24;\n\ncontract Bug {\n uint owner;\n\n function sensitive_function(address owner) public {\n // ...\n require(owner == msg.sender);\n }\n\n function alternate_sensitive_function() public {\n address owner = msg.sender;\n // ...\n require(owner == msg.sender);\n }\n}\n```\n`sensitive_function.owner` shadows `Bug.owner`. As a result, the use of `owner` in `sensitive_function` might be incorrect.",
"recommendation": "Rename the local variables that shadow another component."
},
{
"index": 50,
"check": "uninitialized-fptr-cst",
"title": "Uninitialized function pointer calls in constructors",
"impact": "Low",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors",
"description": "solc versions `0.4.5`-`0.4.26` and `0.5.0`-`0.5.8` contain a compiler bug leading to unexpected behavior when calling uninitialized function pointers in constructors.",
"exploit_scenario": "\n```solidity\ncontract bad0 {\n\n constructor() public {\n /* Uninitialized function pointer */\n function(uint256) internal returns(uint256) a;\n a(10);\n }\n\n}\n```\nThe call to `a(10)` will lead to unexpected behavior because function pointer `a` is not initialized in the constructor.",
"recommendation": "Initialize function pointers before calling. Avoid function pointers if possible."
},
{
"index": 51,
"check": "variable-scope",
"title": "Local variables used prior their declaration",
"impact": "Low",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables",
"description": "Detects the possible usage of a variable before the declaration is stepped over (either because it is later declared, or declared in another scope).",
"exploit_scenario": "\n```solidity\ncontract C {\n function f(uint z) public returns (uint) {\n uint y = x + 9 + z; // 'z' is used pre-declaration\n uint x = 7;\n\n if (z % 2 == 0) {\n uint max = 5;\n // ...\n }\n\n // 'max' was intended to be 5, but it was mistakenly declared in a scope and not assigned (so it is zero).\n for (uint i = 0; i < max; i++) {\n x += 1;\n }\n\n return x;\n }\n}\n```\nIn the case above, the variable `x` is used before its declaration, which may result in unintended consequences. \nAdditionally, the for-loop uses the variable `max`, which is declared in a previous scope that may not always be reached. This could lead to unintended consequences if the user mistakenly uses a variable prior to any intended declaration assignment. It also may indicate that the user intended to reference a different variable.",
"recommendation": "Move all variable declarations prior to any usage of the variable, and ensure that reaching a variable declaration does not depend on some conditional if it is used unconditionally."
},
{
"index": 52,
"check": "void-cst",
"title": "Constructor called not implemented",
"impact": "Low",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor",
"description": "Detect the call to a constructor that is not implemented",
"exploit_scenario": "\n```solidity\ncontract A{}\ncontract B is A{\n constructor() public A(){}\n}\n```\nWhen reading `B`'s constructor definition, we might assume that `A()` initiates the contract, but no code is executed.",
"recommendation": "Remove the constructor call."
},
{
"index": 53,
"check": "calls-loop",
"title": "Multiple calls in a loop",
"impact": "Low",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop",
"description": "Calls inside a loop might lead to a denial-of-service attack.",
"exploit_scenario": "\n```solidity\ncontract CallsInLoop{\n\n address[] destinations;\n\n constructor(address[] newDestinations) public{\n destinations = newDestinations;\n }\n\n function bad() external{\n for (uint i=0; i < destinations.length; i++){\n destinations[i].transfer(i);\n }\n }\n\n}\n```\nIf one of the destinations has a fallback function that reverts, `bad` will always revert.",
"recommendation": "Favor [pull over push](https://github.com/ethereum/wiki/wiki/Safety#favor-pull-over-push-for-external-calls) strategy for external calls."
},
{
"index": 54,
"check": "events-access",
"title": "Missing Events Access Control",
"impact": "Low",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control",
"description": "Detect missing events for critical access control parameters",
"exploit_scenario": "\n```solidity\ncontract C {\n\n modifier onlyAdmin {\n if (msg.sender != owner) throw;\n _;\n }\n\n function updateOwner(address newOwner) onlyAdmin external {\n owner = newOwner;\n }\n}\n```\n`updateOwner()` has no event, so it is difficult to track off-chain owner changes.\n",
"recommendation": "Emit an event for critical parameter changes."
},
{
"index": 55,
"check": "events-maths",
"title": "Missing Events Arithmetic",
"impact": "Low",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic",
"description": "Detect missing events for critical arithmetic parameters.",
"exploit_scenario": "\n```solidity\ncontract C {\n\n modifier onlyOwner {\n if (msg.sender != owner) throw;\n _;\n }\n\n function setBuyPrice(uint256 newBuyPrice) onlyOwner public {\n buyPrice = newBuyPrice;\n }\n\n function buy() external {\n ... // buyPrice is used to determine the number of tokens purchased\n } \n}\n```\n`setBuyPrice()` does not emit an event, so it is difficult to track changes in the value of `buyPrice` off-chain. \n",
"recommendation": "Emit an event for critical parameter changes."
},
{
"index": 56,
"check": "incorrect-unary",
"title": "Dangerous unary expressions",
"impact": "Low",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions",
"description": "Unary expressions such as `x=+1` probably typos.",
"exploit_scenario": "\n```Solidity \ncontract Bug{\n uint public counter;\n\n function increase() public returns(uint){\n counter=+1;\n return counter;\n }\n}\n```\n`increase()` uses `=+` instead of `+=`, so `counter` will never exceed 1.",
"recommendation": "Remove the unary expression."
},
{
"index": 57,
"check": "missing-zero-check",
"title": "Missing Zero Address Validation",
"impact": "Low",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation",
"description": "Detect missing zero address validation.",
"exploit_scenario": "\n```solidity\ncontract C {\n\n modifier onlyAdmin {\n if (msg.sender != owner) throw;\n _;\n }\n\n function updateOwner(address newOwner) onlyAdmin external {\n owner = newOwner;\n }\n}\n```\nBob calls `updateOwner` without specifying the `newOwner`, so Bob loses ownership of the contract.\n",
"recommendation": "Check that the address is not zero."
},
{
"index": 58,
"check": "reentrancy-benign",
"title": "Benign reentrancy vulnerabilities",
"impact": "Low",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2",
"description": "\nDetection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).\nOnly report reentrancy that acts as a double call (see `reentrancy-eth`, `reentrancy-no-eth`).",
"exploit_scenario": "\n```solidity\n function callme(){\n if( ! (msg.sender.call()() ) ){\n throw;\n }\n counter += 1\n } \n```\n\n`callme` contains a reentrancy. The reentrancy is benign because it's exploitation would have the same effect as two consecutive calls.",
"recommendation": "Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
},
{
"index": 59,
"check": "reentrancy-events",
"title": "Reentrancy vulnerabilities leading to out-of-order Events",
"impact": "Low",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3",
"description": "\nDetection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).\nOnly report reentrancies leading to out-of-order events.",
"exploit_scenario": "\n```solidity\n function bug(Called d){\n counter += 1;\n d.f();\n emit Counter(counter);\n }\n```\n\nIf `d.()` re-enters, the `Counter` events will be shown in an incorrect order, which might lead to issues for third parties.",
"recommendation": "Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
},
{
"index": 60,
"check": "timestamp",
"title": "Dangerous usage of `block.timestamp`",
"impact": "Low",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp",
"description": "Dangerous usage of `block.timestamp`. `block.timestamp` can be manipulated by miners.",
"exploit_scenario": "\"Bob's contract relies on `block.timestamp` for its randomness. Eve is a miner and manipulates `block.timestamp` to exploit Bob's contract.",
"recommendation": "Avoid relying on `block.timestamp`."
},
{
"index": 61,
"check": "assembly",
"title": "Assembly usage",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage",
"description": "The use of assembly is error-prone and should be avoided.",
"exploit_scenario": "",
"recommendation": "Do not use `evm` assembly."
},
{
"index": 62,
"check": "assert-state-change",
"title": "Assert state change",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change",
"description": "Incorrect use of `assert()`. See Solidity best [practices](https://solidity.readthedocs.io/en/latest/control-structures.html#id4).",
"exploit_scenario": "\n```solidity\ncontract A {\n\n uint s_a;\n\n function bad() public {\n assert((s_a += 1) > 10);\n }\n}\n```\nThe assert in `bad()` increments the state variable `s_a` while checking for the condition.\n",
"recommendation": "Use `require` for invariants modifying the state."
},
{
"index": 63,
"check": "boolean-equal",
"title": "Comparison to boolean constant",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality",
"description": "Detects the comparison to boolean constants.",
"exploit_scenario": "\n```solidity\ncontract A {\n\tfunction f(bool x) public {\n\t\t// ...\n if (x == true) { // bad!\n // ...\n }\n\t\t// ...\n\t}\n}\n```\nBoolean constants can be used directly and do not need to be compare to `true` or `false`.",
"recommendation": "Remove the equality to the boolean constant."
},
{
"index": 64,
"check": "cyclomatic-complexity",
"title": "Detects functions with high (> 11) cyclomatic complexity",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#cyclomatic-complexity",
"description": "Detects functions with high (> 11) cyclomatic complexity.",
"exploit_scenario": "",
"recommendation": "Reduce cyclomatic complexity by splitting the function into several smaller subroutines."
},
{
"index": 65,
"check": "deprecated-standards",
"title": "Deprecated Solidity Standards",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards",
"description": "Detect the usage of deprecated standards.",
"exploit_scenario": "\n```solidity\ncontract ContractWithDeprecatedReferences {\n // Deprecated: Change block.blockhash() -> blockhash()\n bytes32 globalBlockHash = block.blockhash(0);\n\n // Deprecated: Change constant -> view\n function functionWithDeprecatedThrow() public constant {\n // Deprecated: Change msg.gas -> gasleft()\n if(msg.gas == msg.value) {\n // Deprecated: Change throw -> revert()\n throw;\n }\n }\n\n // Deprecated: Change constant -> view\n function functionWithDeprecatedReferences() public constant {\n // Deprecated: Change sha3() -> keccak256()\n bytes32 sha3Result = sha3(\"test deprecated sha3 usage\");\n\n // Deprecated: Change callcode() -> delegatecall()\n address(this).callcode();\n\n // Deprecated: Change suicide() -> selfdestruct()\n suicide(address(0));\n }\n}\n```",
"recommendation": "Replace all uses of deprecated symbols."
},
{
"index": 66,
"check": "erc20-indexed",
"title": "Un-indexed ERC20 event parameters",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters",
"description": "Detects whether events defined by the `ERC20` specification that should have some parameters as `indexed` are missing the `indexed` keyword.",
"exploit_scenario": "\n```solidity\ncontract ERC20Bad {\n // ...\n event Transfer(address from, address to, uint value);\n event Approval(address owner, address spender, uint value);\n\n // ...\n}\n```\n`Transfer` and `Approval` events should have the 'indexed' keyword on their two first parameters, as defined by the `ERC20` specification.\nFailure to include these keywords will exclude the parameter data in the transaction/block's bloom filter, so external tooling searching for these parameters may overlook them and fail to index logs from this token contract.",
"recommendation": "Add the `indexed` keyword to event parameters that should include it, according to the `ERC20` specification."
},
{
"index": 67,
"check": "function-init-state",
"title": "Function initializing state variables",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state",
"description": "Detects the immediate initialization of state variables through function calls that are not pure/constant, or that use non-constant state variable.",
"exploit_scenario": "\n```solidity\ncontract StateVarInitFromFunction {\n\n uint public v = set(); // Initialize from function (sets to 77)\n uint public w = 5;\n uint public x = set(); // Initialize from function (sets to 88)\n address public shouldntBeReported = address(8);\n\n constructor(){\n // The constructor is run after all state variables are initialized.\n }\n\n function set() public returns(uint) {\n // If this function is being used to initialize a state variable declared\n // before w, w will be zero. If it is declared after w, w will be set.\n if(w == 0) {\n return 77;\n }\n\n return 88;\n }\n}\n```\nIn this case, users might intend a function to return a value a state variable can initialize with, without realizing the context for the contract is not fully initialized. \nIn the example above, the same function sets two different values for state variables because it checks a state variable that is not yet initialized in one case, and is initialized in the other. \nSpecial care must be taken when initializing state variables from an immediate function call so as not to incorrectly assume the state is initialized.\n",
"recommendation": "Remove any initialization of state variables via non-constant state variables or function calls. If variables must be set upon contract deployment, locate initialization in the constructor instead."
},
{
"index": 68,
"check": "low-level-calls",
"title": "Low level calls",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls",
"description": "The use of low-level calls is error-prone. Low-level calls do not check for [code existence](https://solidity.readthedocs.io/en/v0.4.25/control-structures.html#error-handling-assert-require-revert-and-exceptions) or call success.",
"exploit_scenario": "",
"recommendation": "Avoid low-level calls. Check the call success. If the call is meant for a contract, check for code existence."
},
{
"index": 69,
"check": "missing-inheritance",
"title": "Missing inheritance",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance",
"description": "Detect missing inheritance.",
"exploit_scenario": "\n```solidity\ninterface ISomething {\n function f1() external returns(uint);\n}\n\ncontract Something {\n function f1() external returns(uint){\n return 42;\n }\n}\n```\n`Something` should inherit from `ISomething`. \n",
"recommendation": "Inherit from the missing interface or contract."
},
{
"index": 70,
"check": "naming-convention",
"title": "Conformity to Solidity naming conventions",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions",
"description": "\nSolidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions) that should be followed.\n#### Rule exceptions\n- Allow constant variable name/symbol/decimals to be lowercase (`ERC20`).\n- Allow `_` at the beginning of the `mixed_case` match for private variables and unused parameters.",
"exploit_scenario": "",
"recommendation": "Follow the Solidity [naming convention](https://solidity.readthedocs.io/en/v0.4.25/style-guide.html#naming-conventions)."
},
{
"index": 71,
"check": "pragma",
"title": "If different pragma directives are used",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used",
"description": "Detect whether different Solidity versions are used.",
"exploit_scenario": "",
"recommendation": "Use one Solidity version."
},
{
"index": 72,
"check": "redundant-statements",
"title": "Redundant statements",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements",
"description": "Detect the usage of redundant statements that have no effect.",
"exploit_scenario": "\n```solidity\ncontract RedundantStatementsContract {\n\n constructor() public {\n uint; // Elementary Type Name\n bool; // Elementary Type Name\n RedundantStatementsContract; // Identifier\n }\n\n function test() public returns (uint) {\n uint; // Elementary Type Name\n assert; // Identifier\n test; // Identifier\n return 777;\n }\n}\n```\nEach commented line references types/identifiers, but performs no action with them, so no code will be generated for such statements and they can be removed.",
"recommendation": "Remove redundant statements if they congest code but offer no value."
},
{
"index": 73,
"check": "solc-version",
"title": "Incorrect Solidity version",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity",
"description": "\n`solc` frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks.\nWe also recommend avoiding complex `pragma` statement.",
"exploit_scenario": "",
"recommendation": "\nDeploy with any of the following Solidity versions:\n- 0.8.18\n\nThe recommendations take into account:\n- Risks related to recent releases\n- Risks of complex code generation changes\n- Risks of new language features\n- Risks of known bugs\n\nUse a simple pragma version that allows any of these versions.\nConsider using the latest version of Solidity for testing."
},
{
"index": 74,
"check": "unimplemented-functions",
"title": "Unimplemented functions",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions",
"description": "Detect functions that are not implemented on derived-most contracts.",
"exploit_scenario": "\n```solidity\ninterface BaseInterface {\n function f1() external returns(uint);\n function f2() external returns(uint);\n}\n\ninterface BaseInterface2 {\n function f3() external returns(uint);\n}\n\ncontract DerivedContract is BaseInterface, BaseInterface2 {\n function f1() external returns(uint){\n return 42;\n }\n}\n```\n`DerivedContract` does not implement `BaseInterface.f2` or `BaseInterface2.f3`.\nAs a result, the contract will not properly compile. \nAll unimplemented functions must be implemented on a contract that is meant to be used.",
"recommendation": "Implement all unimplemented functions in any contract you intend to use directly (not simply inherit from)."
},
{
"index": 75,
"check": "unused-state",
"title": "Unused state variables",
"impact": "Informational",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable",
"description": "Unused state variable.",
"exploit_scenario": "",
"recommendation": "Remove unused state variables."
},
{
"index": 76,
"check": "costly-loop",
"title": "Costly operations in a loop",
"impact": "Informational",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop",
"description": "Costly operations inside a loop might waste gas, so optimizations are justified.",
"exploit_scenario": "\n```solidity\ncontract CostlyOperationsInLoop{\n\n uint loop_count = 100;\n uint state_variable=0;\n\n function bad() external{\n for (uint i=0; i < loop_count; i++){\n state_variable++;\n }\n }\n\n function good() external{\n uint local_variable = state_variable;\n for (uint i=0; i < loop_count; i++){\n local_variable++;\n }\n state_variable = local_variable;\n }\n}\n```\nIncrementing `state_variable` in a loop incurs a lot of gas because of expensive `SSTOREs`, which might lead to an `out-of-gas`.",
"recommendation": "Use a local variable to hold the loop computation result."
},
{
"index": 77,
"check": "dead-code",
"title": "Functions that are not used",
"impact": "Informational",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code",
"description": "Functions that are not sued.",
"exploit_scenario": "\n```solidity\ncontract Contract{\n function dead_code() internal() {}\n}\n```\n`dead_code` is not used in the contract, and make the code's review more difficult.",
"recommendation": "Remove unused functions."
},
{
"index": 78,
"check": "reentrancy-unlimited-gas",
"title": "Reentrancy vulnerabilities through send and transfer",
"impact": "Informational",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4",
"description": "\nDetection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).\nOnly report reentrancy that is based on `transfer` or `send`.",
"exploit_scenario": "\n```solidity\n function callme(){\n msg.sender.transfer(balances[msg.sender]):\n balances[msg.sender] = 0;\n } \n```\n\n`send` and `transfer` do not protect from reentrancies in case of gas price changes.",
"recommendation": "Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy)."
},
{
"index": 79,
"check": "similar-names",
"title": "Variable names are too similar",
"impact": "Informational",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar",
"description": "Detect variables with names that are too similar.",
"exploit_scenario": "Bob uses several variables with similar names. As a result, his code is difficult to review.",
"recommendation": "Prevent variables from having similar names."
},
{
"index": 80,
"check": "too-many-digits",
"title": "Conformance to numeric notation best practices",
"impact": "Informational",
"confidence": "Medium",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits",
"description": "\nLiterals with many digits are difficult to read and review.\n",
"exploit_scenario": "\n```solidity\ncontract MyContract{\n uint 1_ether = 10000000000000000000; \n}\n```\n\nWhile `1_ether` looks like `1 ether`, it is `10 ether`. As a result, it's likely to be used incorrectly.\n",
"recommendation": "\nUse:\n- [Ether suffix](https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#ether-units),\n- [Time suffix](https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#time-units), or\n- [The scientific notation](https://solidity.readthedocs.io/en/latest/types.html#rational-and-integer-literals)\n"
},
{
"index": 81,
"check": "constable-states",
"title": "State variables that could be declared constant",
"impact": "Optimization",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant",
"description": "State variables that are not updated following deployment should be declared constant to save gas.",
"exploit_scenario": "",
"recommendation": "Add the `constant` attribute to state variables that never change."
},
{
"index": 82,
"check": "external-function",
"title": "Public function that could be declared external",
"impact": "Optimization",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external",
"description": "`public` functions that are never called by the contract should be declared `external`, and its immutable parameters should be located in `calldata` to save gas.",
"exploit_scenario": "",
"recommendation": "Use the `external` attribute for functions never called from the contract, and change the location of immutable parameters to `calldata` to save gas."
},
{
"index": 83,
"check": "immutable-states",
"title": "State variables that could be declared immutable",
"impact": "Optimization",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable",
"description": "State variables that are not updated following deployment should be declared immutable to save gas.",
"exploit_scenario": "",
"recommendation": "Add the `immutable` attribute to state variables that never change or are set only in the constructor."
},
{
"index": 84,
"check": "var-read-using-this",
"title": "Contract reads its own variable using `this`",
"impact": "Optimization",
"confidence": "High",
"wiki_url": "https://github.com/crytic/slither/wiki/Vulnerabilities-Description#public-variable-read-in-external-context",
"description": "The contract reads its own variable using `this`, adding overhead of an unnecessary STATICCALL.",
"exploit_scenario": "\n```solidity\ncontract C {\n mapping(uint => address) public myMap;\n function test(uint x) external returns(address) {\n return this.myMap(x);\n }\n}\n```\n",
"recommendation": "Read the variable directly from storage instead of calling the contract."
}
]