Post

以太坊代币标准 ERC20、ERC721和ERC1155

以太坊代币标准 ERC20、ERC721和ERC1155

ERC20:同质化代币标准

ERC20 是以太坊上最广泛使用的代币标准,用于创建同质化代币(每个代币都是相同的、可互换的)。

ERC20 应用场景

  • DeFi 协议代币:Uniswap (UNI)、Compound (COMP)
  • 稳定币:USDC、USDT、DAI
  • 治理代币:用于 DAO 投票和治理
  • 实用代币:平台内的功能性代币

ERC721:非同质化代币标准

ERC721 用于创建非同质化代币(NFT),每个代币都是独一无二的,不可替换。

ERC1155:多代币标准

ERC1155 是一个革命性的标准,允许在单个合约中管理多种类型的代币(同质化和非同质化)。

三种标准的对比分析

特征ERC20ERC721ERC1155
代币类型同质化非同质化多类型支持
可替换性完全可替换不可替换根据类型决定
批量操作不支持不支持原生支持
Gas 效率中等
存储成本中等
应用场景货币、代币艺术品、收藏品游戏道具、多资产

Gas 成本比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 铸造100个不同的代币

// ERC721方式:需要100次交易
for(uint i = 0; i < 100; i++) {
    nft.mint(to, i, uri); // ~50,000 gas 每次
}
// 总计:~5,000,000 gas

// ERC1155方式:只需1次交易
uint256[] memory ids = new uint256[](100);
uint256[] memory amounts = new uint256[](100);
// ... 填充数组
multiToken.mintBatch(to, ids, amounts, types, uris); // ~500,000 gas
// 总计:~500,000 gas (节省90%!)

实际应用场景

1. DeFi 协议设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 组合使用不同标准的DeFi协议
contract DeFiProtocol {
    IERC20 public governanceToken;    // 治理代币
    IERC721 public membershipNFT;     // 会员NFT
    IERC1155 public rewardAssets;     // 奖励资产

    function stakingReward(address user, uint256 amount) external {
        // 基于ERC721会员等级和ERC20质押量计算奖励
        uint256 memberLevel = getMemberLevel(user);
        uint256 rewardId = calculateRewardType(amount, memberLevel);

        rewardAssets.safeTransferFrom(
            address(this),
            user,
            rewardId,
            amount,
            ""
        );
    }
}

2. 游戏资产管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
contract GameEconomy {
    IERC1155 public gameAssets;

    // 定义不同类型的游戏道具
    uint256 public constant GOLD_COIN = 1;      // 同质化货币
    uint256 public constant SWORD_COMMON = 100; // 普通武器
    uint256 public constant SWORD_RARE = 101;   // 稀有武器
    uint256 public constant UNIQUE_PET = 1000;  // 独特宠物(NFT)

    function craftItem(uint256[] memory materials, uint256[] memory amounts) external {
        // 销毁材料
        gameAssets.safeBatchTransferFrom(
            msg.sender,
            address(0), // 销毁地址
            materials,
            amounts,
            ""
        );

        // 创造新道具
        uint256 newItemId = calculateCraftResult(materials);
        gameAssets.safeTransferFrom(
            address(this),
            msg.sender,
            newItemId,
            1,
            ""
        );
    }
}

3. NFT 市场优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
contract OptimizedMarketplace {
    struct Listing {
        address seller;
        uint256 price;
        bool active;
    }

    mapping(address => mapping(uint256 => Listing)) public listings;

    // 支持ERC721和ERC1155的统一接口
    function listItem(
        address tokenContract,
        uint256 tokenId,
        uint256 amount,
        uint256 price,
        bool isERC1155
    ) external {
        if (isERC1155) {
            require(
                IERC1155(tokenContract).balanceOf(msg.sender, tokenId) >= amount,
                "Insufficient balance"
            );
            require(
                IERC1155(tokenContract).isApprovedForAll(msg.sender, address(this)),
                "Not approved"
            );
        } else {
            require(
                IERC721(tokenContract).ownerOf(tokenId) == msg.sender,
                "Not owner"
            );
            require(amount == 1, "ERC721 amount must be 1");
        }

        listings[tokenContract][tokenId] = Listing({
            seller: msg.sender,
            price: price,
            active: true
        });
    }
}

最佳实践和安全考虑

1. 重入攻击防护

重入攻击是指: 攻击者在合约执行 call(或 transfer)向外部地址发送 ETH 时,外部合约在接收到 ETH 的回调中再次调用当前合约的函数,从而重复提取资产。

1
2
3
4
5
6
7
8
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract SecureToken is ReentrancyGuard {
    function transfer(address to, uint256 amount) external nonReentrant returns (bool) {
        // 转账逻辑
        return true;
    }
}

2. 整数溢出防护

1
2
3
4
5
6
7
8
9
10
// 使用SafeMath或Solidity 0.8+的内置检查
contract SafeToken {
    using SafeMath for uint256; // 对于0.8以下版本

    function transfer(address to, uint256 amount) external returns (bool) {
        balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);
        balanceOf[to] = balanceOf[to].add(amount);
        return true;
    }
}

3. 访问控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import "@openzeppelin/contracts/access/Ownable.sol";

contract ControlledToken is Ownable {
    bool public paused = false;

    modifier whenNotPaused() {
        require(!paused, "Contract is paused");
        _;
    }

    function pause() external onlyOwner {
        paused = true;
    }

    function unpause() external onlyOwner {
        paused = false;
    }
}

4. 元数据标准化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
contract StandardizedNFT {
    // 遵循OpenSea元数据标准
    function tokenURI(uint256 tokenId) public view returns (string memory) {
        return string(abi.encodePacked(baseURI, tokenId.toString(), ".json"));
    }

    // 元数据结构示例:
    // {
    //   "name": "Item Name",
    //   "description": "Item Description",
    //   "image": "https://example.com/image.png",
    //   "attributes": [
    //     {"trait_type": "Rarity", "value": "Legendary"},
    //     {"trait_type": "Power", "value": 100}
    //   ]
    // }
}

5. Gas 优化策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
contract GasOptimizedContract {
    // 使用packed结构体节省存储
    struct PackedData {
        uint128 amount;  // 而不是uint256
        uint64 timestamp;
        uint32 tokenId;
        uint32 reserved;
    }

    // 批量操作减少gas消耗
    function batchMint(address[] calldata recipients, uint256[] calldata amounts) external {
        require(recipients.length == amounts.length, "Length mismatch");

        uint256 length = recipients.length;
        for (uint256 i = 0; i < length;) {
            _mint(recipients[i], amounts[i]);
            unchecked { ++i; } // Gas优化
        }
    }
}

总结

ERC20、ERC721 和 ERC1155 各有其独特的应用场景和优势:

  • ERC20 适合创建货币类代币,如治理代币、实用代币和稳定币
  • ERC721 专门用于独特的数字资产,如艺术品、域名和身份证明
  • ERC1155 提供了最大的灵活性,特别适合需要管理多种资产类型的应用

选择合适的标准需要考虑以下因素:

  1. 应用需求:同质化 vs 非同质化 vs 混合
  2. Gas 效率:ERC1155 在批量操作中表现最佳
  3. 开发复杂度:ERC20 最简单,ERC1155 最复杂
  4. 生态兼容性:考虑与现有 DeFi、钱包的兼容性
This post is licensed under CC BY 4.0 by the author.