1

If a contract has a payable function, which forwards ether to another contract, but the second contract throws, how can you properly prepare for a throw in the first contract? Will the throw leave the money in the first contract, and if so can you return this money to the initial msg.sender?

1

Very important to follow a safe three-step process.

  1. Optimistic accounting (counter-intuitive but correct to do it first)
  2. Try the send() and check the result (true or false).
  3. On fail, either revert the accounting step-by-step, or throw (which reverts state changes including the account, returns the ETH and destroys the gas in one move.).

Example (Simplest interpretation I know with a full stop):

function forwardFunds(address recipient) payable returns(bool success) {
  LogForwarded(msg.sender, msg.value, recipient);
  if(!recipient.send(msg.value)) throw;
  return true; // doesn't make it this far in case of trouble
}

If the receiver throws, this function will throw as well, the event (i called it LogForwarded) that represents the "accounting" step will not occur and the received msg.value will be returned to msg.sender. Nevermind that the accounting event appears to come first, because throw will reliably revert that state change.

Check out "Reentrancy" and other stuff here: https://github.com/ConsenSys/smart-contract-best-practices. The three-step process above covers your concern and also synthesizes the know-how described (in the link) into a pattern I find easy to remember and apply consistently.

Hope it helps.

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.