Platform: Code4rena
Start Date: 12/07/2022
Pot Size: $35,000 USDC
Total HM: 13
Participants: 78
Period: 3 days
Judge: 0xean
Total Solo HM: 6
Id: 135
League: ETH
Rank: 1/78
Findings: 3
Award: $3,503.48
🌟 Selected for report: 1
🚀 Solo Findings: 0
As defined in the docs for Euler, ERC4626, Compound and Aave, when withdrawing and depositing funds the amount
specified corresponds excactly to how many of the underlying assets are deposited or withdrawn.
However, as specified by Yearn, the yearn withdraw amount
parameter specifies how many shares
are burnt instead of underlying assets retrieved. Two scenarios can occur from then on, if there are not enough shares then the transaction will revert and users will not be able to redeem the underlying assets from Yearn. If there are enough shares, then a higher number of assets will be withdrawn then expected (as assets per share will only increase). This means that once the user receives their underlying assets at a 1:1 peg the excess amoutns will be permanently locked in the vault contract.
All scenarios use Yearn finance as the protocol, the other protocols are unaffected
Scenario #1
100 / 200 * 50 = 25
shares are minted for the vault so we now have 75 shares and 300 uTokens in the yearn vaultScenario #2
100 / 100 * 50 = 50
shares are minted for the vault so we now have 100 shares and 200 uTokens in the yearn vaultVS Code
In the withdraw()
function in Swivel.sol, calculating the price per share and use that to retrieve the correct number of underlying assets
e.g.
uint256 pricePerShare = IYearnVault(c).pricePerShare(); return IYearnVault(c).withdraw(a / pricePerShare) >= 0;
#0 - JTraversa
2022-07-15T23:17:03Z
Duplicate of #30
#1 - scaraven
2022-07-16T09:47:01Z
I do not understand how this is a duplicate of #30, #30 talks about a problem with redeemUnderlying()
in Compound while this issue talks about a problem with withdraw()
when using yearn
#2 - JTraversa
2022-07-17T07:28:59Z
They both cannot be true at once however. Either the lib expects shares, or the lib expects assets. His suggestion notes inconsistency and recommends changing the compound redeem to align with yearn, while you note the inconsistency and recommend fixing the yearn math. At the end of the day the issue is the "mismatch".
#3 - scaraven
2022-07-17T08:04:03Z
Fair enough, that makes sense. I would still disagree with their interpretation of the issue, it is clear from the code that a
represents the underlying assets. If a
does represent the number of shares then other functions such as authRedeemzcTokens
would be plain wrong because it would be redeeming each zcToken as if it was one share not one underlying asset.
#4 - JTraversa
2022-07-17T09:07:55Z
Yeah I actually kind of agree with you. We intended the implementation to align more with your ticket.
That said it might be worth a judge's input.
If they think theyre different, the other ticket is invalid/should be disputed and this one is correct.
#5 - bghughes
2022-08-04T23:44:06Z
Confirmed good issue and mark #30 as a duplicate
#6 - robrobbins
2022-09-01T18:31:48Z
🌟 Selected for report: bin2chen
Also found by: 0x52, 0xDjango, 0xSky, Picodes, auditor0517, rokinot, ronnyx2017, scaraven
106.8838 USDC - $106.88
https://github.com/code-423n4/2022-07-swivel/blob/daf72892d8a8d6eaa43b9e7d1924ccb0e612ee3c/Marketplace/MarketPlace.sol#L148-L167 https://github.com/code-423n4/2022-07-swivel/blob/daf72892d8a8d6eaa43b9e7d1924ccb0e612ee3c/Marketplace/Interfaces.sol#L52 https://github.com/code-423n4/2022-07-swivel/blob/daf72892d8a8d6eaa43b9e7d1924ccb0e612ee3c/Swivel/Swivel.sol#L620
authRedeem()
in Marketplace.sol uses the ISwivel interface and calls authRedeem()
at Swivel.sol instead of authRedeemZcToken
which does not exist. Therefore any transaction where a user tries to redeem their zcTokens for uTokens will fail.
zcToken.withdraw()
marketplace.authRedeem()
is called which then calls ISwivel(swivel).authRedeem()
VS Code
Change authRedeemZcToken()
in Swivel.sol to authRedeem()
#0 - JTraversa
2022-07-20T07:36:36Z
Duplicate of #39
#1 - robrobbins
2022-08-03T20:16:55Z
see #186
#2 - bghughes
2022-08-04T23:44:38Z
Duplicate of #39
🌟 Selected for report: joestakey
Also found by: 0x1f8b, 0x52, 0xDjango, 0xNazgul, 0xNineDec, 8olidity, Avci, Bahurum, Bnke0x0, Chom, ElKu, Funen, GimelSec, JC, Junnon, Kaiziron, Meera, PaludoX0, Picodes, ReyAdmirado, Sm4rty, Soosh, Waze, _Adam, __141345__, ak1, aysha, benbaessler, bin2chen, c3phas, cccz, cryptphi, csanuragjain, defsec, exd0tpy, fatherOfBlocks, gogo, hake, hansfriese, itsmeSTYJ, jonatascm, kyteg, mektigboy, oyc_109, pashov, rbserver, rishabh, robee, rokinot, sach1r0, sashik_eth, scaraven, simon135, slywaters
44.5897 USDC - $44.59
Compounding.sol implements underlyingAssets()
and exchangeRate()
for Rari Fuse. It however does not allow for withdrawals or deposits in Swivel.sol. Therefore a user can create a market for Rari but is barred from depositing or withdrawing funds making this functionality obselete
Consider adding the withdraw()
and deposit()
abstractions for RariFuse or removing it alltogether
Occurences: https://github.com/code-423n4/2022-07-swivel/blob/daf72892d8a8d6eaa43b9e7d1924ccb0e612ee3c/VaultTracker/Compounding.sol#L44 https://github.com/code-423n4/2022-07-swivel/blob/daf72892d8a8d6eaa43b9e7d1924ccb0e612ee3c/Tokens/Compounding.sol#L44 https://github.com/code-423n4/2022-07-swivel/blob/daf72892d8a8d6eaa43b9e7d1924ccb0e612ee3c/Marketplace/Compounding.sol#L54 https://github.com/code-423n4/2022-07-swivel/blob/daf72892d8a8d6eaa43b9e7d1924ccb0e612ee3c/Marketplace/Compounding.sol#L72 https://github.com/code-423n4/2022-07-swivel/blob/daf72892d8a8d6eaa43b9e7d1924ccb0e612ee3c/Creator/Compounding.sol#L44
#0 - robrobbins
2022-08-25T21:29:13Z
there was some missing logic in the audit repo, that was added (missing rari conditional)
libFuse was removed here:
#1 - robrobbins
2022-08-25T21:29:54Z