Platform: Code4rena
Start Date: 20/09/2022
Pot Size: $30,000 USDC
Total HM: 12
Participants: 198
Period: 3 days
Judge: 0xean
Total Solo HM: 2
Id: 164
League: ETH
Rank: 119/198
Findings: 2
Award: $27.95
π Selected for report: 0
π Solo Findings: 0
π Selected for report: AkshaySrivastav
Also found by: 0v3rf10w, 0x040, 0x1f8b, 0x4non, 0x5rings, 0x85102, 0xA5DF, 0xDecorativePineapple, 0xNazgul, 0xSky, 0xSmartContract, 0xbepresent, 0xf15ers, 0xmatt, 2997ms, Aeros, Aymen0909, B2, Bahurum, Bnke0x0, CertoraInc, Chom, ChristianKuri, CodingNameKiki, Deivitto, Diana, Diraco, Dravee, ElKu, Funen, IllIllI, JC, JLevick, JohnSmith, JohnnyTime, KIntern_NA, Lambda, Margaret, MasterCookie, OptimismSec, RaymondFam, Respx, ReyAdmirado, RockingMiles, Rohan16, Rolezn, Ruhum, RustyRabbit, Sm4rty, SooYa, StevenL, TomJ, Tomo, V_B, Waze, Yiko, __141345__, a12jmx, ajtra, ak1, async, ayeslick, aysha, berndartmueller, bin2chen, bobirichman, brgltd, bulej93, c3phas, carrotsmuggler, cccz, ch13fd357r0y3r, chatch, cryptostellar5, cryptphi, csanuragjain, d3e4, datapunk, delfin454000, dic0de, djxploit, durianSausage, eighty, erictee, exd0tpy, fatherOfBlocks, gogo, got_targ, hansfriese, ignacio, ikbkln, indijanc, innertia, joestakey, karanctf, ladboy233, leosathya, lukris02, martin, medikko, millersplanet, nalus, natzuu, neko_nyaa, neumo, obront, oyc_109, pcarranzav, peanuts, pedr02b2, pedroais, peiw, peritoflores, prasantgupta52, rajatbeladiya, rbserver, reassor, ret2basic, rokinot, romand, rotcivegaf, rvierdiiev, sach1r0, seyni, sikorico, slowmoses, sorrynotsorry, supernova, tibthecat, tnevler, ubermensch, yongskiws, zzykxx, zzzitron
18.8577 USDC - $18.86
All source files specify solidity version 0.8.14 EXCEPT for VariableSupplyERC20Token.sol which specifies ^0.8.14. Is there a reason for this?
Consider using the same version of solidity in all files.
Also consider using the most recent version of solidity. 0.8.17 is already released.
// Potential TODO: sanity check, if _linearVestAmount == 0, should we perhaps force that start and end ts are the same? https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L266
Each event should use three indexed fields if there are three or more fields in the event.
event ClaimRevoked(address indexed _recipient, uint112 _numTokensWithheld, uint256 revocationTimestamp, Claim _claim); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L69
// Therefore, we have valid scenarios if either of them is 0 // However, if both are 0 we might have a valid scenario as well - user just wants to create a token but doesn't want to mint anything // Should we allow this? require(initialSupply_ > 0 || maxSupply_ > 0, "INVALID_AMOUNT"); https://github.com/code-423n4/2022-09-vtvl/blob/main/contracts/token/VariableSupplyERC20Token.sol#L24-L27
I would say, the answer to above question is βyesβ and the code line therefore is erroneous. Either way, the question should be somehow resolved.
π Selected for report: IllIllI
Also found by: 0v3rf10w, 0x040, 0x1f8b, 0x4non, 0x85102, 0xA5DF, 0xDanielC, 0xNazgul, 0xSmartContract, 0xbepresent, 0xc0ffEE, 0xsam, 2997ms, AkshaySrivastav, Amithuddar, Atarpara, Aymen0909, B2, Bnke0x0, CertoraInc, Chom, ChristianKuri, CodingNameKiki, Deivitto, Diana, DimitarDimitrov, Diraco, Funen, JC, JLevick, JohnSmith, Junnon, KIntern_NA, Lambda, MasterCookie, Matin, Noah3o6, Ocean_Sky, OptimismSec, RaymondFam, Respx, ReyAdmirado, RockingMiles, Rohan16, Rolezn, Ruhum, Saintcode_, Satyam_Sharma, Sm4rty, SnowMan, SooYa, Sta1400, StevenL, Tadashi, Tagir2003, TomJ, Tomio, Tomo, V_B, Waze, WilliamAmbrozic, Yiko, __141345__, a12jmx, adriro, ajtra, ak1, async, aysha, beardofginger, bobirichman, brgltd, bulej93, c3phas, carrotsmuggler, caventa, ch0bu, cryptostellar5, cryptphi, csanuragjain, d3e4, delfin454000, dharma09, djxploit, durianSausage, eighty, emrekocak, erictee, exd0tpy, fatherOfBlocks, francoHacker, gianganhnguyen, gogo, got_targ, hxzy, ignacio, ikbkln, imare, indijanc, jag, jpserrat, karanctf, ladboy233, leosathya, lucacez, lukris02, m9800, malinariy, martin, medikko, mics, millersplanet, mrpathfindr, nalus, natzuu, neko_nyaa, oyc_109, pauliax, peanuts, pedroais, peiw, pfapostol, prasantgupta52, rbserver, ret2basic, rokinot, rotcivegaf, rvierdiiev, sach1r0, samruna, seyni, slowmoses, subtle77, supernova, tgolding55, tibthecat, tnevler, w0Lfrum, yaemsobak, zishansami
9.0866 USDC - $9.09
Pre-increment uses a little less gas.
for (uint256 i = 0; i < length; i++) { https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L353
Require strings and revert strings use about 50 more gas than custom errors.
require(supply_ > 0, "NO_ZERO_MINT"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/token/FullPremintERC20Token.sol#L11
require(initialSupply_ > 0 || maxSupply_ > 0, "INVALID_AMOUNT"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/token/VariableSupplyERC20Token.sol#L27
require(account != address(0), "INVALID_ADDRESS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/token/VariableSupplyERC20Token.sol#L37
require(amount <= mintableSupply, "INVALID_AMOUNT"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/token/VariableSupplyERC20Token.sol#L41
require(_admins[_msgSender()], "ADMIN_ACCESS_REQUIRED"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/AccessProtected.sol#L25
require(admin != address(0), "INVALID_ADDRESS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/AccessProtected.sol#L40
require(address(_tokenAddress) != address(0), "INVALID_ADDRESS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L82
require(_claim.startTimestamp > 0, "NO_ACTIVE_CLAIM"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L107
require(_claim.isActive == true, "NO_ACTIVE_CLAIM"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L111
// require(_claim.linearVestAmount + _claim.cliffAmount > 0, "INVALID_VESTED_AMOUNT"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L114
// require(_claim.endTimestamp > 0, "NO_END_TIMESTAMP"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L115
require(_claim.startTimestamp == 0, "CLAIM_ALREADY_EXISTS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L129
// require(_claim.isActive == false, "CLAIM_ALREADY_EXISTS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L133
// require(_claim.endTimestamp == 0, "CLAIM_ALREADY_EXISTS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L136
// require(_claim.linearVestAmount + _claim.cliffAmount == 0, "CLAIM_ALREADY_EXISTS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L137
// require(_claim.amountWithdrawn == 0, "CLAIM_ALREADY_EXISTS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L138
require(_recipient != address(0), "INVALID_ADDRESS"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L255
require(_linearVestAmount + _cliffAmount > 0, "INVALID_VESTED_AMOUNT"); // Actually only one of linearvested/cliff amount must be 0, not necessarily both https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L256
require(_startTimestamp > 0, "INVALID_START_TIMESTAMP"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L257
// require(_endTimestamp > 0, "_endTimestamp must be valid"); // not necessary because of the next condition (transitively) https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L261
require(_startTimestamp < _endTimestamp, "INVALID_END_TIMESTAMP"); // _endTimestamp must be after _startTimestamp https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L262
require(_releaseIntervalSecs > 0, "INVALID_RELEASE_INTERVAL"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L263
require((_endTimestamp - _startTimestamp) % _releaseIntervalSecs == 0, "INVALID_INTERVAL_LENGTH"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L264
require(tokenAddress.balanceOf(address(this)) >= numTokensReservedForVesting + allocatedAmount, "INSUFFICIENT_BALANCE"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L295
require(_startTimestamps.length == length && _endTimestamps.length == length && _cliffReleaseTimestamps.length == length && _releaseIntervalsSecs.length == length && _linearVestAmounts.length == length && _cliffAmounts.length == length, "ARRAY_LENGTH_MISMATCH" ); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L344-L351
require(allowance > usrClaim.amountWithdrawn, "NOTHING_TO_WITHDRAW"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L374
require(amountRemaining >= _amountRequested, "INSUFFICIENT_BALANCE"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L402
require( _claim.amountWithdrawn < finalVestAmt, "NO_UNVESTED_AMOUNT"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L426
require(_otherTokenAddress != tokenAddress, "INVALID_TOKEN"); // tokenAddress address is already sure to be nonzero due to constructor https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L447
require(bal > 0, "INSUFFICIENT_BALANCE"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L449
Using UINT256(1) for true and UINT256(2) for false costs less gas than using boolean variables.
mapping(address => bool) private _admins; // user address => admin? mapping https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/AccessProtected.sol#L12
Non-const variables should not be initialized to their default value. Just using the default costs less gas. For example use: uint256 abc; Instead of: uint256 abc=0;
uint112 public numTokensReservedForVesting = 0; https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L27
uint112 vestAmt = 0; https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L148
for (uint256 i = 0; i < length; i++) { https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L353
See link for a detailed discussion. https://github.com/code-423n4/2022-01-xdefi-findings/issues/128
require( ( _cliffReleaseTimestamp > 0 && _cliffAmount > 0 && _cliffReleaseTimestamp <= _startTimestamp ) || ( _cliffReleaseTimestamp == 0 && _cliffAmount == 0 ), "INVALID_CLIFF"); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L270-L278
require(_startTimestamps.length == length && _endTimestamps.length == length && _cliffReleaseTimestamps.length == length && _releaseIntervalsSecs.length == length && _linearVestAmounts.length == length && _cliffAmounts.length == length, "ARRAY_LENGTH_MISMATCH" ); https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L344-L351
Using ints or uints smaller than 256 bits can cost extra gas since the EVM operates with 32 bytes at a time. Consider using int256 or uint256. You can downcast them when necessary.
uint40 startTimestamp; // When does the vesting start (40 bits is enough for TS) https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L35
uint40 endTimestamp; // When does the vesting end - the vesting goes linearly between the start and end timestamps https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L36
uint40 cliffReleaseTimestamp; // At which timestamp is the cliffAmount released. This must be <= startTimestamp https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L37
uint40 releaseIntervalSecs; // Every how many seconds does the vested amount increase. https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L38
uint40 currentVestingDurationSecs = _referenceTs - _claim.startTimestamp; // How long since the start https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L167
uint40 truncatedCurrentVestingDurationSecs = (currentVestingDurationSecs / _claim.releaseIntervalSecs) * _claim.releaseIntervalSecs; https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L169
uint40 finalVestingDurationSecs = _claim.endTimestamp - _claim.startTimestamp; // length of the interval https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L170
uint40 _startTimestamp, https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L247
uint40 _endTimestamp, https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L248
uint40 _cliffReleaseTimestamp, https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L249
uint40 _releaseIntervalSecs, https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L250
uint40 _startTimestamp, https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L319
uint40 _endTimestamp, https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L320
uint40 _cliffReleaseTimestamp, https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L321
uint40 _releaseIntervalSecs, https://github.com/code-423n4/2022-09-vtvl/tree/main/contracts/VTVLVesting.sol#L322