学习记录
搭建僵尸工厂 - Solidity学习

搭建僵尸工厂 - Solidity学习笔记

📖 课程概览

完成度: 100% ✅
课程来源: CryptoZombies教程
技术栈: Solidity, 智能合约开发

🎯 学习目标

  • 掌握Solidity智能合约基础语法
  • 理解以太坊智能合约的工作原理
  • 学会创建和部署简单的智能合约
  • 实现一个完整的僵尸工厂游戏合约

📝 核心知识点

1. Solidity基础语法

合约结构

pragma solidity >=0.5.0 <0.6.0;
 
contract ZombieFactory {
    // 状态变量
    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;
    
    // 结构体
    struct Zombie {
        string name;
        uint dna;
    }
    
    // 数组
    Zombie[] public zombies;
    
    // 映射
    mapping (uint => address) public zombieToOwner;
    mapping (address => uint) ownerZombieCount;
    
    // 事件
    event NewZombie(uint zombieId, string name, uint dna);
}

数据类型详解

  • uint: 无符号整数,默认uint256
  • string: 字符串类型
  • address: 以太坊地址类型
  • mapping: 哈希表,类似字典
  • array: 数组,可以是动态或固定大小

2. 核心功能实现

僵尸创建函数

function _createZombie(string memory _name, uint _dna) internal {
    uint id = zombies.push(Zombie(_name, _dna)) - 1;
    zombieToOwner[id] = msg.sender;
    ownerZombieCount[msg.sender]++;
    emit NewZombie(id, _name, _dna);
}
 
function _generateRandomDna(string memory _str) private view returns (uint) {
    uint rand = uint(keccak256(abi.encodePacked(_str)));
    return rand % dnaModulus;
}
 
function createRandomZombie(string memory _name) public {
    require(ownerZombieCount[msg.sender] == 0);
    uint randDna = _generateRandomDna(_name);
    randDna = randDna - randDna % 100;
    _createZombie(_name, randDna);
}

3. 重要概念解析

函数修饰符

  • public: 任何人都可以调用
  • private: 只有合约内部可以调用
  • internal: 合约内部和继承合约可以调用
  • external: 只能从合约外部调用

函数状态修饰符

  • view: 只读函数,不修改状态
  • pure: 纯函数,不读取也不修改状态
  • payable: 可以接收以太币的函数

特殊变量

  • msg.sender: 调用函数的地址
  • msg.value: 发送的以太币数量
  • block.timestamp: 当前区块时间戳

4. 安全性考虑

require语句

function createRandomZombie(string memory _name) public {
    require(ownerZombieCount[msg.sender] == 0, "User already has a zombie");
    // 函数逻辑...
}

访问控制

modifier onlyOwnerOf(uint _zombieId) {
    require(msg.sender == zombieToOwner[_zombieId]);
    _;
}
 
function changeName(uint _zombieId, string calldata _newName) external onlyOwnerOf(_zombieId) {
    zombies[_zombieId].name = _newName;
}

🛠️ 完整合约代码

pragma solidity >=0.5.0 <0.6.0;
 
contract ZombieFactory {
 
    event NewZombie(uint zombieId, string name, uint dna);
 
    uint dnaDigits = 16;
    uint dnaModulus = 10 ** dnaDigits;
 
    struct Zombie {
        string name;
        uint dna;
        uint32 level;
        uint32 readyTime;
        uint16 winCount;
        uint16 lossCount;
    }
 
    Zombie[] public zombies;
 
    mapping (uint => address) public zombieToOwner;
    mapping (address => uint) ownerZombieCount;
 
    function _createZombie(string memory _name, uint _dna) internal {
        uint id = zombies.push(Zombie(_name, _dna, 1, uint32(now + cooldownTime), 0, 0)) - 1;
        zombieToOwner[id] = msg.sender;
        ownerZombieCount[msg.sender]++;
        emit NewZombie(id, _name, _dna);
    }
 
    function _generateRandomDna(string memory _str) private view returns (uint) {
        uint rand = uint(keccak256(abi.encodePacked(_str)));
        return rand % dnaModulus;
    }
 
    function createRandomZombie(string memory _name) public {
        require(ownerZombieCount[msg.sender] == 0);
        uint randDna = _generateRandomDna(_name);
        randDna = randDna - randDna % 100;
        _createZombie(_name, randDna);
    }
 
}

🤔 学习心得与思考

技术收获

  1. 智能合约思维: 学会了用去中心化的思维设计应用逻辑
  2. Gas优化: 理解了Gas机制,学会编写高效的合约代码
  3. 安全编程: 掌握了智能合约的安全最佳实践

实际应用场景

  • 数字收藏品 (NFT): 僵尸可以作为NFT进行交易
  • 游戏开发: 区块链游戏的基础架构
  • DeFi应用: 质押、治理等机制的基础

遇到的挑战

  1. Gas费用: 每次交易都需要支付Gas费用
  2. 不可修改性: 智能合约部署后难以修改
  3. 调试困难: 相比传统开发,调试更加复杂

🔗 相关资源

📅 后续学习计划

  • 学习更高级的Solidity特性(继承、接口、库)
  • 深入研究DeFi协议的实现原理
  • 学习智能合约测试框架(Truffle, Hardhat)
  • 探索Layer 2解决方案(Polygon, Optimism)
  • 学习前端与智能合约的交互(Web3.js, Ethers.js)

🏆 项目成果

通过这个课程,我成功:

  • ✅ 创建了第一个智能合约
  • ✅ 理解了区块链开发的基本概念
  • ✅ 掌握了Solidity的核心语法
  • ✅ 学会了智能合约的部署和交互

这个项目为我进入Web3开发领域打下了坚实的基础!


最后更新时间: 2025/8/9