Yieldy contest - Lambda's results

A protocol for gaining single side yields on various tokens.

General Information

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

Yieldy

Findings Distribution

Researcher Performance

Rank: 1/99

Findings: 5

Award: $5,457.45

🌟 Selected for report: 2

🚀 Solo Findings: 2

Findings Information

🌟 Selected for report: Lambda

Labels

bug
3 (High Risk)
resolved
sponsor confirmed

Awards

4039.0029 USDC - $4,039.00

External Links

Lines of code

https://github.com/code-423n4/2022-06-yieldy/blob/34774d3f5e9275978621fd20af4fe466d195a88b/src/contracts/Staking.sol#L308

Vulnerability details

Impact

The withdraw function of the ETH Tokemak pool has an additional parameter asEth. This can be seen in the Tokemak Github repository or also when looking at the deployed code of the ETH pool. Compare that to e.g. the USDC pool, which does not have this parameter.

This means that the call to withdraw will when the staking token is ETH / WETH and no withdrawals would be possible.

Proof of Concept

A new Staking contract with ETH / WETH as the staking token is deployed. Deposits in Tokemak work fine, so users stake their tokens. However, because of the previously described issue, no withdrawal is possible, leaving the funds locked.

Handle the case where the underlying asset is WETH / ETH separately and pass this boolean in that case.

Findings Information

🌟 Selected for report: 0x1f8b

Also found by: BowTiedWardens, Lambda, StErMi, berndartmueller, csanuragjain, neumo, rfa

Labels

bug
duplicate
2 (Med Risk)

Awards

119.2495 USDC - $119.25

External Links

Lines of code

https://github.com/code-423n4/2022-06-yieldy/blob/34774d3f5e9275978621fd20af4fe466d195a88b/src/contracts/BatchRequests.sol#L37 https://github.com/code-423n4/2022-06-yieldy/blob/34774d3f5e9275978621fd20af4fe466d195a88b/src/contracts/BatchRequests.sol#L93

Vulnerability details

Impact

When contracts[i] is the 0 address (which happens after removeAddress was called), IStaking(contracts[i]).canBatchTransactions() will fail for this index, meaning that the whole function will always fail.

Check if the address is equal to 0.

#0 - toshiSat

2022-06-27T23:50:33Z

duplicate #241

Findings Information

🌟 Selected for report: Lambda

Labels

bug
2 (Med Risk)
sponsor acknowledged

Awards

1211.7009 USDC - $1,211.70

External Links

Lines of code

https://github.com/code-423n4/2022-06-yieldy/blob/34774d3f5e9275978621fd20af4fe466d195a88b/src/contracts/Staking.sol#L98

Vulnerability details

Impact

In the constructor of Staking.sol, it is not enforced that the _firstEpochEndTime is larger than the current block.timestamp. If a low value is accidentally passed (or even 0), rebase can be called multiple times in sucession, causing the epoch.number to increase. Therefore, the coolDown & warmUp period can be circumvented in such a scenario, as epoch.number >= info.expiry (in _isClaimAvailable and _isClaimWithdrawAvailable) will return true after rebase caused several increases of epoch.number.

Either require that _firstEpochEndTime is larger than block.timestamp or set the expiry of the first epoch to block.timestamp + _epochDuration.

#0 - toshiSat

2022-06-27T23:48:37Z

This is something we thought about and will most likely set the period temporarily 1 higher when launching with low initial epoch durations

  • The comment in Line 323 of Staking.sol is wrong, which can be confusing. In the case of unstakeAllFromTokemak, we have per definition balance == _amount (as the balance of the pool is passed from unstakeAllFromTokemak).
  • The variable name in Line 112 of LiquidityReserve.sol still refers to the old project (FOX).
  • Hardcoding the COW contract addresses in Line 73 and Line 74 of Staking.sol goes against best practices.
  • In Line 88 of Staking.sol, the code from line 84 is duplicated, i.e. the yieldy token approval for the liquidity reserve is executed two times.
  • Duplicated code: In Line 144 and Line 372 of Staking.sol, the function _getTokemakBalance could be used.
  • amountToRequest should be passed to requestWithdrawal in Line 326 of Staking.sol, otherwise the wrong value is used when balance < _amount.
  • In Line 372, tokePoolContract was already instantiated with ITokePool, there is no reason to call ITokePool(tokePoolContract) instead of tokePoolContract.balanceOf
  • In Line 100 of Yieldy.sol, the new supply is passed as _previousCirculating to _storeRebase. In Line 121, this leads to totalStakedBefore and totalStakedAfter always being equal (and a wrong rebasePercent, which is also calculated with the _previousCirculating.
  • The creditAmount calculation in Yieldy.sol is inconsistent. In transferFrom, creditsForTokenBalance is called, whereas the calculation is done directly in transfer, _mint, and _burn. Consider using one consistent method for that.
  • To have a consistent behavior with rebase, it should be require(_totalSupply <= MAX_SUPPLY, ...); in Line 257 of Yieldy.sol, i.e. _totalSupply == MAX_SUPPLY should also be allowed.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter