📚 第四章 | Solidity 基础语法全面讲解
——打好基础,才能在智能合约世界走得更远!
✅ 本章导读
无论是写 ERC20、NFT,还是更复杂的 DeFi、DAO 合约,Solidity 的基础语法都是你绕不开的核心。
写合约跟普通的 JS、Python、Java 程序不同,它要跑在区块链上,任何一次失误,都会付出“真实代价”。
- 有人权限控制没搞好,资金被黑客一撸到底
- 有人因为数据类型没弄懂,合约直接锁死没人能用
这些事故,大多是“基础不扎实”惹的祸。
这一章,我们详细讲一讲 Solidity 的核心基础语法,手把手让你理解“为什么”和“怎么用”。
这篇文章读完,你就能自己写一个“可运行”的基础合约,跟链上世界打个招呼。
✅ 本章核心内容
- Solidity 的基础数据类型
- 状态变量和函数
- 函数的可见性和状态修饰符
- 事件(Events)
- 常用数据结构(数组、映射、结构体)
- 函数修饰符(权限控制)
- 错误处理
- 小结 + 作业挑战
1️⃣ Solidity 是什么语言?
首先,Solidity 是一种静态类型语言。
- 静态类型 = 每个变量声明时,必须写明数据类型
- 这是为了安全和性能优化,写代码时就避免数据混乱
- 很像 JS 和 C++ 的语法结构,但运行在以太坊虚拟机(EVM)里
2️⃣ Solidity 版本选择(很重要)
建议直接用最新稳定版 0.8.x
系列,特别是 0.8.19
或更高。
为什么?
- 内置了溢出检查(以前 0.7 版本经常溢出被打爆)
- 支持自定义错误,Gas 更便宜
- EVM 和主流工具(Hardhat / Foundry / OpenZeppelin)兼容性最好
每个合约第一行代码写版本声明👇
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
📌
SPDX-License-Identifier
是开源协议声明,养成习惯一定要写。
3️⃣ Solidity 常用数据类型
✅ 值类型(Value Types)
值类型的数据,直接存储的是数值,而不是指向值的引用。
值类型复制时,值是复制的副本。
常用值类型
类型 | 说明 | 示例值 |
---|---|---|
bool | 布尔类型,值为 true 或 false | true |
uint | 无符号整数,默认 uint256 | 100 |
int | 有符号整数 | -100 |
address | 区块链地址 | 0xabc... |
bytes | 定长字节数组(通常用于 hash) | bytes32 |
string | 字符串 | "Hello" |
enum | 枚举类型,预定义的状态机 | enum Status {ON, OFF} |
示例
bool public isActive = true;
uint256 public totalSupply = 10000;
address public owner = msg.sender;
📌
uint
默认等价于uint256
,链上永远不要偷懒写uint
。
✅ 引用类型(Reference Types)
引用类型的数据,存储的是地址引用,而不是实际的值。
修改引用类型数据时,可能直接影响链上数据(耗费 Gas)。
常用引用类型
类型 | 说明 |
---|---|
array | 数组(静态/动态) |
mapping | 映射(key-value 对应关系) |
struct | 自定义结构体 |
存储关键字
关键字 | 场景 |
---|---|
storage | 永久存储在链上,读写都贵 |
memory | 临时数据,函数结束后消失 |
calldata | 外部调用参数,读更便宜 |
function setName(string memory _name) public {
name = _name; // name 为状态变量 storage
}
📌 经常有新手
memory
和storage
混淆,记住:storage
是链上的“硬盘”,memory
是函数内存条。
4️⃣ 状态变量和局部变量
✅ 状态变量(State Variables)
- 定义在合约外层,存储在链上
- 可以
public
公开读,自动生成 getter 方法
uint public count = 0;
✅ 局部变量(Local Variables)
- 写在函数内部,执行完函数自动消失
function foo() public pure returns (uint) {
uint temp = 123;
return temp;
}
5️⃣ 常量和不可变变量
类型 | 场景 |
---|---|
constant | 编译时确定,值永远不会变 |
immutable | 部署时确定,之后不能改 |
uint constant MAX_SUPPLY = 10000;
address immutable OWNER;
constructor() {
OWNER = msg.sender;
}
📌
constant
常用于配置参数;immutable
用于合约初始化参数(例如所有者)。
6️⃣ 函数详解
✅ 函数结构
function transfer(address _to, uint256 _amount) public returns (bool) {
// 函数逻辑
}
✅ 可见性(Visibility)
修饰符 | 说明 |
---|---|
public | 任何人/合约都能调 |
private | 仅合约内部 |
internal | 合约内部 + 继承合约 |
external | 只能外部账户/合约调用 |
📌
external
调用需要this.方法()
,消耗 Gas 高,慎用!
✅ 状态修饰符
修饰符 | 说明 |
---|---|
view | 只读状态,不消耗 Gas |
pure | 不读不写状态,纯计算 |
payable | 接收 ETH |
function getBalance() public view returns (uint) {
return address(this).balance;
}
7️⃣ 事件(Events)
事件是 DApp 前端监听合约状态变化的唯一途径。
举个例子,你发布 ERC20 代币,钱包页面余额变化监听的就是事件。
event Transfer(address indexed from, address indexed to, uint256 value);
function transfer(address _to, uint256 _amount) public {
emit Transfer(msg.sender, _to, _amount);
}
📌
indexed
用来筛选日志,最多支持 3 个indexed
参数。
8️⃣ 映射(Mappings)
映射(mapping
)是 Solidity 最常用的数据结构!
用于地址余额、权限白名单、NFT 所有者等。
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
✅ 特点
- 默认值是 0
- 不可遍历
- 没有
.length
属性 - 用事件记录变化,供前端查阅
9️⃣ 结构体(Structs)
自定义数据结构,结构清晰、易管理。
struct User {
string name;
uint256 age;
}
mapping(address => User) public users;
function register(string memory _name, uint256 _age) public {
users[msg.sender] = User(_name, _age);
}
🔟 函数修饰符(Modifiers)
常用于权限控制、逻辑复用。
比如 onlyOwner
管理员权限。
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
function withdraw() public onlyOwner {
payable(owner).transfer(address(this).balance);
}
1️⃣1️⃣ 错误处理
Solidity 有三种常见的错误处理方式
函数 | 用途 |
---|---|
require | 参数/条件检查(推荐) |
revert | 主动触发回滚 |
assert | 内部状态检查(调试) |
function transfer(address _to, uint256 _amount) public {
require(balances[msg.sender] >= _amount, "Not enough balance");
balances[msg.sender] -= _amount;
balances[_to] += _amount;
}
✅ 本章小结
这一章我们详细讲解了 Solidity 最基础的语法
✅ 数据类型和存储位置
✅ 状态变量和局部变量
✅ 函数结构和可见性
✅ 修饰符和事件
✅ 映射、结构体等关键数据结构
✅ 错误处理机制
✅ 下一章预告|第五章
👉 Solidity 数据类型深度解析
memory
和storage
的性能优化address payable
和 ETH 接收处理- 自定义
Error
类型节省 Gas - 开始打磨“合约安全”的基本功
转载自CSDN-专业IT技术社区
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_73054711/article/details/146457217