Platform: Code4rena
Start Date: 28/09/2023
Pot Size: $36,500 USDC
Total HM: 5
Participants: 115
Period: 6 days
Judge: 0xDjango
Total Solo HM: 1
Id: 290
League: ETH
Rank: 31/115
Findings: 2
Award: $185.96
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Bauchibred
Also found by: 0x3b, 0xDetermination, 0xMosh, 0xScourgedev, 0xTheC0der, 0xTiwa, 0xWaitress, 0xdice91, 0xfusion, 0xpiken, 0xprinc, 0xweb3boy, ArmedGoose, Aymen0909, Breeje, Brenzee, Daniel526, DavidGiladi, DeFiHackLabs, Flora, Fulum, HChang26, Hama, IceBear, J4X, Krace, KrisApostolov, Maroutis, Mirror, MohammedRizwan, Norah, PwnStars, SPYBOY, TangYuanShen, Testerbot, ThreeSigma, Tricko, al88nsk, alexweb3, ast3ros, berlin-101, bin2chen, blutorque, btk, d3e4, deth, e0d1n, ether_sky, ge6a, gkrastenov, glcanvas, hals, imare, inzinko, jkoppel, jnforja, joaovwfreire, josephdara, kutugu, lotux, lsaudit, mahdirostami, merlin, n1punp, nadin, neumo, nisedo, nobody2018, oakcobalt, orion, peanuts, pep7siup, pina, ptsanev, rokinot, rvierdiiev, said, santipu_, sashik_eth, seerether, squeaky_cactus, terrancrypt, tonisives, twicek, vagrant, xAriextz, y4y
62.2092 USDC - $62.21
IPrime.sol
and Prime.sol
The function accrueInterest(address vToken)
is marked as external
in IPrime.sol
and public
in Prime.sol
. This will lead to an issue when in future the interface is inherited in any other smart contract, then the function accrueInterest(address vToken)
will not be able to be called internally. <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/IPrime.sol#L9
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L554 <br>
Mitigation : either change the visibility of the function to public
or create another IPrime.sol
in future to inherit with the required visibility of that function.
PrimeLiquidityPrivider.sol/setPrimeToken()
is very much vulnerable to frontrun by the function releaseFunds()
of the same contract.The prime tokens either releases sends the funds to the old prime contract, or just stop them from going them to the old contract. If the intention is to not let go the funds to the old contract(which is possible due to the frontrun by the releasefunds
function under certain conditions), then pause the funds transfer using pauseFundsTransfer()
function and then change the prime contract address.
PrimeStorage.sol/STAKING_PERIOD
This comment says that this variable gives number of days for staking the token, but this actually gives number of seconds for which the tokens should be staked <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeStorage.sol#L39
<br>
Mitigation : change the comment to number of seconds
or change the variable to 90 days
Solidity version 0.8.13
& 0.8.14
have a security vulnerability related to assembly blocks that write to memory. Almost all in-scope contracts are written in this version, and hence will the upcoming contracts be for the consistency. The issue is fixed in version 0.8.15
and is explained here. While the problem is with the legacy optimizer, it is still correct to enforce latest Solidity version (0.8.21) or at least the one enforced in other popular library code as OpenZeppelin (0.8.19).
PrimeLiquidityProvider.sol/lastAccruedBlock
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L23-L24 <br> The comment says
/// @notice The rate at which token is distributed to the Prime contract
But the actual use of it is to see the last block at which the accrueTokens()
function is called. So the better way is
/// @notice The last block at which the tokens were accrued
PrimeLiquidityProvider.sol
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L15 <br>
Variable named as EXP_SCALE = 1e18
is redundant as not used in this contract, its used in Prime.sol
but is taken from PrimeStorage.sol
by inheriting that contract.
PrimeLiquidityProvider.sol
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L48 <br> This event is not used anywhere in this contract.
PrimeLiquidityProvider.sol
The events FundsTransferPaused()
and FundsTransferResumed()
should be emitted when the functions pauseFundsTransfer()
and resumeFundsTransfer()
are called. But these are not emitted anytime.
<br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L51-L54 <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L132-L144 <br>
prime
address in PrimeLiquidityProvider.sol
during the initialize
function is called.PrimeLiquidityProvider.sol/setPrimeToken()
lacks input validation fot the prime address to be a contractPrimeLiquidityProvider.sol/sweepTokens()
should also include the transfer of some non-erc tokens that don't follow the standard of EIP-20.Not all the tokens have the methods of safeTransfer
.
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L216
Prime.sol
event name is UserScoreUpdated()
and contain the old and new score of the user. <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L71
Prime.sol/constructor()
The addresses of WBNB
and VBNB
should also be checked to be contract and contain the bytecode. This extra check as the variables are immutable and any mistake will lead to the new contract deploy, and in sometimes the funds to be stuck. <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L107-L108
Prime.sol/togglePause()
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L419 <br>
event isPaused(indexed bool _status);
Prime.sol/claimTimeRemaining()
should check for the eligibility for the user otherwise the eligible user and ineligible users will see the same output at the very first secondAt the first second after the xvsStaked()
is called, the function claimTimeRemaining()
returns 90 days and for the person who is not eligible, the results are same. This is misleading, and should be changed for the person who is not eligible (meybe revert for them). <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L478
#0 - 0xRobocop
2023-10-07T01:49:31Z
L-02 Dup of #148
#1 - c4-pre-sort
2023-10-07T01:49:37Z
0xRobocop marked the issue as sufficient quality report
#2 - c4-judge
2023-11-03T02:49:59Z
fatherGoose1 marked the issue as grade-a
🌟 Selected for report: DavidGiladi
Also found by: 0x3b, 0xWaitress, 0xhacksmithh, 0xprinc, hihen, jkoppel, lsaudit, oakcobalt, pavankv, pontifex
123.7515 USDC - $123.75
Scores.sol/calculateScore(...)
function.This edge case can also be included to save the gas for computing the ratios, exponents and logarithms. <br> https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/libs/Scores.sol#L22-L23
if(alphaNumerator == 0){return capital} else if(alphaNumerator == alphaDenominator){return xvs}
PrimeStorage.sol/protocolShareReserve
can be made as immutable as there is no variable that changes this variable in Prime.sol
after initializehttps://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeStorage.sol#L103
Mitigation : make this immutable or make a function that changes the protocolShareReserve
address variable
PrimeStorage.sol/primeLiquidityProvider
as an instance of PrimeLiquidityProvider.sol
.This variable is been used in the Prime.sol
always after assigning it the ABI of PrimeLiquidityProvider.sol
which always needs making a new variable that is used to call the functions of PrimeLiquidityProvider.sol
externally. <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L559 <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L687 <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L976 <br>
balance value in memory in PrimeLiquidityProvider.sol/sweepTokens()
as it is used only one time.<br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L217
variable blockNumber
as it is used only one time in PrimeLiquidityProvider.sol/_initializeToken()
<br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L288-L298
lastAccruedBlock[token_]
as variable as the variable is used only one time in PrimeLiquidityProvider.sol/_ensureTokenInitialized()
<br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/PrimeLiquidityProvider.sol#L332
totalStaked
for _xvsBalanceOfUser()
in Prime.sol/xvsUpdated()
as it is ussed only one time
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L366
uint i = 0;
and just by uint i;
Many instances in Prime.sol
include <br>
Many instances of in Prime.sol
include <br>
The function accrueInterestAndUpdateScore()
has the same lines of code as these so instead of writing these lines in updateScores()
<br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L213-L214 <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L389 <br>
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L459 <br>
IVToken market = IVToken(vToken); unreleasedPSRIncome[_getUnderlying(address(market))] = 0;
This statement is redundant as the instance created from address is never used for external call, and is then used to just extract the address itself.
delete
keyword instead of manually setting the variable to default value.Using delete
keyword is incentivised by Ethereum
by returning some gas in computation. So use delete
here :
delete tokens[user].exists; delete tokens[user].isIrrevocable;
https://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L750-L751
Prime.sol/_getUnderlying()
functionhttps://github.com/code-423n4/2023-09-venus/blob/main/contracts/Tokens/Prime/Prime.sol#L932
So, better version of this code will be
if (vToken == VBNB) { return vToken;
instead of writing return VBNB
which is fetched from storage.
#0 - c4-pre-sort
2023-10-07T06:37:45Z
0xRobocop marked the issue as sufficient quality report
#1 - c4-judge
2023-11-03T17:04:47Z
fatherGoose1 marked the issue as grade-a