1

I have been getting into mitigating reentrancy issues and safe ether transfer recently and have come up with the following 'safe transfer' code. Workflow:

  1. deploy contract Foo
  2. send ether to Foo
  3. execute function safeTransfer specifying the destination address and value in wei

    pragma solidity ^0.4.11;
    
    contract Interface {
        function pay();
    }
    
    contract Foo {
    
        function safeTransfer (address _to, uint256 _amount)
        {
            Bar a = new Bar(_to);
            a.transfer(_amount);
            Interface b = Interface(a);
            b.pay();
        }
    
        function () payable {}
    }
    
    contract Bar {
    
        address payee;
    
        function Bar (address _payee)
            {
                payee = _payee;
            }
    
        function () payable {}
    
        function pay () 
            {
                selfdestruct(payee);
            }
    }
    

At ~150k gas this is rather expensive but it works. I am aware of the pull payment best practise but would much prefer a convenient automated payments method. Any thoughts on how to potentially optimise this idea for use as payment option in a contract?

1

If your goal is to mitigate reentrancy vulnerability, transfer() has a gas stipend of only 2300 which is enough only to publish an event. In other words, as long as you stick to `transfer it's not possible to call back your contract.

There is a small potential for improvement if you pass _payee directly to pay() function saving a bit of storage:

function pay (address _payee) 
    {
        selfdestruct(_payee);
    }

But I'm afraid that if you want to use a selfdestruct safety feature you will need to pay for contract creation every time - which is a very expensive operation.

  • 1
    Yes - true - but I also want to refund bids on items once a higher bid comes in and using transfer to a contract without a payable fallback can hold my contract hostage without a safe transfer method or pull withdrawal. – Steve Jul 6 '17 at 14:00
  • Now I see your point. Very interesting approach. There is a small potential for improvement if you pass _payee directly to pay() function saving a bit of storage. But I'm afraid that if you want to use a selfdestruct safety feature you will need to pay for contract creation every time - which is a very expensive operation. – Jakub Wojciechowski Jul 6 '17 at 14:26
  • Oh yes - thanks! Good point re passing _payee directly to pay(). I am going to go down the safe withdrawal route though. My method is just too expensive. – Steve Jul 6 '17 at 16:46
  • If this answer helped or solved your issue, please mark it as accepted or upvote ;) – Jakub Wojciechowski Jul 8 '17 at 16:34
  • Can you edit your answer to include passing _payee directly to pay()? – Steve Jul 9 '17 at 6:41

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.