乐闻世界logo
搜索文章和话题

What are Ethereum Improvement Proposals (EIPs)? Please explain important proposals such as EIP-1559, ERC-20, and ERC-721

2月21日 14:16

Ethereum Improvement Proposals (EIPs) are formal mechanisms for proposing new features, standards, or process improvements in the Ethereum ecosystem. Here's a comprehensive analysis of EIPs:

Basic Concepts of EIPs

EIP is a standardized process for proposing new ideas to the Ethereum community, gathering feedback, and reaching consensus. Similar to Bitcoin's BIP (Bitcoin Improvement Proposals).

EIP Types

1. Standards Track

Proposals that affect most or all Ethereum implementations, including network protocols, block/transaction validation rules, etc.

Subtypes:

  • Core: Core protocol changes (e.g., EIP-1559)
  • Networking: Network protocol changes
  • Interface: Client API changes
  • ERC: Application layer standards (e.g., ERC-20, ERC-721)

2. Meta EIP

Proposals that change the EIP process itself.

Examples:

  • EIP-1: The EIP process itself

3. Informational EIP

Design issues or general guidelines that don't propose new features.

Examples:

  • EIP-1: EIP process guide

EIP Process

1. Proposal Stage

markdown
# EIP-XXXX: Title ## Simple Summary Brief description of the proposal ## Abstract Detailed description of the proposal ## Motivation Why this proposal is needed ## Specification Technical specification ## Rationale Rationale for design decisions ## Backwards Compatibility Backwards compatibility analysis ## Test Cases Test cases ## Implementations List of implementations ## Security Considerations Security considerations ## Copyright Copyright notice

2. Review Stage

  • Community discussion
  • Technical review
  • Security audit

3. Last Call

  • Final review
  • Collect final feedback

4. Merge Stage

  • Merge into protocol
  • Deploy implementation

Famous EIP Analysis

1. EIP-1559: Ethereum Transaction Fee Market Reform

solidity
// EIP-1559 transaction structure struct EIP1559Transaction { uint256 chainId; // Chain ID uint256 nonce; // Transaction nonce uint256 maxPriorityFeePerGas; // Tip uint256 maxFeePerGas; // Maximum gas fee address to; // Recipient uint256 value; // Transfer amount bytes data; // Transaction data uint256 accessListLength; // Access list length AccessListEntry[] accessList; // Access list } // Gas fee calculation function calculateGasFee( uint256 baseFee, uint256 maxPriorityFeePerGas, uint256 maxFeePerGas ) public pure returns (uint256) { uint256 effectivePriorityFeePerGas = min( maxPriorityFeePerGas, maxFeePerGas - baseFee ); return baseFee + effectivePriorityFeePerGas; } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; }

Features:

  • Base Fee automatically adjusts
  • Tip incentivizes miners/validators
  • More predictable transaction fees
  • EIP-1559 transaction type

2. EIP-20: Token Standard

solidity
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface IERC20 { event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); } contract ERC20 is IERC20 { string public name; string public symbol; uint8 public decimals = 18; uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; constructor(string memory _name, string memory _symbol, uint256 _totalSupply) { name = _name; symbol = _symbol; totalSupply = _totalSupply; balanceOf[msg.sender] = _totalSupply; emit Transfer(address(0), msg.sender, _totalSupply); } function transfer(address to, uint256 amount) external returns (bool) { _transfer(msg.sender, to, amount); return true; } function approve(address spender, uint256 amount) external returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transferFrom(address from, address to, uint256 amount) external returns (bool) { uint256 currentAllowance = allowance[from][msg.sender]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); allowance[from][msg.sender] = currentAllowance - amount; _transfer(from, to, amount); return true; } function _transfer(address from, address to, uint256 amount) internal { require(balanceOf[from] >= amount, "ERC20: transfer amount exceeds balance"); balanceOf[from] -= amount; balanceOf[to] += amount; emit Transfer(from, to, amount); } }

3. EIP-721: Non-Fungible Token Standard

