> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# GasRefund

> Gas refunds after transaction execution

# GasRefund

`GasRefund` represents gas refunded after transaction execution. Post-London (EIP-3529), refunds are capped at `gasUsed / 5`.

## Type Definition

```typescript theme={null}
type GasRefundType = bigint & { readonly [brand]: "GasRefund" };
```

Branded bigint representing gas refund (always non-negative).

## Gas Refund Mechanics

### Pre-London (Before EIP-3529)

Large refunds were possible from:

* **SSTORE clear**: 15,000 gas (clearing storage slot)
* **SELFDESTRUCT**: 24,000 gas (destroying contract)

**Problem**: Caused "gas tokens" - exploiting refunds for profit.

### Post-London (EIP-3529)

Refunds significantly reduced:

* **Cap**: Maximum refund = `gasUsed / 5` (20% of gas used)
* **SSTORE clear**: Still generates 15,000 refund, but capped
* **SELFDESTRUCT**: No longer gives refund

**Effect**: Eliminated gas token exploits, simplified gas economics.

## API

### Constructors

#### `from(value)`

Create GasRefund from number, bigint, or string.

```typescript theme={null}
import { GasRefund } from '@tevm/primitives';

// SSTORE clear refund
const refund = GasRefund.from(15000n);

// No refund
const noRefund = GasRefund.from(0n);

// From number
const ref2 = GasRefund.from(15000);
```

**Throws**: `InvalidFormatError` if value is negative.

### Conversions

#### `toNumber(refund)`

Convert to number.

```typescript theme={null}
const refund = GasRefund.from(15000n);
GasRefund.toNumber(refund); // 15000
```

#### `toBigInt(refund)`

Convert to bigint (identity operation).

```typescript theme={null}
const refund = GasRefund.from(15000n);
GasRefund.toBigInt(refund); // 15000n
```

#### `toHex(refund)`

Convert to hex string.

```typescript theme={null}
const refund = GasRefund.from(15000n);
GasRefund.toHex(refund); // "0x3a98"
```

### Comparisons

#### `equals(ref1, ref2)`

Check equality.

```typescript theme={null}
GasRefund.equals(15000n, 15000n); // true
GasRefund.equals(15000n, 20000n); // false
```

### Utilities

#### `cappedRefund(refund, gasUsed)`

Apply EIP-3529 refund cap.

```typescript theme={null}
const refund = GasRefund.from(15000n); // SSTORE clear
const gasUsed = 50000n;

// Cap = 50000 / 5 = 10000
const capped = GasRefund.cappedRefund(refund, gasUsed);
// 10000n (reduced from 15000n)
```

Post-London enforcement: `min(refund, gasUsed / 5)`

## Usage Examples

### Calculate Effective Gas Cost

```typescript theme={null}
import { GasUsed, GasRefund } from '@tevm/primitives';

const gasUsed = GasUsed.from(60000n);
const gasPrice = 20_000_000_000n; // 20 gwei

// Transaction clears 2 storage slots
const totalRefund = GasRefund.from(30000n); // 2 × 15000

// Apply EIP-3529 cap
const capped = GasRefund.cappedRefund(totalRefund, GasUsed.toBigInt(gasUsed));
// 12000n (60000 / 5)

// Calculate net cost
const grossCost = GasUsed.calculateCost(gasUsed, gasPrice);
const refundValue = GasRefund.toBigInt(capped) * gasPrice;
const netCost = grossCost - refundValue;

console.log(`Gross cost: ${grossCost} Wei`);
console.log(`Refund: ${refundValue} Wei`);
console.log(`Net cost: ${netCost} Wei`);
```

### Compare Pre/Post London

```typescript theme={null}
import { GasRefund } from '@tevm/primitives';

const sstoreClear = GasRefund.from(15000n);
const gasUsed = 50000n;

// Pre-London: Full refund
const preLondon = GasRefund.toBigInt(sstoreClear);
console.log(`Pre-London refund: ${preLondon}`); // 15000

// Post-London: Capped refund
const postLondon = GasRefund.cappedRefund(sstoreClear, gasUsed);
console.log(`Post-London refund: ${postLondon}`); // 10000

const reduction = preLondon - GasRefund.toBigInt(postLondon);
console.log(`Reduction: ${reduction} gas (${(reduction / preLondon * 100).toFixed(0)}%)`);
```

