-
Notifications
You must be signed in to change notification settings - Fork 7
/
bot-report.json
3942 lines (3942 loc) · 341 KB
/
bot-report.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
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{
"reportUid": "8W4H9LUDWm7",
"labels": [
{
"name": "QA (Quality Assurance)",
"color": "1D76DB"
}
],
"comment": "LightChaser-V3",
"footnote": "V4 wen?",
"findings": [
{
"severity": "Medium",
"title": "High level access functions can create points of failure (Not captured by 4nalyzer) ",
"description": "High-level access functions in software, especially those with administrative privileges, can lead to points of failure due to their potential for misuse and unauthorized access. These functions, if compromised, can allow attackers to escalate privileges, leading to unauthorized control or access to sensitive data and functionalities. Insecure direct object references, where user inputs aren't properly validated, can exacerbate this risk, allowing attackers to manipulate the system. Ensuring robust access control and validation mechanisms is crucial to mitigate these vulnerabilities",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n201: function setAdmin(address _newAdmin) external {\n202: _revertIfNotAdmin(); // <= FOUND\n203: _setAdmin(_newAdmin);\n204: }\n\n```\n",
"loc": [
"[202](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L202-L202)"
]
},
{
"content": "```solidity\n210: function setRewardNotifier(address _rewardNotifier, bool _isEnabled) external {\n211: _revertIfNotAdmin(); // <= FOUND\n212: isRewardNotifier[_rewardNotifier] = _isEnabled;\n213: emit RewardNotifierSet(_rewardNotifier, _isEnabled);\n214: }\n\n```\n",
"loc": [
"[211](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L211-L211)"
]
},
{
"content": "```solidity\n110: function setAdmin(address _newAdmin) external {\n111: _revertIfNotAdmin(); // <= FOUND\n112: if (_newAdmin == address(0)) revert V3FactoryOwner__InvalidAddress();\n113: emit AdminSet(admin, _newAdmin);\n114: admin = _newAdmin;\n115: }\n\n```\n",
"loc": [
"[111](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L111-L111)"
]
},
{
"content": "```solidity\n119: function setPayoutAmount(uint256 _newPayoutAmount) external {\n120: _revertIfNotAdmin(); // <= FOUND\n121: if (_newPayoutAmount == 0) revert V3FactoryOwner__InvalidPayoutAmount();\n122: emit PayoutAmountSet(payoutAmount, _newPayoutAmount);\n123: payoutAmount = _newPayoutAmount;\n124: }\n\n```\n",
"loc": [
"[120](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L120-L120)"
]
},
{
"content": "```solidity\n131: function enableFeeAmount(uint24 _fee, int24 _tickSpacing) external {\n132: _revertIfNotAdmin(); // <= FOUND\n133: FACTORY.enableFeeAmount(_fee, _tickSpacing);\n134: }\n\n```\n",
"loc": [
"[132](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L132-L132)"
]
},
{
"content": "```solidity\n142: function setFeeProtocol(\n143: IUniswapV3PoolOwnerActions _pool,\n144: uint8 _feeProtocol0,\n145: uint8 _feeProtocol1\n146: ) external {\n147: _revertIfNotAdmin(); // <= FOUND\n148: _pool.setFeeProtocol(_feeProtocol0, _feeProtocol1);\n149: }\n\n```\n",
"loc": [
"[147](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L147-L147)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Some if-statement can be converted to a ternary ",
"description": "Improving code readability and compactness is an integral part of optimal programming practices. The use of ternary operators in place of if-else conditions is one such measure. Ternary operators allow us to write conditional statements in a more concise manner, thereby enhancing readability and simplicity. They follow the syntax `condition ? exprIfTrue : exprIfFalse`, which interprets as \"if the condition is true, evaluate to `exprIfTrue`, else evaluate to `exprIfFalse`\". By adopting this approach, we make our code more streamlined and intuitive, which could potentially aid in better understanding and maintenance of the codebase.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n577: if (block.timestamp >= rewardEndTime) {\n578: scaledRewardRate = (_amount * SCALE_FACTOR) / REWARD_DURATION; // <= FOUND\n579: }\n\n```\n",
"loc": [
"[577](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L577-L578)"
]
}
]
},
{
"severity": "Gas",
"title": "Multiple accesses of the same mapping/array key/index should be cached ",
"description": "Caching repeated accesses to the same mapping or array key/index in smart contracts can lead to significant gas savings. In Solidity, each read operation from storage (like accessing a value in a mapping or array using a key or index) costs gas. By storing the accessed value in a local variable and reusing it within the function, you avoid multiple expensive storage read operations. This practice is particularly beneficial in loops or functions with multiple reads of the same data. Implementing this caching approach enhances efficiency and reduces transaction costs, which is crucial for optimizing smart contract performance and user experience on the blockchain.",
"gasSavings": 168,
"category": null,
"instances": [
{
"content": "```solidity\n605: function _fetchOrDeploySurrogate(address _delegatee)\n606: internal\n607: returns (DelegationSurrogate _surrogate)\n608: {\n609: _surrogate = surrogates[_delegatee]; // <= FOUND\n610: \n611: if (address(_surrogate) == address(0)) {\n612: _surrogate = new DelegationSurrogate(STAKE_TOKEN, _delegatee);\n613: surrogates[_delegatee] = _surrogate; // <= FOUND\n614: emit SurrogateDeployed(_delegatee, address(_surrogate));\n615: }\n616: }\n\n```\n",
"loc": [
"[605](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L605-L613)"
]
},
{
"content": "```solidity\n740: function _claimReward(address _beneficiary) internal {\n741: _checkpointGlobalReward();\n742: _checkpointReward(_beneficiary);\n743: \n744: uint256 _reward = unclaimedRewardCheckpoint[_beneficiary]; // <= FOUND\n745: if (_reward == 0) return;\n746: unclaimedRewardCheckpoint[_beneficiary] = 0; // <= FOUND\n747: emit RewardClaimed(_beneficiary, _reward);\n748: \n749: SafeERC20.safeTransfer(REWARD_TOKEN, _beneficiary, _reward);\n750: }\n\n```\n",
"loc": [
"[740](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L740-L746)"
]
}
]
},
{
"severity": "Gas",
"title": "Only emit event in setter function if the state variable was changed ",
"description": "Emitting events in setter functions of smart contracts only when state variables change saves gas. This is because emitting events consumes gas, and unnecessary events, where no actual state change occurs, lead to wasteful consumption.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n210: function setRewardNotifier(address _rewardNotifier, bool _isEnabled) external { // <= FOUND\n211: _revertIfNotAdmin();\n212: isRewardNotifier[_rewardNotifier] = _isEnabled;\n213: emit RewardNotifierSet(_rewardNotifier, _isEnabled); // <= FOUND\n214: }\n\n```\n",
"loc": [
"[210](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L210-L213)"
]
},
{
"content": "```solidity\n771: function _setAdmin(address _newAdmin) internal { // <= FOUND\n772: _revertIfAddressZero(_newAdmin);\n773: emit AdminSet(admin, _newAdmin); // <= FOUND\n774: admin = _newAdmin;\n775: }\n\n```\n",
"loc": [
"[771](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L771-L773)"
]
}
]
},
{
"severity": "Gas",
"title": "State variables used within a function more than once should be cached to save gas ",
"description": "Cache such variables and perform operations on them, if operations include modifications to the state variable(s) then remember to equate the state variable to it's cached counterpart at the end",
"gasSavings": 200,
"category": null,
"instances": [
{
"content": "```solidity\n229: function rewardPerTokenAccumulated() public view returns (uint256) { // <= FOUND\n230: if (totalStaked == 0) return rewardPerTokenAccumulatedCheckpoint; // <= FOUND\n231: \n232: return rewardPerTokenAccumulatedCheckpoint // <= FOUND\n233: + (scaledRewardRate * (lastTimeRewardDistributed() - lastCheckpointTime)) / totalStaked; // <= FOUND\n234: }\n\n```\n",
"loc": [
"[229](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L229-L233)"
]
}
]
},
{
"severity": "NonCritical",
"title": "It is standard for all external and public functions to be override from an interface ",
"description": "This is to ensure the whole API is extracted in a interface",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n201: function setAdmin(address _newAdmin) external \n\n```\n",
"loc": [
"[201](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L201-L201)"
]
},
{
"content": "```solidity\n210: function setRewardNotifier(address _rewardNotifier, bool _isEnabled) external \n\n```\n",
"loc": [
"[210](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L210-L210)"
]
},
{
"content": "```solidity\n256: function stake(uint256 _amount, address _delegatee)\n257: external\n258: returns (DepositIdentifier _depositId)\n259: \n\n```\n",
"loc": [
"[256](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L256-L256)"
]
},
{
"content": "```solidity\n271: function stake(uint256 _amount, address _delegatee, address _beneficiary)\n272: external\n273: returns (DepositIdentifier _depositId)\n274: \n\n```\n",
"loc": [
"[271](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L271-L271)"
]
},
{
"content": "```solidity\n292: function permitAndStake(\n293: uint256 _amount,\n294: address _delegatee,\n295: address _beneficiary,\n296: uint256 _deadline,\n297: uint8 _v,\n298: bytes32 _r,\n299: bytes32 _s\n300: ) external returns (DepositIdentifier _depositId) \n\n```\n",
"loc": [
"[292](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L292-L292)"
]
},
{
"content": "```solidity\n315: function stakeOnBehalf(\n316: uint256 _amount,\n317: address _delegatee,\n318: address _beneficiary,\n319: address _depositor,\n320: bytes memory _signature\n321: ) external returns (DepositIdentifier _depositId) \n\n```\n",
"loc": [
"[315](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L315-L315)"
]
},
{
"content": "```solidity\n342: function stakeMore(DepositIdentifier _depositId, uint256 _amount) external \n\n```\n",
"loc": [
"[342](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L342-L342)"
]
},
{
"content": "```solidity\n360: function permitAndStakeMore(\n361: DepositIdentifier _depositId,\n362: uint256 _amount,\n363: uint256 _deadline,\n364: uint8 _v,\n365: bytes32 _r,\n366: bytes32 _s\n367: ) external \n\n```\n",
"loc": [
"[360](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L360-L360)"
]
},
{
"content": "```solidity\n382: function stakeMoreOnBehalf(\n383: DepositIdentifier _depositId,\n384: uint256 _amount,\n385: address _depositor,\n386: bytes memory _signature\n387: ) external \n\n```\n",
"loc": [
"[382](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L382-L382)"
]
},
{
"content": "```solidity\n410: function alterDelegatee(DepositIdentifier _depositId, address _newDelegatee) external \n\n```\n",
"loc": [
"[410](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L410-L410)"
]
},
{
"content": "```solidity\n423: function alterDelegateeOnBehalf(\n424: DepositIdentifier _depositId,\n425: address _newDelegatee,\n426: address _depositor,\n427: bytes memory _signature\n428: ) external \n\n```\n",
"loc": [
"[423](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L423-L423)"
]
},
{
"content": "```solidity\n453: function alterBeneficiary(DepositIdentifier _depositId, address _newBeneficiary) external \n\n```\n",
"loc": [
"[453](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L453-L453)"
]
},
{
"content": "```solidity\n466: function alterBeneficiaryOnBehalf(\n467: DepositIdentifier _depositId,\n468: address _newBeneficiary,\n469: address _depositor,\n470: bytes memory _signature\n471: ) external \n\n```\n",
"loc": [
"[466](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L466-L466)"
]
},
{
"content": "```solidity\n499: function withdraw(DepositIdentifier _depositId, uint256 _amount) external \n\n```\n",
"loc": [
"[499](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L499-L499)"
]
},
{
"content": "```solidity\n512: function withdrawOnBehalf(\n513: DepositIdentifier _depositId,\n514: uint256 _amount,\n515: address _depositor,\n516: bytes memory _signature\n517: ) external \n\n```\n",
"loc": [
"[512](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L512-L512)"
]
},
{
"content": "```solidity\n536: function claimReward() external \n\n```\n",
"loc": [
"[536](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L536-L536)"
]
},
{
"content": "```solidity\n544: function claimRewardOnBehalf(address _beneficiary, bytes memory _signature) external \n\n```\n",
"loc": [
"[544](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L544-L544)"
]
},
{
"content": "```solidity\n570: function notifyRewardAmount(uint256 _amount) external \n\n```\n",
"loc": [
"[570](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L570-L570)"
]
},
{
"content": "```solidity\n201: function setAdmin(address _newAdmin) external \n\n```\n",
"loc": [
"[201](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L201-L201)"
]
},
{
"content": "```solidity\n119: function setPayoutAmount(uint256 _newPayoutAmount) external \n\n```\n",
"loc": [
"[119](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L119-L119)"
]
},
{
"content": "```solidity\n131: function enableFeeAmount(uint24 _fee, int24 _tickSpacing) external \n\n```\n",
"loc": [
"[131](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L131-L131)"
]
},
{
"content": "```solidity\n142: function setFeeProtocol(\n143: IUniswapV3PoolOwnerActions _pool,\n144: uint8 _feeProtocol0,\n145: uint8 _feeProtocol1\n146: ) external \n\n```\n",
"loc": [
"[142](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L142-L142)"
]
},
{
"content": "```solidity\n181: function claimFees(\n182: IUniswapV3PoolOwnerActions _pool,\n183: address _recipient,\n184: uint128 _amount0Requested,\n185: uint128 _amount1Requested\n186: ) external returns (uint128, uint128) \n\n```\n",
"loc": [
"[181](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L181)"
]
},
{
"content": "```solidity\n220: function lastTimeRewardDistributed() public view returns (uint256) \n\n```\n",
"loc": [
"[220](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L220-L220)"
]
},
{
"content": "```solidity\n229: function rewardPerTokenAccumulated() public view returns (uint256) \n\n```\n",
"loc": [
"[229](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L229-L229)"
]
},
{
"content": "```solidity\n241: function unclaimedReward(address _beneficiary) public view returns (uint256) \n\n```\n",
"loc": [
"[241](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L241-L241)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Overly complicated arithmetic ",
"description": "To maintain readability in code, particularly in Solidity which can involve complex mathematical operations, it is often recommended to limit the number of arithmetic operations to a maximum of 2-3 per line. Too many operations in a single line can make the code difficult to read and understand, increase the likelihood of mistakes, and complicate the process of debugging and reviewing the code. Consider splitting such operations over more than one line, take special care when dealing with division however. Try to limit the number of arithmetic operations to a maximum of 3 per line.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n232: \n233: return rewardPerTokenAccumulatedCheckpoint\n234: + (scaledRewardRate * (lastTimeRewardDistributed() - lastCheckpointTime)) / totalStaked; // <= FOUND\n\n```\n",
"loc": [
"[234](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L234-L234)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Some tokens may revert when zero value transfers are made ",
"description": "Reason: In Solidity, ERC20 token transfers of value 0 can sometimes lead to unexpected issues. This is particularly relevant when dealing with fractional token amounts that round to 0 when less than 1 of the smallest unit is transferred, leading to an effective transfer of nothing while still consuming gas. Furthermore, some ERC20 token implementations may revert on attempts to transfer a value of 0. However, note that this issue doesn't generally apply to wrapper native tokens like WETH.\n\nResolution: It's advisable to include a condition before any transfer operation to bypass the transaction if the transfer amount is 0. This saves unnecessary gas expenditure and prevents potential function reverts. For handling fractions, ensure token decimals are appropriately assigned and contemplate setting a minimum transfer threshold to avoid rounding down to 0. When dealing with wrapped tokens like WETH, special consideration should be given to their unique characteristics.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n623: function _stakeTokenSafeTransferFrom(address _from, address _to, uint256 _value) internal { // <= FOUND\n624: SafeERC20.safeTransferFrom(IERC20(address(STAKE_TOKEN)), _from, _to, _value); // <= FOUND\n625: }\n\n```\n",
"loc": [
"[623](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L623-L624)"
]
},
{
"content": "```solidity\n181: function claimFees(\n182: IUniswapV3PoolOwnerActions _pool,\n183: address _recipient,\n184: uint128 _amount0Requested,\n185: uint128 _amount1Requested\n186: ) external returns (uint128, uint128) {\n187: PAYOUT_TOKEN.safeTransferFrom(msg.sender, address(REWARD_RECEIVER), payoutAmount); // <= FOUND\n188: REWARD_RECEIVER.notifyRewardAmount(payoutAmount);\n189: (uint128 _amount0, uint128 _amount1) =\n190: _pool.collectProtocol(_recipient, _amount0Requested, _amount1Requested);\n191: \n193: if (_amount0 < _amount0Requested || _amount1 < _amount1Requested) {\n194: revert V3FactoryOwner__InsufficientFeesCollected();\n195: }\n196: emit FeesClaimed(address(_pool), msg.sender, _recipient, _amount0, _amount1);\n197: return (_amount0, _amount1);\n198: }\n\n```\n",
"loc": [
"[181](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L187)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Consider adding emergency-stop functionality ",
"description": "In the event of a security breach or any unforeseen emergency, swiftly suspending all protocol operations becomes crucial. Having a mechanism in place to halt all functions collectively, instead of pausing individual contracts separately, substantially enhances the efficiency of mitigating ongoing attacks or vulnerabilities. This not only quickens the response time to potential threats but also reduces operational stress during these critical periods. Therefore, consider integrating a 'circuit breaker' or 'emergency stop' function into the smart contract system architecture. Such a feature would provide the capability to suspend the entire protocol instantly, which could prove invaluable during a time-sensitive crisis management situation.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n31: contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces \n\n```\n",
"loc": [
"[31](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L31-L31)"
]
},
{
"content": "```solidity\n30: contract V3FactoryOwner \n\n```\n",
"loc": [
"[30](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L30-L30)"
]
},
{
"content": "```solidity\n20: contract DelegationSurrogate \n\n```\n",
"loc": [
"[20](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L20-L20)"
]
}
]
},
{
"severity": "Gas",
"title": "Consider Using Solady's Gas Optimized Lib for Math",
"description": "In instances where many similar mathematical operations are performed, consider using Solday's math lib to benefit from the gas saving it can introduce.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n232: \n233: return rewardPerTokenAccumulatedCheckpoint\n234: + (scaledRewardRate * (lastTimeRewardDistributed() - lastCheckpointTime)) / totalStaked; // <= FOUND\n\n```\n",
"loc": [
"[232](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L232-L234)"
]
},
{
"content": "```solidity\n242: return unclaimedRewardCheckpoint[_beneficiary]\n243: + (\n244: earningPower[_beneficiary]\n245: * (rewardPerTokenAccumulated() - beneficiaryRewardPerTokenCheckpoint[_beneficiary]) // <= FOUND\n246: ) / SCALE_FACTOR; // <= FOUND\n\n```\n",
"loc": [
"[242](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L242-L246)"
]
},
{
"content": "```solidity\n578: scaledRewardRate = (_amount * SCALE_FACTOR) / REWARD_DURATION; // <= FOUND\n\n```\n",
"loc": [
"[578](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L578-L578)"
]
},
{
"content": "```solidity\n581: scaledRewardRate = (_remainingReward + _amount * SCALE_FACTOR) / REWARD_DURATION; // <= FOUND\n\n```\n",
"loc": [
"[581](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L581-L581)"
]
}
]
},
{
"severity": "Gas",
"title": "It is a waste of GAS to emit variable literals",
"description": "Emitting variable literals (true, false, 'hello', 1 etc...) in events is inefficient, as it consumes extra gas without providing added value. These literals are fixed values that can be accessed or hardcoded elsewhere in the smart contract or application, making their inclusion in events redundant and an unnecessary drain on resources during transaction execution.",
"gasSavings": 40,
"category": null,
"instances": [
{
"content": "```solidity\n662: emit BeneficiaryAltered(_depositId, address(0), _beneficiary); // <= FOUND\n\n```\n",
"loc": [
"[662](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L662-L662)"
]
},
{
"content": "```solidity\n663: emit DelegateeAltered(_depositId, address(0), _delegatee); // <= FOUND\n\n```\n",
"loc": [
"[663](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L663-L663)"
]
},
{
"content": "```solidity\n105: emit AdminSet(address(0), _admin); // <= FOUND\n\n```\n",
"loc": [
"[105](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L105-L105)"
]
},
{
"content": "```solidity\n105: emit PayoutAmountSet(0, _payoutAmount); // <= FOUND\n\n```\n",
"loc": [
"[105](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L105-L105)"
]
},
{
"content": "```solidity\n196: emit FeesClaimed(address(_pool), msg.sender, _recipient, _amount0, _amount1); // <= FOUND\n\n```\n",
"loc": [
"[196](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L196-L196)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Return values not checked for approve()",
"description": "The ERC-20 token standard does not dictate that the approve function must return a value. The function signature in the ERC-20 standard is function approve(address spender, uint tokens) public returns (bool success);. However, a well-implemented ERC-20 token contract will typically have approve return a boolean value indicating whether or not the operation was successful.\n\nIt's crucial to note that not all token contracts follow this practice. Some might not return a value, or they might return a value in a non-standard way. This inconsistency among token contracts is one reason why it's important to handle token interactions carefully in your smart contracts and to check the return value of approve when possible.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n27: _token.approve(msg.sender, type(uint256).max); // <= FOUND\n\n```\n",
"loc": [
"[27](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L27-L27)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Contracts are vulnerable to fee-on-transfer accounting-related issues",
"description": "The below-listed functions use `transferFrom()` to move funds from the sender to the recipient but fail to verify if the received token amount matches the transferred amount. This could pose an issue with fee-on-transfer tokens, where the post-transfer balance might be less than anticipated, leading to balance inconsistencies. There might be subsequent checks for a second transfer, but an attacker might exploit leftover funds (such as those accidentally sent by another user) to gain unjustified credit. A practical solution is to gauge the balance prior and post-transfer, and consider the differential as the transferred amount, instead of the predefined amount.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n623: function _stakeTokenSafeTransferFrom(address _from, address _to, uint256 _value) internal {\n624: SafeERC20.safeTransferFrom(IERC20(address(STAKE_TOKEN)), _from, _to, _value); // <= FOUND\n625: }\n\n```\n",
"loc": [
"[623](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L623-L624)"
]
},
{
"content": "```solidity\n181: function claimFees(\n182: IUniswapV3PoolOwnerActions _pool,\n183: address _recipient,\n184: uint128 _amount0Requested,\n185: uint128 _amount1Requested\n186: ) external returns (uint128, uint128) {\n187: PAYOUT_TOKEN.safeTransferFrom(msg.sender, address(REWARD_RECEIVER), payoutAmount); // <= FOUND\n188: REWARD_RECEIVER.notifyRewardAmount(payoutAmount);\n189: (uint128 _amount0, uint128 _amount1) =\n190: _pool.collectProtocol(_recipient, _amount0Requested, _amount1Requested);\n191: \n193: if (_amount0 < _amount0Requested || _amount1 < _amount1Requested) {\n194: revert V3FactoryOwner__InsufficientFeesCollected();\n195: }\n196: emit FeesClaimed(address(_pool), msg.sender, _recipient, _amount0, _amount1);\n197: return (_amount0, _amount1);\n198: }\n\n```\n",
"loc": [
"[181](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L187)"
]
}
]
},
{
"severity": "Low",
"title": "No limits when setting fees",
"description": "When settings fees state variables, ensure there a require checks in place to prevent incorrect values from being set. This is particularly important when dealing with fee values as without checks fees can be set to 100%",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n142: function setFeeProtocol(\n143: IUniswapV3PoolOwnerActions _pool,\n144: uint8 _feeProtocol0,\n145: uint8 _feeProtocol1\n146: ) external {\n147: _revertIfNotAdmin();\n148: _pool.setFeeProtocol(_feeProtocol0, _feeProtocol1);\n149: }\n\n```\n",
"loc": [
"[142](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L142-L142)"
]
}
]
},
{
"severity": "Low",
"title": "Loss of precision",
"description": "Dividing by large numbers in Solidity can cause a loss of precision due to the language's inherent integer division behavior. Solidity does not support floating-point arithmetic, and as a result, division between integers yields an integer result, truncating any fractional part. When dividing by a large number, the resulting value may become significantly smaller, leading to a loss of precision, as the fractional part is discarded.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n241: function unclaimedReward(address _beneficiary) public view returns (uint256) { // <= FOUND\n242: return unclaimedRewardCheckpoint[_beneficiary]\n243: + (\n244: earningPower[_beneficiary]\n245: * (rewardPerTokenAccumulated() - beneficiaryRewardPerTokenCheckpoint[_beneficiary])\n246: ) / SCALE_FACTOR;\n247: }\n\n```\n",
"loc": [
"[241](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L241-L241)"
]
}
]
},
{
"severity": "Low",
"title": "Missing zero address check in constructor",
"description": "In Solidity, constructors often take address parameters to initialize important components of a contract, such as owner or linked contracts. However, without a check, there's a risk that an address parameter could be mistakenly set to the zero address (0x0). This could occur due to a mistake or oversight during contract deployment. A zero address in a crucial role can cause serious issues, as it cannot perform actions like a normal address, and any funds sent to it are irretrievable. Therefore, it's crucial to include a zero address check in constructors to prevent such potential problems. If a zero address is detected, the constructor should revert the transaction.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n190: constructor(IERC20 _rewardToken, IERC20Delegates _stakeToken, address _admin) // <= FOUND\n191: EIP712(\"UniStaker\", \"1\")\n192: {\n193: REWARD_TOKEN = _rewardToken;\n194: STAKE_TOKEN = _stakeToken;\n195: _setAdmin(_admin);\n196: }\n\n```\n",
"loc": [
"[190](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L190-L190)"
]
},
{
"content": "```solidity\n25: constructor(IERC20Delegates _token, address _delegatee) { // <= FOUND\n26: _token.delegate(_delegatee);\n27: _token.approve(msg.sender, type(uint256).max);\n28: }\n\n```\n",
"loc": [
"[25](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L25-L25)"
]
}
]
},
{
"severity": "Low",
"title": "Approve type(uint256).max may not work with some tokens",
"description": "The `approve` function in ERC-20 tokens allows a user to permit another user or contract to spend tokens on their behalf. Setting the approval to `type(uint256).max` is often used as a way to grant an indefinite approval, as this value is the maximum possible value of a `uint256` variable in Solidity. \n\nHowever, some tokens may not function as expected when `type(uint256).max` is used. These tokens may have an atypical implementation of the `transferFrom` function, which is used in combination with `approve`. This function might behave differently when confronted with such a high allowance, possibly due to custom logic in the contract that wasn't designed to handle these edge cases. \n\nMoreover, tokens that have a built-in burning or fees mechanism could behave unpredictably when the maximum allowance is set. This can lead to potential vulnerabilities or misinterpretations of contract behavior.\n\nResolution: It's advisable to be conservative with the `approve` function and only approve the specific amount of tokens that need to be spent for the specific operation you're performing. If you need to provide an extensive allowance, ensure you've thoroughly analyzed the token contract to understand how it behaves with high allowances. Alternatively, consider implementing a mechanism in your contract to handle token allowances in a more dynamic way, adjusting them as needed for each operation, rather than relying on a single indefinite approval.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n27: _token.approve(msg.sender, type(uint256).max); // <= FOUND\n\n```\n",
"loc": [
"[27](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L27-L27)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Revert on Transfer to the Zero Address",
"description": "Many ERC-20 and ERC-721 token contracts implement a safeguard that reverts transactions which attempt to transfer tokens to the zero address. This is because such transfers are often the result of programming errors. The OpenZeppelin library, a popular choice for implementing these standards, includes this safeguard. For token contract developers who want to avoid unintentional transfers to the zero address, it's good practice to include a condition that reverts the transaction if the recipient's address is the zero address. ",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n623: function _stakeTokenSafeTransferFrom(address _from, address _to, uint256 _value) internal { // <= FOUND\n624: SafeERC20.safeTransferFrom(IERC20(address(STAKE_TOKEN)), _from, _to, _value); // <= FOUND\n625: }\n\n```\n",
"loc": [
"[623](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L623-L624)"
]
},
{
"content": "```solidity\n638: function _stake(address _depositor, uint256 _amount, address _delegatee, address _beneficiary)\n639: internal\n640: returns (DepositIdentifier _depositId)\n641: {\n642: _revertIfAddressZero(_delegatee);\n643: _revertIfAddressZero(_beneficiary);\n644: \n645: _checkpointGlobalReward();\n646: _checkpointReward(_beneficiary);\n647: \n648: DelegationSurrogate _surrogate = _fetchOrDeploySurrogate(_delegatee);\n649: _depositId = _useDepositId();\n650: \n651: totalStaked += _amount;\n652: depositorTotalStaked[_depositor] += _amount;\n653: earningPower[_beneficiary] += _amount;\n654: deposits[_depositId] = Deposit({\n655: balance: _amount,\n656: owner: _depositor,\n657: delegatee: _delegatee,\n658: beneficiary: _beneficiary\n659: });\n660: _stakeTokenSafeTransferFrom(_depositor, address(_surrogate), _amount); // <= FOUND\n661: emit StakeDeposited(_depositor, _depositId, _amount, _amount);\n662: emit BeneficiaryAltered(_depositId, address(0), _beneficiary);\n663: emit DelegateeAltered(_depositId, address(0), _delegatee);\n664: }\n\n```\n",
"loc": [
"[638](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L638-L660)"
]
},
{
"content": "```solidity\n669: function _stakeMore(Deposit storage deposit, DepositIdentifier _depositId, uint256 _amount)\n670: internal\n671: {\n672: _checkpointGlobalReward();\n673: _checkpointReward(deposit.beneficiary);\n674: \n675: DelegationSurrogate _surrogate = surrogates[deposit.delegatee];\n676: \n677: totalStaked += _amount;\n678: depositorTotalStaked[deposit.owner] += _amount;\n679: earningPower[deposit.beneficiary] += _amount;\n680: deposit.balance += _amount;\n681: _stakeTokenSafeTransferFrom(deposit.owner, address(_surrogate), _amount); // <= FOUND\n682: emit StakeDeposited(deposit.owner, _depositId, _amount, deposit.balance);\n683: }\n\n```\n",
"loc": [
"[669](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L669-L681)"
]
},
{
"content": "```solidity\n688: function _alterDelegatee(\n689: Deposit storage deposit,\n690: DepositIdentifier _depositId,\n691: address _newDelegatee\n692: ) internal {\n693: _revertIfAddressZero(_newDelegatee);\n694: DelegationSurrogate _oldSurrogate = surrogates[deposit.delegatee];\n695: emit DelegateeAltered(_depositId, deposit.delegatee, _newDelegatee);\n696: deposit.delegatee = _newDelegatee;\n697: DelegationSurrogate _newSurrogate = _fetchOrDeploySurrogate(_newDelegatee);\n698: _stakeTokenSafeTransferFrom(address(_oldSurrogate), address(_newSurrogate), deposit.balance); // <= FOUND\n699: }\n\n```\n",
"loc": [
"[688](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L688-L698)"
]
},
{
"content": "```solidity\n723: function _withdraw(Deposit storage deposit, DepositIdentifier _depositId, uint256 _amount)\n724: internal\n725: {\n726: _checkpointGlobalReward();\n727: _checkpointReward(deposit.beneficiary);\n728: \n729: deposit.balance -= _amount; \n730: totalStaked -= _amount;\n731: depositorTotalStaked[deposit.owner] -= _amount;\n732: earningPower[deposit.beneficiary] -= _amount;\n733: _stakeTokenSafeTransferFrom(address(surrogates[deposit.delegatee]), deposit.owner, _amount); // <= FOUND\n734: emit StakeWithdrawn(_depositId, _amount, deposit.balance);\n735: }\n\n```\n",
"loc": [
"[723](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L723-L733)"
]
},
{
"content": "```solidity\n740: function _claimReward(address _beneficiary) internal {\n741: _checkpointGlobalReward();\n742: _checkpointReward(_beneficiary);\n743: \n744: uint256 _reward = unclaimedRewardCheckpoint[_beneficiary];\n745: if (_reward == 0) return;\n746: unclaimedRewardCheckpoint[_beneficiary] = 0;\n747: emit RewardClaimed(_beneficiary, _reward);\n748: \n749: SafeERC20.safeTransfer(REWARD_TOKEN, _beneficiary, _reward); // <= FOUND\n750: }\n\n```\n",
"loc": [
"[740](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L740-L749)"
]
}
]
},
{
"severity": "Low",
"title": "Consider implementing two-step procedure for updating protocol addresses",
"description": "Implementing a two-step procedure for updating protocol addresses adds an extra layer of security. In such a system, the first step initiates the change, and the second step, after a predefined delay, confirms and finalizes it. This delay allows stakeholders or monitoring tools to observe and react to unintended or malicious changes. If an unauthorized change is detected, corrective actions can be taken before the change is finalized. To achieve this, introduce a \"proposed address\" state variable and a \"delay period\". Upon an update request, set the \"proposed address\". After the delay, if not contested, the main protocol address can be updated.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n201: function setAdmin(address _newAdmin) external { // <= FOUND\n202: _revertIfNotAdmin();\n203: _setAdmin(_newAdmin);\n204: }\n\n```\n",
"loc": [
"[201](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L201-L201)"
]
},
{
"content": "```solidity\n210: function setRewardNotifier(address _rewardNotifier, bool _isEnabled) external { // <= FOUND\n211: _revertIfNotAdmin();\n212: isRewardNotifier[_rewardNotifier] = _isEnabled;\n213: emit RewardNotifierSet(_rewardNotifier, _isEnabled);\n214: }\n\n```\n",
"loc": [
"[210](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L210-L210)"
]
},
{
"content": "```solidity\n110: function setAdmin(address _newAdmin) external { // <= FOUND\n111: _revertIfNotAdmin();\n112: if (_newAdmin == address(0)) revert V3FactoryOwner__InvalidAddress();\n113: emit AdminSet(admin, _newAdmin);\n114: admin = _newAdmin;\n115: }\n\n```\n",
"loc": [
"[110](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L110-L110)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Constructors missing validation",
"description": "In Solidity, when values are being assigned in constructors to unsigned or integer variables, it's crucial to ensure the provided values adhere to the protocol's specific operational boundaries as laid out in the project specifications and documentation. If the constructors lack appropriate validation checks, there's a risk of setting state variables with values that could cause unexpected and potentially detrimental behavior within the contract's operations, violating the intended logic of the protocol. This can compromise the contract's security and impact the maintainability and reliability of the system. In order to avoid such issues, it is recommended to incorporate rigorous validation checks in constructors. These checks should align with the project's defined rules and constraints, making use of Solidity's built-in require function to enforce these conditions. If the validation checks fail, the require function will cause the transaction to revert, ensuring the integrity and adherence to the protocol's expected behavior.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n190: constructor(IERC20 _rewardToken, IERC20Delegates _stakeToken, address _admin)\n191: EIP712(\"UniStaker\", \"1\")\n192: {\n193: REWARD_TOKEN = _rewardToken; // <= FOUND\n194: STAKE_TOKEN = _stakeToken; // <= FOUND\n195: _setAdmin(_admin);\n196: }\n\n```\n",
"loc": [
"[190](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L190-L194)"
]
},
{
"content": "```solidity\n88: constructor(\n89: address _admin,\n90: IUniswapV3FactoryOwnerActions _factory,\n91: IERC20 _payoutToken,\n92: uint256 _payoutAmount,\n93: INotifiableRewardReceiver _rewardReceiver\n94: ) {\n95: if (_admin == address(0)) revert V3FactoryOwner__InvalidAddress();\n96: if (_payoutAmount == 0) revert V3FactoryOwner__InvalidPayoutAmount();\n97: \n98: admin = _admin;\n99: FACTORY = _factory; // <= FOUND\n100: PAYOUT_TOKEN = _payoutToken; // <= FOUND\n101: payoutAmount = _payoutAmount;\n102: REWARD_RECEIVER = _rewardReceiver; // <= FOUND\n103: \n104: emit AdminSet(address(0), _admin);\n105: emit PayoutAmountSet(0, _payoutAmount);\n106: }\n\n```\n",
"loc": [
"[88](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L88-L102)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Contracts use infinite approvals with no means to revoke",
"description": "Contracts that implement infinite approvals without providing a mechanism to revoke them can pose security risks. Infinite approvals allow a spender to withdraw an unlimited amount of tokens, potentially leading to abuse or exploitation if the spender's address is compromised. To mitigate this risk, it's advisable to include functions that allow users to set and modify allowances. Implementing a method to revoke or adjust these infinite approvals enhances user control and security. This approach ensures users can manage their token allowances effectively, reducing the likelihood of unauthorized token transfers and increasing overall trust in the contract's safety.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n20: contract DelegationSurrogate { // <= FOUND\n21: \n25: constructor(IERC20Delegates _token, address _delegatee) {\n26: _token.delegate(_delegatee);\n27: _token.approve(msg.sender, type(uint256).max); // <= FOUND\n28: }\n29: }\n\n```\n",
"loc": [
"[20](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L20-L27)"
]
}
]
},
{
"severity": "Low",
"title": "Division in comparison",
"description": "To ensure accuracy in comparisons within programming, especially when dealing with integers, it's often more efficient to use multiplication rather than division. This approach stems from the fact that division operations are generally slower and more complex than multiplication. And in the context of solidity they can cause precision errors.\n\nSuppose you want to compare if a/b is greater than c/d (where a, b, c, and d are integers). Instead of performing division, which is prone to precision errors, you can cross-multiply to avoid division. The comparison a/b > c/d is equivalent to a*d > b*c. This way, you only use multiplication, which is faster and avoids potential inaccuracies or complexities associated with division.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n587: \n588: if ((scaledRewardRate / SCALE_FACTOR) == 0) revert UniStaker__InvalidRewardRate(); // <= FOUND\n\n```\n",
"loc": [
"[587](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L587-L588)"
]
}
]
},
{
"severity": "Low",
"title": "Use forceApprove in place of approve",
"description": "The forceApprove function is a specialized solution addressing the issues that arise with non-standard ERC-20 tokens, such as USDT, which exhibit non-standard behavior in their approve function. These tokens may necessitate setting the allowance to 0 before changing it, may not return a boolean value from approve calls, or may return false instead of reverting on failure. OpenZeppelin's SafeERC20 library includes a forceApprove method to safely handle these peculiarities, ensuring that smart contracts can interact with such tokens without transaction failures. It rectifies inconsistencies by ensuring that all token interactions, including approvals, adhere to expected standards, even when the underlying tokens do not. ",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n27: _token.approve(msg.sender, type(uint256).max); // <= FOUND\n\n```\n",
"loc": [
"[27](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L27-L27)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Large transfers may not work with some ERC20 tokens",
"description": "Large transfers with some ERC20 tokens may not work due to various reasons. Some tokens may have transfer restrictions built into the contract, such as daily transfer limits or maximum transfer sizes per transaction, to comply with regulatory requirements or to mitigate risks. Others may face issues with rounding errors when dealing with large quantities, especially if they have a high number of decimal places. Resolution involves carefully reading the token's contract to understand its constraints and behaviors and performing transfers accordingly. It may also be necessary to split large transfers into smaller increments if the token enforces specific transfer limits.",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n623: function _stakeTokenSafeTransferFrom(address _from, address _to, uint256 _value) internal { // <= FOUND\n624: SafeERC20.safeTransferFrom(IERC20(address(STAKE_TOKEN)), _from, _to, _value); // <= FOUND\n625: }\n\n```\n",
"loc": [
"[623](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L623-L624)"
]
},
{
"content": "```solidity\n740: function _claimReward(address _beneficiary) internal { // <= FOUND\n741: _checkpointGlobalReward();\n742: _checkpointReward(_beneficiary);\n743: \n744: uint256 _reward = unclaimedRewardCheckpoint[_beneficiary];\n745: if (_reward == 0) return;\n746: unclaimedRewardCheckpoint[_beneficiary] = 0;\n747: emit RewardClaimed(_beneficiary, _reward);\n748: \n749: SafeERC20.safeTransfer(REWARD_TOKEN, _beneficiary, _reward);\n750: }\n\n```\n",
"loc": [
"[740](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L740-L740)"
]
},
{
"content": "```solidity\n181: function claimFees(\n182: IUniswapV3PoolOwnerActions _pool,\n183: address _recipient,\n184: uint128 _amount0Requested,\n185: uint128 _amount1Requested\n186: ) external returns (uint128, uint128) {\n187: PAYOUT_TOKEN.safeTransferFrom(msg.sender, address(REWARD_RECEIVER), payoutAmount); // <= FOUND\n188: REWARD_RECEIVER.notifyRewardAmount(payoutAmount);\n189: (uint128 _amount0, uint128 _amount1) =\n190: _pool.collectProtocol(_recipient, _amount0Requested, _amount1Requested);\n191: \n193: if (_amount0 < _amount0Requested || _amount1 < _amount1Requested) {\n194: revert V3FactoryOwner__InsufficientFeesCollected();\n195: }\n196: emit FeesClaimed(address(_pool), msg.sender, _recipient, _amount0, _amount1);\n197: return (_amount0, _amount1);\n198: }\n\n```\n",
"loc": [
"[181](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L181-L187)"
]
}
]
},
{
"severity": "NonCritical",
"title": "NatSpec: @notice tags missing from contract/abstract/library/interface/function/modifier/constructor/receive/fallback",
"description": "",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n190: constructor(IERC20 _rewardToken, IERC20Delegates _stakeToken, address _admin)\n191: EIP712(\"UniStaker\", \"1\")\n192: \n\n```\n",
"loc": [
"[190](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L190-L190)"
]
},
{
"content": "```solidity\n88: constructor(\n89: address _admin,\n90: IUniswapV3FactoryOwnerActions _factory,\n91: IERC20 _payoutToken,\n92: uint256 _payoutAmount,\n93: INotifiableRewardReceiver _rewardReceiver\n94: ) \n\n```\n",
"loc": [
"[88](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L88-L88)"
]
},
{
"content": "```solidity\n25: constructor(IERC20Delegates _token, address _delegatee) \n\n```\n",
"loc": [
"[25](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L25-L25)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Natspec @author is missing from contract/interface/library",
"description": "",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n4: /// @notice A subset of the ERC20Votes-style governance token to which UNI conforms.\n5: /// Methods related to standard ERC20 functionality and to delegation are included.\n6: /// These methods are needed in the context of this system. Methods related to check pointing,\n7: /// past voting weights, and other functionality are omitted.\n8: interface IERC20Delegates {\n9: // ERC20 related methods\n10: function allowance(address account, address spender) external view returns (uint256);\n11: function approve(address spender, uint256 rawAmount) external returns (bool);\n12: function balanceOf(address account) external view returns (uint256);\n13: function decimals() external view returns (uint8);\n14: function symbol() external view returns (string memory);\n15: function totalSupply() external view returns (uint256);\n16: function transfer(address dst, uint256 rawAmount) external returns (bool);\n17: function transferFrom(address src, address dst, uint256 rawAmount) external returns (bool);\n18: function permit(\n19: address owner,\n20: address spender,\n21: uint256 rawAmount,\n22: uint256 deadline,\n23: uint8 v,\n24: bytes32 r,\n25: bytes32 s\n26: ) external;\n27: \n28: // ERC20Votes delegation methods\n29: function delegate(address delegatee) external;\n30: function delegates(address) external view returns (address);\n31: }\n\n```\n",
"loc": [
"[4](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/interfaces/IERC20Delegates.sol#L4-L4)"
]
},
{
"content": "```solidity\n4: /// @title The interface for the Uniswap V3 Factory\n5: /// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the\n6: /// protocol fees\n7: /// @dev Stripped down and renamed from:\n8: /// https://github.com/Uniswap/v3-core/blob/d8b1c635c275d2a9450bd6a78f3fa2484fef73eb/contracts/interfaces/IUniswapV3Factory.sol\n9: interface IUniswapV3FactoryOwnerActions {\n10: /// @notice Returns the current owner of the factory\n11: /// @dev Can be changed by the current owner via setOwner\n12: /// @return The address of the factory owner\n13: function owner() external view returns (address);\n14: \n15: /// @notice Updates the owner of the factory\n16: /// @dev Must be called by the current owner\n17: /// @param _owner The new owner of the factory\n18: function setOwner(address _owner) external;\n19: \n20: /// @notice Enables a fee amount with the given tickSpacing\n21: /// @dev Fee amounts may never be removed once enabled\n22: /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)\n23: /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the\n24: /// given fee amount\n25: function enableFeeAmount(uint24 fee, int24 tickSpacing) external;\n26: \n27: /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled\n28: /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the\n29: /// calling context\n30: /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled\n31: /// fee\n32: /// @return The tick spacing\n33: function feeAmountTickSpacing(uint24 fee) external view returns (int24);\n34: }\n\n```\n",
"loc": [
"[4](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/interfaces/IUniswapV3FactoryOwnerActions.sol#L4-L4)"
]
},
{
"content": "```solidity\n4: /// @title Permissioned pool actions\n5: /// @notice Contains pool methods that may only be called by the factory owner\n6: /// @dev Vendored from\n7: /// https://github.com/Uniswap/v3-core/blob/d8b1c635c275d2a9450bd6a78f3fa2484fef73eb/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol\n8: interface IUniswapV3PoolOwnerActions {\n9: /// @notice Set the denominator of the protocol's % share of the fees\n10: /// @param feeProtocol0 new protocol fee for token0 of the pool\n11: /// @param feeProtocol1 new protocol fee for token1 of the pool\n12: function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\n13: \n14: /// @notice Collect the protocol fee accrued to the pool\n15: /// @param recipient The address to which collected protocol fees should be sent\n16: /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only\n17: /// token1\n18: /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only\n19: /// token0\n20: /// @return amount0 The protocol fee collected in token0\n21: /// @return amount1 The protocol fee collected in token1\n22: function collectProtocol(address recipient, uint128 amount0Requested, uint128 amount1Requested)\n23: external\n24: returns (uint128 amount0, uint128 amount1);\n25: }\n\n```\n",
"loc": [
"[4](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/interfaces/IUniswapV3PoolOwnerActions.sol#L4-L4)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Natspec @title is missing from contract/interface/library",
"description": "",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n8: interface IERC20Delegates \n\n```\n",
"loc": [
"[8](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/interfaces/IERC20Delegates.sol#L8-L8)"
]
}
]
},
{
"severity": "NonCritical",
"title": "NatSpec: @dev tags missing from contract/abstract/library/interface/function/modifier/constructor/receive/fallback",
"description": "",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n31: contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces \n\n```\n",
"loc": [
"[31](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L31-L31)"
]
},
{
"content": "```solidity\n30: contract V3FactoryOwner \n\n```\n",
"loc": [
"[30](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L30-L30)"
]
},
{
"content": "```solidity\n20: contract DelegationSurrogate \n\n```\n",
"loc": [
"[20](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L20-L20)"
]
},
{
"content": "```solidity\n8: interface IERC20Delegates \n\n```\n",
"loc": [
"[8](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/interfaces/IERC20Delegates.sol#L8-L8)"
]
},
{
"content": "```solidity\n10: interface INotifiableRewardReceiver \n\n```\n",
"loc": [
"[10](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/interfaces/INotifiableRewardReceiver.sol#L10-L10)"
]
},
{
"content": "```solidity\n220: function lastTimeRewardDistributed() public view returns (uint256) \n\n```\n",
"loc": [
"[220](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L220-L220)"
]
},
{
"content": "```solidity\n229: function rewardPerTokenAccumulated() public view returns (uint256) \n\n```\n",
"loc": [
"[229](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L229-L229)"
]
},
{
"content": "```solidity\n241: function unclaimedReward(address _beneficiary) public view returns (uint256) \n\n```\n",
"loc": [
"[241](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L241-L241)"
]
},
{
"content": "```solidity\n382: function stakeMoreOnBehalf(\n383: DepositIdentifier _depositId,\n384: uint256 _amount,\n385: address _depositor,\n386: bytes memory _signature\n387: ) external \n\n```\n",
"loc": [
"[382](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L382-L382)"
]
},
{
"content": "```solidity\n536: function claimReward() external \n\n```\n",
"loc": [
"[536](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L536-L536)"
]
},
{
"content": "```solidity\n544: function claimRewardOnBehalf(address _beneficiary, bytes memory _signature) external \n\n```\n",
"loc": [
"[544](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L544-L544)"
]
},
{
"content": "```solidity\n605: function _fetchOrDeploySurrogate(address _delegatee)\n606: internal\n607: returns (DelegationSurrogate _surrogate)\n608: \n\n```\n",
"loc": [
"[605](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L605-L605)"
]
},
{
"content": "```solidity\n623: function _stakeTokenSafeTransferFrom(address _from, address _to, uint256 _value) internal \n\n```\n",
"loc": [
"[623](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L623-L623)"
]
},
{
"content": "```solidity\n630: function _useDepositId() internal returns (DepositIdentifier _depositId) \n\n```\n",
"loc": [
"[630](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L630-L630)"
]
},
{
"content": "```solidity\n753: function _checkpointGlobalReward() internal \n\n```\n",
"loc": [
"[753](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L753-L753)"
]
},
{
"content": "```solidity\n771: function _setAdmin(address _newAdmin) internal \n\n```\n",
"loc": [
"[771](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L771-L771)"
]
},
{
"content": "```solidity\n779: function _revertIfNotAdmin() internal view \n\n```\n",
"loc": [
"[779](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L779-L779)"
]
},
{
"content": "```solidity\n787: function _revertIfNotDepositOwner(Deposit storage deposit, address owner) internal view \n\n```\n",
"loc": [
"[787](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L787-L787)"
]
},
{
"content": "```solidity\n794: function _revertIfAddressZero(address _account) internal pure \n\n```\n",
"loc": [
"[794](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L794-L794)"
]
},
{
"content": "```solidity\n803: function _revertIfSignatureIsNotValidNow(address _signer, bytes32 _hash, bytes memory _signature)\n804: internal\n805: view\n806: \n\n```\n",
"loc": [
"[803](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L803-L803)"
]
},
{
"content": "```solidity\n201: function setAdmin(address _newAdmin) external \n\n```\n",
"loc": [
"[201](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L201-L201)"
]
},
{
"content": "```solidity\n119: function setPayoutAmount(uint256 _newPayoutAmount) external \n\n```\n",
"loc": [
"[119](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L119-L119)"
]
},
{
"content": "```solidity\n190: constructor(IERC20 _rewardToken, IERC20Delegates _stakeToken, address _admin)\n191: EIP712(\"UniStaker\", \"1\")\n192: \n\n```\n",
"loc": [
"[190](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L190-L190)"
]
},
{
"content": "```solidity\n88: constructor(\n89: address _admin,\n90: IUniswapV3FactoryOwnerActions _factory,\n91: IERC20 _payoutToken,\n92: uint256 _payoutAmount,\n93: INotifiableRewardReceiver _rewardReceiver\n94: ) \n\n```\n",
"loc": [
"[88](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L88-L88)"
]
},
{
"content": "```solidity\n25: constructor(IERC20Delegates _token, address _delegatee) \n\n```\n",
"loc": [
"[25](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/DelegationSurrogate.sol#L25-L25)"
]
}
]
},
{
"severity": "NonCritical",
"title": "NatSpec: @param tags missing from function/modifier/constructor",
"description": "",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n241: function unclaimedReward(address _beneficiary) public view returns (uint256) \n\n```\n",
"loc": [
"[241](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L241-L241)"
]
},
{
"content": "```solidity\n638: function _stake(address _depositor, uint256 _amount, address _delegatee, address _beneficiary)\n639: internal\n640: returns (DepositIdentifier _depositId)\n641: \n\n```\n",
"loc": [
"[638](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L638-L638)"
]
},
{
"content": "```solidity\n669: function _stakeMore(Deposit storage deposit, DepositIdentifier _depositId, uint256 _amount)\n670: internal\n671: \n\n```\n",
"loc": [
"[669](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L669-L669)"
]
},
{
"content": "```solidity\n688: function _alterDelegatee(\n689: Deposit storage deposit,\n690: DepositIdentifier _depositId,\n691: address _newDelegatee\n692: ) internal \n\n```\n",
"loc": [
"[688](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L688-L688)"
]
},
{
"content": "```solidity\n704: function _alterBeneficiary(\n705: Deposit storage deposit,\n706: DepositIdentifier _depositId,\n707: address _newBeneficiary\n708: ) internal \n\n```\n",
"loc": [
"[704](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L704-L704)"
]
},
{
"content": "```solidity\n723: function _withdraw(Deposit storage deposit, DepositIdentifier _depositId, uint256 _amount)\n724: internal\n725: \n\n```\n",
"loc": [
"[723](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L723-L723)"
]
},
{
"content": "```solidity\n740: function _claimReward(address _beneficiary) internal \n\n```\n",
"loc": [
"[740](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L740-L740)"
]
}
]
},
{
"severity": "NonCritical",
"title": "NatSpec: @return tags missing from function/modifier/constructor",
"description": "",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n638: function _stake(address _depositor, uint256 _amount, address _delegatee, address _beneficiary)\n639: internal\n640: returns (DepositIdentifier _depositId)\n641: \n\n```\n",
"loc": [
"[638](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/UniStaker.sol#L638-L638)"
]
}
]
},
{
"severity": "NonCritical",
"title": "Floating pragma should be avoided",
"description": "",
"gasSavings": null,
"category": null,
"instances": [
{
"content": "```solidity\n2: pragma solidity ^0.8.23; // <= FOUND\n\n```\n",
"loc": [
"[2](https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/interfaces/IUniswapV3FactoryOwnerActions.sol#L2-L2)"