Platform: Code4rena
Start Date: 23/06/2023
Pot Size: $60,500 USDC
Total HM: 31
Participants: 132
Period: 10 days
Judge: 0xean
Total Solo HM: 10
Id: 254
League: ETH
Rank: 18/132
Findings: 5
Award: $570.57
🌟 Selected for report: 0
🚀 Solo Findings: 0
281.1877 USDC - $281.19
EUSD treats sharesAmount == 0
as totalSupply == 0
, which is wrong and when exchangeRate = share / amount > 1
, resulting in excess tokens being minted to users.
uint256 sharesAmount = getSharesByMintedEUSD(_mintAmount); if (sharesAmount == 0) { // EUSD totalSupply is 0: assume that shares correspond to EUSD 1-to-1 sharesAmount = _mintAmount; }
Assume exchangeRate increases to 2.1:
But the user is unaware, because he thinks that only 2 EUSD are mint
Manual review
Check _totalSupply
not sharesAmount
Context
#0 - c4-pre-sort
2023-07-10T12:05:45Z
JeffCX marked the issue as duplicate of #106
#1 - c4-judge
2023-07-28T15:32:13Z
0xean marked the issue as satisfactory
#2 - c4-judge
2023-07-28T19:44:39Z
0xean changed the severity to 3 (High Risk)
🌟 Selected for report: No12Samurai
145.801 USDC - $145.80
ProtocolRewardsPool rewards are divided into categories that cannot be simply added, mixing them together and impact on the previous staking users' reward.
We can look at how rewards are calculated based on the code. There are three categories:
They are three different categories, can not be simply added together, we use EUSD share as the base:
These is the problems of rewardPerTokenStored
caculation in notifyRewardAmount
, and there are corresponding problems in getReward
: After fixing the calculation issue with rewardPerTokenStored
, the reward(EUSD share) will need to be converted to the corresponding token amount when distributing USDC and PEUSD.
Finally, explain why there is an impact on the previous staking users' reward:
Manual review
The number of rewards should not be simply added up; they need to be converted to the same type first
Context
#0 - c4-pre-sort
2023-07-10T19:36:25Z
JeffCX marked the issue as duplicate of #869
#1 - c4-judge
2023-07-28T15:36:57Z
0xean marked the issue as satisfactory
#2 - c4-judge
2023-07-28T19:43:45Z
0xean changed the severity to 2 (Med Risk)
#3 - c4-judge
2023-07-29T22:06:50Z
0xean marked the issue as duplicate of #604
84.3563 USDC - $84.36
ProtocolRewardsPool getReward function EUSD.transferShares
's amount miscalculation, as a result, users cannot claim rewards when the contract does not have enough EUSD.
uint256 balance = EUSD.sharesOf(address(this)); uint256 eUSDShare = balance >= reward ? reward : reward - balance; EUSD.transferShares(msg.sender, eUSDShare);
If balance < reward
, eUSDShare should be balance
instead of reward - balance
.
Manual review
Use correct amount
Context
#0 - c4-pre-sort
2023-07-10T13:46:34Z
JeffCX marked the issue as duplicate of #161
#1 - c4-judge
2023-07-28T15:44:24Z
0xean marked the issue as satisfactory
🌟 Selected for report: bytes032
Also found by: 0xMAKEOUTHILL, 0xgrbr, 0xkazim, 0xnacho, Arz, Co0nan, CrypticShepherd, Cryptor, HE1M, Iurii3, LaScaloneta, LokiThe5th, LuchoLeonel1, MrPotatoMagic, Musaka, Qeew, RedTiger, SovaSlava, Toshii, Vagner, a3yip6, azhar, bart1e, devival, hl_, jnrlouis, kutugu, peanuts, pep7siup, qpzm, smaul
1.3247 USDC - $1.32
https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/LybraRETHVault.sol#L47 https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/pools/LybraWbETHVault.sol#L35
The getExchangeRate / exchangeRate function is inexistence, causing LybraRETHVault / LybraWbETHVault vault to be unavailable.
According to the actual contract address, the names of the functions that obtain exchangeRate are getExchangeRate
and exchangeRate
, not getExchangeRatio
or exchangeRatio
.
Manual review
Modify function name and interface
Context
#0 - c4-pre-sort
2023-07-08T14:27:48Z
JeffCX marked the issue as duplicate of #27
#1 - c4-judge
2023-07-28T17:15:43Z
0xean marked the issue as satisfactory
🌟 Selected for report: 0xnev
Also found by: 0xRobocop, 0xbrett8571, 0xkazim, 0xnacho, 3agle, 8olidity, ABAIKUNANBAEV, Bauchibred, Co0nan, CrypticShepherd, D_Auditor, DelerRH, HE1M, Iurii3, Kaysoft, MrPotatoMagic, RedOneN, RedTiger, Rolezn, SanketKogekar, Sathish9098, Timenov, Toshii, Vagner, bart1e, bytes032, codetilda, devival, halden, hals, kutugu, m_Rassska, naman1778, nonseodion, seth_lawson, solsaver, squeaky_cactus, totomanov, y51r, yudan, zaevlad
57.9031 USDC - $57.90
ID | Title | Severity |
---|---|---|
[L-01] | The collateralAmount and getClaimAbleLBR have an accuracy error | Low |
[L-02] | The extraRatio and rewardRatio updates should pass through the time lock | Low |
[L-03] | StakedLBRLpValue value can be manipulated | Low |
[L-04] | There are accuracy problems in EUSD internal accounting calculations | Low |
[N-01] | Decimals for collateral and USD may not be equal | Non-Critical |
[N-02] | ProtocolRewardsPool getReward event parameter miscalculation | Non-Critical |
uint256 collateralAmount = (((eusdAmount * 1e18) / assetPrice) * (10000 - configurator.redemptionFee())) / 10000;
function getClaimAbleLBR(address user) public view returns (uint256 amount) { if (time2fullRedemption[user] > lastWithdrawTime[user]) { amount = block.timestamp > time2fullRedemption[user] ? unstakeRatio[user] * (time2fullRedemption[user] - lastWithdrawTime[user]) : unstakeRatio[user] * (block.timestamp - lastWithdrawTime[user]); } }
The collateralAmount and getClaimAbleLBR have precision error in dividing before multiplying.
Multiply before divide
The calculation of incentives in EUSDMiningIncentives relies on extraRatio and rewardRatio, whose updates depend on the owner instead of the time lock.
If the owner updates the extraRatio and rewardRatio in an instant, such as reducing them, the user will not have time to claim the previous reward and will have less to claim later.
But a small number of people like searchers will listen to mempool to frontrun to claim the previous reward, which is unfair.
It should be updated with a time lock so that most users have time to claim their previous rewards.
The extraRatio and rewardRatio updates should pass through the time lock
StakedLBRLpValue using the balance in the uniswap lp pool to calculate the value is not a problem for internal temporary use, because even if staker temporarily manipulates the price to avoid liquidation, it would not be sustainable for long.
However, if an external contract invokes this interface, it may cause a loss. It is better to use reserve rather than balance to calculate the lp value.
Use reserve rather than balance to calculate the lp value.
The core problem is that the getSharesByMintedEUSD
function has an accuracy error. In EUSD, due to the presence of burnShares
, the exchangeRate of balance / share
will increase. Assume exchangeRate increase to 1.1.
When a user or other contract interacts with EUSD, if the input amount is 1, it is converted to 0 shares, that is, the amount of the user account will not change, which can cause a series of problems for external contracts.
For example, tranfer and burn trigger the transfer event, which causes the external contract to think that the transfer has been made, but the actual user amount remains unchanged.
The precision error is reduced to 0 and a zero-value event should be triggered
Code do not take into account collateral and usd decimals may not equal. Although the LST used now is all 18.
Add decimals convert.
} else { if(peUSDBalance > 0) { peUSD.transfer(msg.sender, peUSDBalance); } ERC20 token = ERC20(configurator.stableToken()); uint256 tokenAmount = (reward - eUSDShare - peUSDBalance) * token.decimals() / 1e18; token.transfer(msg.sender, tokenAmount); emit ClaimReward(msg.sender, EUSD.getMintedEUSDByShares(eUSDShare), address(token), reward - eUSDShare, block.timestamp); } } else { emit ClaimReward(msg.sender, EUSD.getMintedEUSDByShares(eUSDShare), address(0), 0, block.timestamp); }
For other stable token, tokenAmount is reward - eUSDShare - peUSDBalance
, not reward - eUSDShare
; For EUSD, tokenAmount is reward
not 0
and address is address(EUSD)
.
Fix event parameter
#0 - c4-pre-sort
2023-07-27T20:17:25Z
JeffCX marked the issue as high quality report
#1 - c4-judge
2023-07-27T23:57:45Z
0xean marked the issue as grade-a
#2 - c4-sponsor
2023-07-29T10:54:41Z
LybraFinance marked the issue as sponsor acknowledged