Numoen contest - Aymen0909's results

Automated exchange for power perpetuals.

General Information

Platform: Code4rena

Start Date: 26/01/2023

Pot Size: $60,500 USDC

Total HM: 7

Participants: 31

Period: 6 days

Judge: berndartmueller

Total Solo HM: 3

Id: 207

League: ETH

Numoen

Findings Distribution

Researcher Performance

Rank: 31/31

Findings: 1

Award: $45.43

Gas:
grade-b

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Awards

45.4256 USDC - $45.43

Labels

bug
G (Gas Optimization)
grade-b
G-02

External Links

Gas Optimizations

Summary

IssueInstances
1Usage of uint/int smaller than 32 bytes (256 bits) cost more gas2
2Using storage instead of memory for struct/array saves gas1
3Rearrange the Position's update function to save gas1
4Use unchecked blocks to save gas4
5x += y/x -= y costs more gas than x = x + y/x = x - y for state variables4
6public functions not called by the contract should be declared external instead2

Findings

1- Usage of uint/int smaller than 32 bytes (256 bits) cost more gas :

State variable declared as uint/int smaller than 32 bytes (256 bits) will cost more gas when used in the code logic as the compiler must first convert them back to uint256 before using them, the only case where using smaller uint/int size matter is when you store many state variables in the same storage slot otherwise it's better to declare them as uint256 to save gas in functions calls.

There are 2 instances of this issue :

File: core/Pair.sol Line 40

uint120 public override reserve0;

File: core/Pair.sol Line 43

uint120 public override reserve1;

2- Using storage instead of memory for struct/array saves gas :

When fetching data from a storage location, assigning the data to a memory variable causes all fields of the struct/array to be read from storage, which incurs a Gcoldsload (2100 gas) for each field of the struct/array. If the fields are read from the new memory variable, they incur an additional MLOAD rather than a cheap stack read. Instead of declearing the variable with the memory keyword, declaring the variable with the storage keyword and caching any fields that need to be re-read in stack variables, will be much cheaper, only incuring the Gcoldsload for the fields actually read. The only time it makes sense to read the whole struct/array into a memory variable, is if the full struct/array is being returned by the function, is being passed to a function that requires memory, or if the array/struct is being read from another memory array/struct

There is 1 instance of this issue :

File: core/Lendgine.sol Line 167

Position.Info memory positionInfo = positions[msg.sender];

3- Rearrange the Position's update function to save gas :

The update function function in the Position contract contains many unecessary lines of code which cost more gas and can lead to stack too deep errors, thus the function should be optimized to save gas on each call and should be modified as follow :

function update( mapping(address => Position.Info) storage self, address owner, int256 sizeDelta, uint256 rewardPerPosition ) internal { Position.Info storage positionInfo = self[owner]; Position.Info memory _positionInfo = positionInfo; // revert immediately if no position if (sizeDelta == 0 && _positionInfo.size == 0) revert NoPositionError(); uint256 tokensOwed; if (_positionInfo.size > 0) { tokensOwed = newTokensOwed(_positionInfo, rewardPerPosition); } // update position size only when there is delta != 0 if (sizeDelta != 0) positionInfo.size = PositionMath.addDelta(_positionInfo.size, sizeDelta); positionInfo.rewardPerPositionPaid = rewardPerPosition; if (tokensOwed > 0) positionInfo.tokensOwed = _positionInfo.tokensOwed + tokensOwed; }

4- Use unchecked blocks to save gas :

Solidity version 0.8+ comes with implicit overflow and underflow checks on unsigned integers. When an overflow or an underflow isn’t possible (as an example, when a comparison is made before the arithmetic operation), some gas can be saved by using an unchecked block.

There are 4 instances of this issue:

File: core/JumpRate.sol Line 20

uint256 excessUtil = util - kink;

The above operation cannot underflow due to the check at Line 16 so it should be marked as unchecked.

File: core/Lendgine.sol Line 201

position.tokensOwed = tokensOwed - collateral;

The above operation cannot underflow because of the Line 198 which ensures that we always have tokensOwed >= collateral , so it should be marked as unchecked.

File: core/Lendgine.sol Line 256

totalLiquidityBorrowed = _totalLiquidityBorrowed - dilutionLP;

The above operation cannot underflow because of the Line 253 which ensures that we always have _totalLiquidityBorrowed >= dilutionLP , so it should be marked as unchecked.

File: periphery/LiquidityManager.sol Line 242

position.tokensOwed -= amount;

The above operation cannot underflow because of the Line 241 which ensures that we always have position.tokensOwed >= amount , so it should be marked as unchecked.

5- x += y/x -= y costs more gas than x = x + y/x = x - y for state variables :

Using the addition operator instead of plus-equals saves 113 gas as explained here

There are 4 instances of this issue:

File: core/Lendgine.sol Line 91

totalLiquidityBorrowed += liquidity;

File: core/Lendgine.sol Line 114

totalLiquidityBorrowed -= liquidity;

File: core/Lendgine.sol Line 176

totalPositionSize -= size;

File: core/Lendgine.sol Line 257

rewardPerPositionStored += FullMath.mulDiv(dilutionSpeculative, 1e18, totalPositionSize);

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

The public functions that are not called inside the contract should be declared external instead to save gas.

There are 2 instances of this issue:

File: periphery/Payment.sol Line 25

function unwrapWETH(uint256 amountMinimum, address recipient) public

File: periphery/Payment.sol Line 35

function sweepToken(address token, uint256 amountMinimum, address recipient) public

#0 - c4-judge

2023-02-16T11:18:23Z

berndartmueller marked the issue as grade-b

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