Platform: Code4rena
Start Date: 27/04/2023
Pot Size: $90,500 USDC
Total HM: 4
Participants: 43
Period: 7 days
Judge: GalloDaSballo
Id: 233
League: ETH
Rank: 32/43
Findings: 2
Award: $161.62
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: volodya
Also found by: 0xWaitress, 0xnev, ABA, Aymen0909, Cyfrin, QiuhaoLi, RaymondFam, btk, bughunter007, ihtishamsudo, juancito, libratus, niser93, sashik_eth
71.6048 USDC - $71.60
deposit()
does not emit an event, So it is difficult to track changes in the value of totalShares
offchainfunction deposit(IERC20 token, uint256 amount) external virtual override onlyWhenNotPaused(PAUSED_DEPOSITS) onlyStrategyManager returns (uint256 newShares) { require(token == underlyingToken, "StrategyBase.deposit: Can only deposit underlyingToken"); /** * @notice calculation of newShares *mirrors* `underlyingToShares(amount)`, but is different since the balance of `underlyingToken` * has already been increased due to the `strategyManager` transferring tokens to this strategy prior to calling this function */ if (totalShares == 0) { newShares = amount; } else { uint256 priorTokenBalance = _tokenBalance() - amount; if (priorTokenBalance == 0) { newShares = amount; } else { newShares = (amount * totalShares) / priorTokenBalance; } } // checks to ensure correctness / avoid edge case where share rate can be massively inflated as a 'griefing' sort of attack require(newShares != 0, "StrategyBase.deposit: newShares cannot be zero"); uint256 updatedTotalShares = totalShares + newShares; require(updatedTotalShares >= MIN_NONZERO_TOTAL_SHARES, "StrategyBase.deposit: updated totalShares amount would be nonzero but below MIN_NONZERO_TOTAL_SHARES"); // update total share amount totalShares = updatedTotalShares; return newShares; }
Emit events to notify about updated total shares.
L110:totalShares = updatedTotalShares; //Should be updated with the emit emit TotalSharesUpdated(totalShares);
Emit The Event outside the deposit()
event TotalSharesUpdated(uint256 totalShares);
withdraw()
at #L142computePhase0BeaconBlockHeaderRoot()
is never used and should be removedfunction computePhase0BeaconBlockHeaderRoot(bytes32[NUM_BEACON_BLOCK_HEADER_FIELDS] calldata blockHeaderFields) internal pure returns(bytes32) { bytes32[] memory paddedHeaderFields = new bytes32[](2**BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT); for (uint256 i = 0; i < NUM_BEACON_BLOCK_HEADER_FIELDS; ++i) { paddedHeaderFields[i] = blockHeaderFields[i]; } return Merkle.merkleizeSha256(paddedHeaderFields); }
computePhase0BeaconBlockHeaderRoot()
Should be removed to reduce code & to not make a code's review difficultBeaconChainProofs.sol#L130-138
computePhase0BeaconStateRoot()
Is Never Used & Should Be RemovedBeaconChainProofs.sol#L140-148
computePhase0ValidatorRoot()
Is Never Used & Should Be RemovedBeaconChainProofs.sol#L150-158
computePhase0Eth1DataRoot()
Is Never Used & Should Be Removed#0 - c4-judge
2023-06-02T09:38:51Z
GalloDaSballo marked the issue as grade-b
🌟 Selected for report: neutiyoo
Also found by: 0xSmartContract, 0xnev, Aymen0909, QiuhaoLi, ReyAdmirado, clayj, ihtishamsudo, naman1778, niser93, pontifex, tonisives, turvy_fuzz
90.0161 USDC - $90.02
sharesToUnderlyingView()
the function that may result in saving gasfunction sharesToUnderlyingView(uint256 amountShares) public view virtual override returns (uint256) { if (totalShares == 0) { return amountShares; } else { return (_tokenBalance() * amountShares) / totalShares; } }
function sharesToUnderlyingView(uint256 amountShares) public view virtual override returns (uint256) { if (totalShares == 0) { return amountShares; } uint256 tokenBalance = _tokenBalance(); // Check for edge case where amountShares is equal to totalShares if (amountShares == totalShares) { return tokenBalance; } uint256 underlyingAmount = tokenBalance * amountShares; // The division can be moved outside the else block to save gas when totalShares is not equal to zero return underlyingAmount / totalShares; }
Declared a tokenBalance variable to store the _tokenBalance()
value once, instead of calling the function twice.
Added a check for an edge case where amountShares
is equal to totalShares
, which avoids performing a multiplication and division that would return the same value.
Moved the division operation outside the else block to avoid performing unnecessary calculations when totalShares is equal to zero.
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
import { IERC20 as ERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
StrategyBase.sol#L6-8 StrategyManager.sol#L4-10 EigenPodManager.sol#L4-9 EigenPod.sol#L4-7 DelayedWithdrawalRouter.sol#L4-6
#0 - GalloDaSballo
2023-06-01T16:53:07Z
1R for first finding
#1 - c4-judge
2023-06-01T16:59:06Z
GalloDaSballo marked the issue as grade-b