solidity
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface IERC721 { event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); function balanceOf(address owner) external view returns (uint256 balance); function ownerOf(uint256 tokenId) external view returns (address owner); function safeTransferFrom(address from, address to, uint256 tokenId) external; function transferFrom(address from, address to, uint256 tokenId) external; function approve(address to, uint256 tokenId) external; function getApproved(uint256 tokenId) external view returns (address operator); function setApprovalForAll(address operator, bool _approved) external; function isApprovedForAll(address owner, address operator) external view returns (bool); } contract ERC721 is IERC721 { string public name; string public symbol; mapping(uint256 => address) public ownerOf; mapping(address => uint256) public balanceOf; mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } function transferFrom(address from, address to, uint256 tokenId) external { require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } function approve(address to, uint256 tokenId) external { address owner = ownerOf[tokenId]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "ERC721: approve caller is not owner nor approved for all"); getApproved[tokenId] = to; emit Approval(owner, to, tokenId); } function setApprovalForAll(address operator, bool _approved) external { isApprovedForAll[msg.sender][operator] = _approved; emit ApprovalForAll(msg.sender, operator, _approved); } function _transfer(address from, address to, uint256 tokenId) internal { require(ownerOf[tokenId] == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); delete getApproved[tokenId]; ownerOf[tokenId] = to; balanceOf[from]--; balanceOf[to]++; emit Transfer(from, to, tokenId); } function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { address owner = ownerOf[tokenId]; return (spender == owner || getApproved[tokenId] == spender || isApprovedForAll[owner][spender]); } }

4. EIP-1155: Multi-Token Standard

solidity
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface IERC1155 { event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); function balanceOf(address account, uint256 id) external view returns (uint256); function balanceOfBatch(address[] memory accounts, uint256[] memory ids) external view returns (uint256[] memory); function setApprovalForAll(address operator, bool approved) external; function isApprovedForAll(address account, address operator) external view returns (bool); function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) external; function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) external; } contract ERC1155 is IERC1155 { mapping(uint256 => mapping(address => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; function balanceOf(address account, uint256 id) external view returns (uint256) { return balanceOf[id][account]; } function balanceOfBatch(address[] memory accounts, uint256[] memory ids) external view returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; i++) { batchBalances[i] = balanceOf[ids[i]][accounts[i]]; } return batchBalances; } function setApprovalForAll(address operator, bool approved) external { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) external { require(from == msg.sender || isApprovedForAll[from][msg.sender], "ERC1155: caller is not owner nor approved"); require(to != address(0), "ERC1155: transfer to the zero address"); balanceOf[id][from] -= amount; balanceOf[id][to] += amount; emit TransferSingle(msg.sender, from, to, id, amount); } function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) external { require(from == msg.sender || isApprovedForAll[from][msg.sender], "ERC1155: caller is not owner nor approved"); require(to != address(0), "ERC1155: transfer to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); for (uint256 i = 0; i < ids.length; i++) { balanceOf[ids[i]][from] -= amounts[i]; balanceOf[ids[i]][to] += amounts[i]; } emit TransferBatch(msg.sender, from, to, ids, amounts); } }

EIP Best Practices

1. Proposal Preparation

  • Thoroughly research existing EIPs
  • Discuss ideas with community
  • Prepare detailed technical specifications

2. Community Participation

  • Discuss on Ethereum Magicians forum
  • Submit PR on GitHub
  • Attend community meetings

3. Technical Review

  • Seek expert review
  • Conduct security audits
  • Write test cases

4. Documentation

  • Clear descriptions
  • Complete specifications
  • Example code

Important EIP List

Core Protocol

  • EIP-155: Simple replay attack protection
  • EIP-1559: Transaction fee market reform
  • EIP-2930: Transaction type access list
  • EIP-3074: Abstract accounts

Token Standards

  • EIP-20: ERC-20 token standard
  • EIP-721: ERC-721 NFT standard
  • EIP-1155: Multi-token standard
  • EIP-777: Token standard (ERC-20 compatible)

Application Layer

  • EIP-137: ENS domain registration
  • EIP-191: Signed data
  • EIP-712: Typed structured data hashing and signing
  • EIP-165: Standard interface detection

EIP is an important mechanism for Ethereum evolution, driving technological innovation and standardization through community collaboration.

标签:以太坊