Platform: Code4rena
Start Date: 21/06/2022
Pot Size: $50,000 USDC
Total HM: 31
Participants: 99
Period: 5 days
Judges: moose-code, JasoonS, denhampreen
Total Solo HM: 17
Id: 139
League: ETH
Rank: 27/99
Findings: 3
Award: $368.53
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: WatchPug
Also found by: BowTiedWardens, cccz, minhquanym, parashar, pashov, shung, zzzitron
241.4803 USDC - $241.48
When warmUpPeriod
is greater than 1, a third person can stake to the victim to prolong the warmUp expiry.
The expiry prolongation also happens with cool down, although a third party cannot do the similar attack. If the user unstakes within the cool down period, the cool down expiry will be pushed back.
This proof of concept demonstrates that staker2 is staking for staker1, and as the result staker1's warm up expiry is updated. The warmUpPeriod in the above example was set to 2. The staker1 stakes and waits for one epoch, then staker2 stakes a small amount on behalf of staker1. After another epoch, the staker1 expects to be able to claim, however since the staker2 staked in the previous epoch, the staker1 cannot claim. If the staker2 keep using this tactic, the staker1 cannot claim unless the warmUpPeriod is set to be less than or equal to 1. Otherwise, the staker1 should just unstake.
hardhat
The stake(uint256,address)
is used in the Migration
, so it is needed. One idea to prevent another person to call it is, to add an access control.
Another idea is to manage the warmUpInfo and coolDownInfo differently.
#0 - toshiSat
2022-06-27T23:15:25Z
#109
#1 - itsmetechjay
2022-06-28T13:14:28Z
Per help desk request, we've updated this QA report with the warden's additional findings. The request came in before contest close.
🌟 Selected for report: 0xDjango
Also found by: BowTiedWardens, Metatron, cccz, hansfriese, shung, ych18, zzzitron
https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Staking.sol#L79-L80 https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Staking.sol#L157-L160
After updating the curve pool using setCurvePool
, one cannot use instantUnstakeCurve
anymore, because TOKE_POOL
is not approved to the new curve pool.
There is no other way to approve, so the instantUnstakeCurve
functionality cannot be used with any new curve pool. When no curve pool was set in the initialize
function, then there is no way to use the instantUnstakeCurve
functionality.
This proof of concept demonstrates that the instantUnstakeCurve
reverts after the curve pool is updated.
The set up for the proof of concept is almost identical to the test/stakingTest.ts except the curve pool was set to zero in the initialize.
Then the curve pool was updated by calling the setCurvePool
function, then attempt to call instantUnstakeCurve
, which reverts.
hardhat
Add the approve logic to the setCurvePool or setToAndFromCurve. Also consider adding logic to un-approve the previous curve pool, just in case the curve pool might be compromised.
#0 - toshiSat
2022-06-27T23:15:56Z
duplicate #165
🌟 Selected for report: IllIllI
Also found by: 0x1337, 0x1f8b, 0x29A, 0x52, 0xDjango, 0xNazgul, 0xNineDec, 0xc0ffEE, 0xf15ers, 0xmint, Bnke0x0, BowTiedWardens, Chom, ElKu, FudgyDRS, Funen, GalloDaSballo, GimelSec, JC, Kaiziron, Lambda, Limbooo, Metatron, MiloTruck, Noah3o6, Picodes, PumpkingWok, PwnedNoMore, Sm4rty, StErMi, TomJ, TrungOre, UnusualTurtle, Waze, _Adam, aga7hokakological, ak1, antonttc, berndartmueller, cccz, cryptphi, csanuragjain, defsec, delfin454000, dipp, elprofesor, exd0tpy, fatherOfBlocks, hake, hansfriese, hubble, joestakey, kenta, ladboy233, mics, oyc_109, pashov, pedr02b2, reassor, robee, samruna, scaraven, shung, sikorico, simon135, sseefried, tchkvsky, unforgiven, zzzitron
54.6089 USDC - $54.61
creditsForAmount
instead of manually calculating in Yieldy
. It is easy to read and less error-prone to reuse functions..Yieldy
In the transferFrom
functions, the _to
address is not checked for zero address.
Yieldy
creditBalances[_from] = creditBalances[_from] - creditAmount;
When updating the creditBalances
in the transferFrom
, the balance was not checked against the transferring amount. A transaction transferring more than the balance will not go through, thanks to the underflow check in solidity version 8. But it is still good to add the check to revert with the proper reason or custom error.
BatchRequests
Upon removeAddress
, it will delete the item at index i. So, to use the contracts
array, one should be prepared to encounter zero addresses.
// in canBatchContracts bool canBatch = IStaking(contracts[i]).canBatchTransactions();
The canBatchContracts
and canBatchContractByIndex
do not check for the zero address. It will revert when those functions should make a call to the zero address.
Staking
Staking contract is approving liquidity reserve twice.
#0 - itsmetechjay
2022-06-28T13:12:27Z
Per help desk request, we've updated this QA report with the warden's additional findings. The request came in before contest close.