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: 101/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
Uninitialized variables are assigned with the types default value. Explicitly initializing a variable with it's default value costs unnecesary gas. Not overwriting the default for stack variables saves 8 gas. Storage and memory variables have larger savings
Delete useless variable declarations to save gas.
2022-09-y2k-finance/blob/main/src/Vault.sol#L443
for (uint256 i = 0; i < epochsLength(); i++) {
Use != 0 when comparing uint variables to zero, which cannot hold values below zero
You should change from > 0
to !=0
.
2022-09-y2k-finance/blob/main/src/Vault.sol#L187
require(msg.value > 0, "ZeroValue");
2022-09-y2k-finance/blob/main/src/oracles/PegOracle.sol#L98
require(price1 > 0, "Chainlink price <= 0");
2022-09-y2k-finance/blob/main/src/oracles/PegOracle.sol#L121
require(price2 > 0, "Chainlink price <= 0");
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L119
require(amount > 0, "Cannot withdraw 0");
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L134
if (reward > 0) {
Shortening revert strings to fit in 32 bytes will decrease gas costs for deployment and gas costs when the revert condition has been met.
Use short statements instead of long statement.
2022-09-y2k-finance/blob/main/src/SemiFungibleVault.sol#L118
"Only owner can withdraw, or owner has approved receiver for all"
2022-09-y2k-finance/blob/main/src/oracles/PegOracle.sol#L23
require(_oracle1 != address(0), "oracle1 cannot be the zero address");
2022-09-y2k-finance/blob/main/src/oracles/PegOracle.sol#L24
require(_oracle2 != address(0), "oracle2 cannot be the zero address");
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L8
} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L16
} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L219
"Cannot withdraw the staking token"
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L228
"Previous rewards period must be complete before changing the duration for the new period"
See this issue You can save about 5000 gas per instance in deploying contracrt. You can save about 80 gas per instance if using assembly to execute the function.
Please follow this link to make corrections
2022-09-y2k-finance/blob/main/src/Controller.sol#L179
keccak256(
2022-09-y2k-finance/blob/main/src/Controller.sol#L235
keccak256(
2022-09-y2k-finance/blob/main/src/Vault.sol#L388
keccak256(abi.encodePacked(symbol)) ==
2022-09-y2k-finance/blob/main/src/Vault.sol#L389
keccak256(abi.encodePacked("rY2K"))
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L278
keccak256(abi.encodePacked(_marketVault.index, _marketVault.epochBegin, _marketVault.epochEnd)),
2022-09-y2k-finance/blob/main/src/rewards/RewardsFactory.sol#L118
bytes32 hashedIndex = keccak256(abi.encode(_marketIndex, _epochEnd));
2022-09-y2k-finance/blob/main/src/rewards/RewardsFactory.sol#L125
keccak256(
2022-09-y2k-finance/blob/main/src/rewards/RewardsFactory.sol#L150
return keccak256(abi.encode(_index, _epoch));
Version 0.8.0~, it can calculate as a SafeMath
without using it.
Delete the import to save gas.
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L4
import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol";
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L29
using SafeMath for uint256;
See this issue
If a function modifier such as onlyOwner
is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are CALLVALUE(2),DUP1(3),ISZERO(3),PUSH2(3),JUMPI(10),PUSH1(3),DUP1(3),REVERT(0),JUMPDEST(1),POP(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost
Saves 2400 gas per instance in deploying contracrt.
Saves about 20 gas per instance if using assembly to executing the function.
You should add the keyword payable
to those functions.
2022-09-y2k-finance/blob/main/src/Vault.sol#L277
function changeTreasury(address _treasury) public onlyFactory {
2022-09-y2k-finance/blob/main/src/Vault.sol#L287
function changeTimewindow(uint256 _timewindow) public onlyFactory {
2022-09-y2k-finance/blob/main/src/Vault.sol#L295
function changeController(address _controller) public onlyFactory {
2022-09-y2k-finance/blob/main/src/Vault.sol#L309
onlyFactory
2022-09-y2k-finance/blob/main/src/Vault.sol#L338
onlyController
2022-09-y2k-finance/blob/main/src/Vault.sol#L350
function setClaimTVL(uint256 id, uint256 claimTVL) public onlyController {
2022-09-y2k-finance/blob/main/src/Vault.sol#L362
onlyController
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L186
) public onlyAdmin returns (address insr, address rsk) {
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L253
) public onlyAdmin {
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L295
function setController(address _controller) public onlyAdmin {
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L310
onlyAdmin
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L329
onlyAdmin
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L347
onlyAdmin
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L366
function changeOracle(address _token, address _oracle) public onlyAdmin {
2022-09-y2k-finance/blob/main/src/rewards/RewardsFactory.sol#L85
onlyAdmin
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L186
onlyRewardsDistribution
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L215
onlyOwner
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L225
function setRewardsDuration(uint256 _rewardsDuration) external onlyOwner {
++i
instead of i++
You can get cheaper for loops (at least 25 gas, however can be up to 80 gas under certain conditions), by rewriting The post-increment operation (i++) boils down to saving the original value of i, incrementing it and saving that to a temporary place in memory, and then returning the original value; only after that value is returned is the value of i actually updated (4 operations).On the other hand, in pre-increment doesn't need to store temporary(2 operations) so, the pre-increment operation uses less opcodes and is thus more gas efficient.
You should change from i++ to ++i.
2022-09-y2k-finance/blob/main/src/Vault.sol#L443
for (uint256 i = 0; i < epochsLength(); i++) {
You can save about 35 gas per instance if you change from x+=y**
** to x=x+y
This works equally well for subtraction, multiplication and division.
You should change from x+=y
to x=x+y
.
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L195
marketIndex += 1;
indexed
for uint, bool, and addressUsing the indexed keyword for value types such as uint, bool, and address saves gas costs, as seen in the example below. However, this is only the case for value types, whereas indexing bytes and strings are more expensive than their unindexed version. Also indexed keyword has more merits. It can be useful to have a way to monitor the contract's activity after it was deployed. One way to accomplish this is to look at all transactions of the contract, however that may be insufficient, as message calls between contracts are not recorded in the blockchain. Moreover, it shows only the input parameters, not the actual changes being made to the state. Also events could be used to trigger functions in the user interface.
Up to three indexed
can be used per event and should be added.
2022-09-y2k-finance/blob/main/src/Controller.sol#L49
event DepegInsurance(
2022-09-y2k-finance/blob/main/src/SemiFungibleVault.sol#L35
event Deposit(
2022-09-y2k-finance/blob/main/src/SemiFungibleVault.sol#L51
event Withdraw(
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L49
event MarketCreated(
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L69
event EpochCreated(
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L85
event controllerSet(address indexed newController);
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L91
event changedTreasury(address _treasury, uint256 indexed _marketIndex);
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L97
event changedVaultFee(uint256 indexed _marketIndex, uint256 _feeRate);
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L103
event changedTimeWindow(uint256 indexed _marketIndex, uint256 _timeWindow);
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L109
event changedController(
2022-09-y2k-finance/blob/main/src/VaultFactory.sol#L113
event changedOracle(address indexed _token, address _oracle);
2022-09-y2k-finance/blob/main/src/rewards/RewardsFactory.sol#L39
event CreatedStakingReward(
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L51
event RewardAdded(uint256 reward);
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L52
event Staked(address indexed user, uint256 id, uint256 amount);
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L53
event Withdrawn(address indexed user, uint256 id, uint256 amount);
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L54
event RewardPaid(address indexed user, uint256 reward);
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L55
event RewardsDurationUpdated(uint256 newDuration);
2022-09-y2k-finance/blob/main/src/rewards/StakingRewards.sol#L56
event Recovered(address token, uint256 amount);