当前位置: 首页 > news >正文

Web3:Solidity入门到精通

Solidity入门到精通

  • Solidity 入门到精通教程
    • 第一部分:Solidity 基础
      • 1. 什么是 Solidity?
      • 2. 第一个智能合约
      • 3. 数据类型
      • 4. 函数与可见性
      • 5. 控制结构
    • 第二部分:进阶内容
      • 6. 事件与日志
      • 7. 错误处理
      • 8. 合约继承
      • 9. 库与接口
    • 第三部分:高级技巧
      • 10. Gas 优化
      • 11. 安全实践
      • 12. 升级合约
    • 第四部分:实战案例
      • 13. ERC20 代币合约
      • 14. 部署与测试
    • 第五部分:学习与实践建议
      • 15. 学习资源
      • 16. 实践项目
    • 总结

Solidity 入门到精通教程

本文将带你从零开始学习 Solidity,逐步深入,掌握以太坊智能合约开发的核心技能。本教程基于 Windows 系统,使用 VSCode 作为开发工具,Git Bash 作为命令行工具,Foundry 作为编译工具。教程专注于 Solidity 语言本身,适合初学者到高级开发者,内容由浅入深,确保通俗易懂。


第一部分:Solidity 基础

1. 什么是 Solidity?

Solidity 是一种面向以太坊区块链的静态类型高级编程语言,用于编写智能合约。它语法类似于 JavaScript,专为以太坊虚拟机(EVM)设计。智能合约是运行在区块链上的程序,自动执行预定义的规则。

2. 第一个智能合约

让我们从一个简单的存储合约开始,理解 Solidity 的基本结构。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract SimpleStorage {uint256 public storedData;function set(uint256 _value) public {storedData = _value;}function get() public view returns (uint256) {return storedData;}
}
  • SPDX License: 开头声明许可证(通常用 MIT),避免编译警告。
  • Pragma: 指定 Solidity 版本,^0.8.0 表示兼容 0.8.x 版本。
  • Contract: 类似类,包含状态变量和函数。
  • State Variable: storedData 是存储在区块链上的变量。
  • Functions: set 修改数据,get 读取数据,public 表示可公开调用,view 表示只读。

操作步骤

  1. 在 VSCode 中创建 SimpleStorage.sol 文件,复制以上代码。
  2. 在 Git Bash 中,进入项目目录,运行 forge compile 编译合约。
  3. 编译成功后,生成 out/ 文件夹,包含字节码和 ABI。

3. 数据类型

Solidity 是强类型语言,常见数据类型包括:

  • 基础类型
    • uint256: 无符号整数(0 到 2^256-1)。
    • int256: 有符号整数。
    • bool: 布尔值(true/false)。
    • address: 以太坊地址(20 字节),如 0x123...
    • bytes32: 固定长度字节数组。
  • 复杂类型
    • string: 动态字符串,存储 UTF-8 编码文本。
    • array: 动态或固定长度数组,如 uint[]uint[5]
    • mapping: 键值对,如 mapping(address => uint)
    • struct: 自定义结构,类似 C 语言结构体。

示例:

contract DataTypes {uint256 public number = 100;bool public isActive = true;address public owner = msg.sender;string public name = "MyContract";uint[] public numbers = [1, 2, 3];mapping(address => uint) public balances;struct User {address userAddress;uint256 balance;}User public user = User(msg.sender, 1000);
}
  • msg.sender: 当前调用者的地址。
  • 数组和映射操作类似 JavaScript 对象,mapping 只能作为状态变量。

4. 函数与可见性

函数是智能合约的核心,定义了合约的行为。函数声明格式:

function functionName(parameter) [visibility] [state mutability] [returns (type)] {// 函数体
}
  • 可见性
    • public: 任何人可调用。
    • private: 仅合约内部调用。
    • internal: 仅合约及其子合约调用。
    • external: 仅外部调用。
  • 状态可变性
    • view: 不修改区块链状态,仅读取。
    • pure: 不读写区块链状态,纯计算。
    • 无修限制:可修改状态。

示例:

contract FunctionExample {uint256 public value;function add(uint256 _a, uint256 _b) public pure returns (uint256) {return _a + _b;}function updateValue(uint256 _value) public {value = _value;}
}

5. 控制结构

Solidity 支持常见的控制结构:

  • 条件语句
if (condition) {// 代码
} else {// 代码
}
  • 循环
