Platform: Code4rena
Start Date: 31/01/2023
Pot Size: $90,500 USDC
Total HM: 47
Participants: 169
Period: 7 days
Judge: LSDan
Total Solo HM: 9
Id: 211
League: ETH
Rank: 50/169
Findings: 1
Award: $305.80
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x3b, 0xAgro, 0xBeirao, 0xMirce, 0xNineDec, 0xRobocop, 0xSmartContract, 0xTraub, 0xWeiss, 2997ms, 41i3xn, Awesome, Aymen0909, Bauer, Bnke0x0, Breeje, Cryptor, DadeKuma, Deathstore, Deekshith99, DevABDee, DevTimSch, Dewaxindo, Diana, Ermaniwe, Guild_3, H0, IceBear, Inspectah, JDeryl, Kaiziron, Kaysoft, Kenshin, Mukund, Praise, RaymondFam, Rickard, Rolezn, Ruhum, Sathish9098, SkyWalkerMan, SleepingBugs, UdarTeam, Udsen, Walter, aashar, adeolu, apvlki, arialblack14, ast3ros, btk, chaduke, chandkommanaboyina, chrisdior4, climber2002, codetilda, cryptonue, cryptostellar5, csanuragjain, ddimitrov22, descharre, dharma09, doublesharp, eccentricexit, ethernomad, fs0c, georgits, halden, hansfriese, hashminer0725, immeas, lukris02, luxartvinsec, matrix_0wl, merlin, mookimgo, mrpathfindr, nadin, olegthegoat, pavankv, rbserver, rebase, savi0ur, sayan, scokaf, seeu, shark, simon135, tnevler, tsvetanovv, ulqiorra, ustas, waldenyan20, y1cunhui, yongskiws, yosuke
305.798 USDC - $305.80
As of now block.timestamp.safeCastTo32()
will always revert when the block.timestamp
is greater than type(uint32).max
:= 4294967295. block.timestamp
returns the current seconds since unix epoch. A unix time of 4294967295 would imply a date and time of Sunday, 7 February 2106 06:28:15 GMT (can be verified here). In approximetly 83 years all functions that implement the call block.timestamp.safeCastTo32()
will always revert.
/src/utils/MultiRewardEscrow.sol
114: uint32 start = block.timestamp.safeCastTo32() + offset; 163: escrows[escrowId].lastUpdateTime = block.timestamp.safeCastTo32(); 175: block.timestamp.safeCastTo32() < escrow.start
/src/utils/MultiRewardStaking.sol
276: ? block.timestamp.safeCastTo32() 284: lastUpdatedTimestamp: block.timestamp.safeCastTo32() 309: prevEndTime > block.timestamp ? prevEndTime : block.timestamp.safeCastTo32(), 346: rewardInfos[rewardToken].lastUpdatedTimestamp = block.timestamp.safeCastTo32(); 409: rewardInfos[_rewardToken].lastUpdatedTimestamp = block.timestamp.safeCastTo32();
As of Solidity 0.8 overflows are handled automatically; however, not for casting. For example uint32(4294967300)
will result in 4
without reversion. Consider using a SafeCast.
/src/vault/VaultController.sol
314: uint8 len = uint8(vaults.length); 336: uint8 len = uint8(vaults.length); 353: uint8 len = uint8(vaults.length); 373: uint8 len = uint8(vaults.length); 436: uint8 len = uint8(vaults.length); 488: uint8 len = uint8(vaults.length); 517: uint8 len = uint8(vaults.length); 563: uint8 len = uint8(templateCategories.length); 583: uint8 len = uint8(templateCategories.length); 606: uint8 len = uint8(vaults.length); 619: uint8 len = uint8(vaults.length); 632: uint8 len = uint8(vaults.length); 645: uint8 len = uint8(vaults.length); 765: uint8 len = uint8(adapters.length); 805: uint8 len = uint8(adapters.length);
It is understood that the knowledge of this TODO and generally why TODOs should be removed is understood by the team here. This issue is left in as it does not technically void scope and can be beneficial for future auditors.
TODO
s should not be in production code. Each TODO
should either be discarded or implemented if needed prior to production.
/src/vault/adapter/abstracts/AdapterBase.sol
516: // TODO use deterministic fee recipient proxy
For better style and less computation consider replacing any power of 10 exponentiation (10**3
) with its equivalent scientific notation (1e3
).
/src/vault/adapter/yearn/YearnAdapter.sol
25: uint256 constant DEGRADATION_COEFFICIENT = 10**18;
Consider using OpenZeppelin's ECDSA contract instead of raw ecrecover
.
/src/utils/MultiRewardStaking.sol
459: address recoveredAddress = ecrecover(
/src/vault/Vault.sol
678: address recoveredAddress = ecrecover(
The Solidity Style Guide suggests the following function order: constructor, receive function (if exists), fallback function (if exists), external, public, internal, private.
The following contracts are not compliant (examples are only to prove the functions are out of order NOT a full description):
The Solidity Style Guide suggests the following contract layout order: Type declarations, State variables, Events, Modifiers, Functions.
The following contracts are not compliant (examples are only to prove the layout are out of order NOT a full description):
Lines with greater length than 120 characters are used. The Solidity Style Guide suggests that all lines should be 120 characters or less in width.
The following lines are longer than 120 characters, it is suggested to shorten these lines:
/src/vault/AdminProxy.sol
/src/vault/VaultRegistry.sol
/src/vault/DeploymentController.sol
/src/vault/TemplateRegistry.sol
/src/vault/adapter/yearn/YearnAdapter.sol
/src/utils/MultiRewardEscrow.sol
/src/vault/adapter/beefy/BeefyAdapter.sol
/src/utils/MultiRewardStaking.sol
/src/vault/Vault.sol
/src/vault/VaultController.sol
/src/vault/adapter/abstracts/AdapterBase.sol
The Solidity Style Guide suggests the following modifer order: Visibility, Mutability, Virtual, Override, Custom modifiers.
/src/vault/adapter/abstracts/AdapterBase.sol
_deposit
('internal', 'nonReentrant', 'virtual', 'override'): override (Override) positioned after nonReentrant (Custom Modifiers).21 out of 35 of the contracts in scope are missing a @title
tag. Given that 14 contracts all have a @title
tag, consider adding one per the 21 remaining contracts.
EIP165.sol, OnlyStrategy.sol, WithRewards.sol, IEIP165.sol, IAdminProxy.sol, IWithRewards.sol, ICloneFactory.sol, IStrategy.sol, ICloneRegistry.sol, IPermissionRegistry.sol, IVaultRegistry.sol, IYearn.sol, IAdapter.sol, IDeploymentController.sol, ITemplateRegistry.sol, IMultiRewardEscrow.sol, IERC4626.sol, IBeefy.sol, IMultiRewardStaking.sol, IVault.sol, and IVaultController.sol are missing a @title
tag.
Almost all comments have an initial space after //
or ///
while one does not. It is best for code clearity to keep a consistent style.
// foo
): EIP165.sol, OnlyStrategy.sol, AdminProxy.sol, WithRewards.sol, CloneFactory.sol, PermissionRegistry.sol, CloneRegistry.sol, VaultRegistry.sol, DeploymentController.sol, TemplateRegistry.sol, YearnAdapter.sol, MultiRewardEscrow.sol, BeefyAdapter.sol, MultiRewardStaking.sol, Vault.sol, VaultController.sol, AdapterBase.sol, IEIP165.sol, IAdminProxy.sol, IWithRewards.sol, ICloneFactory.sol, IStrategy.sol, ICloneRegistry.sol, IPermissionRegistry.sol, IVaultRegistry.sol, IYearn.sol, IAdapter.sol, IDeploymentController.sol, ITemplateRegistry.sol, IMultiRewardEscrow.sol, IERC4626.sol, IMultiRewardStaking.sol, IVault.sol, and IVaultController.sol.//foo
).Some functions use named returns and others do not. It is best for code clearity to keep a consistent style.
returns(uint256 foo)
): AdminProxy.sol, CloneFactory.sol, and DeploymentController.sol.returns(uint256)
): EIP165.sol, WithRewards.sol, PermissionRegistry.sol, CloneRegistry.sol, VaultRegistry.sol, TemplateRegistry.sol, YearnAdapter.sol, MultiRewardEscrow.sol, and BeefyAdapter.sol.Consider fixing all spelling mistakes.
/src/vault/AdminProxy.sol
Owns
is misspelled as ownes
.The headers in the codebase are not centered. For example, this line is not centered with this line. Consider centering all headers.
The code coverage of the files in scope is not 100%. Consider a test coverage of 100%.
Some contract in the codebase have a space after the license and before the pragma, but some do not. The following contracts do not have a space, all else do:
Consider using bytes.concat()
instead of abi.encodePacked()
in contracts with Solidity version >= 0.8.4.
/src/utils/MultiRewardEscrow.sol
104: bytes32 id = keccak256(abi.encodePacked(token, account, amount, nonce));
/src/utils/MultiRewardStaking.sol
49: _name = string(abi.encodePacked("Staked ", IERC20Metadata(address(_stakingToken)).name())); 50: _symbol = string(abi.encodePacked("pst-", IERC20Metadata(address(_stakingToken)).symbol())); 461: abi.encodePacked(
/src/vault/Vault.sol
94: abi.encodePacked("Popcorn", name(), block.timestamp, "Vault") 680: abi.encodePacked(
There is an inconsistency in the capitalization of comments. For example, this line is not capitilized while this line is. Consider capitilizing all comments.
Using named returns may help developers understand what is being returned, but this should be in a @return
tag. There is no need to confuse developers.
/src/vault/AdminProxy.sol
/src/vault/adapter/abstracts/AdapterBase.sol
There is a general inconsistency with puncuation in comments, specifically trailing .
s. The following items are proof by example and not every case in the codebase:
It seems as though the word LOGIC
is shortened to LOGC
. Consider spelling the word in full to dilute possible confusion given it is only a one characer difference.
Not all headers follow the same general format. Consider sticking to the same format.
Example 1:
/*////////////////////////////////////////////////////////////// REWARDS ACCRUAL LOGIC //////////////////////////////////////////////////////////////*/
Example 2:
// MANAGEMENT FUNCTIONS - FEES
In the lock function of MultiRewardEscrow.sol L114 can overflow (revert) without a proper error message. Consider adding an error message for when a user inputs a large offset
.
The variable highWaterMark_
in the function accruedPerformanceFee
appears to be a cache variable that is never used. When returning from the function highWaterMark
is used instead of highWaterMark_
. Consider using highWaterMark_
or removing it.
A view modifier can be added to the following functions to get rid of compiler warnings:
_registerVault
has a parameter address vault
that is never used. Consider attending to any security issues that may arrise from the non-use, and possibly removing the parameter.
In Vault.sol the phrase rage quit
is used (ex) which seems to be in jest; however, it is not good to use assumptive language. For individuals that are unaware of the jestful nature (EX. non-native English speakers, etc.) who may also be docile, the assumption that quitting is due to "rage" may be subliminally damaging to ones initial intent with the system.
It is best practice to document interfaces just like you would core contracts. Most interfaces do not have much internal documentation (comments). For example: IEIP165.sol, IAdminProxy.sol, IWithRewards.sol, etc. are missing all comments aside from the license identifiers. Consider documenting all interfaces to the level you would core contracts.
#0 - c4-judge
2023-02-28T17:44:09Z
dmvt marked the issue as grade-a