1
月
在社区成长 1 月
LEVEL 1
1 XP
一、背景:钱包为什么是进入 WEB3 的第一道门
很多新手把钱包理解成“存放代币的软件”,这个说法并不准确。链上资产实际记录在区块链账本中,钱包主要负责管理密钥、派生地址、构造交易和生成数字签名。只要掌握对应私钥,就可以控制该地址下的资产;如果私钥或助记词丢失,通常也不存在传统互联网产品中的“找回密码”。
因此,WEB3 入门不能只学会点击“连接钱包”,还需要理解钱包、RPC 节点、智能合约和区块浏览器各自承担什么角色。本文使用本地开发链和 Ethereum Sepolia 测试网完成一次完整实践,不接触真实资金,也不针对任何未授权目标进行测试。
二、核心原理
1. 地址与私钥
私钥是一段随机数,钱包根据私钥计算公钥,再由公钥派生出地址。地址可以公开,用于收款和查询;私钥、助记词及 Keystore 密码不能公开。
钱包中的“余额”并不是保存在手机或浏览器里,而是钱包通过 RPC 节点查询链上状态后展示出来。卸载钱包不会让链上资产消失,但如果没有备份助记词或私钥,就可能永久失去控制权。
2. RPC 节点
RPC 可以理解为应用访问区块链的接口。常见方法包括:
- eth_chainId:查询当前网络的链 ID;
- eth_getBalance:查询原生代币余额;
- eth_call:只读调用合约,不产生链上交易;
- eth_estimateGas:估算交易所需 Gas;
- eth_sendRawTransaction:广播已经签名的交易;
- eth_getTransactionReceipt:查询交易是否被打包及执行结果。
钱包可以在本地完成签名,但交易仍需通过 RPC 广播。RPC 服务方不能直接修改一笔已经签名交易中的收款地址和金额,但不可信 RPC 可能返回误导性查询结果、记录访问行为、拒绝广播交易,或给出异常的 Gas 建议。因此,主网操作应使用可信节点,并通过区块浏览器或第二个独立 RPC 交叉验证重要结果。
3. 交易、Gas 与确认
一笔普通 EVM 交易通常包含发送方、接收方、金额、nonce、Gas 限制、费用参数、链 ID和可选的 data。nonce 是发送方地址的交易序号,可以防止同一笔签名交易被无限重复执行。链 ID用于阻止交易被简单复制到另一条不相关的链上。
交易广播成功只代表节点接受了它,并不等于已经执行。需要等待交易进入区块并检查 receipt 中的 status。status 为 1 通常表示执行成功,为 0 表示执行失败;即使失败,已消耗的 Gas 一般也不会退回。
三、前置条件
建议准备以下环境:
- Node.js 18 或更高版本;
- npm;
- 一个支持 EVM 网络的钱包;
- 可选:Foundry 的 Anvil,用于本地链实验;
- Sepolia 测试网 RPC 地址;
- 少量 Sepolia 测试 ETH。
测试币没有主网资产价值,不要向声称可以“购买高价值测试币”的陌生人付款。水龙头入口和领取规则可能变化,应从钱包、客户端或生态项目的官方文档进入,不要直接相信搜索广告和私信链接。
四、第一步:先在本地链认识账户和交易
如果已经安装 Foundry,可以在终端运行:
anvil
Anvil 会启动一个本地 EVM 网络,默认 RPC 通常为:
终端还会显示若干预置测试账户和私钥。这些私钥是公开的,只能用于本地实验。绝对不要向这些地址转入主网资产,也不要把这些私钥导入长期使用的钱包。
新开一个终端,通过 JSON-RPC 查询链 ID:
curl -s -X POST http://127.0.0.1:8545 -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
返回结果通常是十六进制链 ID。继续查询某个 Anvil 测试地址的余额:
curl -s -X POST http://127.0.0.1:8545 -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["替换为Anvil显示的测试地址","latest"],"id":2}'
余额返回值同样是十六进制,并以 wei 为单位。1 ETH 等于 10 的 18 次方 wei。直接看十六进制不直观,后续可以用 ethers.js 自动格式化。
五、第二步:使用 ethers.js 连接 RPC
创建实验目录并安装依赖:
mkdir web3-first-tx
cd web3-first-tx
npm init -y
npm install ethers dotenv
在 package.json 中加入:
"type": "module"
创建 .env 文件:
RPC_URL=http://127.0.0.1:8545
PRIVATE_KEY=替换为Anvil提供的某个测试私钥
.env 必须加入 .gitignore:
.env
node_modules/
创建 index.js:
import "dotenv/config";
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const network = await provider.getNetwork();
const balance = await provider.getBalance(wallet.address);
const nonce = await provider.getTransactionCount(wallet.address, "pending");
console.log("chainId:", network.chainId.toString());
console.log("address:", wallet.address);
console.log("balance:", ethers.formatEther(balance), "ETH");
console.log("pending nonce:", nonce);
运行:
node index.js
这一步是只读查询,不会产生 Gas。务必检查 chainId,避免以为自己在测试网,实际却连接到了其他网络。
六、第三步:在本地发送第一笔交易
在 index.js 后面加入以下代码。为了避免填错其他地址,示例向自己的地址发送 0 ETH,仅用于观察完整交易生命周期:
const feeData = await provider.getFeeData();
console.log("gasPrice:", feeData.gasPrice?.toString() ?? "EIP-1559 network");
const tx = await wallet.sendTransaction({
to: wallet.address,
value: 0n
});
console.log("transaction hash:", tx.hash);
const receipt = await tx.wait();
console.log("blockNumber:", receipt.blockNumber);
console.log("status:", receipt.status);
console.log("gasUsed:", receipt.gasUsed.toString());
再次运行:
node index.js
虽然转账金额是 0,但交易仍然需要签名、广播、排序和执行,因此依旧会消耗本地测试 Gas。可以记录交易前后余额,验证余额减少部分主要来自手续费。
七、第四步:切换到 Sepolia 测试网
完成本地实验后,再进入公共测试网。Sepolia 的 chainId 是 11155111。先从可信来源获取 Sepolia RPC,并把 .env 中的 RPC_URL 替换为该地址。
私钥方面,建议新建一个“仅用于测试网”的独立钱包账户。不要使用持有主网资产的钱包,更不要把主钱包助记词复制到脚本、云服务器或在线调试工具中。
在钱包中添加或切换 Sepolia 网络后,从官方文档指向的水龙头领取少量测试 ETH。到账后先运行只读脚本,确认:
- 输出的 chainId 为 11155111;
- 脚本地址与钱包中的测试地址一致;
- 余额已经大于 0;
- RPC 没有报网络不匹配或限流错误。
确认无误后再运行发送交易的代码。获得交易哈希后,可在支持 Sepolia 的区块浏览器中查询。重点查看:
- From 和 To 是否符合预期;
- Value 是否为预期数值;
- Status 是否成功;
- Gas Used 与实际手续费;
- Input Data 是否为空;
- 区块确认数量是否增加。
不要把“钱包弹出了签名窗口”当成安全证明。真正应该核对的是当前网络、目标地址、金额、调用方法、代币授权额度和交易 data。
八、从移动应用安全角度理解连接钱包
移动端 DApp 常通过内置浏览器、Deep Link、Universal Link、App Link 或 WalletConnect 与钱包交互。这里有几个典型攻击面:
1. Deep Link 被错误应用接管
如果应用只使用自定义 Scheme,而没有可靠校验来源和回调参数,其他应用可能尝试伪造跳转。防御上应优先使用经过域名验证的 Universal Link 或 App Link,并校验会话标识、来源域名和一次性 nonce。
2. 剪贴板地址被替换
部分恶意软件会监控剪贴板并替换收款地址。粘贴后必须人工核对地址开头和结尾,较大金额还应先做小额测试。地址簿也应展示明确标签,而不是只显示缩略地址。
3. WalletConnect 会话权限过大
连接成功不代表可以永久信任。应检查会话允许的链、账户和方法,用完后及时断开。钱包端应清楚展示请求来自哪个域名、要在哪条链执行什么方法。
4. 盲签名
如果钱包只能显示十六进制 data,而不能解析实际动作,新手不应继续签名。特别要警惕无限额度 approve、Permit 类签名、NFT 批量授权和可转移资产的代理权限。普通消息签名也可能被用于登录或授权,并非“一定不花 Gas 就一定安全”。
九、风险与注意事项
1. 助记词永不输入网页
正常 DApp 连接钱包时不需要用户在网页中输入助记词。任何以“同步钱包、解锁空投、修复节点”为理由索取助记词的页面,都应立即关闭。
2. 测试私钥与正式私钥彻底隔离
Anvil 等本地工具展示的默认私钥是公开测试数据。测试网私钥也不应与主网高价值账户共用。很多资产损失并不是密码学被攻破,而是开发者把 .env、日志、截图或代码仓库公开了。
3. 不要只看代币名称
任何人都可能部署名称和符号相同的代币。识别资产时应核对网络和合约地址,不要仅凭图标、名称或钱包自动展示结果判断真伪。
4. 授权不等于转账
approve 通常不会立即转走代币,但会给指定合约未来调用 transferFrom 的权限。无限授权虽然方便,却扩大了风险范围。对不熟悉的 DApp 应设置合理额度,并定期检查和撤销不再使用的授权。
5. 验证交易模拟结果
部分钱包会显示余额变化或风险提示,但模拟依赖节点状态和解析能力,不能替代人工核对。对于复杂合约交互,应在测试网、本地分叉环境或经过授权的实验环境先验证,不要直接用真实资产试错。
6. 不把区块浏览器状态和业务到账混为一谈
链上交易成功,只能证明交易按合约逻辑执行成功。跨链桥、交易平台充值或其他业务系统可能还需要更多确认和后台处理。反过来,交易 status 为 0 时,即使已经扣除 Gas,也不表示资产转移成功。
十、常见问题
问题一:为什么测试 ETH 到账了,钱包仍显示 0?
先检查钱包网络是否为 Sepolia,再核对地址是否一致。也可能是 RPC 缓存、请求限流或界面未刷新。可以用第二个可信 RPC 或区块浏览器交叉查询。
问题二:交易一直处于 pending 怎么办?
常见原因包括费用过低、RPC 未成功广播、网络拥堵,或者同一地址存在更早的低费用交易。不要连续盲目重发。先按地址和 nonce 查询待处理交易,再使用钱包提供的加速或取消功能。取消本质上通常是用相同 nonce 发送一笔费用更高的新交易。
问题三:为什么余额足够,交易仍提示 insufficient funds?
发送方不仅要支付 value,还要预留 Gas 费用。发送全部余额时尤其容易遇到这个问题。代币转账虽然 value 常为 0,但仍需原生代币支付 Gas。
问题四:eth_call 是否绝对安全?
eth_call 不会直接写入链上,也不消耗真实 Gas,但不可信 RPC 可以返回错误结果,调用内容也可能泄露查询意图。涉及重要决策时,应使用可信节点或多个节点复核。
问题五:可以把私钥直接写进 index.js 吗?
实验中也不推荐。至少应使用 .env 并避免提交版本库。生产环境还应使用系统密钥库、硬件钱包、签名服务或专门的密钥管理系统,并限制日志输出。移动端应优先使用 Android Keystore 或 iOS Keychain 等系统能力,但仍需考虑设备解锁状态、备份策略和被 root 或越狱后的风险。
十一、总结
完成这次实践后,应该建立以下基本认知:钱包管理的是密钥和签名能力,资产状态存在链上;RPC 是应用连接区块链的入口;链 ID、地址、金额、nonce、Gas 和 data 是交易核对重点;交易哈希不是成功凭证,最终需要检查 receipt;测试网和本地链适合学习,但测试私钥绝不能复用到主网。
对新手来说,最稳妥的学习顺序是:先在 Anvil 本地链查询余额和发送交易,再使用独立测试钱包连接 Sepolia,最后才尝试代币授权和智能合约交互。每增加一种功能,都同步理解它新增的攻击面和撤销方法。WEB3 操作不可逆的特点决定了安全不能只靠事后补救,签名前的核对、密钥隔离和最小权限才是最有效的防线。
很多新手把钱包理解成“存放代币的软件”,这个说法并不准确。链上资产实际记录在区块链账本中,钱包主要负责管理密钥、派生地址、构造交易和生成数字签名。只要掌握对应私钥,就可以控制该地址下的资产;如果私钥或助记词丢失,通常也不存在传统互联网产品中的“找回密码”。
因此,WEB3 入门不能只学会点击“连接钱包”,还需要理解钱包、RPC 节点、智能合约和区块浏览器各自承担什么角色。本文使用本地开发链和 Ethereum Sepolia 测试网完成一次完整实践,不接触真实资金,也不针对任何未授权目标进行测试。
二、核心原理
1. 地址与私钥
私钥是一段随机数,钱包根据私钥计算公钥,再由公钥派生出地址。地址可以公开,用于收款和查询;私钥、助记词及 Keystore 密码不能公开。
钱包中的“余额”并不是保存在手机或浏览器里,而是钱包通过 RPC 节点查询链上状态后展示出来。卸载钱包不会让链上资产消失,但如果没有备份助记词或私钥,就可能永久失去控制权。
2. RPC 节点
RPC 可以理解为应用访问区块链的接口。常见方法包括:
- eth_chainId:查询当前网络的链 ID;
- eth_getBalance:查询原生代币余额;
- eth_call:只读调用合约,不产生链上交易;
- eth_estimateGas:估算交易所需 Gas;
- eth_sendRawTransaction:广播已经签名的交易;
- eth_getTransactionReceipt:查询交易是否被打包及执行结果。
钱包可以在本地完成签名,但交易仍需通过 RPC 广播。RPC 服务方不能直接修改一笔已经签名交易中的收款地址和金额,但不可信 RPC 可能返回误导性查询结果、记录访问行为、拒绝广播交易,或给出异常的 Gas 建议。因此,主网操作应使用可信节点,并通过区块浏览器或第二个独立 RPC 交叉验证重要结果。
3. 交易、Gas 与确认
一笔普通 EVM 交易通常包含发送方、接收方、金额、nonce、Gas 限制、费用参数、链 ID和可选的 data。nonce 是发送方地址的交易序号,可以防止同一笔签名交易被无限重复执行。链 ID用于阻止交易被简单复制到另一条不相关的链上。
交易广播成功只代表节点接受了它,并不等于已经执行。需要等待交易进入区块并检查 receipt 中的 status。status 为 1 通常表示执行成功,为 0 表示执行失败;即使失败,已消耗的 Gas 一般也不会退回。
三、前置条件
建议准备以下环境:
- Node.js 18 或更高版本;
- npm;
- 一个支持 EVM 网络的钱包;
- 可选:Foundry 的 Anvil,用于本地链实验;
- Sepolia 测试网 RPC 地址;
- 少量 Sepolia 测试 ETH。
测试币没有主网资产价值,不要向声称可以“购买高价值测试币”的陌生人付款。水龙头入口和领取规则可能变化,应从钱包、客户端或生态项目的官方文档进入,不要直接相信搜索广告和私信链接。
四、第一步:先在本地链认识账户和交易
如果已经安装 Foundry,可以在终端运行:
anvil
Anvil 会启动一个本地 EVM 网络,默认 RPC 通常为:
终端还会显示若干预置测试账户和私钥。这些私钥是公开的,只能用于本地实验。绝对不要向这些地址转入主网资产,也不要把这些私钥导入长期使用的钱包。
新开一个终端,通过 JSON-RPC 查询链 ID:
curl -s -X POST http://127.0.0.1:8545 -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
返回结果通常是十六进制链 ID。继续查询某个 Anvil 测试地址的余额:
curl -s -X POST http://127.0.0.1:8545 -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["替换为Anvil显示的测试地址","latest"],"id":2}'
余额返回值同样是十六进制,并以 wei 为单位。1 ETH 等于 10 的 18 次方 wei。直接看十六进制不直观,后续可以用 ethers.js 自动格式化。
五、第二步:使用 ethers.js 连接 RPC
创建实验目录并安装依赖:
mkdir web3-first-tx
cd web3-first-tx
npm init -y
npm install ethers dotenv
在 package.json 中加入:
"type": "module"
创建 .env 文件:
RPC_URL=http://127.0.0.1:8545
PRIVATE_KEY=替换为Anvil提供的某个测试私钥
.env 必须加入 .gitignore:
.env
node_modules/
创建 index.js:
import "dotenv/config";
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const network = await provider.getNetwork();
const balance = await provider.getBalance(wallet.address);
const nonce = await provider.getTransactionCount(wallet.address, "pending");
console.log("chainId:", network.chainId.toString());
console.log("address:", wallet.address);
console.log("balance:", ethers.formatEther(balance), "ETH");
console.log("pending nonce:", nonce);
运行:
node index.js
这一步是只读查询,不会产生 Gas。务必检查 chainId,避免以为自己在测试网,实际却连接到了其他网络。
六、第三步:在本地发送第一笔交易
在 index.js 后面加入以下代码。为了避免填错其他地址,示例向自己的地址发送 0 ETH,仅用于观察完整交易生命周期:
const feeData = await provider.getFeeData();
console.log("gasPrice:", feeData.gasPrice?.toString() ?? "EIP-1559 network");
const tx = await wallet.sendTransaction({
to: wallet.address,
value: 0n
});
console.log("transaction hash:", tx.hash);
const receipt = await tx.wait();
console.log("blockNumber:", receipt.blockNumber);
console.log("status:", receipt.status);
console.log("gasUsed:", receipt.gasUsed.toString());
再次运行:
node index.js
虽然转账金额是 0,但交易仍然需要签名、广播、排序和执行,因此依旧会消耗本地测试 Gas。可以记录交易前后余额,验证余额减少部分主要来自手续费。
七、第四步:切换到 Sepolia 测试网
完成本地实验后,再进入公共测试网。Sepolia 的 chainId 是 11155111。先从可信来源获取 Sepolia RPC,并把 .env 中的 RPC_URL 替换为该地址。
私钥方面,建议新建一个“仅用于测试网”的独立钱包账户。不要使用持有主网资产的钱包,更不要把主钱包助记词复制到脚本、云服务器或在线调试工具中。
在钱包中添加或切换 Sepolia 网络后,从官方文档指向的水龙头领取少量测试 ETH。到账后先运行只读脚本,确认:
- 输出的 chainId 为 11155111;
- 脚本地址与钱包中的测试地址一致;
- 余额已经大于 0;
- RPC 没有报网络不匹配或限流错误。
确认无误后再运行发送交易的代码。获得交易哈希后,可在支持 Sepolia 的区块浏览器中查询。重点查看:
- From 和 To 是否符合预期;
- Value 是否为预期数值;
- Status 是否成功;
- Gas Used 与实际手续费;
- Input Data 是否为空;
- 区块确认数量是否增加。
不要把“钱包弹出了签名窗口”当成安全证明。真正应该核对的是当前网络、目标地址、金额、调用方法、代币授权额度和交易 data。
八、从移动应用安全角度理解连接钱包
移动端 DApp 常通过内置浏览器、Deep Link、Universal Link、App Link 或 WalletConnect 与钱包交互。这里有几个典型攻击面:
1. Deep Link 被错误应用接管
如果应用只使用自定义 Scheme,而没有可靠校验来源和回调参数,其他应用可能尝试伪造跳转。防御上应优先使用经过域名验证的 Universal Link 或 App Link,并校验会话标识、来源域名和一次性 nonce。
2. 剪贴板地址被替换
部分恶意软件会监控剪贴板并替换收款地址。粘贴后必须人工核对地址开头和结尾,较大金额还应先做小额测试。地址簿也应展示明确标签,而不是只显示缩略地址。
3. WalletConnect 会话权限过大
连接成功不代表可以永久信任。应检查会话允许的链、账户和方法,用完后及时断开。钱包端应清楚展示请求来自哪个域名、要在哪条链执行什么方法。
4. 盲签名
如果钱包只能显示十六进制 data,而不能解析实际动作,新手不应继续签名。特别要警惕无限额度 approve、Permit 类签名、NFT 批量授权和可转移资产的代理权限。普通消息签名也可能被用于登录或授权,并非“一定不花 Gas 就一定安全”。
九、风险与注意事项
1. 助记词永不输入网页
正常 DApp 连接钱包时不需要用户在网页中输入助记词。任何以“同步钱包、解锁空投、修复节点”为理由索取助记词的页面,都应立即关闭。
2. 测试私钥与正式私钥彻底隔离
Anvil 等本地工具展示的默认私钥是公开测试数据。测试网私钥也不应与主网高价值账户共用。很多资产损失并不是密码学被攻破,而是开发者把 .env、日志、截图或代码仓库公开了。
3. 不要只看代币名称
任何人都可能部署名称和符号相同的代币。识别资产时应核对网络和合约地址,不要仅凭图标、名称或钱包自动展示结果判断真伪。
4. 授权不等于转账
approve 通常不会立即转走代币,但会给指定合约未来调用 transferFrom 的权限。无限授权虽然方便,却扩大了风险范围。对不熟悉的 DApp 应设置合理额度,并定期检查和撤销不再使用的授权。
5. 验证交易模拟结果
部分钱包会显示余额变化或风险提示,但模拟依赖节点状态和解析能力,不能替代人工核对。对于复杂合约交互,应在测试网、本地分叉环境或经过授权的实验环境先验证,不要直接用真实资产试错。
6. 不把区块浏览器状态和业务到账混为一谈
链上交易成功,只能证明交易按合约逻辑执行成功。跨链桥、交易平台充值或其他业务系统可能还需要更多确认和后台处理。反过来,交易 status 为 0 时,即使已经扣除 Gas,也不表示资产转移成功。
十、常见问题
问题一:为什么测试 ETH 到账了,钱包仍显示 0?
先检查钱包网络是否为 Sepolia,再核对地址是否一致。也可能是 RPC 缓存、请求限流或界面未刷新。可以用第二个可信 RPC 或区块浏览器交叉查询。
问题二:交易一直处于 pending 怎么办?
常见原因包括费用过低、RPC 未成功广播、网络拥堵,或者同一地址存在更早的低费用交易。不要连续盲目重发。先按地址和 nonce 查询待处理交易,再使用钱包提供的加速或取消功能。取消本质上通常是用相同 nonce 发送一笔费用更高的新交易。
问题三:为什么余额足够,交易仍提示 insufficient funds?
发送方不仅要支付 value,还要预留 Gas 费用。发送全部余额时尤其容易遇到这个问题。代币转账虽然 value 常为 0,但仍需原生代币支付 Gas。
问题四:eth_call 是否绝对安全?
eth_call 不会直接写入链上,也不消耗真实 Gas,但不可信 RPC 可以返回错误结果,调用内容也可能泄露查询意图。涉及重要决策时,应使用可信节点或多个节点复核。
问题五:可以把私钥直接写进 index.js 吗?
实验中也不推荐。至少应使用 .env 并避免提交版本库。生产环境还应使用系统密钥库、硬件钱包、签名服务或专门的密钥管理系统,并限制日志输出。移动端应优先使用 Android Keystore 或 iOS Keychain 等系统能力,但仍需考虑设备解锁状态、备份策略和被 root 或越狱后的风险。
十一、总结
完成这次实践后,应该建立以下基本认知:钱包管理的是密钥和签名能力,资产状态存在链上;RPC 是应用连接区块链的入口;链 ID、地址、金额、nonce、Gas 和 data 是交易核对重点;交易哈希不是成功凭证,最终需要检查 receipt;测试网和本地链适合学习,但测试私钥绝不能复用到主网。
对新手来说,最稳妥的学习顺序是:先在 Anvil 本地链查询余额和发送交易,再使用独立测试钱包连接 Sepolia,最后才尝试代币授权和智能合约交互。每增加一种功能,都同步理解它新增的攻击面和撤销方法。WEB3 操作不可逆的特点决定了安全不能只靠事后补救,签名前的核对、密钥隔离和最小权限才是最有效的防线。