29

Gas refunds are provided when clearing storage or calling SELFDESTRUCT on contracts.

The Yellow Paper mentions that refunds are "being capped up to a maximum of half...". What exactly is this "half" and the other components that sum up to a refund? Preferred answer will explain with a specific example (since the Yellow Paper has the definitions).

What are the limits? What attacks would have been possible if refunds were not limited?

eth
  • 85,679
  • 53
  • 285
  • 406

3 Answers3

29

The following opcodes trigger a refund

  • SELFDESTRUCT
  • SSTORE[x] = 0 (i.e. deletion)

SELFDESTRUCT refunds 24.000 and SSTORE clear refunds 15.000 gas. The accumulated refund can not exceed half the gas used for the current context (i.e. the initial call).

Let's take the following example:

Current state of the contract's storage

0x00: 1
0x01: 1

And the following execution

PUSH 0
PUSH 0
SSTORE ; set contents of address 0x0 to 0 (i.e. delete)

This would result in the following gas sum 21000 + 3 + 3 + 5000 (tx_gas + push_gas + push_gas + sstore_clear_gas). The total amount of which may be refunded is therefor gas_sum / 2 (13.003). The amount refunded is 15.000 but since this clearly exceeds the maximum of 13.003 we cap it to that amount.

And the reason why we cap this is so that the miner does not end up paying for the actual execution of the contract :-)

EDIT:

If the refunds weren't capped we would run in to 2 issues:

  1. It disincentives running any contracts that refund;
  2. Miners may end up paying for the execution.

It would be disincentive to run these type of transactions if they weren't capped because at the end of the execution the refund is reduced from the amount that which a miner gets (i.e. gasUsed * tx.price). Capping at say the gasUsed would render the execution useless to the miner (it doesn't get rewarded for running the contract). This brings us to the second point; having a higher refund than the gas used would therefor end up in a negative gas usage and would therefor have to be reduced from the miner's balance. No miner in their right mind is going to pay you for execution your call.

eth
  • 85,679
  • 53
  • 285
  • 406
Jeffrey W.
  • 1,939
  • 15
  • 14
  • with 1) you mean "it disincentives miners running any contracts that refund" right? not a 'user'? – Ruben de Vries Jun 21 '16 at 10:30
  • Indeed @RubendeVries – Jeffrey W. Jun 21 '16 at 12:26
  • 2
    In other words, if I understand correctly, you don't want people to create a bunch of contracts during quiet times with low gas price and then suicide() them during an ICO with high gas prices. – Sjors Provoost Aug 22 '17 at 16:58
  • This is a great explanation and it'd be really useful to have it in the yellow paper! – Paul Razvan Berg Jan 05 '19 at 19:06
  • @JeffreyW. wrong Answer! Used gas and remaining gas are 2 differents things. Used gas increase each times an Instrcution is executed, thereby (and unlike some explorers are suggesting), refunding doesn t decrease miner rewards. But it s worse than that: the person who launched the transaction would still get more ether than what was paid in gas: they would be genereted out of nothing resulting in inflation! This is clearer when you read the source code from officials implementations than the yellow paper. – user2284570 Jul 24 '19 at 11:24
  • @user2284570 you think I’d know having written the actual implementation. I suggest you re-read my answer – Jeffrey W. Jul 25 '19 at 12:36
  • @JeffreyW. maybe ᴇᴛᴄ is now behaving differently (failed to find their equivalent for yellow paper)… Anyway, since it’s for ᴇᴛʜ, does the cap is per transaction or per contract call (since a contract can call another contract) ? – user2284570 Jul 30 '19 at 21:00
  • @user2284570 per tx and I’m fairly sure that ETC, given it’s merely a copy of ETH with a few modifications, has the same mechanic in place. – Jeffrey W. Aug 01 '19 at 08:34
  • @JeffreyW. And if I understand correctly, refund balance isn’t available immediately for using more gas… So when is it credited to gas balance ? – user2284570 Aug 04 '19 at 13:18
  • @user2284570 at the very end of the transaction, when all actions have been completed. The gas used is reduced by the refund amount, basically reducing the gas spent. – Jeffrey W. Aug 05 '19 at 14:25
  • 1
    Hi everyone. How does it work ? who won ? My main question is that if the transaction needed above 21000+5000+3+3 = 26003 and the refund is 15,000. why not give 15,000 refund to the user instead of 13,003. If we give 15,000 refund, we are left with 26003 - 15000 = 11003 which goes to the miner. So miner still is incentivized. any idea ? – Nika Kurashvili Jan 29 '21 at 16:16
10

Another important "limit" is that the gas refund is provided only 1 time, at the very end of the transaction's execution.

This means that a transaction cannot use its own gas refund to pay for any part of its execution.

A refund cannot be used to avoid Out of Gas exceptions, as illustrated by these examples:

How come I need to specify a higher gasLimit than estimateGas?

How to clear large arrays without blowing the gas limit?

eth
  • 85,679
  • 53
  • 285
  • 406
  • Indeed. This would destroy the security of .send and .transfer if gas refund was provided as it was burned, as the receiving contract could use its gas stores to reenter into the calling function and change its state. – Nicholas Pipitone Nov 16 '18 at 00:18
6

The reason for 50% gas refund cap is given in Design Rationale:

The 50% cap is needed to ensure that a miner given a transaction with some quantity of gas can still determine an upper bound on the computational time to execute the transaction.

medvedev1088
  • 10,996
  • 5
  • 35
  • 63