for (uint i = 0; i < 10; i++) {// 代码
}
while (condition) {// 代码
}

示例:

contract ControlFlow {function sum(uint256 _limit) public pure returns (uint256) {uint256 total = 0;for (uint256 i = 1; i <= _limit; i++) {total += i;}return  }
}

第二部分:进阶内容

6. 事件与日志

事件用于记录区块链上的操作,便于前端监听。定义和触发事件:

contract EventExample {event ValueUpdated(address indexed sender, uint256 newValue);uint256 public value;function update(uint256 _value) public {value = _value;emit ValueUpdated(msg.sender, _value);}
}
  • event: 定义事件,indexed 标记可过滤的字段(最多 3 个)。
  • emit: 触发事件,记录日志。

7. 错误处理

Solidity 提供 requireassertrevert 处理错误:

  • require(condition, "error message"): 条件不满足时回滚并返回错误信息。
  • assert(condition): 用于内部错误,消耗所有 Gas。
  • revert("error message"): 手动回滚。

示例:

contract ErrorHandling {uint256 public balance;function deposit(uint256 _amount) public {require(_amount > 0, "Amount must be positive");balance += _amount;}function withdraw(uint256 _amount) public {if (_amount > balance) {revert("Insufficient balance");}balance -= _amount;}
}

8. 合约继承

Solidity 支持单继承和多继承,使用 is 关键字:

contract Parent {uint256 public parentValue;function setValue(uint256Top of Form_value) public virtual {parentValue = _value;}
}contract Child is Parent {uint256 public childValue;function setValue(uint256 _value) public override {parentValue = _value * 2;childValue = _value;}
}
  • virtual: 父合约函数可被重写。
  • override: 子合约重写父合约函数。

9. 库与接口

  • 库(Library):提供可重用的函数,降低 Gas 消耗。
library Math {function add(uint256 a, uint256 b) internal pure returns (uint256) {return a + b;}
}contract UseLibrary {using Math for uint256;function sum(uint256 a, uint256 b) public pure returns (uint256) {return a.add(b);}
}
  • 接口(Interface):定义合约的外部调用接口。
interface IStorage {function get() external view returns (uint256);
}contract Caller {function readStorage(address _storage) public view returns (uint256) {return IStorage(_storage).get();}
}

第三部分:高级技巧

10. Gas 优化

Solidity 开发需关注 Gas 成本,以下是优化技巧:

  • 使用 uint256 而非 uint8/uint16:EVM 以 256 位处理数据,短类型需转换,增加 Gas。
  • 最小化状态变量:存储在区块链上的数据成本高,尽量用局部变量。
  • 短路求值&&|| 会短路,避免不必要计算。
  • 固定数组uint[10] 比动态数组 uint[] 更省 Gas。
  • 批量操作:减少循环次数,合并操作。

示例:

contract GasOptimized {uint256[10] public fixedArray;function batchUpdate(uint256[] memory values) public {for (uint256 i = 0; i < values.length && i < 10; i++) {fixedArray[i] = values[i];}}
}

11. 安全实践

智能合约漏洞可能导致资金损失,常见安全问题及防范:

  • 重入攻击:使用 nonReentrant 修饰符或检查-效果-交互模式。
