Platform: Code4rena
Start Date: 08/05/2023
Pot Size: $90,500 USDC
Total HM: 17
Participants: 102
Period: 7 days
Judge: 0xean
Total Solo HM: 4
Id: 236
League: ETH
Rank: 7/102
Findings: 4
Award: $2,930.40
π Selected for report: 1
π Solo Findings: 0
π Selected for report: peanuts
Also found by: 0xStalin, jasonxiale, volodya
731.996 USDC - $732.00
https://github.com/code-423n4/2023-05-venus/blob/main/contracts/Lens/PoolLens.sol#L266-L273
Incorrectly calculation of the totalBadDebtUsd for an entire pool. Depending on the usage the protol has for this information it could disrupt core mechanisms or cause problems with the internal accounting
Following the math applied on the ChainlinkOracle
contract of the Venus Protocol, the price is returned in the scale of 10 ^ (36 - underlying asset decimals))
Example
WBNB (18 decimals in BSC). USD price: $300. Value returned by the Oracles: 300^1e18 TRX (6 decimals in BSC). USD price: $0.068. Value returned by the Oracles: 0.068^1e30
Manual Audit
Make sure to divide the result of multiplying the badDebt()
of the current market * the price of the underlyingasset by 10^18 to normalize the units before assigning the value of the badDebtUsd
badDebt.badDebtUsd = (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) / 1e18;
Decimal
#0 - c4-judge
2023-05-17T16:47:49Z
0xean marked the issue as duplicate of #468
#1 - c4-judge
2023-05-18T10:42:46Z
0xean marked the issue as not a duplicate
#2 - c4-judge
2023-05-18T10:42:53Z
0xean marked the issue as duplicate of #316
#3 - c4-judge
2023-06-05T14:24:58Z
0xean marked the issue as satisfactory
#4 - c4-judge
2023-06-05T14:41:13Z
0xean changed the severity to 2 (Med Risk)
π Selected for report: 0xStalin
Also found by: J4de, rvierdiiev
1409.77 USDC - $1,409.77
https://github.com/code-423n4/2023-05-venus/blob/main/contracts/Comptroller.sol#L469-L472
Borrowers can cause DoS when liquidator attempts to liquidate a 100% of the borrower's position. The borrower just need to frontrun the liquidation tx and repay a slightly portion of the debt, paying as low as 1 wei will make the borrowBalance to be less than what it was when the liquidator sent the tx to liquidate the position.
If aliquidator intends to liquidate the entire position, but the borrower frontruns the liquidator's transaction and repays an insignificant amount of the total debt, will cause the borrowBalance to be less than it was when the liquidator sent its transaction, thus, will cause the value of the maxClose variable to be less than the repayAmount that the liquidator set to liquidate the whole position, which will end up causing the tx to be reverted because of this validation
Example
maxClose
was at that point, the borrower realizes that the 100% of its position will be liquidated and then frontruns the liquidation transaction by repaying an insignificant amount of the total borrow.Manual Audit
Instead of reverting the tx if the repayAmount is greater than maxClose, recalculate the final repayAmount to be paid during the execution of the liquidation and return this calculated value back to the function that called the preLiquidateHook()
function preLiquidateHook( ... uint256 repayAmount, ... + ) external override returns(uint256 repayAmountFinal) { ... ... - if (repayAmount > maxClose) { - revert TooMuchRepay(); - } + repayAmountFinal = repayAmount > maxClose ? maxClose : repayAmount
DoS
#0 - c4-judge
2023-05-17T20:22:58Z
0xean marked the issue as primary issue
#1 - c4-sponsor
2023-05-23T20:44:59Z
chechu marked the issue as disagree with severity
#2 - chechu
2023-05-23T20:45:03Z
Suggestion: Med
Front running attacks can be easily avoid by liquidator, connecting to the right nodes and using private mempools. Moreover, the borrower will need to spend gas to defend their position against several liquidators
#3 - 0xean
2023-05-31T00:11:57Z
I think M makes sense here, but will be open to warden comments during QA process.
#4 - c4-judge
2023-05-31T00:12:09Z
0xean changed the severity to 2 (Med Risk)
#5 - c4-judge
2023-06-05T14:24:06Z
0xean marked the issue as satisfactory
#6 - c4-judge
2023-06-05T16:59:37Z
0xean marked the issue as selected for report
π Selected for report: 0xnev
Also found by: 0xStalin, BugBusters, chaieth
731.996 USDC - $732.00
https://github.com/code-423n4/2023-05-venus/blob/main/contracts/RiskFund/RiskFund.sol#L265
Selling of asset tokens misses the transaction expiration check, which may lead to reward tokens being sold at a price that's lower than the market price at the moment of a swap.
The _swapAsset()
function, which is responsible for selling tokens on Pancackeswap, sets the deadline argument of the amountOutMin
call to block.timestamp
, which basically disables the transaction expiration check because the deadline will be set to whatever timestamp the block including the transaction is minted at.
Transaction expiration check (implemented in Pancackeswap via the deadline
argument) allows users of Pancackeswap to protect from selling tokens at an outdated price that's lower than the current price. Consider this scenario:
RiskFund.swapPoolsAssets()
function is called.amountOutMin
was calculated based on an outdated baseToken price which is now lower than the current price, the swapping is sandwiched by a MEV bot. The bot decreases the price of the reward token in a Pancackeswap pool so than the minimum output amount check still holds and earns a profit from the swapping happing at a lower price.Manual Audit
Consider a reasonable value to the deadline argument. For example, Uniswap sets it to 30 minutes on the Ethereum mainnet and to 5 minutes on L2 networks, taking as reference those values, estimate how much time would be a reasonable value for the BSC chain. Also consider letting the caller to change the value when on-chain conditions change and may require a different value.
MEV
#0 - c4-judge
2023-05-18T12:01:46Z
0xean marked the issue as duplicate of #167
#1 - c4-judge
2023-06-05T14:15:34Z
0xean marked the issue as satisfactory