1️⃣Initial Review
Scoping
You can read about the scope details here.
Commit Hash: e8ce05f5530ca965165d41547b289604f873fdf6
In Scope:
Install Solidity Metrics in VsCode
Reconnaissance
Code Review
Tools to Run
Slither
Aderyn
Reviewing the flashloan() function
The flashloan() function can be found in the source file /src/protocol/ThunderLoan.sol
This flashloan
function contains several security issues, particularly related to reentrancy and the potential for underpayment of the loan. Let's break them down:
1. Reentrancy Vulnerability:
Problem: The function calls
receiverAddress.functionCall()
before verifying that the loan has been paid back with the fee. If thereceiverAddress
contract is malicious or vulnerable, it could re-enter theflashloan
function (via some other code path) and perform another action before the current execution is completed. This can lead to a situation where the state is manipulated in an unexpected way, potentially allowing thereceiverAddress
to escape paying back the full amount.Mitigation: To avoid reentrancy, you should update the contract’s state to reflect that the flash loan has been completed before making any external calls. Moving the
s_currentlyFlashLoaning[token] = false;
statement to just after the loan execution or using a mutex-style lock to prevent reentrancy is advisable.
2. Lack of Checks After External Call:
Problem: After the external call to
receiverAddress.functionCall()
, the contract only checks the ending balance against the starting balance plus the fee. This check is performed after transferring the loan amount and making the external call, which could potentially be manipulated in some cases, especially if other operations are taking place concurrently.Mitigation: You should ensure that the contract's state is securely updated before and after any external call. Rechecking balances after every state-changing operation can help mitigate some risks.
3. Slippage and Fee Manipulation:
Problem: The contract does not protect against slippage or manipulation of the fee by the
updateExchangeRate(fee)
function. If an attacker can manipulate the exchange rate or fee calculation, they could potentially pay back less than required.Mitigation: Ensure that the fee is calculated in a secure and predictable manner, ideally resistant to external manipulation. Consider implementing checks that prevent fee manipulation.
4. Denial of Service (DoS) via Flash Loan Execution:
Problem: If the
receiverAddress
contract is not properly coded or intentionally malfunctions (e.g., reverts duringfunctionCall
), it could prevent the flash loan from being successfully executed and returned, potentially locking funds in the contract.Mitigation: Implement fallback mechanisms or timeouts to handle such cases, ensuring that the contract does not get stuck in an unusable state.
5. Event Emission Before State Changes:
Problem: The event
FlashLoan
is emitted before the state changes_currentlyFlashLoaning[token] = true;
. This could lead to discrepancies between the emitted event and the actual state of the contract if the transaction fails after the event is emitted but before the state change.Mitigation: Emit events after making state changes to ensure that the event data reflects the true state of the contract.
6. Failure to Handle Edge Cases:
Problem: The function assumes that the
receiverAddress
contract will always return the funds along with the fee. However, if theexecuteOperation
function fails, the contract does not seem to have a fallback mechanism to handle this scenario.Mitigation: Implement additional checks and conditions to handle cases where the
executeOperation
fails or reverts, possibly involving a revert with a more descriptive error message or taking alternative actions.
7. Potential for Reentrancy in updateExchangeRate(fee)
:
updateExchangeRate(fee)
:Problem: If the
updateExchangeRate
function is vulnerable to reentrancy or relies on external inputs, it could be exploited by a malicious actor.Mitigation: Carefully review and secure the
updateExchangeRate
function to ensure it is not vulnerable to manipulation or reentrancy attacks.
PoC
Steps to Execute
Deploy the
MaliciousReceiver
Contract:Deploy the
MaliciousReceiver
contract, passing the address of the vulnerable flash loan contract and the ERC20 token address as constructor parameters.
Call
startAttack
:Call the
startAttack
function on theMaliciousReceiver
contract, specifying the amount of tokens to borrow and any necessary parameters.
Exploit the Reentrancy:
During the execution of
executeOperation
, theMaliciousReceiver
contract re-enters theflashloan
function before the original loan is settled. This can lead to unexpected behavior, such as draining funds, executing multiple loans, or causing other state manipulation.
Last updated
Was this helpful?