Platform: Code4rena
Start Date: 10/02/2022
Pot Size: $30,000 USDC
Total HM: 5
Participants: 24
Period: 3 days
Judge: harleythedog
Total Solo HM: 3
Id: 86
League: ETH
Rank: 13/24
Findings: 2
Award: $201.57
🌟 Selected for report: 0
🚀 Solo Findings: 0
126.0044 USDC - $126.00
swap
:Assessed risk: 2/10
Urgency: N/A
Codebase frequency: 1
Users would typically not swap against the same token, hence, developers must put in place a check against such swaps. Because of the rapid development and innovation that happens within the ETH smart contract ecosystem, one should never assume that what does not go wrong now will not go wrong in a few months, hence no exceptions are to be made when it comes to security and best practices.
function performSwap( IERC20 sellToken, IERC20 buyToken, bytes calldata swapCallData ) external payable override returns (uint256[] memory amounts, address[] memory tokens) { amounts = new uint256[](2); tokens = new address[](2); uint256 buyBalanceBeforePurchase = buyToken.balanceOf(address(this)); uint256 sellBalanceBeforePurchase = sellToken.balanceOf(address(this)); ...
operators/ZeroEx/ZeroExOperator.sol line 21
Adding a require statement would prevent such a swap.
require(buyToken != sellToken, "ERR: same token swap");
_weight != 0
check in FeeSplitterAssessed risk: 2/10
Urgency: N/A
Codebase frequency: 1
Keeping a consistent check among all functions of the contract that deal with _weight
is important, both from the security and clean code philosophies. One of the functions implemented in FeeSplitter.sol
does not check against the latest _weight
to be different than 0
, contrary to all the similar functions that have this check.
function updateShareholder(uint256 _accountIndex, uint96 _weight) external onlyOwner { require(_accountIndex < shareholders.length, "FS: INVALID_ACCOUNT_INDEX"); totalWeights = totalWeights + _weight - shareholders[_accountIndex].weight; require(totalWeights != 0, "FS: TOTAL_WEIGHTS_ZERO"); shareholders[_accountIndex].weight = _weight; emit ShareholderUpdated(shareholders[_accountIndex].account, _weight); }
FeeSplitter.sol line 134
Add a check against the _weight
being 0.
require(_weight != 0, "FS: ZERO_WEIGHT");
#0 - maximebrugel
2022-02-15T17:21:36Z
https://github.com/code-423n4/2022-02-nested-findings/issues/10
#1 - harleythedogC4
2022-03-01T02:31:41Z
My personal judgements:
#2 - harleythedogC4
2022-03-03T02:29:49Z
Now, here is the methodology I used for calculating a score for each QA report. I first assigned each submission to be either non-critical (1 point), very-low-critical (5 points) or low-critical (10 points), depending on how severe/useful the issue is. The score of a QA report is the sum of these points, divided by the maximum number of points achieved by a QA report. This maximum number was 26 points, achieved by https://github.com/code-423n4/2022-02-nested-findings/issues/66.
The number of points achieved by this report is 6 points. Thus the final score of this QA report is (6/26)*100 = 23.
🌟 Selected for report: pauliax
Also found by: 0x1f8b, Dravee, GreyArt, Omik, ShippooorDAO, Tomio, bobi, cmichel, csanuragjain, defsec, gzeon, kenta, kenzo, m_smirnova2020, rfa, robee, sirhashalot, ye0lde
75.5694 USDC - $75.57
shareholders
array.Caching arrays is a powerful way of lowering the gas fees. Since in a for
loop accessing memory array’s indexes would consume more gas than accessing the same array’s cached indexes as the length of the array becomes larger and larger, it is crucial to do the caching wherever possible.
FeeSplitter.sol line 320 # (_addShareholder function)
Cache the array in a similar way:
function _addShareholder(address _account, uint96 _weight) private { require(_weight != 0, "FS: ZERO_WEIGHT"); require(_account != address(0), "FS: INVALID_ADDRESS"); Shareholder[] memory shareholdersCache = shareholders; for (uint256 i = 0; i < shareholders.length; i++) { require(shareholdersCache[i].account != _account, "FS: ALREADY_SHAREHOLDER"); } shareholders.push(Shareholder(_account, _weight)); totalWeights += _weight; emit ShareholdersAdded(_account, _weight); }
#0 - adrien-supizet
2022-02-15T12:03:47Z
Confirmed
#1 - maximebrugel
2022-02-18T17:31:23Z
The array wont be very large
#2 - harleythedogC4
2022-03-13T03:27:08Z
My personal judgments:
#3 - harleythedogC4
2022-03-13T06:20:13Z
Now, here is the methodology I used for calculating a score for each gas report. I first assigned each submission to be either small-optimization (1 point), medium-optimization (5 points) or large-optimization (10 points), depending on how useful the optimization is. The score of a gas report is the sum of these points, divided by the maximum number of points achieved by a gas report. This maximum number was 10 points, achieved by #67.
The number of points achieved by this report is 1 points. Thus the final score of this gas report is (1/10)*100 = 10.