Platform: Code4rena
Start Date: 07/07/2023
Pot Size: $121,650 USDC
Total HM: 36
Participants: 111
Period: 7 days
Judge: Picodes
Total Solo HM: 13
Id: 258
League: ETH
Rank: 77/111
Findings: 1
Award: $24.30
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: c3phas
Also found by: 0x11singh99, 0xAnah, 0xn006e7, LeoS, Rageur, Raihan, ReyAdmirado, Rolezn, SAAJ, SAQ, SM3_SS, Udsen, alymurtazamemon, hunter_w3b, koxuan, naman1778, petrichor, ybansal2403
24.2984 USDC - $24.30
Some files were imported and were not used these files costs gas during deployment and generally this is bad coding practice
In the file below E
was imported with the statement import { SD59x18, toSD59x18, E } from "prb-math/SD59x18.sol";
but was not used you should consider removing it from the imports.
In the file below wadMul
, toWadUnsafe
and unsafeWadDiv
were imported with the statement import { wadExp, wadLn, wadMul, unsafeWadMul, toWadUnsafe, unsafeWadDiv, wadDiv } from "solmate/utils/SignedWadMath.sol";
but were not used you should consider removing it from the imports.
In the file below fromUD60x18
was imported with the statement import { UD60x18, toUD60x18, fromUD60x18 } from "prb-math/UD60x18.sol";
but were not used you should consider removing it from the imports.
In the file below uMAX_UD60x18
was imported with the statement import { UD60x18, uMAX_UD60x18 } from "prb-math/UD60x18.sol";
but were not used you should consider removing it from the imports.
In the file below E
, toSD59x18
and fromSD59x18
were imported with the statement import { E, SD59x18, sd, toSD59x18, fromSD59x18 } from "prb-math/SD59x18.sol";
but were not used you should consider removing it from the imports.
In the file below UD60x18
and ud
were imported with the statement import { UD60x18, ud, toUD60x18, fromUD60x18, intoSD59x18 } from "prb-math/UD60x18.sol";
but were not used you should consider removing it from the imports.
In the file below toUD34x4
was imported with the statement import { UD34x4, fromUD60x18 as fromUD60x18toUD34x4, intoUD60x18 as fromUD34x4toUD60x18, toUD34x4 } from "./libraries/UD34x4.sol";
but were not used you should consider removing it from the imports.
In the file below LiquidationPair
was imported with the statement import { LiquidationPair } from "v5-liquidator/LiquidationPair.sol";
but were not used you should consider removing it from the imports.
In the file below E
, toSD59x18
and fromSD59x18
were imported with the statement import { E, SD59x18, sd, toSD59x18, fromSD59x18 } from "prb-math/SD59x18.sol";
but were not used you should consider removing it from the imports.
In the file below intoSD59x18
was imported with the statement import { UD60x18, ud, toUD60x18, fromUD60x18, intoSD59x18 } from "prb-math/UD60x18.sol";
but were not used you should consider removing it from the imports.
In the file below UD2x18
and intoUD60x18
were imported with the statement import { UD2x18, intoUD60x18 } from "prb-math/UD2x18.sol";
but were not used you should consider removing it from the imports.
https://github.com/GenerationSoftware/pt-v5-prize-pool/blob/4bc8a12b857856828c018510b5500d722b79ca3a/src/abstract/TieredLiquidityDistributor.sol#L7
In the file below SD1x18
and UNIT
were imported with the statement import { SD1x18, unwrap, UNIT } from "prb-math/SD1x18.sol";
but were not used you should consider removing it from the imports.
When constants and immutable are marked public, extra getter functions are created, increasing the deployment cost. Marking these functions private will decrease gas cost. One can still read these variables through the source code. If they need to be accessed by an external contract, a separate single getter function can be used to return all constants as a tuple.
/// @notice The Prize Pool that this Claimer is claiming prizes for PrizePool public immutable prizePool; /// @notice The maximum fee that can be charged as a portion of the smallest prize size. Fixed point 18 number UD2x18 public immutable maxFeePortionOfPrize; /// @notice The VRGDA decay constant computed in the constructor SD59x18 public immutable decayConstant; /// @notice The minimum fee that will be charged uint256 public immutable minimumFee; uint256 public immutable timeToReachMaxFee;
The code above should be refactored to:
/// @notice The Prize Pool that this Claimer is claiming prizes for PrizePool private immutable prizePool; /// @notice The maximum fee that can be charged as a portion of the smallest prize size. Fixed point 18 number UD2x18 private immutable maxFeePortionOfPrize; /// @notice The VRGDA decay constant computed in the constructor SD59x18 private immutable decayConstant; /// @notice The minimum fee that will be charged uint256 private immutable minimumFee; uint256 private immutable timeToReachMaxFee; function getConstants() public view returns ( PrizePool, UD2x18, SD59x18, uint256, uint256 ) { return ( prizePool, maxFeePortionOfPrize, decayConstant, minimumFee, timeToReachMaxFee ) }
SD1x18 public immutable smoothing; /// @notice The token that is being contributed and awarded as prizes. IERC20 public immutable prizeToken; /// @notice The Twab Controller to use to retrieve historic balances. TwabController public immutable twabController; /// @notice The draw manager address. address public drawManager; /// @notice The number of seconds between draws. uint32 public immutable drawPeriodSeconds; /// @notice Percentage of prizes that must be claimed to bump the number of tiers. UD2x18 public immutable claimExpansionThreshold;
The code above should be refactored to:
SD1x18 private immutable smoothing; /// @notice The token that is being contributed and awarded as prizes. IERC20 private immutable prizeToken; /// @notice The Twab Controller to use to retrieve historic balances. TwabController private immutable twabController; /// @notice The number of seconds between draws. uint32 private immutable drawPeriodSeconds; /// @notice Percentage of prizes that must be claimed to bump the number of tiers. UD2x18 private immutable claimExpansionThreshold; function getConstants() public view returns ( SD1x18, IERC20, TwabController, uint32, UD2x18 ) { return ( smoothing, prizeToken, twabController, drawPeriodSeconds, claimExpansionThreshold ) }
/// @notice Allows users to revoke their chances to win by delegating to the sponsorship address. address public constant SPONSORSHIP_ADDRESS = address(1); /// @notice Sets the minimum period length for Observations. When a period elapses, a new Observation is recorded, otherwise the most recent Observation is updated. uint32 public immutable PERIOD_LENGTH; /// @notice Sets the beginning timestamp for the first period. This allows us to maximize storage as well as line up periods with a chosen timestamp. /// @dev Ensure that the PERIOD_OFFSET is in the past. uint32 public immutable PERIOD_OFFSET;
the above code should be refactored to:
/// @notice Allows users to revoke their chances to win by delegating to the sponsorship address. address private constant SPONSORSHIP_ADDRESS = address(1); /// @notice Sets the minimum period length for Observations. When a period elapses, a new Observation is recorded, otherwise the most recent Observation is updated. uint32 priavte immutable PERIOD_LENGTH; /// @notice Sets the beginning timestamp for the first period. This allows us to maximize storage as well as line up periods with a chosen timestamp. /// @dev Ensure that the PERIOD_OFFSET is in the past. uint32 private immutable PERIOD_OFFSET; function getConstants() public view returns ( address, uint32, uint32 ) { return (SPONSORSHIP_ADDRESS, PERIOD_LENGTH, PERIOD_OFFSET) }
Some varibles were defined even though they are used once. Not defining variables can reduce gas cost and contract size.
function setYieldFeeRecipient(address yieldFeeRecipient_) external onlyOwner returns (address) { address _previousYieldFeeRecipient = _yieldFeeRecipient; _setYieldFeeRecipient(yieldFeeRecipient_); emit YieldFeeRecipientSet(_previousYieldFeeRecipient, yieldFeeRecipient_); return yieldFeeRecipient_; }
In the above code _previousYieldFeeRecipient
variable is unnecessary we could save gas cost for MLOAD
and MSTORE
operations if we refactor the code to:
function setYieldFeeRecipient(address yieldFeeRecipient_) external onlyOwner returns (address) { emit YieldFeeRecipientSet(_yieldFeeRecipient, yieldFeeRecipient_); _setYieldFeeRecipient(yieldFeeRecipient_); return yieldFeeRecipient_; }
function setYieldFeePercentage(uint256 yieldFeePercentage_) external onlyOwner returns (uint256) { uint256 _previousYieldFeePercentage = _yieldFeePercentage; _setYieldFeePercentage(yieldFeePercentage_); emit YieldFeePercentageSet(_previousYieldFeePercentage, yieldFeePercentage_); return yieldFeePercentage_; }
In the above code _previousYieldFeePercentage
variable is unnecessary we could save gas cost for MLOAD
and MSTORE
operations if we refactor the code to:
function setYieldFeePercentage(uint256 yieldFeePercentage_) external onlyOwner returns (uint256) { emit YieldFeePercentageSet(_yieldFeePercentage, yieldFeePercentage_); _setYieldFeePercentage(yieldFeePercentage_); return yieldFeePercentage_; }
function setClaimer(address claimer_) external onlyOwner returns (address) { address _previousClaimer = _claimer; _setClaimer(claimer_); emit ClaimerSet(_previousClaimer, claimer_); return claimer_; }
In the above code _previousClaimer
variable is unnecessary we could save gas cost for MLOAD
and MSTORE
operations if we refactor the code to:
function setClaimer(address claimer_) external onlyOwner returns (address) { emit ClaimerSet(_claimer, claimer_); _setClaimer(claimer_); return claimer_; }
#0 - c4-judge
2023-07-18T18:53:31Z
Picodes marked the issue as grade-b
#1 - PierrickGT
2023-09-09T00:25:11Z
G-01: has been fixed G-02: these variables need to be public and since this contract needs to be compiled with via-ir, we can't add public functions to access the private variables G-03: fixed in the following PR: https://github.com/GenerationSoftware/pt-v5-vault/pull/45