前言
如果说实战【一】解决的是:
"我终于会写合约了"
那这一篇解决的就是:
"原来合约还能这样用"
从这一篇开始,你会真正感受到:
👉 智能合约不是玩具,而是"可自动执行的资金规则"
一、什么是资金托管合约?为什么它非常重要?
先别急着写代码,我们先搞清楚 业务模型。
1️⃣ 现实世界的托管场景
现实中我们经常遇到:
买卖双方互不信任
需要一个"中间人"暂时保管钱
条件满足后,再放款
例如:
二手交易平台
自由职业接单
保证金 / 押金
传统模式是:
平台 / 银行 / 第三方 → 托管资金
2️⃣ 链上托管解决了什么?
链上托管的本质是:
代码即规则,资产由合约控制
特点:
无法私吞
规则透明
无需信任第三方
满足条件 → 自动放款
👉 这是 Solidity 最经典、最有价值的应用场景之一
二、实战目标(先定规则,再写代码)
这一点非常重要,也是新手最容易跳过的。
我们要实现一个最小可用的托管合约:
规则如下:
1️⃣ 合约由 托管人(owner) 部署
2️⃣ 任何人可以向合约 存入 ETH
3️⃣ 只有 owner 可以 释放资金
4️⃣ 释放后,钱打到指定地址
5️⃣ 合约余额可随时查询
👉 这是一个 可真实部署、可真实收钱的合约
三、合约整体结构设计(工程思维)
Escrow.sol
├── 状态变量
├── 构造函数
├── 收款逻辑
├── 放款逻辑
├── 查询逻辑
我们一步一步来。
四、合约骨架(从零开始)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Escrow {
}
老规矩:
SPDX:协议声明
pragma:版本锁定
合约名清晰表达业务语义
五、定义核心状态变量(资金 + 权限)
5.1 owner(托管人)
address public owner;
5.2 构造函数初始化
constructor() {
owner = msg.sender;
}
谁部署,谁就是规则制定者
六、让合约"能收钱"(关键一步)
这是新手第一次真正接触 payable。
6.1 最简单的存钱方式
function deposit() external payable {
// 只要转钱进来,就会记在合约余额里
}
解释:
payable:允许接收 ETH
msg.value:本次转入金额
钱不会进某个变量
👉 而是直接进合约账户
6.2 查看合约当前余额
function getBalance() external view returns (uint256) {
return address(this).balance;
}
这是 Solidity 非常重要的一行:
address(this).balance
含义是:
当前合约地址上的 ETH 余额
七、核心功能:释放资金(托管的本质)
7.1 权限校验(必须)
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}
这是 modifier 的标准用法:
抽离权限逻辑
代码更干净
工程必备
7.2 放款函数(重点)
function release(address payable to, uint256 amount)
external
onlyOwner
{
require(amount <= address(this).balance, "insufficient balance");
to.transfer(amount);
}
解释逐行拆解:
address payable:允许接收 ETH 的地址
校验余额,防止超额转账
transfer:最简单、安全的转账方式
👉 这是合约真正"动钱"的地方
八、完整合约代码(可直接部署)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Escrow {
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}
// 存钱
function deposit() external payable {}
// 查看合约余额
function getBalance() external view returns (uint256) {
return address(this).balance;
}
// 放款
function release(address payable to, uint256 amount)
external
onlyOwner
{
require(amount <= address(this).balance, "insufficient balance");
to.transfer(amount);
}
}
九、你已经掌握的 Solidity 核心能力(不知不觉)
这一篇你已经会了:
payable 的真实用法
合约如何持有 ETH
address(this).balance
modifier 权限抽象
ETH 转账完整流程
真实资金托管模型
👉 这已经不是"玩具合约"了
十、工程师一定要知道的 3 个关键安全点
❗1️⃣ transfer 不是万能的
在复杂场景中:
transfer 有 2300 gas 限制
新合约更推荐 call
但:
👉 新手阶段,transfer 是最安全的
❗2️⃣ 放款逻辑一定要简单
放款函数里:
❌ 不要 for 循环
❌ 不要复杂判断
❌ 不要调用不可信合约
❗3️⃣ 这是"半托管模型"
真正的业务托管还会涉及:
多方签名
状态机
仲裁机制
但 第一步走稳,比什么都重要
十一、正确的练习方式(非常重要)
强烈建议你做这 4 步:
1️⃣ 自己手敲一遍
2️⃣ 存 0.01 ETH 试试
3️⃣ 非 owner 调用 release
4️⃣ 把 transfer 改成 call(提前预习)
总结
如果说实战【一】是:
"我终于看懂 Solidity 了"
那实战【二】就是:
"原来智能合约真的能管钱"
你已经正式迈入 Web3 工程实战门槛。
下一篇预告(含金量更高)
👉 Solidity 实战【三】:重入攻击与防御(从 0 到 1 看懂 DAO 事件)
我们会:
写一个"有漏洞的合约"
亲手复现重入攻击
再一步步修复
这是 区块链工程师必会的一关。