Ethos Reserve contest - Budaghyan's results

A CDP-backed stablecoin platform designed to generate yield on underlying assets to establish a sustainable DeFi stable interest rate.

General Information

Platform: Code4rena

Start Date: 16/02/2023

Pot Size: $144,750 USDC

Total HM: 17

Participants: 154

Period: 19 days

Judge: Trust

Total Solo HM: 5

Id: 216

League: ETH

Ethos Reserve

Findings Distribution

Researcher Performance

Rank: 136/154

Findings: 1

Award: $42.07

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Ethos Reserve

[G-01] INTERNAL FUNCTIONS ONLY CALLED ONCE CAN BE INLINED TO SAVE GAS

Not inlining costs 20 to 40 gas because of two extra JUMP instructions and additional stack operations needed for function calls.

Instances 47

-BorrowerOperations line 438 -BorrowerOperations line 455 -BorrowerOperations line 476 -BorrowerOperations line 524 -BorrowerOperations line 533 -BorrowerOperations line 537 -BorrowerOperations line 546 -BorrowerOperations line 551 -BorrowerOperations line 555 -BorrowerOperations line 567 -BorrowerOperations line 571 -BorrowerOperations line 624 -BorrowerOperations line 636 -BorrowerOperations line 640 -BorrowerOperations line 661 -BorrowerOperations line 682 -TroveManager line 478 -TroveManager line 582 -TroveManager line 671 -TroveManager line 785 -TroveManager line 864 -TroveManager line 1213 -TroveManager line 1321 -TroveManager line 1339 -TroveManager line 1516 -TroveManager line 1538 -ActivePool line 320 -SortedTroves line 338 -SortedTroves line 402 -LQTYStaking line 251 -LQTYStaking line 261 -LQTYStaking line 265 -LQTYStaking line 269 -LUSDToken line 320 -LUSDToken line 328 -LUSDToken line 360 -LUSDToken line 365 -LUSDToken line 375 -LUSDToken line 380 -LUSDToken line 393 -ReaperVaultV2 line 462 -ReaperStrategyGranarySupplyOnly line 86 -ReaperStrategyGranarySupplyOnly line 176 -ReaperStrategyGranarySupplyOnly line 206

[G-02] <X> += <Y> COSTS MORE GAS THAN <X> = <X> + <Y> FOR STATE VARIABLES

Using the addition operator instead of plus-equals saves gas

Instances 19

-ReaperVaultV2 line 168 -ReaperVaultV2 line 194 -ReaperVaultV2 line 196 -ReaperVaultV2 line 214 -ReaperVaultV2 line 390 -ReaperVaultV2 line 391 -ReaperVaultV2 line 395 -ReaperVaultV2 line 396 -ReaperVaultV2 line 444 -ReaperVaultV2 line 445 -ReaperVaultV2 line 450 -ReaperVaultV2 line 451 -ReaperVaultV2 line 452 -ReaperVaultV2 line 505 -ReaperVaultV2 line 514 -ReaperVaultV2 line 515 -ReaperVaultV2 line 516 -ReaperVaultV2 line 520 -ReaperVaultV2 line 521

[G-03] CAN DECLARE THE VARIABLE OUTSIDE THE LOOP TO SAVE GAS

Gas is not wasted on redeclaration of the variable for every iteration.

Instances 18

-CollateralConfig line 57 -CollateralConfig line 63 -TroverManager line 610 -ActivePool line 109 -ActivePool line 110 -LQTYStaking line 207 -LQTYStaking line 208 -LQTYStaking line 229 -LQTYStaking line 242 -ReaperVaultV2 line 265 -ReaperVaultV2 line 378 -ReaperVaultV2 line 379 -ReaperVaultV2 line 384 -ReaperVaultV2 line 385 -ReaperVaultV2 line 386 -ReaperStrategyGranarySupplyOnly line 118 -ReaperStrategyGranarySupplyOnly line 120 -ReaperStrategyGranarySupplyOnly line 166

[G-04] EXPRESSIONS FOR CONSTANT VALUES SUCH AS A CALL TO KECCAK256(), SHOULD USE IMMUTABLE RATHER THAN CONSTANT

