Assume that we have two MultiSend function, one for ether and another for ERC20/ERC223 token respectively.

My question is what would happen if one or more of the address fail. Will all the transaction be reverted and stuck forever? eg: One of the ether is transfer to address of smart contract that reject incoming ether transfer().

To simplify, i think that it will be a success transfer for an address but not the case for a contract address.

If it is the case, wouldn't that the MultiSend() function will not be succeed forever? And what is the solution to it. Or it just ignore the fail transaction only.

The full code can be view here

  function multiTransfer(address[] _addresses, uint[] _amounts)
    payable public returns(bool)
        uint toReturn = msg.value;
        for (uint i = 0; i < _addresses.length; i++) {
            _safeTransfer(_addresses[i], _amounts[i]);
            toReturn = SafeMath.sub(toReturn, _amounts[i]);
            MultiTransfer(msg.sender, msg.value, _addresses[i], _amounts[i]);
        _safeTransfer(msg.sender, toReturn);
        return true;

 function multiERC20Transfer(
        ERC20 _token,
        address[] _addresses,
        uint[] _amounts
    ) public {
        for (uint i = 0; i < _addresses.length; i++) {
            _safeERC20Transfer(_token, _addresses[i], _amounts[i]);

All the calls to state modifying contract functions are transactions. When one calls multiTransfer() for example, they initiate just one transaction.

That transaction can succeed, or it can fail. If it fails, it is fully reverted.

In the docs it's specified that:

Solidity uses state-reverting exceptions to handle errors. Such an exception will undo all changes made to the state in the current call (and all its sub-calls) and also flag an error to the caller.

Warning - in the same doc, bit below, they say one could encounter exceptions that don't revert the transaction:

Exceptions to this rule are send and the low-level functions call, delegatecall and callcode – those return false in case of an exception instead of “bubbling up”.

However, the contract you showed uses .transfer() for sending ETH, which makes it throw an exception, and thus reverting the whole transaction if it fails.

  • So if the transfer is used in this case, weren't it there will be cases where the multisend function will never be able to success (eg: one of the address is a smart contract address that implement function to reject transfer of ether). Then in this case multisend will always fail. Am i right? Nov 11 '18 at 8:22
  • yes, you're right Nov 11 '18 at 8:24
  • Then why were it widely implemented in first place for multisending eth/token. Is there no better alternative than this? IMHO, from my understanding there should not be cases which result in the transaction will never succeed forever for best practice. Nov 11 '18 at 8:28
  • you can modify that contract and have it fail for some transfers, while succeeding for others: use .send() instead of .transfer() in the _safeTransfer(), get rid of the require() wrapping the sending calls in the _safeERC20Transfer() and _safeCall() functions. Nov 11 '18 at 8:34

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.