Platform: Code4rena
Start Date: 07/09/2022
Pot Size: $20,000 CANTO
Total HM: 7
Participants: 65
Period: 1 day
Judge: 0xean
Total Solo HM: 3
Id: 159
League: ETH
Rank: 10/65
Findings: 2
Award: $249.68
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: Chom
Also found by: 0xSmartContract, Jeiwan, SinceJuly, V_B, cccz, linmiaomiao
1303.145 CANTO - $210.46
Hackers can deploy tokens with respective names as the stable ones to impersonate the stable token. Then hackers can get profit from the malicious price oracle.
string memory symbol = ctoken.symbol(); if (compareStrings(symbol, "cCANTO")) { underlying = address(wcanto); return getPriceNote(address(wcanto), false); } else { underlying = address(ICErc20(address(ctoken)).underlying()); // We are getting the price for a CErc20 lending market } //set price statically to 1 when the Comptroller is retrieving Price if (compareStrings(symbol, "cNOTE")) { // note in terms of note will always be 1 return 1e18; // Stable coins supported by the lending market are instantiated by governance and their price will always be 1 note } else if (compareStrings(symbol, "cUSDT") && (msg.sender == Comptroller )) { uint decimals = erc20(underlying).decimals(); return 1e18 * 1e18 / (10 ** decimals); //Scale Price as a mantissa to maintain precision in comptroller } else if (compareStrings(symbol, "cUSDC") && (msg.sender == Comptroller)) { uint decimals = erc20(underlying).decimals(); return 1e18 * 1e18 / (10 ** decimals); //Scale Price as a mantissa to maintain precision in comptroller }
If hackers or malicious admin deploy a non-stable token but has "cNOTE", "cUSDT", or "cUSDC" as symbols, these tokens will act as a stable token while in fact, it isn't.
Use fixed address whitelisting instead for example if (address(ctoken) == cUSDC_address) ...
where cUSDC_address
is an immutable variable set on the constructor.
#0 - tkkwon1998
2022-09-08T20:38:31Z
The warden is saying that malicious parties could deploy a token with the same name to impersonate other tokens, but that these tokens will use the same pricing methodology as the token it is impersonating.
However, as this is an open EVM, anyone could deploy any token name with any underlying price method. I fail to see how this would be an issue, since everything is open source and users can see what they are doing.
#1 - 0xean
2022-09-14T20:04:19Z
What is the benefit the sponsor is trying to achieve by comparing a non unique string compared to a unique address?
While everything is open source, it does seem like this is a pretty bad design choice when compared to the alternative solutions.
#2 - nivasan1
2022-10-11T03:50:21Z
@0xean, the design choice presented here prevents from having multiple dependencies in the initialization of the oracle. Furthermore, the tokens that are referenced here must be supported by governance, so to override the actual prices would require a >51% voting power. As such, even if the exploit exists it is essentially impossible. As such, we do not believe that this is a high / med -risk issue.
#3 - 0xean
2022-10-13T00:30:44Z
Will downgrade to M as there are several external factors for this to become an issue.
🌟 Selected for report: lukris02
Also found by: 0x040, 0x1f8b, 0x52, 0xA5DF, 0xNazgul, 0xSky, Bnke0x0, Bronicle, CertoraInc, Chom, CodingNameKiki, Deivitto, Diraco, Dravee, EthLedger, IgnacioB, JC, JansenC, Jeiwan, R2, RaymondFam, ReyAdmirado, Rolezn, SinceJuly, TomJ, Tomo, Yiko, a12jmx, ajtra, ak1, codexploder, cryptphi, csanuragjain, erictee, fatherOfBlocks, gogo, hake, hansfriese, hickuphh3, ignacio, ontofractal, oyc_109, p_crypt0, pashov, peritoflores, rajatbeladiya, rbserver, rokinot, rvierdiiev, tnevler
242.8216 CANTO - $39.22
https://github.com/code-423n4/2022-09-canto/blob/65fbb8b9de22cf8f8f3d742b38b4be41ee35c468/src/Swap/BaseV1-periphery.sol#L524-L593 https://github.com/code-423n4/2022-09-canto/blob/65fbb8b9de22cf8f8f3d742b38b4be41ee35c468/src/Swap/BaseV1-core.sol#L45
Using an average of 8 periods, each period covering 30 minutes may cause the price to be extremely delayed. Hackers can profit from these delays.
In crypto, the price can +100% in just 30 minutes. Imagine volatility of 8 * 30 = 240 minutes = 4 hours. Hackers can profit a lot from these delays. Moreover, if the market crash just like UST, the liquidator can't liquidate assets in time due to extremely delayed price, causing bad debt.
uint public periodSize = 1800;
Every 30 minutes one observation will be stored.
... uint price = IBaseV1Pair(pair).quote(address(token), decimals, 8); ... for(uint i; i < 8; ++i) { uint token0TVL = assetReserves[i] * (prices[i] / decimals); uint token1TVL = unitReserves[i]; // price of the unit asset is always 1 LpPricesCumulative += (token0TVL + token1TVL) * 1e18 / supply[i]; } uint LpPrice = LpPricesCumulative / 8; // take the average of the cumulative prices ...
Many functions in BaseV1-periphery use an average of 8 periods = 240 minutes = 4 hours which is ridiculously long.
Reduce periodSize to 5 minutes
#0 - nivasan1
2022-09-09T19:39:08Z
The Pricing in the lending market is meant to be as resistant to large swings in volatility as possible to protect suppliers in each cToken market, changing to a shorter period size leaves the possibility of attackers manipulating prices through flash-loans over time. Also the period size can be changed through governance in the case that the community decides to decrease the TWAP.
#1 - 0xean
2022-09-12T14:55:23Z
This is a design tradeoff on the "correct" time for the TWAP, hard to see it as a critical vulnerability. Downgrading to QA. Warden has no QA report, so this will stand as theirs.