November 07, 2023
Beosin Research | Risks in Flashloans in Solidity
In the previous article, we introduced various implementations of flash loans in different programming languages. Although the implementation approaches for various flash loan projects are similar, even minor differences can lead to serious security vulnerabilities. In the upcoming articles, we will sequentially discuss the issues to be aware of and the solutions required for implementing flash loans in Solidity, Move, and Rust languages.
In the design of Solidity-based flash loans, most projects determine whether the caller returns the funds by checking their own balance. This approach, when observed in isolation, seems fine as it ensures the safety of the contract’s funds regardless of the actions taken by the borrower. However, most flash loan projects offer more than just a flash loan feature; the contract often includes other business functions. If these functions affect the contract’s balance, it might create significant security risks.
Note: The following code is intended solely for studying flash loan security issues and may not cover all potential security risks.
The first part involves the flash loan functionality. It initially records the amount of ETH held by the contract before the loan. Upon lending ETH, it calls a specified function in the caller’s designated contract. Finally, it verifies whether the contract’s ETH amount is greater than or equal to the ETH amount before lending plus a 1% transaction fee.
The second part provides the pledging function for flash loan liquidity. Users can pledge ETH to the flash loan contract and earn profits through the fees collected from flash loans.
However, this contract contains a very common reentrancy bug, enabling the caller to bypass the final check of the flash loan while pledging.
Next, we’ll use the following Proof of Concept (PoC) code to test an attack on the aforementioned flash loan project. The main idea is to exploit the flash loan’s callback function to conduct a reentrancy attack, converting normal business actions into repayment actions, ultimately draining the flash loan contract’s ETH.
Start by calling the start() function in the PoC contract, initiating the flash loan. The loan amount is set as the ETH balance of the flash loan contract minus one, to avoid calculation errors during the subsequent deposit() step, provided as a callback parameter for the back() function.
Then, in the back() function, the borrowed ETH plus a slight fee is pledged back into the flash loan contract, generating token coins for the PoC contract. When the back() function ends, the flash loan contract will check the repayment status. Due to the updated ETH balance during the pledge, the check will pass. Finally, the PoC contract uses the token coins to withdraw ETH.
Testing in the local environment:
Firstly, deploy the flash loan contract and deposit 50 ETH from a specific address into it, simulating the project’s initiation.
Deploy the PoC contract and transfer some fees to the loan contract’s address in preparation for the subsequent flash loan fee check.
Call the start() function in the PoC contract, and you’ll notice that the ETH from the loan contract has been transferred to the PoC contract.
The loan contract is left with only a balance of 1 wei.
The PoC contract now holds 52 ETH, yielding a profit of 50 ETH.
For flash loan projects that use balance for verification and have other business functions related to balance operations, it’s advisable to implement a reentrancy lock between the flash loan function and other business functions to prevent re-entry into the contract during the flash loan, which could affect the final check.
Alternatively, maintain separate ledgers to record information related to other business functions. During the flash loan function check, cross-verify the separate ledger. For example, in the given code, the deposit function could include a ledger to record the pledged amount. In the flash_loan function, subtract this ledger data from the flash loan amount before and after the process for verification.
Utilize alternative repayment verification methods, such as with ERC20 token flash loans, using the SafeTransferFrom function for transfers, implementing a “forced” repayment approach.
If you need any blockchain security services, welcome to contact us:
Related Project Secure Score
Guess you like
Analysis of $2.18 Million Loss in Hacker Attack on OnyxProtocol
November 03, 2023
What security issues should developers consider when building Solana projects?
November 09, 2023
The Booming BTC Ecosystem: Exploring Opportunities and Risks in Derivative Protocols
November 13, 2023
Poloniex under Justin Sun Hacked for Over a Billion Dollars, Raft Project Loses $3.4 Million
November 14, 2023