智能合约开发Solidity 基础语法
基础1-2周
Solidity 基础语法
掌握 Solidity 语言基础,包括数据类型、函数、修饰器、事件等核心概念
🎯 学习要点
理解 EVM 存储模型(storage/memory/calldata)
掌握函数可见性(public/private/internal/external)
熟悉事件机制与 Gas 优化
学会错误处理(require/revert/assert)
📚 课程章节
开发环境搭建(Foundry/Hardhat)1小时
数据类型与变量2小时
函数与修饰器2小时
事件与日志1.5小时
错误处理1小时
代码示例
基础合约结构
展示了合约的基本结构,包括状态变量、函数、修饰器和事件
solidity
1// SPDX-License-Identifier: MIT2pragma solidity ^0.8.20;3 4/**5 * @title SimpleStorage6 * @dev 演示基础数据类型和函数7 */8contract SimpleStorage {9 // 状态变量(存储在 storage)10 uint256 private favoriteNumber;11 address public owner;12 13 // 结构体14 struct Person {15 string name;16 uint256 age;17 }18 19 // 映射20 mapping(address => Person) public people;21 22 // 事件23 event NumberUpdated(uint256 indexed oldNumber, uint256 indexed newNumber, address updater);24 25 // 修饰器26 modifier onlyOwner() {27 require(msg.sender == owner, "Not owner");28 _;29 }30 31 // 构造函数32 constructor() {33 owner = msg.sender;34 }35 36 // 公共函数37 function setNumber(uint256 _number) external onlyOwner {38 uint256 oldNumber = favoriteNumber;39 favoriteNumber = _number;40 emit NumberUpdated(oldNumber, _number, msg.sender);41 }42 43 // 视图函数(不修改状态)44 function getNumber() external view returns (uint256) {45 return favoriteNumber;46 }47 48 // 纯函数(不读取状态)49 function add(uint256 a, uint256 b) external pure returns (uint256) {50 return a + b;51 }52}数据位置与 Gas 优化
理解 storage/memory/calldata 的区别对 Gas 优化至关重要
solidity
1contract DataLocation {2 struct LargeData {3 uint256 id;4 string name;5 bytes data;6 }7 8 LargeData[] public items;9 10 // ❌ 低效:复制到 memory11 function inefficientUpdate(uint256 index) external {12 LargeData memory item = items[index];13 item.id = 999;14 items[index] = item; // 整个结构体写回15 }16 17 // ✅ 高效:直接操作 storage18 function efficientUpdate(uint256 index) external {19 LargeData storage item = items[index];20 item.id = 999; // 只修改一个字段21 }22 23 // calldata:只读,最省 Gas24 function processData(string calldata _text) external pure returns (uint256) {25 return bytes(_text).length;26 }27}错误处理最佳实践
自定义错误比 require 字符串更省 Gas,且提供更好的类型安全
solidity
1contract ErrorHandling {2 error InsufficientBalance(uint256 requested, uint256 available);3 error Unauthorized(address caller);4 5 mapping(address => uint256) public balances;6 address public admin;7 8 // ✅ 推荐:自定义错误(省 Gas)9 function withdraw(uint256 amount) external {10 if (balances[msg.sender] < amount) {11 revert InsufficientBalance({12 requested: amount,13 available: balances[msg.sender]14 });15 }16 balances[msg.sender] -= amount;17 payable(msg.sender).transfer(amount);18 }19 20 // ⚠️ require:适合简单条件检查21 function setAdmin(address newAdmin) external {22 require(msg.sender == admin, "Only admin");23 admin = newAdmin;24 }25 26 // ⚠️ assert:用于不变量检查(会消耗所有剩余 Gas)27 function internalTransfer(address from, address to, uint256 amount) internal {28 balances[from] -= amount;29 balances[to] += amount;30 assert(balances[from] + balances[to] >= amount); // 溢出检查31 }32}