Platform: Code4rena
Start Date: 14/09/2022
Pot Size: $50,000 USDC
Total HM: 25
Participants: 110
Period: 5 days
Judge: hickuphh3
Total Solo HM: 9
Id: 162
League: ETH
Rank: 103/110
Findings: 1
Award: $16.18
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: pfapostol
Also found by: 0x040, 0x1f8b, 0x4non, 0xNazgul, 0xSmartContract, 0xc0ffEE, 0xkatana, Aymen0909, Bnke0x0, Deivitto, Diana, JAGADESH, KIntern_NA, Lambda, MiloTruck, R2, RaymondFam, Respx, ReyAdmirado, Rohan16, RoiEvenHaim, Rolezn, Ruhum, Saintcode_, Samatak, Sm4rty, SnowMan, Tomio, Tomo, WilliamAmbrozic, _Adam, __141345__, ajtra, ak1, async, c3phas, ch0bu, cryptostellar5, d3e4, delfin454000, dharma09, djxploit, durianSausage, eierina, erictee, fatherOfBlocks, gianganhnguyen, gogo, ignacio, imare, jag, jonatascm, leosathya, lukris02, malinariy, oyc_109, pashov, pauliax, peanuts, peiw, prasantgupta52, robee, rokinot, rotcivegaf, rvierdiiev, seyni, simon135, slowmoses, sryysryy, tnevler, zishansami
16.1756 USDC - $16.18
++I
COSTS LESS GAS THAN I++
, ESPECIALLY WHEN IT’S USED IN FOR
-LOOPS (--I
/I--
TOO)Saves 6 gas PER LOOP
There is 1 instance of this issue:
File: Vault.sol 443: for (uint256 i = 0; i < epochsLength(); i++) {
<ARRAY>.LENGTH
SHOULD NOT BE LOOKED UP IN EVERY LOOP OF A FOR
LOOPThe overheads outlined below are PER LOOP, excluding the first loop
MLOAD
(3 gas)CALLDATALOAD
(3 gas)Caching the length changes each of these to a DUP<N>
(3 gas), and gets rid of the extra DUP<N>
needed to store the stack offset.
There is 1 instance of this issue:
File: Vault.sol 443: for (uint256 i = 0; i < epochsLength(); i++) {
With epochsLength()
defined as follow :
File: Vault.sol 430: function epochsLength() public view returns (uint256) { return epochs.length; }
SAFEMATH
ONCE THE SOLIDITY VERSION IS 0.8.0 OR GREATERVersion 0.8.0 introduces internal overflow checks, so using SafeMath
is redundant and adds overhead
There is 1 instance of this issue:
File: rewards/StakingRewards.sol 5: import {SafeTransferLib} from "@solmate/utils/SafeTransferLib.sol";
PRIVATE
RATHER THAN PUBLIC
FOR CONSTANTS, SAVES GASIf needed, the value can be read from the verified contract source code. Savings are due to the compiler not having to create non-payable getter functions for deployment calldata, and not adding another entry to the method ID table.
There is 2 instances of this issue:
File: Controller.sol 16: uint256 public constant VAULTS_LENGTH = 2;
File: SemiFungibleVault.sol 22: bytes internal constant EMPTY = "";
immutable
Avoids a Gsset (20000 gas) in the constructor, and replaces each Gwarmacces (100 gas) with a PUSH32
(3 gas).
File: oracles/PegOracle.sol 10: address public oracle1; 11: address public oracle2; 13: uint8 public decimals;
File: SemiFungibleVault.sol 20: string public name; 21: string public symbol;
File: rewards/RewardsFactory.sol 9: address public admin; 10: address public govToken; 11: address public factory;
PUBLIC
FUNCTIONS NOT CALLED BY THE CONTRACT SHOULD BE DECLARED EXTERNAL
INSTEADContracts are allowed to override their parents’ functions and change the visibility from external
to public
and can save gas by doing so.
There is 25 instances of this issue:
File: Controller.sol 148: function triggerDepeg(uint256 marketIndex, uint256 epochEnd) public isDisaster(marketIndex, epochEnd) { 198: function triggerEndEpoch(uint256 marketIndex, uint256 epochEnd) public {
File: oracles/PegOracle.sol 89: function getOracle1_Price() public view returns (int256 price) {
File: src/SemiFungibleVault.sol 85: function deposit( uint256 id, uint256 assets, address receiver ) public virtual returns (uint256 shares) { 110: function withdraw( uint256 id, uint256 assets, address receiver, address owner ) external virtual returns (uint256 shares) { 189: function previewMint(uint256 id, uint256 shares) public view virtual returns (uint256) { 221: function previewRedeem(uint256 id, uint256 shares) public view virtual returns (uint256) { 237: function maxDeposit(address) public view virtual returns (uint256) { 244: function maxMint(address) public view virtual returns (uint256) { 251: function maxWithdraw(uint256 id, address owner) public view virtual returns (uint256) { 263: function maxRedeem(uint256 id, address owner) public view virtual returns (uint256) {
File: Vault.sol 277: function changeTreasury(address _treasury) public onlyFactory { 287: function changeTimewindow(uint256 _timewindow) public onlyFactory { 295: function changeController(address _controller) public onlyFactory { 307: function createAssets(uint256 epochBegin, uint256 epochEnd, uint256 _withdrawalFee) public onlyFactory { 336: function endEpoch(uint256 id, bool depeg) public onlyController marketExists(id) { 350: function setClaimTVL(uint256 id, uint256 claimTVL) public onlyController { 360: function sendTokens(uint256 id, address _counterparty) public onlyController marketExists(id) { 438: function getNextEpoch(uint256 _epoch) public view returns (uint256 nextEpochEnd) {
File: VaultFactory.sol 178: function createNewMarket( uint256 _withdrawalFee, address _token, int256 _strikePrice, uint256 epochBegin, uint256 epochEnd, address _oracle, string memory _name ) public onlyAdmin returns (address insr, address rsk) { 248: function deployMoreAssets( uint256 index, uint256 epochBegin, uint256 epochEnd, uint256 _withdrawalFee ) public onlyAdmin { 295: function setController(address _controller) public onlyAdmin { 366: function changeOracle(address _token, address _oracle) public onlyAdmin { 385: function getVaults(uint256 index) public view returns (address[] memory vaults) {
File rewards/RewardsFactory.sol 145: function getHashedIndex(uint256 _index, uint256 _epoch) public pure returns (bytes32 hashedIndex) {
#0 - HickupHH3
2022-11-08T09:07:50Z
**State variables only set in the constructor should be declared immutable
Tested with only PegOracle, saved about 30k gas for 3 immutables => about 10k per variable, but this gas saving is only the deployment costs.