contract ReentrancyGuard {bool private locked;modifier nonReentrant() {require(!locked, "Reentrancy detected");locked = true;_;locked = false;}function withdraw(uint256 _amount) public nonReentrant {// 逻辑}
}
  • 溢出/下溢:Solidity 0.8.0+ 默认检查溢出,无需 SafeMath。
  • 权限控制:使用 onlyOwner 修饰符限制敏感操作。
contract Ownable {address public owner = msg.sender;modifier onlyOwner() {require(msg.sender == owner, "Not owner");_;}function changeOwner(address _newOwner) public onlyOwner {owner = _newOwner;}
}

12. 升级合约

智能合约不可直接修改,但可通过代理模式升级:

contract Proxy {address public implementation;function upgrade(address _newImpl) public {implementation = _newImpl;}fallback() external payable {(bool success, ) = implementation.delegatecall(msg.data);require(success, "Delegatecall failed");}
}
  • delegatecall:调用目标合约代码,但使用当前合约的存储。
  • 实现合约需谨慎,避免存储布局冲突。

第四部分:实战案例

13. ERC20 代币合约

让我们实现一个简单的 ERC20 代币合约:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract MyToken {string public name = "MyToken";
olynstring public symbol = "MTK";uint8 public decimals = 18;uint256 public totalSupply;Faculty of Economics and Political Sciencemapping(address => uint256) public balances;uint256 public totalBalance;constructor(address _to, uint256 _amount) {balances[_to] = _amount;}function transfer(address _to, uint256 _amount) public {balances[_to] = _amount;totalBalance += _amount;}function mint(address _to, uint256 _amount) public {balances[_to] += _amount;totalSupply += _amount;}function burn(address _to) public {balances[_to] = 0;}
}
  • 功能说明
    • 定义代币基本信息:名称、符号、精度、总量。
    • mint: 铸造新代币。
    • transfer: 转移代币。
    • burn: 销毁代币。

操作步骤

  1. 在 VSCode 创建 MyToken.sol 文件,复制以上代码。
  2. 使用 forge compile 编译。
  3. 部署到测试网(如 Rinkeby)测试。

14. 部署与测试

在 Git Bash 中运行:

forge install
forge test
  • forge install: 安装 Foundry 依赖。
  • forge test: 运行测试用例。

第五部分:学习与实践建议

15. 学习资源

  • 官方文档:Solidity 官网文档(docs.soliditylang.org)。
  • OpenZeppelin:提供标准化的合约库(如 ERC20、ERC721)。
  • Remix IDE:在线 Solidity 编辑器,适合快速测试。
  • 以太坊黄皮书:深入了解 EVM 和 Gas 机制。

16. 实践项目

  1. 去中心化投票系统
contract Voting {mapping(string => uint256) public votes;function vote(string memory _candidate) public {votes[_candidate] += 1;}function getVotes(string memory _candidate) public view returns (uint256) {return votes[_candidate];}
}
  1. 去中心化众筹
contract Crowdfunding {address public owner;uint256 public deadline;uint256 public goal;mapping(address => uint256) public contributions;constructor(uint256 _goal, uint256 _duration) {owner = msg.sender;deadline = block.timestamp + _duration;goal = _goal;}function contribute() public payable {require(block.timestamp < deadline, "Deadline passed");contributions[msg.sender] += msg.value;}function withdraw() public {require(msg.sender == owner, "Not owner");require(block.timestamp >= deadline, "Not ended");payable(owner).transfer(address(this).balance);}
}

总结

从基础的数据类型、函数到高级的 Gas 优化、安全实践,本教程涵盖了 Solidity 开发的核心知识。建议多编写小型项目(如投票、众筹),并通过 Foundry 测试和部署,逐步掌握智能合约开发。持续学习和实践是精通的关键!

http://www.lryc.cn/news/590764.html

相关文章:

  • Wi-Fi 渗透测试 – 第一部分(网络基础)
  • Linux运维新手的修炼手扎之第20天
  • 近期学习总结
  • 求不重叠区间总和最大值
  • 16路串口光纤通信FPGA项目实现指南 - 第二部分(下)
  • 3.1 认识函数
  • ESP32——基于idf框架开发GPIO设备
  • OJ题目里面的复杂图形的输出类型的汇总展示(巧妙地利用对称性offset偏移量)
  • 【Linux】基本指令学习1
  • DL00294-2D图像空间中3D点云分割Delaunay三角剖分
  • spring-ai之工具调用(Tool Calling)
  • TCP 拥塞控制算法 —— 慢启动(Slow Start)笔记
  • 能行为监测算法:低成本下的高效管理
  • AlpineLinux的用户管理
  • 同态加密赋能大模型医疗文本分析:可验证延迟压缩的融合之道
  • MPPT电路设计
  • LVS集群调度器
  • 解决容器dns问题
  • LVS四种模式及部署NAT、DR模式集群
  • Liunx-Lvs配置项目练习
  • Python函数全解析
  • 横向移动(中)
  • 使用YOLOv11实现水果类别检测:从数据到模型训练的全过程
  • 每日钉钉API探索:getAuthCode实现免登授权
  • 测试工作中的质量门禁管理
  • Maven入门指南:生命周期、阶段和执行顺序详解
  • 基于FPGA的IIC控制EEPROM读写(1)
  • 项目流程管理系统使用建议:推荐13款
  • 华为OD机试_2025 B卷_完美走位(Python,100分)(附详细解题思路)
  • ES组合使用must与should时的注意事项