Instances 18

-ReaperStrategyGranarySupplyOnly line 25 -ReaperStrategyGranarySupplyOnly line 27 -ReaperStrategyGranarySupplyOnly line 29 -ReaperVaultV2 line 40 -ReaperVaultV2 line 73 -ReaperVaultV2 line 74 -ReaperVaultV2 line 75 -ReaperVaultV2 line 76 -TroveManager line 58 -TroveManager line 60 -CollateralConfig line 21 -CollateralConfig line 25 -ReaperBaseStrategyv4 line 24 -ReaperBaseStrategyv4 line 25 -ReaperBaseStrategyv4 line 49 -ReaperBaseStrategyv4 line 50 -ReaperBaseStrategyv4 line 51 -ReaperBaseStrategyv4 line 52

[G-05] ADD UNCHECKED {} FOR SUBTRACTIONS WHERE THE OPERANDS CANNOT UNDERFLOW BECAUSE OF A PREVIOUS REQUIRE() OR IF-STATEMENT

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.

require(a <= b); x = b - a => require(a <= b); unchecked { x = b - a }

Instances 16

-TroveManager line 494 -TroveManager line 496 -ReaperVaultV2 line 235 -ReaperVaultV2 line 244 -ReaperVaultV2 line 245 -ReaperVaultV2 line 384 -ReaperVaultV2 line 451 -ReaperVaultV2 line 526 -ReaperVaultV2 line 528 -ReaperVaultERC4626 line 82 -ReaperVaultERC4626 line 125 -ReaperBaseStrategyv4 line 121 -ReaperBaseStrategyv4 line 123 -ReaperStrategyGranarySupplyOnly line 81 -ReaperStrategyGranarySupplyOnly line 93 -ReaperStrategyGranarySupplyOnly line 100 -ReaperStrategyGranarySupplyOnly line 132

[G-06] NOT USING THE NAMED RETURN VARIABLES WHEN A FUNCTION RETURNS, WASTES DEPLOYMENT GAS

Do not use return at the end of the function

Instances 16

-ReaperStrategyGranarySupplyOnly line 104-106 -ReaperVaultERC4626 line 29-30 -ReaperVaultERC4626 line 37-38 -ReaperVaultERC4626 line 51-53 -ReaperVaultERC4626 line 66-68 -ReaperVaultERC4626 line 79-82 -ReaperVaultERC4626 line 96-97 -ReaperVaultERC4626 line 122-125 -ReaperVaultERC4626 line 165-166 -ReaperVaultERC4626 line 220-221 -ReaperVaultERC4626 line 240-241 -TroveManager line 383-437 -TroveManager line 451-605 -TroveManager line 1196-1226 -TroveManager line 1859-1862 -TroveManager line 1867-1879

[G-07] REQUIRE() OR REVERT() STATEMENTS SHOULD BE USED SORTED FROM CHEAPEST TO MOST EXPENSIVE

Checks that involve constants should come before checks that involve state variables, function calls, and calculations. By doing these checks first, the function is able to revert before wasting a Gcoldsload (2100 gas*) in a function that may ultimately revert in the unhappy case.

Instances 13

In instances given below you need either to swap 2 lines or split 1 require (left statement and right statement relative to &&) into 2 require statements and put them in sorted order in order to save gas

-CollateralConfig line 51-54 -BorrowerOperations line 653 -TroveManager line 1279 -TroveManager line 1342 -TroveManager line 1539 -SortedTroves line 111-115 -SortedTroves line 214-216 -LUSDToken line 347 -LUSDToken line 352 -ReaperVaultV2 line 150-156 -ReaperVaultV2 line 180-181 -ReaperVaultV2 line 321-322 -ReaperBaseStrategyv4 line 96-98

[G-08] BEFORE SOME FUNCTIONS, WE SHOULD CHECK SOME VARIABLES FOR POSSIBLE GAS SAVE

Before transfer, we should check for amount being 0 so the function doesn't run when it's not going to do anything

Instances 13

