Lybra Finance - 0xcm'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: 56/132

Findings: 1

Award: $143.49

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: Neon2835

Also found by: 0xRobocop, 0xcm, Arz, DedOhWale, HE1M, MohammedRizwan, azhar, kankodu, zaevlad

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
duplicate-769

Awards

143.4901 USDC - $143.49

External Links

Lines of code

https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/token/PeUSDMainnetStableVision.sol#L129-L140

Vulnerability details

Impact

The impact of this issue is potentially severe. An attacker can initiate a flash loan under the receiver contract's identity, and the receiver contract will have to bear the associated fees. The receiver contract is unable to verify the initiator of the flash loan due to the absence of a source parameter in the onFlashLoan callback.

Proof of Concept

Given:

  • Contract PeUSDMainnet that allows flash loans with a flash loan fee of 0.3%.
  • FlashBorrower contract that implements onFlashLoan.

When:

  1. Alice, an attacker, initiates a flash loan using the function executeFlashloan of PeUSDMainnet, requesting 1000 eUSD and setting FlashBorrower as the receiver. The expected flash loan fee for this transaction is 3 eUSD (0.3% of 1000 eUSD).
  2. The PeUSDMainnet contract transfers the requested 1000 eUSD to the FlashBorrower contract and calls the onFlashLoan function.
  3. However, since there's no information about who initiated the flash loan in the onFlashLoan function, the FlashBorrower contract cannot verify the initiator and is forced to pay the flash loan fee of 3 eUSD.
  4. The FlashBorrower contract ends up receiving only 997 eUSD (1000 eUSD - 3 eUSD) without having initiated the flash loan transaction, and Alice pays nothing.

A possible mitigation to this problem is to provide the onFlashLoan function with the information about the initiator of the loan, which would allow the receiver to verify who is the actual initiator of the loan. This could be implemented by adding an address initiator parameter to the onFlashLoan function and passing msg.sender to it when calling onFlashLoan in executeFlashloan.

Consider changing the implementation to:

interface FlashBorrower {
    function onFlashLoan(address initiator, uint256 amount, bytes calldata data) external;
}

function executeFlashloan(FlashBorrower receiver, uint256 eusdAmount, bytes calldata data) public payable {
    uint256 shareAmount = EUSD.getSharesByMintedEUSD(eusdAmount);
    EUSD.transferShares(address(receiver), shareAmount);
    receiver.onFlashLoan(msg.sender, shareAmount, data);
    ...
}

In this updated example, the onFlashLoan function now takes an additional parameter initiator which is the address of the initiator of the loan, allowing the receiver to verify the source of the flash loan.

ref: https://eips.ethereum.org/EIPS/eip-3156

Assessed type

Access Control

#0 - c4-pre-sort

2023-07-04T14:01:25Z

JeffCX marked the issue as duplicate of #280

#1 - c4-judge

2023-07-28T15:29:37Z

0xean marked the issue as satisfactory

#2 - c4-judge

2023-07-28T19:46:08Z

0xean changed the severity to 3 (High Risk)

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