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
Rank: 26/88
Findings: 7
Award: $490.36
π Selected for report: 0
π Solo Findings: 0
π Selected for report: Metatron
Also found by: 0x52, WatchPug, auditor0517, cccz, datapunk, hansfriese, hyh, kenzo, kirk-baird, shenwilly, unforgiven
98.9071 USDC - $98.91
https://github.com/code-423n4/2022-06-illuminate/blob/92cbb0724e594ce025d6b6ed050d3548a38c264b/lender/Lender.sol#L294 https://github.com/code-423n4/2022-06-illuminate/blob/92cbb0724e594ce025d6b6ed050d3548a38c264b/lender/Lender.sol#L354
Lender.lend() functions for Swivel and Element don't mint for a user after the swap. So the balance of the principal token for the user will still be zero and he can't get paid back the underlying asset forever.
Solidity Visual Developer of VSCode
The amount of principal token must be minted for the user.
uint256 purchased = yield(u, y, returned, address(this)); IERC5095(principalToken(u, m)).mint(msg.sender, purchased);
uint256 purchased = IElement(e).swap(swap, fund, r, d); IERC5095(principalToken(u, m)).mint(msg.sender, purchased);
#0 - sourabhmarathe
2022-06-29T13:39:42Z
Duplicate of #391.
π Selected for report: Picodes
Also found by: Chom, Lambda, auditor0517, cryptphi, csanuragjain, hansfriese, hyh, kenzo, kirk-baird, pashov, unforgiven, zer0dot
82.1689 USDC - $82.17
Users can't receive back underlying tokens when they redeem.
Like the above comment, this function is designed to transfer underlying token to the user, but it transfers to Redeemer contract.
Solidity Visual Developer of VSCode
Modification for transfer logic.
Safe.transferFrom(IERC20(u), lender, msg.sender, amount);
#0 - sourabhmarathe
2022-06-29T14:18:11Z
Duplicate of #384.
π Selected for report: hyh
Also found by: 0x1f8b, 0x29A, Chom, Soosh, cccz, csanuragjain, hansfriese, itsmeSTYJ, kenzo, pashov, shenwilly, unforgiven
An attacker who has some positive principal balance can steal others' balance. An attacker can set an address where to burn the principal token and he can use another address that has larger than his balance. After the balance is transferred to his address, attacker's balance is remaining and he can continue again.
Solidity Visual Developer of VSCode
The principal token must be burned from the caller directly. We can modify this part like below.
token.burn(msg.sender, amount);
#0 - JTraversa
2022-07-06T18:23:03Z
Duplicate of #387
π Selected for report: kenzo
Also found by: 0x52, 0xkowloon, GalloDaSballo, Metatron, WatchPug, cccz, hansfriese, kirk-baird
54.27 USDC - $54.27
Users don't send the fee in Lender.lend() for Swivel. As a result, the total balance of the lender contract would be less than the amount it must have. So admin would lose fees or Redeemer.redeem() for some users wouldn't work correctly.
Solidity Visual Developer of VSCode
Users must transfer the underlying asset including fees. You can modify this part like below.
Safe.transferFrom(IERC20(u), msg.sender, address(this), lent + totalFee);
#0 - KenzoAgada
2022-06-28T08:16:00Z
Duplicate of #201
π Selected for report: Kumpa
Also found by: Metatron, cccz, cryptphi, hansfriese, jah, kenzo, kirk-baird, pashov, poirots
Lender.lend() for Illuminate and Yield doesn't add fees properly. As a result, admin would withdraw smaller fee than it should.
The estimated fee was transferred to the lender contract properly but that amount is not added to fees. So when admin withdraws fees, it will be less than it should.
But I don't think admin would lose it forever as admin can withdraw whole balance of contract using withdraw().
Solidity Visual Developer of VSCode
We can insert this part here.
fees[u] += calculateFee(a);
#0 - KenzoAgada
2022-06-28T06:43:48Z
Duplicate of #208
π Selected for report: defsec
Also found by: 0x1f8b, 0x29A, 0xDjango, 0xNazgul, 0xNineDec, 0xf15ers, 0xkowloon, 0xmint, Bnke0x0, BowTiedWardens, Chom, ElKu, Funen, GalloDaSballo, GimelSec, IllIllI, JC, Kenshin, Kulk0, Lambda, Limbooo, MadWookie, Metatron, Picodes, Soosh, StErMi, TomJ, WatchPug, Waze, Yiko, _Adam, ak1, asutorufos, aysha, bardamu, catchup, datapunk, delfin454000, dipp, fatherOfBlocks, grGred, hake, hansfriese, hyh, joestakey, kebabsec, kenzo, kirk-baird, oyc_109, pashov, poirots, rfa, robee, saian, sashik_eth, shenwilly, simon135, slywaters, z3s, zeesaw, zer0dot
65.8003 USDC - $65.80
I've found 4 low-risk issues and some non-critical issues.
function setFee(uint256 f) external authorized(admin) returns (bool) { feenominator = f; return true; }
emit Lend(p, u, m, lent);
Originally Lend event should emit returned amount of PT. So it should emit the return value of yield() function. I've explain in detail in my High risk finding "Lender.lend() functions for Swivel and Element don't mint for user after swap."
emit Redeem(0, u, m, amount);
0 must be changed to p because p != 0 in this case.
emit Redeem(p, u, m, amount);
return lent;
It's same as the above L-02 issue. It should return the result of yield() function
/// @return uint128 amount of PT bought
@return uint128 amount of PT sold
/// @param a amount of principal tokens to lend
a is amount of underlying token for lend() functions. Below links are same issues.
// max is the maximum integer value for a 256 unsighed integer
unsighed => unsigned
address illuminateToken = principalToken(u, m);(u, m);
(u, m);
π Selected for report: BowTiedWardens
Also found by: 0v3rf10w, 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, 0xkowloon, Bnke0x0, ElKu, Fitraldys, Funen, GalloDaSballo, IllIllI, JC, Kaiziron, Lambda, MadWookie, Noah3o6, Nyamcil, RoiEvenHaim, TomJ, Tomio, UnusualTurtle, Waze, _Adam, ajtra, asutorufos, bardamu, c3phas, catchup, datapunk, defsec, delfin454000, fatherOfBlocks, grGred, hake, hansfriese, hyh, ignacio, joestakey, kebabsec, ladboy233, oyc_109, pashov, poirots, rfa, robee, sach1r0, samruna, sashik_eth, simon135, slywaters, z3s, zer0dot
63.0781 USDC - $63.08
return feenominator > 0 ? a / feenominator : 0;
for (uint256 i = 0; i < o.length; ) {
for (uint256 i = 0; i < o.length; ) {
uint256 lent = a - fee;
uint256 lent = a - fee;
Safe.transfer(token, admin, balance);
Safe.transfer(token, admin, token.balanceOf(address(this)));
address public apwineAddr;