18

Who will pay the gas in the following scenario?

Lets say we have the following simple function. That sends an amount from the contract back to the sender.. just an example.

    function withdraw() public payable 
    {
       address member = msg.sender;
       member.transfer(msg.value);
    }

The sender to the method will obviously pay the fee to send the transaction to the method and execute the statements. However, who will pay the gas for the resultant transaction that will get created from that code?

Secondly, in general about the transfer() method, what are the default parameters. I know it uses a gas limit of 2100, but what about gas price? Also, does this gas come from the value passed in or from the contracts balance and the whole value will be transferred.

Don't down-vote the question for 'lack of research' I am aware of the usual conditions of gas coming from the balance, in distinction of the transactions value. Just curious about the transfer() method in particular. As there is not a ton of documentation about its implementation as it differs from send(), that i could find.

3 Answers 3

24
+50

who will pay the gas for the resultant transaction that will get created from that code?

The transfer() function doesn't result in a transaction. It results in a message call inside the original transaction initiated by an external account. The blockchain will record a single transaction no matter how many transfer() or call() invocations there are in the code. The gas cost will be deducted from the external account that initiated the transaction.

I know it uses a gas limit of 2100, but what about gas price?

The gas price specified by the external account owner, who initiated the transaction, is used.

Also, does this gas come from the value passed in or from the contracts balance and the whole value will be transferred.

The gas cost will not be subtracted from the contract but instead the external account that initiated the transaction. The gas cost is added on top of the value passed in. The external account must have the balance greater or equal to value + gaslimit * gasprice.

Just curious about the transfer() method in particular. As there is not a ton of documentation about its implementation as it differs from send(), that i could find.

When sending ether be aware of the relative tradeoffs between the use of someAddress.send(), someAddress.transfer(), and someAddress.call.value()():

  • someAddress.send()and someAddress.transfer() are considered safe against reentrancy. While these methods still trigger code execution, the called contract is only given a stipend of 2,300 gas which is currently only enough to log an event.
  • x.transfer(y) is equivalent to require(x.send(y)), it will automatically revert if the send fails.
  • someAddress.call.value(y)() will send the provided ether and trigger code execution. The executed code is given all available gas for execution making this type of value transfer unsafe against reentrancy.

Using send() or transfer() will prevent reentrancy but it does so at the cost of being incompatible with any contract whose fallback function requires more than 2,300 gas. It is also possible to use someAddress.call.value(ethAmount).gas(gasAmount)() to forward a custom amount of gas.

One pattern that attempts to balance this trade-off is to implement both a push and pull mechanism, using send() or transfer() for the push component and call.value()() for the pull component.

It is worth pointing out that exclusive use of send() or transfer() for value transfers does not itself make a contract safe against reentrancy but only makes those specific value transfers safe against reentrancy.

Can read more here https://consensys.github.io/smart-contract-best-practices/recommendations/#be-aware-of-the-tradeoffs-between-send-transfer-and-callvalue


You can find more details in this answer https://ethereum.stackexchange.com/a/38642/18932

1
  • 1
    Got a notification about this question. Coming back to look at this 5 years later. I see how I got into that line of thought - missing a more thorough understanding of the EVM. That was a super helpful answer! Apr 11, 2022 at 22:27
2

The sender to the method will obviously pay the fee to send the transaction to the method and execute the statements. However, who will pay the gas for the resultant transaction that will get created from that code?

Maybe I'm not reading this correctly but you basically answer then ask the question. The sender will pay for the gas.

Secondly, in general about the transfer() method, what are the default parameters. I know it uses a gas limit of 2100, but what about gas price? Also, does this gas come from the value passed in or from the contracts balance and the whole value will be transferred.

transfer() can actually differ based on what is actually in the solidity code itself. It does not necessarily default to 21000. Actually, since the transfer is actually sending data and not a direct payable transaction only, you would have to set a higher gas limit.

As for gas price and gas limit, your actual function call already has a set range or level of gas it will use based on the complexity of the code itself, most of it coming from adding/altering storage.

The default gas price is determined by the medium you use to send the call itself. web3 for example, examines the current situation of the network used and dynamically sets the gas price based on getting confirmation within 5-10 seconds.

Gas limit is also set by web3 dynamically by the expected gas usage for the call. 21000 is commonly seen for payable transfers that do not have additional data.

3
  • Yeah - good point on the 1st point clarification. It came from an bad understanding of the transfer() method. I was not aware that it did not result in a second transaction. Feb 5, 2018 at 21:03
  • If i could mark two answers - your asnwer definitely answers and provides good information. +1 Feb 5, 2018 at 21:13
  • Gas estimation on simple transfers returns a gas fee of 21,040 when estimating with web3 or testing on remix. I'm hoping this is an error as most crypto exchanges are now setting gas limit to 21,000 on withdrawals. Jul 13, 2018 at 20:02
1

Nice qus, Coming to your fist qus:

The sender to the method will obviously pay the fee to send the transaction to the method and execute the statements. However, who will pay the gas for the resultant transaction that will get created from that code?

msg.sender will pay gas. i.e withdraw() method caller will pay for transaction cost. Once your transactions are validated and added to blockchain miners will receive incentive.

Coming to your 2rd Qus Ans:

You can set gas and gas price value by specifing gas and gasPrice along with from and to values for sendTransaction() funtion

web3.eth.sendTransaction({from: 'myWallet', to: 'coinbaseWallet', value: web3.toWei(0.1,'ether'),gas: 5000, gasPrice: web3.toWei(40,'gwei')});
1
  • Thanks. Am aware of the default and accepted parameters for Web3's sendTransaction. My question was specific to solidity's address.transfer() Feb 5, 2018 at 18:17

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.