Solidity 实战【二】:手写一个「链上资金托管合约」

前言

如果说实战【一】解决的是:

"我终于会写合约了"

那这一篇解决的就是:

"原来合约还能这样用"

从这一篇开始,你会真正感受到:

👉 智能合约不是玩具,而是"可自动执行的资金规则"

一、什么是资金托管合约?为什么它非常重要?

先别急着写代码,我们先搞清楚 业务模型。

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 事件)

我们会:

写一个"有漏洞的合约"

亲手复现重入攻击

再一步步修复

这是 区块链工程师必会的一关。

相关推荐
China_Yanhy10 小时前
[特殊字符] 筑牢金融底座:企业级区块链全球化数据库架构设计白皮书
金融·区块链·数据库架构
BlockChain88810 小时前
Solidity 实战【三】:重入攻击与防御(从 0 到 1 看懂 DAO 事件)
go·区块链
企业对冲系统官14 小时前
期货套保系统移动端操作的技术架构与实现
算法·架构·区块链·github
剩下了什么15 小时前
Gf命令行工具下载
go
地球没有花16 小时前
tw引发的对redis的深入了解
数据库·redis·缓存·go
TechubNews16 小时前
BEATOZ区块链专业企业与韩国头部旅游集团MODETOUR从签署MOU迈向网络验证节点合作
大数据·人工智能·区块链
BlockChain8881 天前
字符串最后一个单词的长度
算法·go
龙井茶Sky1 天前
通过higress AI统计插件学gjson表达式的分享
go·gjson·higress插件
数说星榆1811 天前
模型即服务(MaaS)生态的去中心化探索
去中心化·区块链