-ActivePool line 186 -ActivePool line 210 -BorrowerOperations line 231 -CommunityIssuance line 127 -LQTYStaking line 171 -LUSDToken line 198 -LUSDToken line 203 -LUSDToken line 222 -LUSDToken line 237 -LUSDToken line 238 -LUSDToken line 410 -LUSDToken line 526 -LUSDToken line 528

[G-09] OPTIMIZE NAMES TO SAVE GAS

public/external function names and public member variable names can be optimized to save gas. See this link for an example of how it works. Below are the interfaces/abstract contracts that can be optimized so that the most frequently-called functions use the least amount of gas possible during method lookup. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted.

Instances 12

-IActivePool line 8 -IBorrowerOperations line 6 -ICollateralConfig line 5 -ICommunityIssuance line 5 -ILQTYStaking line 5 -ILUSDToken line 8 -ISortedTroves line 6 -ITroveManager line 14 -ReaperVaultV2 line 21 -ReaperVaultERC4626 line 12 -ReaperBaseStrategyv4 line 14 -ReaperStrategyGranarySupplyOnly line 19

[G-10] USE A MORE RECENT VERSION OF SOLIDITY

Use a Solidity version of at least 0.8.2 to get simple compiler automatic inlining.

Use a Solidity version of at least 0.8.3 to get better struct packing and cheaper multiple storage reads.

Use a Solidity version of at least 0.8.10 to have external calls skip contract existence checks if the external call has a return value.

Instances 12

-ActivePool line 3 -BorrowerOperations line 3 -CollateralConfig line 3 -CommunityIssuance line 3 -LQTYStaking line 3 -LUSDToken line 3 -SortedTroves line 3 -TroveManager line 3 -ReaperVaultV2 line 3 -ReaperVaultERC4626 line 3 -ReaperBaseStrategyv4 line 3 -ReaperStrategyGranarySupplyOnly line 3

[G-11] MULTIPLE ADDRESS/ID MAPPINGS CAN BE COMBINED INTO A SINGLE MAPPING OF AN ADDRESS/ID TO A STRUCT, WHERE APPROPRIATE

Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Finally, if both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key’s keccak256 hash (Gkeccak256 - 30 gas) and that calculation’s associated stack operations.

Instances 6

-TroverManager line 94-91 -TroverManager line 104-105 -TroverManager line 119-120 -ActivePool line 44-45 -LQTYStaking line 25, 28, 32 -LUSDToken line 62-64

[G-12] STACK VARIABLE USED AS A CHEAPER CACHE FOR A STATE VARIABLE IS ONLY USED ONCE

Instances 6

-TroveManager line 1557 -TroveManager line 1570 -TroveManager line 1602 -TroveManager line 1694 -CommunityIssuance line 107 -LQTYStaking line 219

[G-13] PUBLIC FUNCTIONS NOT CALLED BY THE CONTRACT SHOULD BE DECLARED EXTERNAL INSTEAD

The following functions could be set external to save gas and improve code quality. External call cost is less expensive than public functions.

Instances 4

-ReaperStrategyGranarySupplyOnly line 62 -ReaperVaultV2 line 295 -TroverManager line 1045 -TroverManager line 1440

[G-14] PACK MULTIPLE VARIABLES INTO FEWER SLOTS

If the sum of the sizes of several variables is less than or equal to 32 bytes they can be packed in one storage slot. To pack them you need to place them next to each other.

Move closer the lines indicated for each contract

Instances 2

-ReaperBaseStrategyv4 line 28<->58 -ReaperVaultV2 line 49<->78

[G-15] USAGE OF UINTS/INTS SMALLER THAN 32 BYTES (256 BITS) INCURS OVERHEAD

When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.

link

Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed.

Instances 1

-TroveManager line 87

[G-16] SHOULD USE ARGUMENTS INSTEAD OF STATE VARIABLE

This will save about 97 gas

Instances 1

-ReaperVaultV2 line 581

[G-17] SUPERFLUOUS EVENT FIELDS

block.number and block.timestamp are added to the event information by default, so adding them manually will waste additional gas.

Instances 1

-TroveManager line 2126

#0 - c4-judge

2023-03-09T12:48:12Z

trust1995 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