⚔️Draining the Naive Receiver
The learning process will be more beneficial for you if you will avoid the hints.
However, if you are frustrated, open these by order of frustration:
Hint 1
Understand through the code the relation in which NaiveReceiverLenderPool
provides flash loans while FlashLoanReceiver
borrows flash loans from the pool.
The two contracts interact directly through smart contract function calls.
The NaiveReceiverLenderPool
calls the FlashLoanReceiver
's onFlashLoan
function, and the FlashLoanReceiver
sends the repayment back to the NaiveReceiverLenderPool
.
Hint 2
The vulnerability resides as an access control issue in the FlashLoanReceiver::onFlashLoan
implementation.
function onFlashLoan(
address,
address token,
uint256 amount,
uint256 fee,
bytes calldata
) external returns(bytes32) {
assembly { // gas savings
if iszero(eq(sload(pool.slot), caller())) {
mstore(0x00, 0x48f5c3ed)
revert(0x1c, 0x04)
}
}
if (token != ETH)
revert UnsupportedCurrency();
uint256 amountToBeRepaid;
unchecked {
amountToBeRepaid = amount + fee;
}
_executeActionDuringFlashLoan();
// Return funds to pool
SafeTransferLib.safeTransferETH(pool, amountToBeRepaid);
return keccak256("ERC3156FlashBorrower.onFlashLoan");
}
The FlashLoanReceiver
contract implements a function that is to be called by the NaiveReceiverLenderPool
, and completely ignoring the first function parameter.
Hint 3
Since the user that implemented the FlashLoanReceiver
contract forgot to validate the receiver
parameter, another user of the NaiveReceiverLenderPool
can deploy a malicious contract that triggers a request of a flash loan on behalf of the FlashLoanReceiver
contract, draining it's funds into the pool.
Last updated