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: 38/100
Findings: 3
Award: $96.33
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x52, 0xf15ers, 0xsanson, Bludya, BondiPestControl, Czar102, GimelSec, Kumpa, _Adam, berndartmueller, catchup, crispymangoes, eccentricexit, ellahi, hake, horsefacts, pedroais, peritoflores, reassor, shenwilly, shung, smiling_heretic, sseefried, throttle
8.1655 USDC - $8.17
https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L119-L121 https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L283-L286
Contract Cally
allows exercising a call option by sending the underlying assets to the exerciser and the strike ETH to the vault's beneficiary. Contract can charge a feeRate
applied during exercising. The issue is that the feeRate
can be dynamically changed by the administrator at any time and the change is applied also to already existing vaults. That means that administrator can launch an attack where he changes the feeRate
to 100%
and then during exercising all funds are transferred to him as a fee.
Exploit Scenario:
feeRate
is 0%
so he creates the vault via createVault
.feeRate
to 100%
via setFee
(or runs front-running attack).setFee
transaction is being included before user's exercise
transaction.This issue is also relevant in case of administrator not being a malicious actor. User accepts some kind of fee that is visible as a feeRate
for example 1%
. Then administrator just change the feeRate to 3%
. User didn't expect that change and effectively loses funds.
Manual Review / VSCode
It is recommended to assign current feeRate
to vault's vault.feeRate
in createVault
. During exercise
only the vault.feeRate
should be used as a feeRate
. In addition it is recommended to add timelock for changing feeRate
via setFee
so it will be not possible to launch front-running attack.
#0 - outdoteth
2022-05-15T19:12:56Z
owner can change fee at any time; https://github.com/code-423n4/2022-05-cally-findings/issues/47
🌟 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
https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L174 https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L200 https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L296
Contract Cally
does not properly handle ERC20 tokens that charge fee on their transfers. Implementation of such a tokens does not transfer exact amount provided to transfer()
but part of it is charged as a fee, burned or used in some other way. This leads to incorrect accounting and effectively to loss of funds.
Manual Review / VSCode
It is recommended to add support for ERC20 tokens with built-in fees. Example of the implementation:
uint256 startingBalance = IERC20(token).balanceOf(address(this)); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); uint256 endingBalance = IERC20(token).balanceOf(address(this)); vault.tokenIdOrAmount = endingBalance - startingBalance;
#0 - outdoteth
2022-05-15T17:17:46Z
reference issue: https://github.com/code-423n4/2022-05-cally-findings/issues/39
🌟 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
77.275 USDC - $77.27
Low
Contract Cally
does not check for zero addresses which might lead to loss of funds, failed transactions and can break the protocol functionality.
token
address - https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L160beneficiary
address - https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L351Manual Review / VSCode
It is recommended to add zero address checks for listed parameters.
Low
Contract Cally
does not implement events for some critical functions. Lack of events makes it difficult for off-chain applications to monitor the protocol.
setFee
event - https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L119-L121withdrawProtocolFees
event - https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L124-L128setVaultBeneficiary
event - https://github.com/code-423n4/2022-05-cally/blob/1849f9ee12434038aa80753266ce6a2f2b082c59/contracts/src/Cally.sol#L351-L357Manual Review / VSCode
It is recommended to add missing events to listed functions.
Low
Function Cally.setFee
is missing check for feeRate_
parameter that should not exceed acceptable by protocol percentage.
Manual Review / VSCode
It is recommended to add check for feeRate_
parameter.
Low
Changing critical addresses such as ownership should be a two-step process where the first transaction (from the old/current address) registers the new address (i.e. grants ownership) and the second transaction (from the new address) replaces the old address with the new one. This gives an opportunity to recover from incorrect addresses mistakenly used in the first step. If not, contract functionality might become inaccessible.
Manual Review / VSCode
It is recommended to implement two-step process for passing ownership.
Non-Critical
Contract uses false
boolean expression for require statements in multiple functions.
Manual Review / VSCode
It is recommended to remove false
expression and use alternative syntax such as:
require(!vault.isExercised, "Vault already exercised");
Non-Critical
Function Cally.createVault
checks if dutchAuctionReserveStrike
is smaller than specified strike option. Incorrect error message "Reserve strike too small" is returned in case of the error. It should be "Reserve strike too big".
require(dutchAuctionReserveStrike < strikeOptions[dutchAuctionStartingStrikeIndex], "Reserve strike too small");
Manual Review / VSCode
It is recommended to change the error message to "Reserve strike too big".
#0 - outdoteth
2022-05-16T19:06:06Z
this can be bumped to medium severity 3. Missing validation for feeRate: https://github.com/code-423n4/2022-05-cally-findings/issues/48
#1 - HardlyDifficult
2022-05-30T19:05:30Z
Per the C4 guidance "part of auditing is demonstrating proper theory of how an issue could be exploited" and that does not seem to be explored here as it was in the primary report.