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: 20/99
Findings: 2
Award: $599.88
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0x52
Also found by: elprofesor
545.2654 USDC - $545.27
Yieldy implements a warmUpPeriod
to prevent new stakers from using freshly minted yieldy tokens in the Staking.sol
contract. warmUpPeriod
is not initialised in the contract initialisation therefore a user can frontrun when the onlyOwner
calls setWarmUpPeriod()
in order to stake in order to bypass possible warmUpPeriods.
Staking.sol
contractsetWarmUpPeriod()
functionwarmUpPeriod
during initialisation#0 - toshiSat
2022-06-27T21:19:48Z
sponsor acknowledged: We are starting with a warmup period of 0 for now and will implement in case it's needed
#1 - JasoonS
2022-08-29T16:55:44Z
Leaving this as medium, a default should be set.
🌟 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
https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Staking.sol#L439-L444 https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Staking.sol#L465-L477
Yieldy implements a warmUpPeriod
to prevent new stakers from using freshly minted yieldy tokens. The function stake()
uses this warm up period as follows:
// skip adding to warmup contract if period is 0 if (warmUpPeriod == 0) { IYieldy(YIELDY_TOKEN).mint(_recipient, _amount); } else { // create a claim and mint tokens so a user can claim them once warm up has passed warmUpInfo[_recipient] = Claim({ amount: info.amount + _amount, credits: info.credits + IYieldy(YIELDY_TOKEN).creditsForTokenBalance(_amount), expiry: epoch.number + warmUpPeriod }); IYieldy(YIELDY_TOKEN).mint(address(this), _amount); }
On line 443
in Staking.sol
the expiry for warmUpInfo[_recipient]
is incremented on behalf of any arbitrary user. This expiry info is then used during any claim()
function call, to calculate how much Yieldy token to transfer from the base contract to the recipient.
If a malicious user was to continuously send a single token every warmUpPeriod
epochs for staking on behalf a victim, they could continuously deny any victim the right to retrieve their Yieldy tokens and therefore cause a targeted denial of service.
stake()
function. This function mints Yieldy tokens and transfers them to the Staking.sol
contract as a temporary custodian until after the expiry
period has elapsed.warmUpPeriod
before they can call the claim()
and retrieve their yieldy tokens.warmUpPeriod
time frame.claim()
function, the function will revert due to the check in isClaimAvailable()
since epoch.number < info.expiry
If this attack is repeated the victim will not be able to withdraw any staking tokens until the attacker has finished.
Ensure that warmup period is only set on new stakers, or prevent arbitrary staking from impacting the expiry of existing stakers.
#0 - toshiSat
2022-06-27T21:25:18Z
duplicate #262