Solidity – Efficiently Using selfdestruct() for Safe Ether Transfer

solidity

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?

Best Answer

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.

Related Topic