solidity地址、智能合约、交易概念
目录
- 地址
- address 的两种子类型(Solidity 0.5.0+)
- address分类
- address 的常用操作和属性
- 总结
- 交易
- 交易的基本结构(由外部发起)
- Gas
- 交易生命周期
- 函数调用与交易
- 常见交易场景
- 总结
地址
在 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 的常用操作和属性
- 查询余额
uint balance = address(addr).balance;
- 转账(三种方式)
方法 | 是否推荐 | 说明 |
---|---|---|
.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");
- 判断是合约还是 EOA
function isContract(address account) public view returns (bool) {uint32 size;assembly {size := extcodesize(account)}return size > 0;
}
extcodesize > 0 → 是合约
extcodesize == 0 → 是外部账户(钱包)
- 地址字面量
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费由两部分组成:
- GasUsage:衡量交易复杂度,代码复杂度越高,消耗的Gas越多。
- GasPrice:单个Gas的价格,由市场供需动态调节。
影响因素
- 网络拥堵:当交易量激增时,Gas费会显著上升以加速处理。
- 矿工策略:矿工根据Gas费高低选择优先处理交易。
交易生命周期
- 用户在钱包(如 MetaMask)中发起操作
- 钱包生成并签名交易
- 交易广播到 P2P 网络
- 矿工/验证者打包进区块
- 区块上链,交易确认
- 智能合约执行,状态变更
- 触发事件(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 | 读操作免费,写操作收费 |
- “交易是区块链的脉搏,每一次调用都是一次心跳”
- “msg.sender 是身份,msg.value 是金钱,emit 是通知”