Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/revm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1722,7 +1722,7 @@ mod tests {
// Simple initcode: PUSH1 0x00 PUSH1 0x00 RETURN (deploys empty contract)
let initcode = vec![0x60, 0x00, 0x60, 0x00, 0xF3];

// T1 costs: CREATE cost (500k) + new account for sender (250k) + new account for contract (250k)
// T1 costs: CREATE cost (500k, fixed upfront contract creation cost) + new account for sender (250k) + base costs
let tx = TxBuilder::new()
.create(&initcode)
.gas_limit(1_000_000)
Expand Down
2 changes: 1 addition & 1 deletion tips/ref-impls/test/helpers/TxBuilder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ library TxBuilder {
uint64 constant STATE_CREATION_COST = 250_000; // SSTORE zero→non-zero
uint64 constant CREATE_BASE_COST = 500_000; // CREATE/CREATE2 base
uint64 constant CODE_DEPOSIT_COST = 1000; // per byte
uint64 constant CREATE_FIELDS_COST = 500_000; // keccak + codesize (2 × 250,000)
uint64 constant CREATE_FIELDS_COST = 500_000; // fixed upfront contract creation cost

// ============ Gas Calculation Helpers ============

Expand Down
54 changes: 28 additions & 26 deletions tips/tip-1000.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ status: Approved

## Abstract

This TIP increases the gas cost for creating new state elements, accounts, and contract code to provide economic protection against state growth spam attacks. The proposal increases the cost of writing a new state element from 20,000 gas to 250,000 gas, introduces a 250,000 gas charge for account creation (when the account's nonce is first written), and implements a new contract creation cost model: 1,000 gas per byte of contract code plus 500,000 gas for keccak hash and codesize fields.
This TIP increases the gas cost for creating new state elements, accounts, and contract code to provide economic protection against state growth spam attacks. The proposal increases the cost of writing a new state element from 20,000 gas to 250,000 gas, introduces a 250,000 gas charge for account creation (when the account's nonce is first written), and implements a new contract creation cost model: 1,000 gas per byte of contract code plus a fixed upfront contract creation cost of 500,000 gas.

## Motivation

Expand Down Expand Up @@ -50,7 +50,10 @@ These units provide precise economic accounting while maintaining human-readable
- Writing a new state element (SSTORE to a zero slot) costs 20,000 gas

**Proposed Behavior:**
- Writing a new state element (SSTORE to a zero slot) costs 250,000 gas
- Writing a new state element (SSTORE to a zero slot) costs 250,000 gas for the state creation component (replacing 20,000 gas)
- The EIP-2929 access cost is charged separately: 2,100 gas for cold access, 100 gas for warm access
- Total cost for a cold zero-to-nonzero SSTORE: 2,100 + 250,000 = 252,100 gas
- Total cost for a warm zero-to-nonzero SSTORE: 100 + 250,000 = 250,100 gas

This applies to all storage slot writes that transition from zero to non-zero, including:
- Contract storage slots
Expand All @@ -77,7 +80,7 @@ This applies to all storage slot writes that transition from zero to non-zero, i
- The charge also applies to other nonces with [nonce keys](/protocol/transactions/spec-tempo-transaction#specification) (2D nonces)
- Transactions with a nonce value of 0 need to supply at least 271,000 gas and are otherwise invalid
- For EOA accounts: charged on the first transaction sent from that address (when the account is first used)
- For contract accounts: charged when the contract is deployed (CREATE or CREATE2)
- For contract accounts: included in the fixed 500,000 gas CREATE cost (see Contract Creation); there is no separate account creation charge
- **Important:** When tokens are transferred TO a new address, the recipient's nonce remains 0, so no account creation cost is charged. The account creation cost only applies when the account is first used (sends a transaction).
- The charge is in addition to any other gas costs for the transaction

Expand All @@ -91,16 +94,16 @@ This applies to all storage slot writes that transition from zero to non-zero, i
**Proposed Behavior:**
- Contract creation replaces the existing EVM per-byte cost with a new pricing model:
- Each byte: 1,000 gas per byte (linear pricing)
- TX create cost: 2 × 250,000 gas = 500,000 gas for keccak hash and nonce fields
- Fixed upfront contract creation cost: 500,000 gas
- This pricing applies to the contract code size (the bytecode being deployed)

**Implementation Details:**
- The code storage cost is calculated as: `code_size × 1,000`
- Additional state creation costs: 2 × 250,000 gas = 500,000 gas for keccak hash and codesize fields
- Fixed upfront contract creation cost: 500,000 gas
- Total contract creation cost: `(code_size × 1,000) + 500,000` gas
- This replaces the existing EVM per-byte cost for contract creation (not an additional charge)
- Applies to both CREATE and CREATE2 operations
- The account creation cost (250,000 gas) is separate and still applies when the contract account's nonce transitions from 0 to 1
- The fixed 500,000 gas covers the contract account creation; there is no separate account creation charge for the contract

### Intrinsic transaction gas

Expand All @@ -109,8 +112,9 @@ A transaction is invalid if the minimal costs of a (reverting) transaction can't
* Transaction with `nonce == 0` require an additional 250,000 gas
* Tempo transactions with any `nonce_key` and `nonce == 0` require an additional 250,000 gas
* Changes to EIP-7702 authorization lists:
* EIP-7702 authorisation list entries with `auth_list.nonce == 0` require an additional 250,000 gas.
* The base cost per authorization is reduced to 12,500 gas
* EIP-7702 authorisation list entries with `auth_list.nonce == 0` require an additional 250,000 gas (account creation for the nonce field)
* EIP-7702 authorisation list entries going from no delegation to delegation require an additional 250,000 gas (state creation for the keccak/code hash field)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not doing this in the code, we just did the previous line. We could fix it by adding more gas if condition
if !authorization.address().is_zero() is true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do this? It does create new state, right?

* There is no refund if the account already exists
* The additional initial cost for CREATE transactions that deploy a contract is increased to 500,000 from currently 32,000 (to reflect the upfront cost in contract creation)
* If the first transaction in a batch is a CREATE transaction, the additional cost of 500,000 needs to be charged
Expand All @@ -126,10 +130,10 @@ Tempo transaction key authorisations can't determine whether it is going to crea

| Operation | Current Gas Cost | Proposed Gas Cost | Change |
|-----------|------------------|-------------------|--------|
| New state element (SSTORE zero → non-zero) | 20,000 | 250,000 | +230,000 |
| New state element (SSTORE zero → non-zero, state creation component) | 20,000 | 250,000 | +230,000 |
| Account creation (first nonce write) | 0 | 250,000 | +250,000 |
| Contract creation (per byte) | 200 | 1,000 | +800 |
| Contract creation (keccak + codesize fields) | Included in base | 500,000 | +500,000 |
| Contract creation (fixed upfront cost) | Included in base | 500,000 | +500,000 |
| Existing state element (SSTORE non-zero → non-zero) | 5,000 | 5,000 | No change |
| Existing state element (SSTORE non-zero → zero) | -15,000 (refund) | -15,000 (refund) | No change |

Expand All @@ -151,7 +155,7 @@ Based on the assumptions:

**Contract Creation:**
- Per byte: 1,000 gas = **0.002 cents (20 microdollars) per byte**
- Keccak + nonce fields: 500,000 gas (2 × 250,000) = **1.0 cent (10,000 microdollars)**
- Fixed upfront cost: 500,000 gas = **1.0 cent (10,000 microdollars)**
- Example: 1,000 byte contract = (1,000 × 1,000) + 500,000 = 1,500,000 gas = **3.0 cents (30,000 microdollars)**

### Attack Cost Analysis
Expand Down Expand Up @@ -219,12 +223,11 @@ These costs serve as a significant economic deterrent against state growth spam
- Example for 1,000 byte contract: 32,000 + (1,000 × 200) = 232,000 gas ≈ 0.46 cents

**Proposed Cost:**
- Account creation: 250,000 gas
- Contract code storage: code_size × 1,000 gas
- Keccak + nonce fields: 500,000 gas (2 × 250,000)
- Example for 1,000 byte contract: 250,000 + (1,000 × 1,000) + 500,000 = 1,750,000 gas ≈ **3.5 cents**
- Fixed upfront contract creation cost: 500,000 gas
- Example for 1,000 byte contract: (1,000 × 1,000) + 500,000 = 1,500,000 gas ≈ **3.0 cents**

**Impact:** Contract deployment costs increase significantly, especially for larger contracts. A 100 byte contract costs (100 × 1,000) + 500,000 + 250,000 = 850,000 gas = 1.7 cents total.
**Impact:** Contract deployment costs increase significantly, especially for larger contracts. A 100 byte contract costs (100 × 1,000) + 500,000 = 600,000 gas = 1.2 cents.

## Implementation Requirements

Expand All @@ -237,14 +240,14 @@ The node implementation must:
- Charge 250,000 gas instead of 20,000 gas for these operations

2. **Detect account creation:**
- Track when an account's nonce transitions from 0 to 1
- Track when an EOA account's nonce transitions from 0 to 1
- Charge 250,000 gas for this transition
- Apply to both EOA and contract account creation
- For contract accounts, the fixed 500,000 gas CREATE cost applies instead

3. **Implement contract creation pricing:**
- Replace existing EVM per-byte cost for contract code storage
- Charge 1,000 gas per byte of contract code (linear pricing)
- Charge 500,000 gas (2 × 250,000) for keccak hash and codesize fields
- Charge a fixed upfront contract creation cost of 500,000 gas
- Total formula: `(code_size × 1,000) + 500,000`
- Apply to both CREATE and CREATE2 operations

Expand All @@ -263,15 +266,14 @@ The test suite must verify:

2. **Account creation:**
- First transaction from EOA charges 250,000 gas for account creation (when nonce transitions 0 → 1)
- Contract deployment (CREATE) charges 250,000 gas for account creation
- Contract deployment (CREATE2) charges 250,000 gas for account creation
- Contract deployment does NOT charge a separate 250,000 gas for the contract's account creation (the nonce write is included in the 500,000 CREATE cost)
- Transfer TO a new address does NOT charge account creation fee (recipient's nonce remains 0)
- Subsequent transactions from the same account do not charge account creation fee

3. **Contract creation:**
- Contract code storage replaces EVM per-byte cost with new pricing model
- Each byte of contract code costs 1,000 gas (linear pricing)
- Keccak hash and codesize fields cost 500,000 gas (2 × 250,000) total
- Fixed upfront contract creation cost: 500,000 gas
- Total cost formula: `(code_size × 1,000) + 500,000` gas
- Example: 100 byte contract costs (100 × 1,000) + 500,000 = 600,000 gas
- Both CREATE and CREATE2 use the same pricing
Expand All @@ -294,7 +296,7 @@ The test suite must verify:
6. **Economic calculations:**
- Verify gas costs match expected dollar amounts
- Verify attack cost calculations for large-scale state creation
- Verify contract creation costs match formula: `(code_size × 1,000) + 500,000 + 250,000` (including account creation)
- Verify contract creation costs match formula: `(code_size × 1,000) + 500,000` (nonce write included in CREATE cost)
- Verify Tempo-specific operations charge correctly for new state creation

---
Expand All @@ -303,17 +305,17 @@ The test suite must verify:

The following invariants must always hold:

1. **State Creation Cost Invariant:** Any SSTORE operation that writes a non-zero value to a zero slot MUST charge exactly 250,000 gas (not 20,000 gas).
1. **State Creation Cost Invariant:** Any SSTORE operation that writes a non-zero value to a zero slot MUST charge 250,000 gas for the state creation component (not 20,000 gas). The total gas charged also includes the EIP-2929 access cost: 2,100 gas for cold access or 100 gas for warm access, resulting in a total of 252,100 gas (cold) or 250,100 gas (warm).

2. **Account Creation Cost Invariant:** The first transaction that causes an account's nonce to transition from 0 to 1 MUST charge exactly 250,000 gas for account creation.
2. **Account Creation Cost Invariant:** The first transaction sent from an EOA (causing the sender's nonce to transition from 0 to 1) MUST charge exactly 250,000 gas for account creation. For contract accounts, the fixed 500,000 gas CREATE cost applies instead.

3. **Existing State Invariant:** SSTORE operations that modify existing non-zero state (non-zero to non-zero) MUST continue to charge 5,000 gas and MUST NOT be affected by this change.

4. **Storage Clearing Invariant:** SSTORE operations that clear storage (non-zero to zero) MUST continue to provide a 15,000 gas refund and MUST NOT be affected by this change.

5. **Gas Accounting Invariant:** The total gas charged for a transaction creating N new state elements and M new accounts (where M is the number of accounts whose nonce transitions from 0 to 1 in this transaction) MUST equal: base_transaction_gas + operation_gas + (N × 250,000) + (M × 250,000). Note: Transferring tokens TO a new address does not create the account (nonce remains 0), so M = 0 in that case.

6. **Contract Creation Cost Invariant:** Contract creation (CREATE/CREATE2) MUST charge exactly `(code_size × 1,000) + 500,000` gas for code storage, replacing the existing EVM per-byte cost. This includes: 1,000 gas per byte of contract code (linear pricing) and 500,000 gas (2 × 250,000) for keccak hash and codesize fields. The account creation cost (250,000 gas) is charged separately.
6. **Contract Creation Cost Invariant:** Contract creation (CREATE/CREATE2) MUST charge exactly `(code_size × 1,000) + 500,000` gas for code storage, replacing the existing EVM per-byte cost. This includes: 1,000 gas per byte of contract code (linear pricing) and a fixed upfront contract creation cost of 500,000 gas. There is no separate account creation charge for the contract.

7. **Economic Deterrent Invariant:** The cost to create 1 TB of state MUST be at least $50 million, and the cost to create 10 TB of state MUST be at least $500 million, based on the assumed gas price of 1 cent per 500,000 gas.

Expand All @@ -324,8 +326,8 @@ The test suite must cover:
1. **Basic state creation:** Single SSTORE to zero slot charges 250,000 gas
2. **Multiple state creation:** Multiple SSTORE operations to zero slots each charge 250,000 gas
3. **Account creation (EOA):** First transaction from new EOA charges 250,000 gas
4. **Account creation (CREATE):** Contract deployment via CREATE charges 250,000 gas for account creation
5. **Account creation (CREATE2):** Contract deployment via CREATE2 charges 250,000 gas for account creation
4. **Contract creation (CREATE):** Contract deployment via CREATE charges a fixed upfront cost of 500,000 gas (no separate account creation charge)
5. **Contract creation (CREATE2):** Contract deployment via CREATE2 charges a fixed upfront cost of 500,000 gas (no separate account creation charge)
6. **Contract creation (small):** Contract with 100 bytes charges (100 × 1,000) + 500,000 = 600,000 gas for code storage
7. **Contract creation (medium):** Contract with 1,000 bytes charges (1,000 × 1,000) + 500,000 = 1,500,000 gas for code storage
8. **Contract creation (large):** Contract with 10,000 bytes charges (10,000 × 1,000) + 500,000 = 10,500,000 gas for code storage
Expand Down
Loading
Loading