Yieldy contest - hansfriese'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: 21/99

Findings: 5

Award: $552.08

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: 0xDjango

Also found by: BowTiedWardens, Metatron, cccz, hansfriese, shung, ych18, zzzitron

Labels

bug
duplicate
2 (Med Risk)

Awards

72.4441 USDC - $72.44

External Links

Lines of code

https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Staking.sol#L157

Vulnerability details

Impact

Staking.setCurvePool() doesn't approve allowance when changes CURVE_POOL. It will affect when users exchange asset through CURVE_POOL.

Proof of Concept

When initialize the contract, Staking contract approves CURVE_POOL here.

But when admin updates CURVE_POOL here, it doesn't approve for the new CURVE_POOL, this exchange logic wouldn't work properly.

Tools Used

Solidity Visual Developer of VSCode

We should approve the new CURVE_POOL. Replace L159 like below. It's not recommended using ERC20.approve() as I suggest in my low risk findings, but I just wrote same as the original one here.

if (CURVE_POOL != address(0)) { IERC20(TOKE_POOL).approve(CURVE_POOL, type(uint256).max); setToAndFromCurve(); }

#0 - toshiSat

2022-06-27T21:24:22Z

duplicate #264

#1 - KenzoAgada

2022-08-26T08:54:41Z

The judging sheet mentions this as duplicate of #222 instead of #165.

Findings Information

🌟 Selected for report: BowTiedWardens

Also found by: PwnedNoMore, TrungOre, hansfriese, hubble, minhquanym, shung

Labels

bug
duplicate
2 (Med Risk)

Awards

72.4441 USDC - $72.44

External Links

Lines of code

https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Yieldy.sol#L100 https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Yieldy.sol#L110-L131

Vulnerability details

Impact

Yieldy._storeRebase() saves and emits wrong values. I don't think the asset will be lost directly because of this but the rebase storage will have wrong values and it might affect the system later.

Proof of Concept

The _previousCirculating must be a previous total supply but it passes current total supply here. As a result, rebasePercent, rebase: rebasePercent,, totalStakedBefore: _previousCirculating,, rebasePercent will be saved and emitted incorrectly.

Tools Used

Solidity Visual Developer of VSCode

We should pass previous total supply here.

_storeRebase(currentTotalSupply, _profit, _epoch);

#0 - toshiSat

2022-06-27T21:23:40Z

duplicate #259

Findings Information

🌟 Selected for report: Chom

Also found by: hansfriese, minhquanym

Labels

bug
duplicate
2 (Med Risk)

Awards

327.1592 USDC - $327.16

External Links

Lines of code

https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Yieldy.sol#L91-L98 https://github.com/code-423n4/2022-06-yieldy/blob/524f3b83522125fb7d4677fa7a7e5ba5a2c0fe67/src/contracts/Yieldy.sol#L257

Vulnerability details

Impact

Yieldy._totalSupply has different upper bounds. Yieldy._mint() will revert when _totalSupply is exactly same as MAX_SUPPLY.

Proof of Concept

From L91-L98, we can see _totalSupply can be same as MAX_SUPPLY and I think "_totalSupply <= MAX_SUPPLY" is reasonable also. Btw here, it checks a strict inequality and _mint() function will be failed when _totalSupply is exactly same as MAX_SUPPLY even though it should work properly.

Tools Used

Solidity Visual Developer of VSCode

We should modify this part.

require(_totalSupply <= MAX_SUPPLY, "Max supply");

#0 - toshiSat

2022-07-28T19:25:46Z

duplicate #200

Low Risk Issues

  1. ERC20.approve() missing return value check. Reference
  1. Check address(0) before transfer funds

Non-critical Issues

  1. Same code
  1. Check underflow same as here.

  1. Use != 0 instead of > 0 for uint variables
  1. X = X + Y is cheaper than X += Y
  1. Non-strict inequalities are cheaper than strict ones
  1. Usage of unchecked can reduce the gas cost
  1. Replace storage to memory if possible
  1. Don't use storage value if you can use local variable instead
  1. Check zero amount before transfer
  1. Don't add duplicate addresses. When it contains same contracts, it will just increase the array length and other functions like this won't be executed for later address because this condition doesn't meet after the first withdrawal request.
  1. Remove elements from array using pop(). Like explained here, "delete" just assigns the initial value but doesn't reduce the length of array. As a result, the array length won't be reduced and it will cost more gas.

We can modify like below. We can assume there is no duplicate elements according to G8. This approach won't save the order of elements after deleting.

uint256 contractsLength = contracts.length; for (uint256 i; i < contractsLength; ) { if (contracts[i] == _address) { contracts[i] = contracts[contractsLength - 1]; contracts.pop(); break; } unchecked { ++i; } }
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