VTVL contest - B2's results

Building no-code token management tools to empower web3 founders and investors, starting with token vesting.

General Information

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

VTVL

Findings Distribution

Researcher Performance

Rank: 120/198

Findings: 2

Award: $27.95

🌟 Selected for report: 0

🚀 Solo Findings: 0

public functions not called by the contract should be declared external instead

Contracts are allowed to override their parents’ functions and change the visibility from external to public

File: contracts/AccessProtected.sol #1 function setAdmin(address admin, bool isEnabled) public onlyAdmin {

Use of Block.timestamp

Block timestamps have historically been used for a variety of applications, such as entropy for random numbers (see the Entropy Illusion for further details), locking funds for periods of time, and various state-changing conditional statements that are time-dependent. Miners have the ability to adjust timestamps slightly, which can prove to be dangerous if block timestamps are used incorrectly in smart contracts.

Proof of Concept Navigate to the following contracts.

Unlocked Pragma

File: contracts/test/TestERC20Token.sol pragma solidity ^0.8.0;

Awards

9.0866 USDC - $9.09

Labels

bug
G (Gas Optimization)

External Links

++i/i++ should be unchecked{++i}/unchecked{i++} when it is not possible for them to overflow, as is the case when used in for- and while-loops

The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas PER LOOP

File: contracts/VTVLVesting.sol #1 for (uint256 i = 0; i < length; i++) { _createClaimUnchecked(_recipients[i], _startTimestamps[i], _endTimestamps[i], _cliffReleaseTimestamps[i], _releaseIntervalsSecs[i], _linearVestAmounts[i], _cliffAmounts[i]); }

Using > 0 costs more gas than != 0 when used on a uint in a require() statement

This change saves 6 gas per instance

File: contracts/token/FullPremintERC20Token.sol #1 require(supply_ > 0, "NO_ZERO_MINT");

It costs more gas to initialize variables to zero than to let the default of zero be applied

File: contracts/VTVLVesting.sol #1 uint112 public numTokensReservedForVesting = 0;

++i costs less gas than ++i, especially when it's used in for-loops (--i/i-- too)

Saves 6 gas PER LOOP

File: contracts/VTVLVesting.sol #1 for (uint256 i = 0; i < length; i++) {

Splitting require() statements that use && saves gas

Instead of using the && operator in a single require statement to check multiple conditions, I suggest using multiple require statements with 1 condition per require statement (saving 3 gas per &):

File: contracts/VTVLVesting.sol #1 require( ( _cliffReleaseTimestamp > 0 && _cliffAmount > 0 && _cliffReleaseTimestamp <= _startTimestamp ) || ( _cliffReleaseTimestamp == 0 && _cliffAmount == 0 ), "INVALID_CLIFF");

Use custom errors rather than revert()/require() strings to save deployment gas

Custom errors are available from solidity version 0.8.4. The instances below match or exceed that version

File: contracts/token/FullPremintERC20Token.sol #1 require(supply_ > 0, "NO_ZERO_MINT");

Don’t compare boolean expressions to boolean literals

if (<x> == true) => if (<x>), if (<x> == false) => if (!<x>)

File: contracts/VTVLVesting.sol #1 require(_claim.isActive == true, "NO_ACTIVE_CLAIM");

<x> += <y> costs more gas than <x> = <x> + <y> for state variables

File: contracts/VTVLVesting.sol #1 numTokensReservedForVesting += allocatedAmount;

Optimize if statament

File: contracts/token/VariableSupplyERC20Token.sol #1
AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter