Illuminate contest - datapunk's results

Your Sole Source For Fixed-Yields.

General Information

Platform: Code4rena

Start Date: 21/06/2022

Pot Size: $55,000 USDC

Total HM: 29

Participants: 88

Period: 5 days

Judge: gzeon

Total Solo HM: 7

Id: 134

League: ETH

Illuminate

Findings Distribution

Researcher Performance

Rank: 2/88

Findings: 13

Award: $5,032.65

🌟 Selected for report: 1

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: cccz

Also found by: 0x52, datapunk

Labels

bug
duplicate
3 (High Risk)

Awards

1021.1856 USDC - $1,021.19

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L465 https://github.com/tempus-finance/tempus-protocol/blob/f431e821c81d8cdeae8ad433d160230563f121de/contracts/TempusController.sol#L59

Vulnerability details

Impact

Confusing at least, potentially wrong

Proof of concept

function depositAndFix( ITempusAMM tempusAMM, ITempusPool tempusPool, uint256 tokenAmount, bool isBackingToken, uint256 minTYSRate, uint256 deadline ) external payable override nonReentrant returns (uint256, uint256)

The function returns two values, while the caller expects only one

uint256 returned = ITempus(tempusAddr).depositAndFix(Any(x), Any(t), a - fee, true, r, d) - illuminateToken.balanceOf(address(this));

Also not sure if subtract illuminateToken.balanceOf(address(this)) is the correct logic here.

Recommendation

Maybe do the following?

uint256 returned = ITempus(tempusAddr).depositAndFix(Any(x), Any(t), a - fee, true, r, d)[0] - illuminateToken.balanceOf(address(this));

#0 - KenzoAgada

2022-06-28T10:41:35Z

Duplicate of #37

Also briefly mentions #222 ("Also not sure if subtract illuminateToken.balanceOf(address(this)) is the correct logic here.") but dunno if that's enough for a separate issue

Findings Information

🌟 Selected for report: kirk-baird

Also found by: csanuragjain, datapunk, ladboy233

Labels

bug
duplicate
3 (High Risk)

Awards

689.3003 USDC - $689.30

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L285

Vulnerability details

Impact

It may have unexpected rounding issues with dividing first

Proof of concept

The repo has changed since the contest started. The original repo has returned += amountLent * (order.premium / order.principal); instead of the currently correct code in https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L285

Recommendation

fixed

#0 - sourabhmarathe

2022-06-29T17:44:40Z

Duplicate of #155.

#1 - gzeoneth

2022-07-29T17:06:04Z

Duplicate of #48

Findings Information

🌟 Selected for report: auditor0517

Also found by: 0x52, cccz, datapunk, kenzo, pashov

Labels

bug
duplicate
3 (High Risk)

Awards

372.2221 USDC - $372.22

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/redeemer/Redeemer.sol#L187

Vulnerability details

Impact

Transferred token to wrong contract

Proof of concept

To redeem, IERC20(principal) should be transferred from lender to redeemer, not marketplace https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/redeemer/Redeemer.sol#L187

Recommendation

Do this instead:

IElementToken(principal).withdrawPrincipal(amount, address(this));

#0 - sourabhmarathe

2022-06-29T17:42:15Z

Duplicate of #182.

Findings Information

Awards

29.8781 USDC - $29.88

Labels

bug
duplicate
3 (High Risk)

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L205

Vulnerability details

Proof of concept

In https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L205, y is checked against u and m, but not p. From the usage, it seems when p == uint8(MarketPlace.Principals.Yield, y is a pool for swapping underlying and yield PT, while when p == uint8(MarketPlace.Principals.Illuminate), y is a pool for swapping underlying and illuminate PTs.

Impact

Without proper checking, it is hard to see if the logic is correct. It might very well be the case, where y is used in wrong scenario.

Recommendation

Check the fyToken in the following fashion:

IYield pool = IYield(y); if (p == uint8(MarketPlace.Principals.Yield && pool.fyToken!=yieldPT) revert WrongY(); else if (p == uint8(MarketPlace.Principals.Yield && pool.fyToken!=yieldPT) revert WrongY();

#0 - JTraversa

2022-07-06T18:06:41Z

Duplicate of #349

#1 - KenzoAgada

2022-07-17T01:28:09Z

Hi @gzeoneth, you marked this as high risk, but the contest readme input sanitation section states that the sponsors purposefully are not "Checking to ensure the protocol enum matches the parameters provided" or checking similar input errors.

#2 - gzeoneth

2022-07-17T04:39:12Z

Hi @gzeoneth, you marked this as high risk, but the contest readme input sanitation section states that the sponsors purposefully are not "Checking to ensure the protocol enum matches the parameters provided" or checking similar input errors.

I believe that only applies to admin functions and not exploitable user function.

#3 - KenzoAgada

2022-07-17T06:17:28Z

Hmm, how come? This is why I think it applies to user functions as well -

  1. It includes "Checking for input amounts of 0" - but AFAIS the admin has no functions that supply input amounts.
  2. It states "we err on the side of having external interfaces validate their input, rather than socializing costs to do checks". The "socializing" part implies to me that other users are involved - which is not relevant for admin-only functions, where the admin is anyway the only one that will pay so there's no socializing. This sentence implies to me that they don't want all the users to pay for checks because one user might submit wrong input.
  3. There's nothing in that section that mentions it's only for admin functions.

Also, in this specific issue the issue itself seems lacking.. - the warden didn't fully mention what's the impact, there's no POC or proper explanation, and the mitigation is also wrong/lacks details.

If we'll say that the issue is exploitable and that the user can supply p==Yield but y=swapIlluminatePTPool, then maybe it should be considered as duplicate of the issues that mention that the user can supply his own/any pool to this function. As this is a private case of that.

#4 - gzeoneth

2022-07-18T04:38:30Z

Hmm, how come? This is why I think it applies to user functions as well -

  1. It includes "Checking for input amounts of 0" - but AFAIS the admin has no functions that supply input amounts.
  2. It states "we err on the side of having external interfaces validate their input, rather than socializing costs to do checks". The "socializing" part implies to me that other users are involved - which is not relevant for admin-only functions, where the admin is anyway the only one that will pay so there's no socializing. This sentence implies to me that they don't want all the users to pay for checks because one user might submit wrong input.
  3. There's nothing in that section that mentions it's only for admin functions.

Also, in this specific issue the issue itself seems lacking.. - the warden didn't fully mention what's the impact, there's no POC or proper explanation, and the mitigation is also wrong/lacks details.

If we'll say that the issue is exploitable and that the user can supply p==Yield but y=swapIlluminatePTPool, then maybe it should be considered as duplicate of the issues that mention that the user can supply his own/any pool to this function. As this is a private case of that.

First off, this is considered as a duplicate of #349 with better explanation which is also a large set of similar findings. Input validation is out-of-scope only if it is not exploitable, e.g. if it will only cause the user to lose fund or the admin might set a wrong parameter because the sponsor expect to catch these error in the UI / toolchain. If it is exploitable (e.g. an attack can gain from it), then it is in-scope.

The socializing part is that you don't check things like 0 in the contract but instead doing it in the UI. If you decided to call the contract directly you are at your own risk, but if you can gain from it then that's an in-scope exploit.

#5 - KenzoAgada

2022-07-18T06:27:26Z

I agree. 👍

Honestly I think in my initial message I got the impression you intend this to be a unique finding, and not a duplicate... don't know now what gave me that impression... Sorry.

Findings Information

🌟 Selected for report: Metatron

Also found by: 0x52, WatchPug, auditor0517, cccz, datapunk, hansfriese, hyh, kenzo, kirk-baird, shenwilly, unforgiven

Labels

bug
duplicate
3 (High Risk)

Awards

98.9071 USDC - $98.91

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L301

Vulnerability details

Proof of concept

In https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L301, yield PTs is purchased to lender.sol (address(this)), yet msg.sender does not have illuminate PTs Minted and distributed.

Impact

msg.sender loses fund since its underlying token is transferred into lender, yet it has no receipt to prove it.

Recommendation

Check the length in the following fashion:

IERC5095(principalToken(u, m)).mint(msg.sender, returned);

#0 - sourabhmarathe

2022-06-29T23:55:04Z

Duplicate of #391.

Findings Information

🌟 Selected for report: WatchPug

Also found by: Lambda, csanuragjain, datapunk

Labels

bug
duplicate
3 (High Risk)
sponsor confirmed

Awards

689.3003 USDC - $689.30

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/redeemer/Redeemer.sol#L143 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/redeemer/Redeemer.sol#L193

Vulnerability details

Impact

Anyone can remove the principal tokens anytime from these protocols

Proof of concept

Tempus and Notional allows for early withdrawal, which is OK as protocol design, but since redeem() function can be called by anyone, this can lead to undesired behavior

Recommendation

Test maturity before calling redeem()

#0 - sourabhmarathe

2022-06-29T17:40:25Z

Duplicate of #159.

Findings Information

🌟 Selected for report: shenwilly

Also found by: Chom, Picodes, cccz, datapunk, kenzo, unforgiven

Labels

bug
duplicate
3 (High Risk)

Awards

287.1428 USDC - $287.14

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/redeemer/Redeemer.sol#L136

Vulnerability details

Impact

Transferred the wrong token, later withdraw will fail from APWine

Proof of concept

To redeem, IERC20(principal) should be transferred from lender to redeemer, not u

Recommendation

Do this instead:

Safe.transferFrom(IERC20(principal), lender, address(this), amount);

#0 - KenzoAgada

2022-06-28T14:03:14Z

Duplicate of #268

Findings Information

🌟 Selected for report: dipp

Also found by: Lambda, WatchPug, cccz, cryptphi, datapunk, hyh, kenzo

Labels

bug
duplicate
3 (High Risk)

Awards

226.125 USDC - $226.12

External Links

#0 - KenzoAgada

2022-06-28T08:28:48Z

Duplicate of #341

Findings Information

🌟 Selected for report: 0x52

Also found by: datapunk, kenzo, kirk-baird, pashov

Labels

bug
duplicate
2 (Med Risk)

Awards

148.8889 USDC - $148.89

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L142 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L157 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L172 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L187

Vulnerability details

Proof of concept

In Marketplace.sol The pool.base()/fyToken() transfers out of its own balance.

  1. It is unclear how these tokens get into Marketplace.
  2. While it is likely the sender sends those tokens int Marketplace first then make the desired calls, it is more clear if transferFrom is used explicitly.
Impact

With transfer(), it is unclear what the workflow looks like to leverage Marketplace for swaps between the zcTokens and underlying assets. With transferFrom(), it would be much clearer. It is also more consistent with mint() and burn() functions.

Recommendation

Change transfer from transferFrom:

Safe.transferFrom(ERC20(address(pool.base())), msg.sender, address(pool), a); OR Safe.transferFrom(ERC20(address(pool.fyToken())), msg.sender, address(pool), a);

#0 - sourabhmarathe

2022-06-29T17:52:51Z

Duplicate of #21.

Findings Information

🌟 Selected for report: datapunk

Labels

bug
2 (Med Risk)
disagree with severity
sponsor confirmed

Awards

1134.6506 USDC - $1,134.65

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L446

Vulnerability details

Impact

The lend function for tempus will fail with the right market.

Proof of concept

checks if (ITempus(principal).yieldBearingToken() != IERC20Metadata(u)), while it should check ITempus(principal).backingToken()

Recommendation

Do this instead:

if (ITempus(principal).backingToken() != IERC20Metadata(u))

#0 - KenzoAgada

2022-06-28T14:58:54Z

I think should probably be medium severity as user funds not at risk.

Findings Information

🌟 Selected for report: hyh

Also found by: datapunk, unforgiven

Labels

bug
duplicate
2 (Med Risk)

Awards

206.7901 USDC - $206.79

External Links

Lines of code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L143 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L158 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L173 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L188 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L648

Vulnerability details

Impact

The preview functions return potential swap results, the caller should check these results first to avoid extreme slippages. Otherwise, the caller functions can be sandwich attacked since there is no slippage tolerance limit and the transaction won't revert even if there was 99% slippage when doing the swaps.

Recommendation

Check preview returns against an acceptable slippage limit, and revert otherwise. If it is too high it can lead to Denial of Service attacks but zero slippage tolerance limit is not much better.

#0 - sourabhmarathe

2022-06-28T21:08:17Z

Duplicate of #389.

#1 - gzeoneth

2022-07-24T15:59:52Z

Consider with warden's QA report #128

Severity: QA

wrong comments

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L153 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/redeemer/Redeemer.sol#L89

Severity: QA

remove extra code

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L627

should be

address illuminateToken = principalToken(u, m);

Severity: QA

Check underlying and maturity of principal token when being set in Marketplace.sol instead of when being used in Lender.sol

Proof of Concept

There are multiple places in Lender.sol such as below, where principal token is checked for underlying token and maturity: https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L331 The check could happen in Marketplace.sol when they are first set in: https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L67 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L98

Impact

Checking Principal address early can:

  1. make sure no mistakes are made when Principal markets are set. As once set, they are immutable.
  2. save gas, when Lender.sol is called to lend, as there is no more need to check validity multiple times.

Move u/m checking to Marketplace.sol from Lender.sol

Severity: Gas

use uint256 max = type(uint256).max in place of uint256 max = 2**256 - 1;

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L84 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L112

Severity: Gas

use ++i in place of i++

https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L96 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L120 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L289

Severity: Gas

Check underlying and maturity of principal token when being set in Marketplace.sol instead of when being used in Lender.sol

Proof of Concept

There are multiple places in Lender.sol such as below, there principal token is checked for underlying token and maturity: https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/lender/Lender.sol#L331 The check could happen in Marketplace.sol when they are first set in: https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L67 https://github.com/code-423n4/2022-06-illuminate/blob/912be2a90ded4a557f121fe565d12ec48d0c4684/marketplace/MarketPlace.sol#L98

Impact

Checking Principal address ealy can:

  1. make sure no mistakes are made when Principal markets are set. As once set, they are immutable.
  2. save gas, when Lender.sol is called to lend, as there is no more need to check validity multiple times.

Move u/m checking to Marketplace.sol from Lender.sol

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