### Multiple Storage Clears

```typescript theme={null}
import { GasRefund } from '@tevm/primitives';

// Transaction clears 5 storage slots
const slotsCleared = 5;
const refundPerSlot = 15000n;
const totalRefund = GasRefund.from(BigInt(slotsCleared) * refundPerSlot);
// 75000n total potential refund

const gasUsed = 100000n;

// Apply cap
const capped = GasRefund.cappedRefund(totalRefund, gasUsed);
// 20000n (100000 / 5)

console.log(`Potential refund: ${GasRefund.toBigInt(totalRefund)}`); // 75000
console.log(`Capped refund: ${capped}`); // 20000
console.log(`Refund lost: ${75000n - capped}`); // 55000
```

## Refund Sources

### SSTORE Operations

| Operation           | Gas Cost   | Refund (Pre-London) | Refund (Post-London) |
| ------------------- | ---------- | ------------------- | -------------------- |
| Zero → Non-zero     | 20,000     | 0                   | 0                    |
| Non-zero → Non-zero | 5,000      | 0                   | 0                    |
| Non-zero → Zero     | 5,000      | 15,000              | Capped at gasUsed/5  |
| Non-zero → Same     | 100 (warm) | 0                   | 0                    |

### SELFDESTRUCT

| Era         | Gas Cost | Refund |
| ----------- | -------- | ------ |
| Pre-London  | 5,000    | 24,000 |
| Post-London | 5,000    | 0      |

## EIP-3529 Rationale

### Problems with Old Refund System

1. **Gas Tokens**: Exploited refunds for profit
   * Store data when gas cheap
   * Clear data when gas expensive
   * Get refund at high gas price

2. **Block Variability**: Large refunds caused unpredictable block gas usage

3. **Complexity**: Made gas economics hard to reason about

### Post-3529 Benefits

1. **No Gas Tokens**: Capped refunds eliminate exploit
2. **Predictable Costs**: Users pay closer to actual gas used
3. **Simpler Economics**: Easier to estimate transaction costs
4. **Faster State Growth**: Reduced incentive to keep unnecessary storage

## Refund Cap Formula

```
effectiveRefund = min(totalRefund, gasUsed / 5)
```

Where:

* `totalRefund`: Sum of all refunds from SSTORE operations
* `gasUsed`: Actual gas consumed by transaction
* Division rounds down (integer division)

## Usage Patterns

### Check if Refund is Capped

```typescript theme={null}
import { GasRefund } from '@tevm/primitives';

function isRefundCapped(refund: bigint, gasUsed: bigint): boolean {
  const refundObj = GasRefund.from(refund);
  const capped = GasRefund.cappedRefund(refundObj, gasUsed);
  return GasRefund.toBigInt(capped) < refund;
}

const refund = 15000n;
const gasUsed = 50000n;
console.log(isRefundCapped(refund, gasUsed)); // true
```

### Calculate Maximum Possible Refund

```typescript theme={null}
import { GasRefund } from '@tevm/primitives';

function maxRefund(gasUsed: bigint): bigint {
  return gasUsed / 5n;
}

const gasUsed = 100000n;
console.log(`Max refund: ${maxRefund(gasUsed)}`); // 20000
```

## London Hard Fork

**Date**: August 5, 2021 (Block 12,965,000)

**Changes**:

* EIP-3529: Refund reduction
* EIP-1559: Fee market change
* EIP-3198: BASEFEE opcode
* EIP-3541: Reject new contracts starting with 0xEF

**Impact**: Most transactions now have zero or minimal refunds.

## See Also

* [GasUsed](/primitives/gas-used) - Actual gas consumed
* [GasEstimate](/primitives/gas-estimate) - Estimate gas before execution
* [EIP-3529](https://eips.ethereum.org/EIPS/eip-3529) - Reduction in refunds
* [EIP-2929](https://eips.ethereum.org/EIPS/eip-2929) - Gas cost increases
* [Yellow Paper Section 6](https://ethereum.github.io/yellowpaper/paper.pdf) - Execution model
