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: 26/100
Findings: 5
Award: $131.33
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: BondiPestControl
Also found by: 0xf15ers, GimelSec, IllIllI, MadWookie, MiloTruck, Ruhum, VAD37, berndartmueller, cccz, csanuragjain, dipp, hake, horsefacts, jayjonah8, m9800, pedroais, throttle
31.6149 USDC - $31.61
When buying an option, the msg.value
of the call to the buyOption function may be larger than the actual value of the premium.
This could lead to users accidently sending more than the cost of the premium and losing the extra ETH.
buyOption
for a vault with a 0.1 ETH premium.msg.value
for the call to 1 ETH.Consider setting the condition on line 224 to require(msg.value == premium, "Incorrect ETH amount sent")
.
#0 - outdoteth
2022-05-15T17:02:20Z
reference issue: https://github.com/code-423n4/2022-05-cally-findings/issues/84
16.9712 USDC - $16.97
Judge has assessed an item in Issue #286 as Medium risk. The relevant finding follows:
No min/max fee rate Line Refrences Cally.sol#L119-121
Description Limits for the fee rate should be set to avoid mistakes when setting the fee. A fee rate that is over 100% could result in the exercise function not being able to execute since the computation on line 289 would result in an underflow and revert.
A constant variable for the max fee rate could be used. The setFee function should check the supplied feeRate against this max fee value.
#0 - HardlyDifficult
2022-06-06T00:23:15Z
🌟 Selected for report: 0x1337
Also found by: 0x52, 0xDjango, 0xsanson, BondiPestControl, BowTiedWardens, GimelSec, IllIllI, MaratCerby, MiloTruck, PPrieditis, TrungOre, VAD37, WatchPug, berndartmueller, cccz, dipp, hake, hickuphh3, horsefacts, hubble, minhquanym, reassor, shenwilly, smiling_heretic
10.8874 USDC - $10.89
Cally.sol#L158-L201 Cally.sol#L258-L297 Cally.sol#L318-L346
If the underlying asset for a vault is a fee-on-transfer ERC20 token then the actual amount received by the contract could be less than the value of tokenIdOrAmount
of the vault.
If the contract does not have enough tokens to cover the difference then the exercise
and withdraw
functions would not work since the safeTransfer function at the end of exercise
and withdraw
would revert due to an insufficient balance.
This could lead to vault owners being unable to access their funds until the contract has enough tokens and option holders might be unable to exercise their option before it expires, leading to lost funds.
Unable to withdraw:
Cally.sol
contract holds none of these tokens before the initial transfer into the contract.createVault
, the amount of vault.tokenIdOrAmount
tokens is transferred from the owner of the vault to the Cally.sol
contract.vault.tokenIdOrAmount
of the tokens.initiateWithdraw
, the withdraw
function reverts when the safeTransfer function is called.Unable to exercise:
exercise
, the safeTransfer at the end of the function will fail if the contract does not have enough tokens. The option holder will not be able to exercise the option.Consider checking the contract's balance before and after ERC20 transfers in createVault
. The vault.tokenIdOrAmount
could be set to the difference of the balances.
#0 - outdoteth
2022-05-15T17:17:29Z
reference issue: https://github.com/code-423n4/2022-05-cally-findings/issues/39
16.9712 USDC - $16.97
The transferFrom function is used in the createVault
, withdraw
and the exercise
functions to transfer the underlying ERC721 vault asset. transferFrom sends an ERC721 asset to a receiver regardless of whether it is able to receive it or not.
In the exercise
function, when msg.sender
is a contract, the transferFrom function could send the underlying ERC721 asset to a contract that cannot interact with an ERC721, effectively locking it.
Consider using safeTransferFrom instead of transferFrom in the exercise
function. This will revert if the onERC721Received
function is not implemented in the receiving contract, not allowing an incompatible contract to exercise the option.
Incompatible contracts would still be able to buy options but would at least not waste more ETH when trying to exercise the option.
#0 - outdoteth
2022-05-15T20:49:18Z
use safeTransferFrom to prevent stuck NFTs: https://github.com/code-423n4/2022-05-cally-findings/issues/38
🌟 Selected for report: hubble
Also found by: 0x1337, 0x1f8b, 0x4non, 0xDjango, 0xf15ers, 0xsanson, 242, Aits, AlleyCat, Bludya, BondiPestControl, BouSalman, BowTiedWardens, CertoraInc, Cityscape, Czar102, FSchmoede, Funen, Hawkeye, IllIllI, JDeryl, Kenshin, Kumpa, MaratCerby, MiloTruck, Picodes, Ruhum, TrungOre, VAD37, WatchPug, Waze, antonttc, bobirichman, catchup, cccz, cryptphi, csanuragjain, delfin454000, dipp, dirk_y, djxploit, eccentricexit, ellahi, fatherOfBlocks, hake, hansfriese, hickuphh3, horsefacts, hyh, jah, joestakey, mics, minhquanym, pedroais, pmerkleplant, radoslav11, reassor, rfa, robee, seanamani, shenwilly, shung, sikorico, sorrynotsorry, sseefried, z3s
54.8916 USDC - $54.89
The condition only passes if the reserve strike is less than the starting strike. So if it fails then the reserve strike is too big and the error message should display something like "Reserve strike too large" or "Starting strike too small."
Limits for the fee rate should be set to avoid mistakes when setting the fee. A fee rate that is over 100% could result in the exercise
function not being able to execute since the computation on line 289 would result in an underflow and revert.
A constant variable for the max fee rate could be used. The setFee
function should check the supplied feeRate
against this max fee value.
#0 - outdoteth
2022-05-16T19:00:36Z
this can be bumped to medium severity: 2: No min/max fee rate: https://github.com/code-423n4/2022-05-cally-findings/issues/48
#1 - HardlyDifficult
2022-05-29T16:22:24Z
Moved No min/max fee rate to https://github.com/code-423n4/2022-05-cally-findings/issues/319