Solidity 入门:交易、转账与智能合约深潜

·

读完 5 分钟,你将一次性搞懂 以太坊交易、ETH/ERC20 转账、合约交互和部署 的全部细节。
把重点放进收藏夹,开发时再照着敲,就能少踩 90% 的坑。

基本概念:以太坊交易是什么?

以太坊可被视为 交易驱动的状态机。任意时刻,链上所有余额、合约、NFT 的状态,都由“刚才已被确认的交易”决定;任何新的 交易 transaction 一旦被矿工打包,就会推动状态再次变化。

一次交易长什么样子?

一条标准交易包含 9 个字段,核心关键词涵盖:recipient、signature、value、data、gasLimit、maxFeePerGas、maxPriorityFeePerGas、nonce。

字段作用&注意点
recipient收款地址,外部账户或智能合约皆可。
signature你钱包私钥的签名,防伪造。
value随交易附赠的 ETH 数量(单位 Wei)。
data与合约交互时必填,调什么函数靠它下指令。
gasLimit / maxFeePerGas / maxPriorityFeePerGas成本防护罩,防止耗费过多手续费。
nonce递增序号,保证先后顺序、抗重放攻击。
小技巧:想替换或“取消”已在交易池的交易?发一笔同等 nonce、更高 priorityFee 的新交易即可 —— 通常是给自己转 0 ETH。

交易分为 3 类

  1. 常规转账:EOA → EOA(外部地址转账)。
  2. 合约执行:EOA → 合约地址,如 mint NFT。
  3. 合约部署:recipient 为空,附带基建代码 → 生成全新合约。

转账 Transfer:ETH vs ERC20

不少人误以为“转账”是同一件事,实际上 ETH 转账与 ERC20 代币转账 底层行为完全不同

ETH 转账

示例代码:

// 这个合约想接受纯 ETH 转账,必须补上 receive 或 fallback
receive() external payable {}

// 如果还想处理附带 data 的转账:
fallback() external payable {
    emit FallbackCalled(msg.data);
}

ERC20 代币转账

标准写法:

// 标准 ERC20 函数原型
function transfer(address _to, uint256 _value) public returns (bool);

合约底层用 mapping(address => uint256) 保存余额,自由度很高 —— 例如你可以在 transfer 中额外燃烧 10% 实现通缩设计。


合约交互:data 字段拆解

向合约发送交易时,data 负责说明具体调用哪个函数、传递什么参数。

结构速读

前 4 Byte:函数选择器 = keccak256("函数签名")[:4]  
后续字节:ABI 编码后的参数

举个 mint 例子:
Function = mint(uint256 _amount) → keccak256 后得 0xa0712d68
data 字段即 0xa0712d68... + ABI 编码的 _amount 值。

👉 想在浏览器实时体验逆向合约 input data?在 Etherscan 一键解析更直观!

合约如何匹配函数?

链上字节码里存在一个自动生成的 dispatcher(语义相当于 C 语言入口 main)。
流程:

  1. 取 input 前 4 字节 → 与函数哈希对比。
  2. 命中 → 跳转至对应函数;未命中 → revert。

部署新合约:部署交易剖析

部署同样是一笔 recipient = 0x0 的特殊交易,data 并非最终运行代码,而是 构造函数输出的字节码生成器

步骤流程

  1. 本地/Remix 编译 Solidity,得到两部分:

    • creationCode = 构造函数 + 逻辑代码。
    • runtimeCode = 去掉构造函数后的真正 ELF,tag 0x60806040... 第二次出现即为 runtime 起点。
  2. 交易广播 → EVM 执行构造函数 → 返回 runtimeCode → 存入区块链,并以 keccak256(sender, nonce) 算法计算新合约地址。

👉 想验证一下?对照刚部署的合约 hash,确认 runtimeCode 是否恰好从第二个 0x60806040 开始!


FAQ:关于交易与合约的 5 个高频疑问

Q1:MetaMask 能发“批量交易”吗?

A:MetaMask 单次请求只能打包 1 条链上交易;如需批量,可手动构造多笔并同 nonce 或者写合约合约包装器一次性完成。

Q2:为什么我把 nonce 设错,交易一直挂起?

A:以太坊严格按照 nonce 顺序执行,若中间某个 nonce 丢失,后续全部 pending。补发缺失 nonce 的交易即可疏通。

Q3:没有 receive/fallback,ETH 就不能打进合约?

A:尝试直接转账会 revert;开发者可设计 deposit() 函数通过调用方式入账并保存余额。

Q4:ERC20 的 transfer 会不会消耗我钱包里的 ETH?

A:会,因为仍是链上交易,需付 gas。代币合约不会从你的 ETH 余额扣钱,但矿工费一样跑不掉。

Q5:为何部署后合约地址和我的测试地址差很远?

A:地址由当时的发起者地址与部署交易对应的 nonce 共同计算,任何细微变量都会改变结果。


小结 & 下一步

把今天梳理的关键词 交易字段、ETH 转账、ERC20 transfer、合约交互、部署生成器 记录到速查表:

下篇我们将借助 Remix & Hardhat 亲手写一条带 receive/fallback 的合约,把它发上测试网并让前端用 ethers.js 跟合约对话。保持关注,下集不迷路!