Platform: Code4rena
Start Date: 26/05/2022
Pot Size: $75,000 USDT
Total HM: 31
Participants: 71
Period: 7 days
Judge: GalloDaSballo
Total Solo HM: 18
Id: 126
League: ETH
Rank: 23/71
Findings: 3
Award: $756.75
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Kumpa
Also found by: SecureZeroX, unforgiven
562.3122 USDT - $562.31
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeAssetDepositor.sol#L38-L51
All ve projects have Max time, and if maxTime
variable is greater than MAX_TIME
of connected ve projects, VeAssetDepositor
could not work.
In Curve fi, MAX_TIME is a 4 years.
But in VeAssetDepositor.sol
, there is no validation for maxTime
If maxTime
is greater than 4 years, the contract won’t be working.
If maxTime
is zero, _lockVeAsset()
function won’t be working as well.
Manual
Add validation for maxTime
or get maxTime from connected ve project.
#0 - jetbrain10
2022-06-15T16:33:03Z
max time is a constant value for each project but it is different for each one that's why it is a variable , but it set for one time only at time of deploy by us so there is no issue as we check it before set
#1 - GalloDaSballo
2022-07-21T02:30:11Z
Dup of #141
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xDjango, 0xNazgul, 0xf15ers, BouSalman, Chom, Deivitto, Dravee, ElKu, FSchmoede, Funen, GimelSec, Hawkeye, MiloTruck, Picodes, SecureZeroX, SmartSek, TerrierLover, WatchPug, _Adam, asutorufos, berndartmueller, c3phas, catchup, cccz, cogitoergosumsw, cryptphi, csanuragjain, delfin454000, dipp, ellahi, gzeon, hansfriese, horsefacts, hyh, kirk-baird, minhquanym, oyc_109, pauliax, reassor, robee, sashik_eth, shenwilly, simon135, sorrynotsorry, sseefried, unforgiven, xiaoming90, z3s
131.1751 USDT - $131.18
It would be great to emit an event before or after updating sensitive variables to make easy to track updates by community.
VE3Token.sol/setOperator() VeTokenMinter.sol / addOperator() VeTokenMinter.sol / removeOperator() VE3DRewardPool.sol / addOperator() VE3DRewardPool.sol / removeOperator() RewardFactory.sol / addOperator() RewardFactory.sol / removeOperator() RewardFactory.sol / setAccess() StashFactory / addOperator() StashFactory / removeOperator()
Recommendation Emit events before or after updating sensitive varaibles.
safeApprove() function of Openzeppelin’s ERC20 have been depreciated. https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2268 https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2219 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L287 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L288 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L301 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L305 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/Booster.sol#L374
Recommendation:
Use safeIncreaseAllowance
or safeDecreaseAllowance
functions instead.
maxTime
of VeAssetDepositor
should be public
Now, the maxTime
of VeAssetDepositor.sol
has been declared as a private
, but I think this should be public
.Recommendation: Check this variable again.
stakeFor
function of VE3DRewardPool.sol
contract.https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L249
In this line, the msg.sender
is a VeAssetDepositor.sol
contract or any other address which is different from user’s address.
Recommendation: Emit event with actual user’s address.
Booster.sol
can be implemented by using OZ contracts.owner
variable and setOwner
function, this can be implemented by inheriting OpenZeppelin Ownable
contract.isShutdown
variable and shutdownSystem
function, this can be implemented by inheriting OpenZeppelin Pausable
contract.setRewardContracts
of Booster.sol
function could emit event without changes.
setRewardContracts
set values only if lockRewards
is address(0), but event is emitted per each function call.So if we use subgraph or anything else, it could lead to track wrong data.
Recommendation:
Emit RewardcontractsUpdated
event inside condition.
ITokenFactory
is an interface of TokenFactory
contract. However TokenFactory
did not inherit ITokenFactory
. This lead unexpected issue – ex. Interface has function, but implementation contract did not implement it.IRewardFactory
and RewardFactory
are same case.
Recommendation: Inherit interfaces, and override functions to avoid any unexpected issues in the future.
#0 - GalloDaSballo
2022-07-09T18:05:12Z
NC
NC because of the code working properly
Valid refactor, value can still be retrieved via looking at constructor (or storage at)
NC
Disagree, code would do the same thing, and would cost more gas
Valid Refactor
2R 3 NC
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, Cityscape, Dravee, ElKu, FSchmoede, Funen, GalloDaSballo, Hawkeye, Kaiziron, MiloTruck, Randyyy, RoiEvenHaim, Ruhum, SecureZeroX, SmartSek, TerrierLover, TomJ, Tomio, WatchPug, Waze, _Adam, asutorufos, c3phas, catchup, cogitoergosumsw, delfin454000, ellahi, fatherOfBlocks, gzeon, hansfriese, horsefacts, jonatascm, minhquanym, oyc_109, pauliax, reassor, robee, sach1r0, saian, sashik_eth, simon135, z3s
63.261 USDT - $63.26
The following smart contracts imported Address.sol
library and using it for address
, but this library is not used anywhere.
Booster.sol DepositToken.sol ExtraRewardStashV1.sol ExtraRewardStashV2.sol ExtraRewardStashV3.sol PoolManager.sol RewardFactory.sol StashFactory.sol TokenFactory.sol VeAssetDepositor.sol VoterProxy.sol VE3Token.sol
The following smart contracts is using SafeERC20
library without any usage.
VE3Token.sol
Recommendation: Remove unused libraries to reduce size of contract.
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeAssetDepositor.sol#L28 Setting zero value is not required and it will just cost gas.
Recommendation Remove zero initialization.
The following functions will only waste gas if condition does not meet.
VeAssetDepositor.sol/setFees()
: waste gas if _lockIncentive
is greater than 30.
VeAssetDepositor.sol/initialLock()
: waste gas if veVeAsset
is not zero.
Booster.sol / setRewardContracts()
: waste gas if lockRewards
is not address(0)
Any variable won’t be updated after this function call, however this will waste gas.
Recommendation Revert tx if condition does not meet.
>= 0
operation does not need for uint
variables.Since uint
variable is always greator or equal than 0, >=0
will be always true.
The following scripts have >=0
check.
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeAssetDepositor.sol#L62
Recommendation:
Remove >=0
condition check for uint
variables.
immutable
.The following variables are set in only constructor, so they can be declared as immutable.
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeAssetDepositor.sol#L30 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeTokenMinter.sol#L16 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeTokenMinter.sol#L18 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeTokenMinter.sol#L19
Recommendation
Make maxTime
variable as a immutable.
VeTokenMinter
is using ERC20
as an interface for veToken
We can use IERC20
interface contract for veToken,
But current code base requires to import whole ERC20 token contract which will increase contract size.Recommendation:
Use IERC20
instead of ERC20
external
The following functions can be declared as a external
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeTokenMinter.sol#L32 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VeTokenMinter.sol#L36 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L114 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L118 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L233 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/RewardFactory.sol#L24 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/RewardFactory.sol#L29
Recommendation
Use external
keyword
https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L148 https://github.com/code-423n4/2022-05-vetoken/blob/main/contracts/VE3DRewardPool.sol#L281]
Recommendation Cache length of array and use it in loop.
updateReward
could be executed twice in withdraw
function at VE3DRewardPool.sol
and BaseRewardPool.sol
Both getReward
and withdraw
functions have updateReward
modifier.
So If claim
param is true in withdraw
function, updateReward
modifier will be called again for getting reward.
This will waste another gas.
Recommendation
Make internal function to get reward without modifier, and call it in withdraw
function.
historialRewards
in rewardTokenInfo
can be removed.
historicalRewards
was not used inside or outside of reward pool contract.If this variable is used for only track, we can use subgraph instead.
Recommendation
Remove historicalRewards
variable.
#0 - GalloDaSballo
2022-07-18T23:30:38Z
4 * 2100 for immutable = 8400 Rest saves less than 500 gas
8900 roughly