Platform: Code4rena
Start Date: 22/09/2022
Pot Size: $30,000 USDC
Total HM: 12
Participants: 133
Period: 3 days
Judge: 0xean
Total Solo HM: 2
Id: 165
League: ETH
Rank: 53/133
Findings: 2
Award: $48.01
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: ladboy233
Also found by: 0xSmartContract, 8olidity, Aymen0909, Chom, IllIllI, OptimismSec, PaludoX0, TomJ, ayeslick, cccz, csanuragjain, joestakey, neko_nyaa, pashov, peritoflores, rbserver, rvierdiiev
19.982 USDC - $19.98
https://github.com/code-423n4/2022-09-frax/blob/main/src/frxETHMinter.sol#L191
Normally Admin should only be allowed to transfer upto currentWithheldETH to himself. But using recoverEther function, Admin can transfer all Ether (which were meant for validators) to himself
function recoverEther(uint256 amount) external onlyByOwnGov { (bool success,) = address(owner).call{ value: amount }(""); require(success, "Invalid transfer"); emit EmergencyEtherRecovered(amount); }
Remove this function if not required
#0 - FortisFortuna
2022-09-25T21:23:09Z
We are well aware of the permission structure. The owner will most likely be a large multisig. We mentioned the Frax Multisig in the scope too. If moving funds, it is assumed someone in the multisig would catch an invalid or malicious address.
#1 - joestakey
2022-09-26T15:04:26Z
Duplicate of #107
🌟 Selected for report: rotcivegaf
Also found by: 0x040, 0x1f8b, 0x4non, 0xNazgul, 0xSmartContract, 0xf15ers, 8olidity, Aymen0909, B2, Bahurum, Bnke0x0, Ch_301, CodingNameKiki, Deivitto, Diana, Funen, IllIllI, JC, JLevick, KIntern_NA, Lambda, OptimismSec, PaludoX0, RockingMiles, Rolezn, Sm4rty, Soosh, Tagir2003, Tointer, TomJ, Triangle, Trust, V_B, Waze, Yiko, __141345__, a12jmx, ajtra, asutorufos, ayeslick, aysha, bbuddha, bharg4v, bobirichman, brgltd, bytera, c3phas, cryptostellar5, cryptphi, csanuragjain, datapunk, delfin454000, durianSausage, exd0tpy, gogo, got_targ, jag, joestakey, karanctf, ladboy233, leosathya, lukris02, mics, millersplanet, natzuu, neko_nyaa, obront, oyc_109, parashar, peritoflores, rbserver, ret2basic, rokinot, ronnyx2017, rvierdiiev, sach1r0, seyni, sikorico, slowmoses, tnevler, yasir, yongskiws
28.0275 USDC - $28.03
In constructor of xERC4626.sol, there is no check to validate if rewardsCycleLength<= block.timestamp.safeCastTo32(). This can cause the full reward distribution to fail since rewardsCycleEnd will become 0 in this case
rewardsCycleEnd = (block.timestamp.safeCastTo32() / rewardsCycleLength) * rewardsCycleLength;
rewardsCycleEnd= (1663949858/2000000000)*2000000000 = 0*2000000000=0
uint32 end = ((timestamp + rewardsCycleLength) / rewardsCycleLength) * rewardsCycleLength; // Since rewardsCycleLength is 0 so this fails as division by zero
In constructor add a new check like below
require(rewardsCycleLength<= block.timestamp.safeCastTo32(), "Invalid reward cycle");
#0 - FortisFortuna
2022-09-26T01:46:32Z
2000000000 seconds is like 63 years. Not going to happen in a real life scenario.
#1 - csanuragjain
2022-09-26T06:32:14Z
@FortisFortuna 2000000000 seconds is just an example (probably a bad example). Any value above block.timestamp.safeCastTo32() will cause rewardsCycleEnd to be 0
#2 - FortisFortuna
2022-09-26T22:55:37Z
Current block.timestamp is like what, 53+ years since the epoch. The reward period is going to be nowhere close to that
#3 - 0xean
2022-10-12T14:26:33Z
This really comes down to input sanitization and the wardens suggestion protects against only a really extreme edge case. Downgrading to QA