Platform: Code4rena
Start Date: 24/06/2021
Pot Size: $80,000 USDC
Total HM: 18
Participants: 12
Period: 7 days
Judge: cemozer
Total Solo HM: 11
Id: 16
League: ETH
Rank: 4/12
Findings: 4
Award: $10,396.42
π Selected for report: 4
π Solo Findings: 1
3019.5792 USDC - $3,019.58
0xsanson
In the Pricing contract, an agent can manipulate the trading prices by spamming an high amount of trades.
Indeed an agent can create an high amount of orders at an arbitrary price and with a near-zero amount (so the agent doesn't even need large funds); next he/she pairs the orders with another account and calls Trader.executeTrade; now every order calls a Pricing.recordTrade using the arbitrary price set by the agent.
Since the trades are all made in the same hour, by the way hourlyTracerPrices[currentHour] is calculated, it skews the average price towards the price set by the agent. This arbitrary value is used to calculate the fundingRates and the fairPrice, letting a malicious agent get the ability to manipulate the market.
https://github.com/code-423n4/2021-06-tracer/blob/main/src/contracts/Pricing.sol#L129
Manual analysis
Pass the fillAmount parameter to recordTrade(...), and calculate hourlyTracerPrices[currentHour].trades summing fillAmount instead of 1 every trade.
#0 - raymogg
2021-07-05T03:03:03Z
Issue is valid, and there appear to be a few other issues that reference similar problems.
The Trader contract will have a whitelist allowing only select relayers to push orders on chain. As long as off chain order books have sufficient liquidity, this issue is then mitigated as users can't just arbitrarily match orders and send them in, they must be matched on a book with liquidity. To alter the price you would then need to eat through significant liquidity (increasing the cost of this attack).
π Selected for report: 0xsanson
6710.1761 USDC - $6,710.18
0xsanson
In LibBalances.applyTrade() we need to collect a fee from the trade. The current code however subtracts a fee from the short position and adds it to the long. The correct implementation is to subtract a fee to both (see TracerPerpetualSwaps.sol#L272). This issue causes withdrawals problems, since Tracer thinks it can withdraw the collect fees, leaving the users with an incorrect amount of quote tokens.
https://github.com/code-423n4/2021-06-tracer/blob/main/src/contracts/lib/LibBalances.sol#L187
Manual analysis
Change +fee to -fee in the highlighted line.
#0 - raymogg
2021-07-05T04:36:05Z
Valid issue π
#1 - kumar-ish
2021-07-15T12:58:54Z
(Accidentally closed)
π Selected for report: 0xsanson
333.3333 USDC - $333.33
0xsanson
We can save gas by substituting getPoolTarget() with levNotionalValue/100, since tracer.leveragedNotionalValue() is already saved in memory.
https://github.com/code-423n4/2021-06-tracer/blob/main/src/contracts/Insurance.sol#L216
Manual analysis.
Substitute getPoolTarget() with levNotionalValue/100.
π Selected for report: 0xsanson
333.3333 USDC - $333.33
0xsanson
In Liquidation.verifyAndSubmitLiquidation(...) we can save the minimumMargin to memory since it's called two times.
https://github.com/code-423n4/2021-06-tracer/blob/main/src/contracts/Liquidation.sol#L171
Manual analysis
Save the result of Balances.minimumMargin(...) to memory.
#0 - kumar-ish
2021-07-15T13:26:19Z
Also closed by accident