📋 文章摘要
作为一个从2019年撸币到2026年仍在写Solidity的老韭菜,很多小伙伴问我怎么快速入门。我把自己最常踩的3个坑、2个实操技巧、1套平台选型模型都浓缩成6条干货,帮助新手少走弯路,直接写出安全合约。
我记得2019年第一次听朋友喊“来写Solidity吧”,他手里拿着一张白纸,随手画了个ERC20,却忘了uint256溢出防护。结果合约部署后,第二天就被人抢走了10万USDT。那一刻,我差点把键盘砸了。说句实话,很多新手都是这么死的:没弄清楚基础概念就盲目上手。今天,我把这几年的血泪教训浓缩成6大避坑,帮你少走弯路,直接写出能跑的合约。
1、别把变量类型当装饰品——必须先懂Solidity的类型系统
新手vs老手的第一道坎,就是变量的默认行为。很多人写uint以为是uint256,其实在0.8.x以后默认是uint256,但在旧版编译器里会变成uint128,导致算术溢出。错误示例:uint balance = msg.value;,不加SafeMath直接相加,很容易被攻击。正确做法:统一声明为uint256,并在关键运算前使用unchecked或SafeMath。下面的表格直观对比了两种写法的安全性:
| 写法 | Solidity >=0.8 | Solidity <0.8 | 是否安全 |
|---|---|---|---|
uint a = b + c; | 自动溢出检查 | 溢出不检查 | ❌ 旧版风险 |
uint256 a = SafeMath.add(b,c); | 兼容所有版本 | 手动检查 | ✅ 推荐 |
这一步是我花了真金白银才学到的,别省略类型声明,否则你的合约随时会被玩坏。
2、函数可见性不是装饰品——每个函数都要明确public/external/internal/private

新手常把所有函数默认写成public,结果导致合约内部逻辑被外部直接调用。老手都会在函数名前明确标注可见性,甚至把内部辅助函数设为internal或private,防止被恶意调用。错误示例:
function setOwner(address _owner) {
owner = _owner;
}
没有public或external,编译不报错但默认是public,安全隐患极大。正确示例:
function setOwner(address _owner) external onlyOwner {
owner = _owner;
}
配合onlyOwner修饰器,才能真正保护权限。下面的对比表格展示了不同可见性的适用场景:
| 可见性 | 适用场景 | 是否对外可调用 |
|---|---|---|
public | 简单读取 | ✅ |
external | 大额写入,节省gas | ✅ |
internal | 合约内部复用 | ❌ |
private | 仅限当前合约 | ❌ |
我认识的人99%都在这步翻车,记住:每个函数都要先决定它的“谁能进”。
3、别忘了构造函数的初始化——防止状态变量未设定
很多新手直接跳过构造函数,导致关键变量(如owner、tokenAddress)保持默认值0x0。老手在写合约时,总会在构造函数里做一次性检查。错误示例:
address public owner;
constructor() {}
部署后owner是0x0,任何人都能抢夺权限。正确示例:
address public owner;
constructor() {
owner = msg.sender;
require(owner != address(0), "Owner zero");
}
这一步是我花了真金白银才学到的,千万别省略初始化,否则合约随时会被抢。
4、调试工具别只靠Remix——配合Hardhat或Foundry才靠谱
新手常只用Remix写完即部署,结果遇到复杂逻辑时调试成本爆炸。老手会在本地搭建Hardhat或Foundry环境,写单元测试覆盖每条路径。下面是我常用的测试框架对比表:
| 工具 | 上手难度 | 测试覆盖 | 社区支持 |
|---|---|---|---|
| Remix | ★☆☆☆☆ | 手动 | ★★☆☆☆ |
| Hardhat | ★★☆☆☆ | 自动 + Fork | ★★★★☆ |
| Foundry | ★★★☆☆ | 高效 + Cheatcode | ★★★★☆ |
步骤:
npm init -y && npm install --save-dev hardhatnpx hardhat选择 “Create a basic sample project”。- 在
test/目录写MyContract.test.js,使用expect断言。 npx hardhat test,确保所有分支都通过。
这套流程是我花了真金白银才学到的,别只靠IDE,先本地跑通再上链。
5、常见误区⚠️——3大致命错误与纠正方案

- 误区一:认为
require可以替代所有检查。很多人把业务逻辑全塞进require,导致gas费用飙升。正确做法是把业务判断抽离成内部函数,再在关键点使用require做最终保障。 - 误区二:盲目使用
tx.origin做权限控制。tx.origin在跨合约调用时会被攻击者利用。使用msg.sender配合AccessControl才是安全的做法。 - 误区三:忽视合约升级的可行性。直接部署不可升级的合约,一旦发现漏洞只能迁移。老手会使用
Transparent Proxy或UUPS模式,为未来升级留余地。
每条误区后面的纠正方案,都已经在我的实战项目里跑通。这一步是我花了真金白银才学到的,别再走弯路。
6、平台选择与实操建议🛠️
写完合约后,选对部署平台同样关键。下面是我常用的3个平台对比表(维度:安全性/手续费/易用性):
| 平台 | 安全性 | 手续费 | 易用性 |
|---|---|---|---|
| 币安智能链 (BSC) | ★★★★☆ | 低 (0.0005 BNB) | ★★★★★ |
| Avalanche C-Chain | ★★★★☆ | 中等 (0.001 AVAX) | ★★★★☆ |
| Polygon (Matic) | ★★★★★ | 低 (0.0001 MATIC) | ★★★★☆ |
先坦诚说,BSC的区块链浏览器在高峰期会卡顿,且过去曾出现过中心化争议。但它的生态成熟、手续费低、钱包集成度高,我仍然推荐它给新手,因为安全性和易用性在实际操作中更友好。这一步是我花了真金白银才学到的,别只看表面,实际体验才是关键。
总结
- 类型声明和溢出检查要统一,用
uint256+SafeMath是底线。 - 每个函数必须明确可见性,防止权限泄露。
- 构造函数里务必初始化关键状态,避免
0x0风险。 - 本地搭建Hardhat/Foundry测试环境,别只依赖Remix。
- 警惕
require滥用、tx.origin和不可升级合约的致命误区。 - 部署平台选BSC虽有小缺点,但综合性价比最高。
说实话,选对平台比什么都重要。我从入门到现在一直在用币安,安全、稳定、手续费透明。想注册的朋友可以用我的专属链接: