solidity地址、智能合约、交易概念

发布于:2025-08-31 ⋅ 阅读:(27) ⋅ 点赞:(0)

地址

在 Solidity 中,地址(address) 是一个非常核心且基础的概念。它是智能合约与外部账户(Externally owned account, EOA)之间交互的“身份标识”,类似于银行账户的账号或电子邮件地址。

程序而言

  • address 是 Solidity 中的一个 值类型(value type)
  • 占 20 个字节(160 位),通常以 42 位十六进制表示(0x 开头)
  • 用于表示:
    • 外部账户(Externally Owned Account, EOA)——由私钥控制的钱包地址
    • 合约账户(Contract Account)——部署在链上的智能合约地址

例如

0x5B38Da6a701c568545dCfcB03FcB875f56beddC4

address 的两种子类型(Solidity 0.5.0+)

类型 说明
address 通用地址类型,可表示 EOA 或合约
address payable 可以接收以太币(ETH)的地址,支持 .transfer() 和 .send()

所有 address payable 都是 address,但反之不成立

如下 将address 能转成 address payable:

address payable user = payable(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);

// address → address payable
address addr = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
address payable payableAddr = payable(addr);

address分类

类型 特点 能否拥有代码 能否发起交易
外部账户(EOA) 由私钥控制的钱包(如 MetaMask) ❌ 无代码 ✅ 可发起交易
合约账户 部署在链上的智能合约 ✅ 有代码 ❌ 不能主动发起交易(只能被调用)

参考理解: https://professional-solidity.readthedocs.io/zh-cn/latest/source/01.hello.html#id5

address 的常用操作和属性

  1. 查询余额
uint balance = address(addr).balance;
  1. 转账(三种方式)
方法 是否推荐 说明
.transfer(amount) ✅ 推荐 最安全,只传递 2300 gas,防止重入攻击
.send(amount) ⚠️ 不推荐 返回 bool,失败不自动 revert
.call{value: amount}(“”) ⚠️ 小心使用 传递所有 gas,可能引发重入攻击
// ✅ 推荐:transfer
payable(user).transfer(1 ether);

// ❌ 不推荐:send 需要手动处理失败
bool success = payable(user).send(1 ether);
require(success, "Send failed");

// 🔥 高级用法:call(可用于调用函数)
(bool success, ) = payable(user).call{value: 1 ether}("");
require(success, "Call failed");
  1. 判断是合约还是 EOA
function isContract(address account) public view returns (bool) {
    uint32 size;
    assembly {
        size := extcodesize(account)
    }
    return size > 0;
}

extcodesize > 0 → 是合约
extcodesize == 0 → 是外部账户(钱包)

  1. 地址字面量
address constant OWNER = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;

注意:地址字面量是 address 类型,不是 address payable

总结

概念 说明
address 20 字节的账户标识
address payable 可接收 ETH 的地址
.balance 查询余额
.transfer() 安全转账
msg.sender 当前调用者地址
tx.origin 原始交易发起者(不推荐使用)

口诀

  • “address 是身份,payable 才能收钱”
  • “.transfer 最安全,.call 要小心”
  • “合约不能主动发交易,只能被调用”

交易

有了地址的概念后,交易的理解则很简单。

交易可以看作一个地址发送到另外一个地址的消息,可能包含一个二进制数据(可以先理解为合约程序,这也是不可篡改的)和以太币。

交易(Transaction) 是由外部账户(EOA,如钱包)发起的一个签名数据包,用于触发区块链上的状态变更,比如:

  • 转账 ETH
  • 部署合约
  • 调用智能合约函数

一旦交易被打包进区块,就不可撤销。

交易的基本结构(由外部发起)

字段 说明
from 发起者地址(msg.sender)
to 接收者地址(如果是合约部署,为空)
value 转账金额(单位:wei)
data 调用数据(函数选择器 + 参数)
gasLimit 最大愿意支付的 gas 数量
gasPrice 每单位 gas 的价格(Gwei)
nonce 发起账户的交易序号
chainId 防重放攻击(如 1=主网,5=Goerli)
Gas

Gas费 是 以太坊 等 区块链网络 中执行交易或智能合约所需的计算资源费用,用于维持网络运行和激励节点参与者。 ‌

Gas费由两部分组成:

  1. GasUsage‌:衡量交易复杂度,代码复杂度越高,消耗的Gas越多。
  2. GasPrice‌:单个Gas的价格,由市场供需动态调节。 ‌

影响因素

  • 网络拥堵‌:当交易量激增时,Gas费会显著上升以加速处理。
  • 矿工策略‌:矿工根据Gas费高低选择优先处理交易。 ‌

交易生命周期

  1. 用户在钱包(如 MetaMask)中发起操作
  2. 钱包生成并签名交易
  3. 交易广播到 P2P 网络
  4. 矿工/验证者打包进区块
  5. 区块上链,交易确认
  6. 智能合约执行,状态变更
  7. 触发事件(Event),前端监听更新

函数调用与交易

类型 是否产生交易 是否收费 示例
交易(Transaction) ✅ 是 ✅ 收 gas 修改状态、转账
调用(Call/View) ❌ 否 ❌ 免费 view 函数查询余额

常见交易场景

场景 Solidity 实现
用户转账 ETH payable(to).transfer(amount)
调用合约函数 contract.func()
部署新合约 new MyContract()
提交投票 vote(candidate) + emit Event
NFT 铸造 mint(to, tokenId)

总结

概念 说明
交易(Transaction) 由 EOA 发起,改变链上状态
msg.sender 直接调用者(推荐用于权限)
tx.origin 原始发起者(不安全,避免使用)
msg.value 随交易发送的 ETH
payable 能接收 ETH 的函数或地址
Call vs Transaction 读操作免费,写操作收费
  1. “交易是区块链的脉搏,每一次调用都是一次心跳”
  2. “msg.sender 是身份,msg.value 是金钱,emit 是通知”