FIAT DAO veFDT contest - LeoS's results

Unlock liquidity for your DeFi fixed income assets.

General Information

Platform: Code4rena

Start Date: 12/08/2022

Pot Size: $35,000 USDC

Total HM: 10

Participants: 126

Period: 3 days

Judge: Justin Goro

Total Solo HM: 3

Id: 154

League: ETH

FIAT DAO

Findings Distribution

Researcher Performance

Rank: 89/126

Findings: 2

Award: $44.84

🌟 Selected for report: 0

🚀 Solo Findings: 0

Low Risk

[L-01] Floating pragma.

It's a good practice to avoid the use of floating pragma. Code must be compiled with the same version it as been tested the most. It also avoids the use of any nightly builds, which can have unexpected and unknown behaviors.

5 instances

Consider replacing ^0.8.3 by 0.8.3.

[L-02] Missing check for address(0) when assigning value to address state variable.

Zero address checking is the best practice to prevent burning fee, unexpected exceptions or the redeployment of the contract.

5 instances:

Consider adding a modifier at the start of those function to check it.

This is low risk because any risk can only result of an owner's error in calling an external function. This can easily be prevented.

Non Critical

[N-01] Typo.

preceeding -> preceding seems more right.

2 instances:

[N-02] Large multiple of ten should use scientific notation for readability and consistency.

There is non consistency in the use of large multiple of ten, it does not help the readability.

2 instances:

Consider changing Point[1000000000000000000] and Point[1000000000] to Point[1e18] and Point[1e9] or Point[10**18] and Point[10**9] for consistency.

[G-01] Index increment can be left uncheck in for loop

For solidity ^0.8.0 there is an overflow check on each increment operation. This check is not needed in those for loop, since it can't overflow.

4 instances:

Consider removing i++ and replacing it by unchecked { ++i; } at the end of the loop. Transforming i++ to ++i is also cheaper.

These gas avg changes can be observed:

MockSmartWallet: quitLock: 201886 -> 201849 (-37) MockSmartWallet: withdraw: 666280 -> 665540 (-740) VotingEscrow: checkpoint: 1272491 -> 1271247 (-1244) VotingEscrow: createLock: 414348 -> 414267 (-81) VotingEscrow: delegate: 650225 -> 649908 (-317) VotingEscrow: increaseAmount: 448554 -> 448332 (-222) VotingEscrow: increaseUnlockTime: 143186 -> 143157 (-29) VotingEscrow: quitLock: 375486 -> 375258 (-228) VotingEscrow: withdraw: 610141 -> 609619 (-522) Deployment: VotingEscrow: 4374350 -> 4353169 (-21 181)

[G-02] Use != 0 instead of > 0 for unsigned integers.

A uint can't be below zero, so != 0 is sufficient and is gas more efficient. epoch, _value are uint.

4 instances

Consider replacing > by !=.

save 3 gas each

[G-03] Unnecessary initialization of variables.

int, uint, bool and address are initialized by default with 0, 0, false and address(0). It is not necessary to initialize these value again.

uint256 i = 0 ; -> uint256 i;

14 instances:

Consider shortening these initializations.

save 3 gas each

[G-04] Expression like x = x + y are cheaper than x += y for states variables.

11 instances:

Consider replacing += and -=

These gas avg changes can be observed:

Blocklist: block: 198815 -> 198813 (-2) MockSmartWallet: createLock: 355494 -> 355472 (-22) MockSmartWallet: delegate: 340388 -> 340384 (-4) MockSmartWallet: quitLock: 201886 -> 201862 (-24) MockSmartWallet: withdraw: 666280 -> 666266 (-14) VotingEscrow: createLock: 414348 -> 414326 (-22) VotingEscrow: delegate: 650225 -> 650221 (-4) VotingEscrow: increaseAmount: 448554 -> 448532 (-22) VotingEscrow: quitLock: 375486 -> 375462 (-24) VotingEscrow : withdraw: 610141 -> 610127 (-14) Deployment: VotingEscrow: 4374350 -> 4367298 (-7052)

[G-05] external function for the owner can be marked as payable.

If a function is guaranteed to revert when called by a normal user, this function can be marked as payable to avoid the check to know if a payment is provided.

4 instances:

Consider adding payable keyword.

Save 21 gas cost each

[G-06] Using storage instead of memory for structs can be cheaper.

A storage structure is pre allocated by the contract, by contrast, a memory one is newly created. Depending on the case both can be used to optimize the gas cost because simply, a storage is cheaper to create but more expensive to read from and to return and a memory on the other hand is more expensive to create but cheaper to read from and to return. We can optimize with trials and errors instead of complex calculations (which will probably work a bit better, but it's not done here).

Following this, we can deduce 8 cases that can be swapped to optimize runtime cost and deployment cost.

8 instances:

Consider changing memory to storage in these lines

These gas avg changes can be observed:

Blocklist: block: 198815 -> 196332 (-2483) VotingEscrow: increaseAmount: 448554 -> 446788 (-1766) Deployment: VotingEscrow: 4374350 -> 4320884 (-53466)
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