2
月
在社区成长 2 月
LEVEL 1
1 XP
一、背景:Web3 新手真正需要理解什么
很多新手第一次接触 Web3,会把“连接钱包”“领取测试币”“发送交易”理解成类似网站登录和银行转账。这个类比并不准确:钱包通常不保存链上资产,而是管理私钥并对交易或消息签名;资产、授权和合约状态记录在区块链上;RPC 节点负责接收查询和广播交易,但不应接触用户私钥。
一次完整的链上交互至少涉及五个对象:钱包、私钥或助记词、RPC 节点、区块链网络、智能合约。安全边界必须明确:私钥只用于本地签名,RPC 只能看到已签名交易和公开地址;网页可以请求签名,但不应获得助记词;区块浏览器用于查看公开状态,却不能证明某个项目一定可信。
本文先使用本地 Anvil 链完成可重复实验,再说明如何迁移到公开测试网。所有测试仅限本地环境、官方测试网和自己部署的合约,不针对任何真实第三方目标。
二、核心原理
1. 地址与私钥
以太坊兼容链上的普通账户通常称为 EOA。地址可由公钥推导,私钥则用于生成签名。知道地址只能观察和收款,知道私钥却可以控制该账户,因此助记词、私钥和钱包备份文件都属于最高敏感信息。
2. 交易与消息签名
链上交易通常包含目标地址、发送金额、调用数据、nonce、gas 参数和 chainId。签名后的交易被广播并执行,可能改变链上状态,也需要支付 gas。
消息签名一般不直接上链,也不天然消耗 gas,但绝不等于“没有风险”。某些签名可被合约或协议用于授权、挂单、登录或资产操作。签名前应核对域名、消息内容、适用链、验证合约、截止时间和 nonce。无法解释的十六进制签名请求应拒绝。
3. RPC 的信任边界
RPC 可以返回余额、区块和交易执行结果,也可接收已签名交易。恶意或异常 RPC 可能隐藏交易、返回错误数据、追踪请求来源或诱导用户连接错误网络,但正常情况下不能仅凭 RPC 请求直接窃取私钥。重要数据应通过第二个独立 RPC 或区块浏览器交叉验证。
4. 授权与转账的区别
ERC-20 的 transfer 是直接转账;approve 是允许 spender 在额度内通过 transferFrom 转走代币。授权成功不代表资产已经转出,但高额度或无限额度授权会形成持续风险。应同时核对代币合约、spender、额度和链 ID。
三、前置条件
建议准备一台个人测试设备,并安装:
1. Git;
2. Foundry 工具链;
3. 一个浏览器钱包;
4. 独立创建的测试钱包,不存放任何真实资产;
5. 可选的 Sepolia 测试网 RPC。
安装 Foundry 可参考其官方仓库提供的安装方式。安装后先执行版本检查:
forge --version
cast --version
anvil --version
不要把网上示例私钥用于主网。Anvil 启动时展示的测试私钥是公开且可预测的,只能用于本地链。
四、分步骤实践:在本地链完成部署与调用
步骤 1:创建项目
执行:
forge init web3-beginner-lab
cd web3-beginner-lab
项目中通常包含 src、script 和 test 目录。下面创建 src/Counter.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Counter {
uint256 public number;
address public immutable owner;
event NumberChanged(uint256 oldValue, uint256 newValue, address caller);
constructor(uint256 initialNumber) {
owner = msg.sender;
number = initialNumber;
}
function setNumber(uint256 newNumber) external {
uint256 oldNumber = number;
number = newNumber;
emit NumberChanged(oldNumber, newNumber, msg.sender);
}
}
这个合约用于演示状态读取、状态修改和事件。owner 仅用于观察部署者,本例的 setNumber 没有访问控制,因此任何地址均可修改 number。这是刻意设计的教学边界,不应直接作为生产业务合约使用。
步骤 2:编译并运行测试
执行:
forge build
forge test -vv
编译成功只能说明语法和类型等检查通过,不能证明合约安全。生产合约还需要测试权限边界、异常路径、整数边界、外部调用、升级机制和经济模型。
步骤 3:启动本地节点
打开一个新终端执行:
anvil
默认 RPC 通常为 http://127.0.0.1:8545,默认 chainId 通常为 31337。以终端实际输出为准。不要把 Anvil RPC 无鉴权暴露到公网,也不要向 Anvil 账户转入真实网络资产。
验证网络:
cast chain-id --rpc-url http://127.0.0.1:8545
cast block-number --rpc-url http://127.0.0.1:8545
步骤 4:部署合约
从 Anvil 输出中选取一个本地测试私钥,并仅在当前本地实验中使用:
forge create src/Counter.sol:Counter --constructor-args 10 --rpc-url http://127.0.0.1:8545 --private-key <ANVIL_LOCAL_PRIVATE_KEY>
命令返回 deployedTo 后,记录为 <CONTRACT_ADDRESS>。私钥直接出现在命令行可能进入 shell 历史,所以即使是测试环境,也应理解这不是生产环境的推荐做法。真实项目应使用硬件钱包、加密密钥库或受控签名系统。
步骤 5:读取链上状态
执行:
cast call <CONTRACT_ADDRESS> "number()(uint256)" --rpc-url http://127.0.0.1:8545
读取操作通常通过 eth_call 模拟执行,不生成链上交易,也不消耗实际 gas。若返回 10,说明构造参数已经写入状态。
继续读取部署者:
cast call <CONTRACT_ADDRESS> "owner()(address)" --rpc-url http://127.0.0.1:8545
应将结果与部署交易的发送方地址对比,不要只依赖肉眼判断合约是否部署成功。
步骤 6:发送状态修改交易
执行:
cast send <CONTRACT_ADDRESS> "setNumber(uint256)" 42 --rpc-url http://127.0.0.1:8545 --private-key <ANVIL_LOCAL_PRIVATE_KEY>
随后再次读取:
cast call <CONTRACT_ADDRESS> "number()(uint256)" --rpc-url http://127.0.0.1:8545
如果返回 42,说明交易已经被打包并改变状态。还应检查交易回执中的 status、blockNumber、from、to 和 gasUsed。仅看到钱包弹出“已发送”并不能证明交易成功,交易也可能因 revert 而失败。
步骤 7:在浏览器钱包中添加本地网络
可按钱包界面添加:
网络名称:Anvil Local
RPC URL:http://127.0.0.1:8545
Chain ID:31337
货币符号:ETH
导入 Anvil 测试账户后,可以观察本地测试余额。注意,钱包中看到相同的“ETH”符号不代表它是主网 ETH;资产价值取决于具体网络和合约地址,而不是图标或名称。
五、迁移到 Sepolia 测试网
在公开测试网上操作前,应新建专用测试钱包,通过可信渠道配置 Sepolia RPC,并从公开测试币渠道获取少量测试币。测试币通常没有真实价值,不应购买来源不明的测试币,也不要在领取页面输入助记词。
先验证 chainId:
cast chain-id --rpc-url <SEPOLIA_RPC_URL>
Sepolia 的 chainId 应为 11155111。如果返回值不符,应停止操作并检查 RPC 配置。部署前可以先查看余额:
cast balance <TEST_ADDRESS> --rpc-url <SEPOLIA_RPC_URL>
更安全的签名方式是使用 Foundry 的加密 keystore,而不是把私钥直接写入命令、脚本或 .env。可通过 cast wallet 的帮助信息确认当前版本支持的具体子命令:
cast wallet --help
无论采用何种方式,都不要把私钥提交到 Git。应检查:
git status
git diff --cached
.env、keystore 和部署配置中的敏感内容应加入 .gitignore。部署后使用区块浏览器核对交易哈希、发送者、合约地址、链和构造参数。验证源码有助于公开字节码对应关系,但“源码已验证”不等于“代码已审计”或“业务可信”。
六、钱包签名前的可操作检查清单
1. 核对当前网络和 chainId,避免在主网误签测试操作;
2. 核对网页域名,书签访问比搜索广告跳转更可靠;
3. 区分连接钱包、消息签名、交易签名和代币授权;
4. 检查交易的 to、value 和函数含义;
5. 对 approve 检查 spender 与 allowance,不默认使用无限授权;
6. 看到 Permit、Permit2 或 typed data 时,检查 token、spender、amount、deadline、nonce、chainId 和 verifyingContract;
7. 无法解码的 calldata 不应仅凭网站按钮文字确认;
8. 高价值地址使用硬件钱包,并进行小额试验;
9. 操作后检查交易回执、余额变化和授权状态;
10. 定期撤销不再使用的授权,但撤销本身也需要链上交易和 gas。
七、风险与注意事项
第一,测试钱包与资产钱包必须隔离。测试过未知 DApp 的地址不应继续作为长期资产地址。
第二,不要截屏或云同步助记词。助记词泄露后,修改钱包密码无法恢复安全,因为密码通常只保护本地钱包文件,无法改变链上账户控制权。
第三,合约地址必须从多个可信来源核对。名称、符号和头像都可以仿冒,同名代币可能对应完全不同的合约。
第四,交易模拟不是绝对保证。链上状态可能在签名和打包之间变化,模拟工具也可能存在覆盖不足。对高价值操作应设置可接受的滑点、截止时间和最小接收量。
第五,Gas Limit 与 Gas Price 的作用不同。Gas Limit 是允许消耗的执行上限,费用参数影响交易被打包的优先级。盲目提高 Gas Limit 不会修复合约逻辑导致的 revert。
第六,本例合约的 setNumber 对所有地址开放。如果业务要求仅管理员可修改,就必须加入明确的访问控制并测试未授权调用会失败。不能因为前端隐藏按钮,就认为合约具备权限控制;攻击者可以绕过前端直接调用公开函数。
八、常见问题
问题 1:连接钱包后,网站是否已经能转走资产?
通常仅连接钱包只会暴露公开地址,不等于获得转账权限。但后续签署恶意交易、代币授权或具有资产操作语义的消息,可能产生损失,因此每次签名仍要单独核对。
问题 2:交易显示 pending 很久怎么办?
先确认网络是否拥堵、nonce 是否连续、费用参数是否过低,以及 RPC 是否正常。不要重复向不同地址发送“补救交易”。钱包提供的加速或取消功能本质上通常是使用相同 nonce 提交替代交易,也不能保证一定成功。
问题 3:交易失败后还会扣费吗?
已被打包但执行 revert 的交易通常仍消耗已经执行部分的 gas,因为节点确实完成了计算和验证。未广播或未被打包的签名请求则不一定产生链上费用。
问题 4:为什么钱包有余额,但 DApp 显示为零?
优先检查是否连接到同一条链、读取的是否为正确代币合约、RPC 是否同步,以及代币 decimals 是否被正确处理。地址相同不代表不同网络上的资产互通。
问题 5:测试网安全就可以随便签名吗?
不可以。如果测试钱包和主钱包复用了助记词,或签名内容实际指向其他链和合约,仍可能影响真实资产。测试网的低价值不能替代密钥隔离。
九、总结
Web3 入门的重点不是记住某个钱包按钮,而是建立可验证的交互流程:先确认网络与 chainId,再确认账户和合约地址;读操作使用独立来源交叉验证;写操作先模拟和小额测试;签名前理解目标、金额、授权和 calldata;签名后检查交易回执与状态变化。
建议新手先在 Anvil 本地链反复完成“部署、读取、发送交易、查看回执”四个动作,再迁移到 Sepolia。任何无法解释其权限边界、签名语义或资产影响的操作,都应暂停。链上记录公开且交易通常不可逆,审慎验证比事后补救更重要。
很多新手第一次接触 Web3,会把“连接钱包”“领取测试币”“发送交易”理解成类似网站登录和银行转账。这个类比并不准确:钱包通常不保存链上资产,而是管理私钥并对交易或消息签名;资产、授权和合约状态记录在区块链上;RPC 节点负责接收查询和广播交易,但不应接触用户私钥。
一次完整的链上交互至少涉及五个对象:钱包、私钥或助记词、RPC 节点、区块链网络、智能合约。安全边界必须明确:私钥只用于本地签名,RPC 只能看到已签名交易和公开地址;网页可以请求签名,但不应获得助记词;区块浏览器用于查看公开状态,却不能证明某个项目一定可信。
本文先使用本地 Anvil 链完成可重复实验,再说明如何迁移到公开测试网。所有测试仅限本地环境、官方测试网和自己部署的合约,不针对任何真实第三方目标。
二、核心原理
1. 地址与私钥
以太坊兼容链上的普通账户通常称为 EOA。地址可由公钥推导,私钥则用于生成签名。知道地址只能观察和收款,知道私钥却可以控制该账户,因此助记词、私钥和钱包备份文件都属于最高敏感信息。
2. 交易与消息签名
链上交易通常包含目标地址、发送金额、调用数据、nonce、gas 参数和 chainId。签名后的交易被广播并执行,可能改变链上状态,也需要支付 gas。
消息签名一般不直接上链,也不天然消耗 gas,但绝不等于“没有风险”。某些签名可被合约或协议用于授权、挂单、登录或资产操作。签名前应核对域名、消息内容、适用链、验证合约、截止时间和 nonce。无法解释的十六进制签名请求应拒绝。
3. RPC 的信任边界
RPC 可以返回余额、区块和交易执行结果,也可接收已签名交易。恶意或异常 RPC 可能隐藏交易、返回错误数据、追踪请求来源或诱导用户连接错误网络,但正常情况下不能仅凭 RPC 请求直接窃取私钥。重要数据应通过第二个独立 RPC 或区块浏览器交叉验证。
4. 授权与转账的区别
ERC-20 的 transfer 是直接转账;approve 是允许 spender 在额度内通过 transferFrom 转走代币。授权成功不代表资产已经转出,但高额度或无限额度授权会形成持续风险。应同时核对代币合约、spender、额度和链 ID。
三、前置条件
建议准备一台个人测试设备,并安装:
1. Git;
2. Foundry 工具链;
3. 一个浏览器钱包;
4. 独立创建的测试钱包,不存放任何真实资产;
5. 可选的 Sepolia 测试网 RPC。
安装 Foundry 可参考其官方仓库提供的安装方式。安装后先执行版本检查:
forge --version
cast --version
anvil --version
不要把网上示例私钥用于主网。Anvil 启动时展示的测试私钥是公开且可预测的,只能用于本地链。
四、分步骤实践:在本地链完成部署与调用
步骤 1:创建项目
执行:
forge init web3-beginner-lab
cd web3-beginner-lab
项目中通常包含 src、script 和 test 目录。下面创建 src/Counter.sol:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Counter {
uint256 public number;
address public immutable owner;
event NumberChanged(uint256 oldValue, uint256 newValue, address caller);
constructor(uint256 initialNumber) {
owner = msg.sender;
number = initialNumber;
}
function setNumber(uint256 newNumber) external {
uint256 oldNumber = number;
number = newNumber;
emit NumberChanged(oldNumber, newNumber, msg.sender);
}
}
这个合约用于演示状态读取、状态修改和事件。owner 仅用于观察部署者,本例的 setNumber 没有访问控制,因此任何地址均可修改 number。这是刻意设计的教学边界,不应直接作为生产业务合约使用。
步骤 2:编译并运行测试
执行:
forge build
forge test -vv
编译成功只能说明语法和类型等检查通过,不能证明合约安全。生产合约还需要测试权限边界、异常路径、整数边界、外部调用、升级机制和经济模型。
步骤 3:启动本地节点
打开一个新终端执行:
anvil
默认 RPC 通常为 http://127.0.0.1:8545,默认 chainId 通常为 31337。以终端实际输出为准。不要把 Anvil RPC 无鉴权暴露到公网,也不要向 Anvil 账户转入真实网络资产。
验证网络:
cast chain-id --rpc-url http://127.0.0.1:8545
cast block-number --rpc-url http://127.0.0.1:8545
步骤 4:部署合约
从 Anvil 输出中选取一个本地测试私钥,并仅在当前本地实验中使用:
forge create src/Counter.sol:Counter --constructor-args 10 --rpc-url http://127.0.0.1:8545 --private-key <ANVIL_LOCAL_PRIVATE_KEY>
命令返回 deployedTo 后,记录为 <CONTRACT_ADDRESS>。私钥直接出现在命令行可能进入 shell 历史,所以即使是测试环境,也应理解这不是生产环境的推荐做法。真实项目应使用硬件钱包、加密密钥库或受控签名系统。
步骤 5:读取链上状态
执行:
cast call <CONTRACT_ADDRESS> "number()(uint256)" --rpc-url http://127.0.0.1:8545
读取操作通常通过 eth_call 模拟执行,不生成链上交易,也不消耗实际 gas。若返回 10,说明构造参数已经写入状态。
继续读取部署者:
cast call <CONTRACT_ADDRESS> "owner()(address)" --rpc-url http://127.0.0.1:8545
应将结果与部署交易的发送方地址对比,不要只依赖肉眼判断合约是否部署成功。
步骤 6:发送状态修改交易
执行:
cast send <CONTRACT_ADDRESS> "setNumber(uint256)" 42 --rpc-url http://127.0.0.1:8545 --private-key <ANVIL_LOCAL_PRIVATE_KEY>
随后再次读取:
cast call <CONTRACT_ADDRESS> "number()(uint256)" --rpc-url http://127.0.0.1:8545
如果返回 42,说明交易已经被打包并改变状态。还应检查交易回执中的 status、blockNumber、from、to 和 gasUsed。仅看到钱包弹出“已发送”并不能证明交易成功,交易也可能因 revert 而失败。
步骤 7:在浏览器钱包中添加本地网络
可按钱包界面添加:
网络名称:Anvil Local
RPC URL:http://127.0.0.1:8545
Chain ID:31337
货币符号:ETH
导入 Anvil 测试账户后,可以观察本地测试余额。注意,钱包中看到相同的“ETH”符号不代表它是主网 ETH;资产价值取决于具体网络和合约地址,而不是图标或名称。
五、迁移到 Sepolia 测试网
在公开测试网上操作前,应新建专用测试钱包,通过可信渠道配置 Sepolia RPC,并从公开测试币渠道获取少量测试币。测试币通常没有真实价值,不应购买来源不明的测试币,也不要在领取页面输入助记词。
先验证 chainId:
cast chain-id --rpc-url <SEPOLIA_RPC_URL>
Sepolia 的 chainId 应为 11155111。如果返回值不符,应停止操作并检查 RPC 配置。部署前可以先查看余额:
cast balance <TEST_ADDRESS> --rpc-url <SEPOLIA_RPC_URL>
更安全的签名方式是使用 Foundry 的加密 keystore,而不是把私钥直接写入命令、脚本或 .env。可通过 cast wallet 的帮助信息确认当前版本支持的具体子命令:
cast wallet --help
无论采用何种方式,都不要把私钥提交到 Git。应检查:
git status
git diff --cached
.env、keystore 和部署配置中的敏感内容应加入 .gitignore。部署后使用区块浏览器核对交易哈希、发送者、合约地址、链和构造参数。验证源码有助于公开字节码对应关系,但“源码已验证”不等于“代码已审计”或“业务可信”。
六、钱包签名前的可操作检查清单
1. 核对当前网络和 chainId,避免在主网误签测试操作;
2. 核对网页域名,书签访问比搜索广告跳转更可靠;
3. 区分连接钱包、消息签名、交易签名和代币授权;
4. 检查交易的 to、value 和函数含义;
5. 对 approve 检查 spender 与 allowance,不默认使用无限授权;
6. 看到 Permit、Permit2 或 typed data 时,检查 token、spender、amount、deadline、nonce、chainId 和 verifyingContract;
7. 无法解码的 calldata 不应仅凭网站按钮文字确认;
8. 高价值地址使用硬件钱包,并进行小额试验;
9. 操作后检查交易回执、余额变化和授权状态;
10. 定期撤销不再使用的授权,但撤销本身也需要链上交易和 gas。
七、风险与注意事项
第一,测试钱包与资产钱包必须隔离。测试过未知 DApp 的地址不应继续作为长期资产地址。
第二,不要截屏或云同步助记词。助记词泄露后,修改钱包密码无法恢复安全,因为密码通常只保护本地钱包文件,无法改变链上账户控制权。
第三,合约地址必须从多个可信来源核对。名称、符号和头像都可以仿冒,同名代币可能对应完全不同的合约。
第四,交易模拟不是绝对保证。链上状态可能在签名和打包之间变化,模拟工具也可能存在覆盖不足。对高价值操作应设置可接受的滑点、截止时间和最小接收量。
第五,Gas Limit 与 Gas Price 的作用不同。Gas Limit 是允许消耗的执行上限,费用参数影响交易被打包的优先级。盲目提高 Gas Limit 不会修复合约逻辑导致的 revert。
第六,本例合约的 setNumber 对所有地址开放。如果业务要求仅管理员可修改,就必须加入明确的访问控制并测试未授权调用会失败。不能因为前端隐藏按钮,就认为合约具备权限控制;攻击者可以绕过前端直接调用公开函数。
八、常见问题
问题 1:连接钱包后,网站是否已经能转走资产?
通常仅连接钱包只会暴露公开地址,不等于获得转账权限。但后续签署恶意交易、代币授权或具有资产操作语义的消息,可能产生损失,因此每次签名仍要单独核对。
问题 2:交易显示 pending 很久怎么办?
先确认网络是否拥堵、nonce 是否连续、费用参数是否过低,以及 RPC 是否正常。不要重复向不同地址发送“补救交易”。钱包提供的加速或取消功能本质上通常是使用相同 nonce 提交替代交易,也不能保证一定成功。
问题 3:交易失败后还会扣费吗?
已被打包但执行 revert 的交易通常仍消耗已经执行部分的 gas,因为节点确实完成了计算和验证。未广播或未被打包的签名请求则不一定产生链上费用。
问题 4:为什么钱包有余额,但 DApp 显示为零?
优先检查是否连接到同一条链、读取的是否为正确代币合约、RPC 是否同步,以及代币 decimals 是否被正确处理。地址相同不代表不同网络上的资产互通。
问题 5:测试网安全就可以随便签名吗?
不可以。如果测试钱包和主钱包复用了助记词,或签名内容实际指向其他链和合约,仍可能影响真实资产。测试网的低价值不能替代密钥隔离。
九、总结
Web3 入门的重点不是记住某个钱包按钮,而是建立可验证的交互流程:先确认网络与 chainId,再确认账户和合约地址;读操作使用独立来源交叉验证;写操作先模拟和小额测试;签名前理解目标、金额、授权和 calldata;签名后检查交易回执与状态变化。
建议新手先在 Anvil 本地链反复完成“部署、读取、发送交易、查看回执”四个动作,再迁移到 Sepolia。任何无法解释其权限边界、签名语义或资产影响的操作,都应暂停。链上记录公开且交易通常不可逆,审慎验证比事后补救更重要。