Lybra Finance - Jorgect's results

A protocol building the first interest-bearing omnichain stablecoin backed by LSD.

General Information

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

Lybra Finance

Findings Distribution

Researcher Performance

Rank: 66/132

Findings: 1

Award: $84.36

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: Musaka

Also found by: Brenzee, Bughunter101, HE1M, Jorgect, kutugu, pep7siup

Labels

bug
2 (Med Risk)
satisfactory
duplicate-223

Awards

84.3563 USDC - $84.36

External Links

Lines of code

https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/miner/ProtocolRewardsPool.sol#L196

Vulnerability details

The ProtocolRewardContract is doing a wrong calculation to pay the rewards in case that the balance of the EURS is not enought (in case that is no enought in EUSD to pay the reward, the contract pay whit other token), i explain this clearly in the proof of concept.

Impact

In some cases the user can no claim his rewards because the function revert

Proof of Concept

To see this problem see this part of the getReward function:

function getReward() external updateReward(msg.sender) { ... uint256 balance = EUSD.sharesOf(address(this)); uint256 eUSDShare = balance >= reward ? reward : reward - balance; EUSD.transferShares(msg.sender, eUSDShare); ...}

https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/miner/ProtocolRewardsPool.sol#L196

If the contract doesn´t has enought balance to pai the whole reward in EUSD, it is substracting the reward and balance, This is wrong and we can see this with this simple example, imagine that the balance is 1 and the reward is 3 the final value of the eUSDShare is gonna be 2 which is still less than the balance, so the transferShares function is gonna revert.

Tools Used

manual review

to avoid this devs can send the whole balance in case that is not enought to pay the reward and then pay with the next token. see the code below :

function getReward() external updateReward(msg.sender) { uint reward = rewards[msg.sender]; if (reward > 0) { rewards[msg.sender] = 0; IEUSD EUSD = IEUSD(configurator.getEUSDAddress()); uint256 balance = EUSD.sharesOf(address(this)); uint256 eUSDShare = balance >= reward ? reward : balance; EUSD.transferShares(msg.sender, eUSDShare); if(reward > eUSDShare) { ERC20 peUSD = ERC20(configurator.peUSD()); uint256 peUSDBalance = peUSD.balanceOf(address(this)); if(peUSDBalance >= reward - eUSDShare) { peUSD.transfer(msg.sender, reward - eUSDShare); emit ClaimReward(msg.sender, EUSD.getMintedEUSDByShares(eUSDShare), address(peUSD), reward - eUSDShare, block.timestamp); } 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); }

Assessed type

Other

#0 - c4-pre-sort

2023-07-10T13:44:58Z

JeffCX marked the issue as duplicate of #161

#1 - c4-judge

2023-07-28T15:44:20Z

0xean marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter