Omniscia Maverick Protocol Audit

MaverickV2VotingEscrowWSync Code Style Findings

MaverickV2VotingEscrowWSync Code Style Findings

MVS-01C: Ineffectual Usage of Safe Arithmetics

Description:

The linked mathematical operation is guaranteed to be performed safely by logical inference, such as surrounding conditionals evaluated in require checks or if-else constructs.

Example:

v2-rewards/contracts/MaverickV2VotingEscrowWSync.sol
39if (newBalance > oldBalance) {
40 _mint(staker, newBalance - oldBalance);
41} else if (newBalance < oldBalance) {
42 _burn(staker, oldBalance - newBalance);
43}

Recommendation:

Given that safe arithmetics are toggled on by default in pragma versions of 0.8.X, we advise the linked statement to be wrapped in an unchecked code block thereby optimizing its execution cost.

Alleviation (07ad29f773f16bdfbae3d97d3a7c2f9d64866093):

The referenced operations have been properly wrapped in an unchecked code block, optimizing their gas cost whilst retaining their security guarantees via each operation's preceding statements.

MVS-02C: Inefficient mapping Lookups

Description:

The linked statements perform key-based lookup operations on mapping declarations from storage multiple times for the same key redundantly.

Example:

v2-rewards/contracts/MaverickV2VotingEscrowWSync.sol
32uint256 oldBalance = syncBalances[staker][legacyLockupIndex];
33Lockup memory lockup = ILegacyVeMav(address(legacyVeMav)).lockups(staker, legacyLockupIndex);
34if (lockup.end != 0 && lockup.end < block.timestamp + MIN_SYNC_DURATION)
35 revert VotingEscrowLockupEndTooShortToSync(lockup.end, block.timestamp + MIN_SYNC_DURATION);
36
37newBalance = lockup.votes;
38if (newBalance != oldBalance) {
39 if (newBalance > oldBalance) {
40 _mint(staker, newBalance - oldBalance);
41 } else if (newBalance < oldBalance) {
42 _burn(staker, oldBalance - newBalance);
43 }
44 syncBalances[staker][legacyLockupIndex] = newBalance;
45 emit Sync(staker, legacyLockupIndex, newBalance);
46}

Recommendation:

As the lookups internally perform an expensive keccak256 operation, we advise the lookups to be cached wherever possible to a single local declaration that either holds the value of the mapping in case of primitive types or holds a storage pointer to the struct contained.

As the compiler's optimizations may take care of these caching operations automatically at-times, we advise the optimization to be selectively applied, tested, and then fully adopted to ensure that the proposed caching model indeed leads to a reduction in gas costs.

Alleviation (07ad29f773):

The Maverick Protocol team requested clarification in relation to this exhibit; mapping lookups can also be optimized via local mapping declarations.

In the instance highlighted, a local mapping(uint256 => uint256) storage stakerBalancePerIndex variable can be declared to optimize the lookups performed by the highlighted statements.

Alleviation (7ad1f96f09):

A local mapping declaration has been introduced as advised, optimizing the gas cost of the MaverickV2VotingEscrowWSync::sync function.