Platform: Code4rena
Start Date: 10/05/2022
Pot Size: $50,000 USDC
Total HM: 13
Participants: 100
Period: 5 days
Judge: HardlyDifficult
Total Solo HM: 1
Id: 122
League: ETH
Rank: 77/100
Findings: 2
Award: $50.21
🌟 Selected for report: 0
🚀 Solo Findings: 0
16.9712 USDC - $16.97
https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L119-L121 https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L289
Owner setting fee rate above 1e18 will dos any exercise() calls.
uint256 fee = 0; if (feeRate > 0) { fee = (msg.value * feeRate) / 1e18; protocolUnclaimedFees += fee; } // increment vault beneficiary's ETH balance ethBalance[getVaultBeneficiary(vaultId)] += msg.value - fee;
if feeRate is set to higher than 1e18, fee will be greater than msg.value. This will result in underflow on line 289 and any call to exercise will revert. This will result in a permanent loss of option premiums with no option to exercise if the feeRate stays above 1e18. Assumes a malicious owner.
Add a cap to feeRate
function setFee(uint256 feeRate_) external onlyOwner { require(feeRate_ <= 1e18, "Invalid Fee Rate"); feeRate = feeRate_; }
#0 - outdoteth
2022-05-15T18:56:05Z
owner can change fee at any time; https://github.com/code-423n4/2022-05-cally-findings/issues/47 owner can set fee greater than 100%: https://github.com/code-423n4/2022-05-cally-findings/issues/48
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xf15ers, 0xkatana, 0xsanson, Bludya, BowTiedWardens, CertoraInc, Cityscape, DavidGialdi, FSchmoede, Fitraldys, Funen, Hawkeye, Kenshin, MadWookie, MaratCerby, MiloTruck, Picodes, RagePit, Tadashi, TerrierLover, TomFrenchBlockchain, VAD37, WatchPug, Waze, _Adam, antonttc, bobirichman, catchup, defsec, delfin454000, djxploit, ellahi, fatherOfBlocks, gzeon, hake, hansfriese, hickuphh3, horsefacts, ignacio, joestakey, jonatascm, mics, minhquanym, oyc_109, pmerkleplant, rfa, robee, rotcivegaf, samruna, shung, sikorico, simon135, z3s
33.2384 USDC - $33.24
https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L188-L190 Replace with
// vault index should always be odd vaultId = vaultIndex; vaultId += 2; vaultIndex = vaultId;
Saves an erreneous SLOAD of vaultIndex. Saves 113 gas per createVault call
https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L444 Replace with
_vaultBeneficiaries[id] = address(0);
An option nft will never have a vault beneficiary, so the isVaultToken check is pointless. Saves about 25 gas in the case of a vault nft id being transferred.
https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L395-L396 Replace with
return premiumOptions[_vaults[vaultId].premiumIndex];
Even though it's a view function, saving the entire Vault struct to memory is expensive. Will save gas on composable contracts.
https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L173 https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L198-L200 No need to store the Vault struct in memory. All of the vault data is sent in the calldata anyway
Recommendation
_vaults[vaultId] = Vault({...}); ... tokenType == TokenType.ERC721 ? ERC721(token).transferFrom(msg.sender, address(this), tokenIdOrAmount) : ERC20(token).safeTransferFrom(msg.sender, address(this), tokenIdOrAmount);
https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L83-L84 currentStrike and dutchAuctionReserveStrike members of Vault struct are unnecessarily large. The max strike price is 6765 ether or 73 bits.
Recommendation: Change currentStrike and dutchAuctionReserveStrike to be between uint80-uint128. This brings the Vault struct to 3 storage slots rather than 4. Changing both to uint128 saves about 2100 gas per call to createVault, exercise, withdraw or buyOption (nearly 2%)