Gas机制与转账设计

Gas机制与转账设计

学习目标

  • 理解区块链的经济模型与激励机制
  • 掌握 Gas、Gas Price、Gas Fee 的概念与关系
  • 理解 Ether 单位与转换
  • 掌握合约转账设计(receive / fallback / payable)

区块链的经济系统

为什么需要经济模型?

  • 计算与存储资源是稀缺的:每个节点都要执行和存储所有交易
  • 共识和 trustless 需要矿工工作:矿工(验证者)需要激励才会持续参与
  • Transaction 执行有成本(gas):gas 费成为矿工的直接激励
  • Ether 是生态系统的原生货币:用于支付 gas 费、转账、合约交互

Ether 单位

1 ETH = 10^18 Wei(Wei 是最小单位)

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract EtherUnits {
    uint public oneWei = 1 wei;
    bool public isOneWei = (1 wei == 1);

    uint public oneEther = 1 ether;
    bool public isOneEther = (1 ether == 1e18);
}

常用单位换算:

单位 Wei 值
1 Wei 1
1 Gwei 10^9
1 Ether 10^18

Gas、Gas Fee、Gas Price

三者的关系

Gas Fee = Gas × Gas Price
  • Gas:完全由执行逻辑决定。固定逻辑的函数,gas 消耗是不变的(例如一次 SSTORE 操作固定消耗 20000 gas)
  • Gas Price:由交易发起者在 transaction 中设定,单位为 Gwei。Gas Price 由市场供需决定——网络拥堵时价格上涨,空闲时价格下降
  • Gas Fee:最终支付的费用,等于实际消耗的 gas 乘以 gas price

Gas机制示意图

Gas Limit

Gas Limit 存在于三个层面:

  1. 交易层面:交易发起者设定 gaslimit,表示最多愿意消耗多少 gas
  2. 合约调用层面:合约间调用时可以指定 gaslimit,控制子调用的 gas 消耗
  3. 区块层面:每个区块有 gaslimit 上限,限制单个区块的总计算量

gasleft() 函数

gasleft() 返回当前剩余可用的 gas,可用于:
- 监控 gas 消耗
- 在 gas 不足前提前退出
- 限制子调用的 gas 消耗

退款规则

  • 剩余未用的 gas 会退款给交易发起者
  • 交易失败(revert / out of gas)时,已消耗的 gas 不退
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract Gas {
    uint public i = 0;
    uint public remained;

    function forever() public {
        while (true) {
            if (i > 100) return;
            if (i == 10) {
                remained = gasleft(); // 记录剩余 gas
            }
            i += 1;
        }
    }
}

contract GasCaller {
    Gas private gas;

    constructor(Gas _gas) {
        gas = _gas;
    }

    function callForever() public {
        gas.forever{gas: 200000}(); // 限制子调用最多消耗 200000 gas
    }
}

合约持有 Ether

  • 合约可以持有 Ether! 合约地址和 EOA 地址一样,都有余额
  • 合约与其他合约或 EOA 之间可以自由转账
  • 典型应用:多签钱包(Multisig Wallet)、DeFi 协议、ICO 合约

转账设计思想

核心理解

转账没有单独的函数,转账是与函数调用一起发生的。

调用合约函数时,通过附加选项 {value: amount} 来同时发送 Ether:

// 通过 call 转账
_to.call{value: 1 ether}("");

// 通过具名函数转账
contract.deposit{value: 1 ether}();

被调用函数解析逻辑(重要!)

当合约收到一笔调用时,EVM 按以下逻辑决定执行哪个函数:

发送 Ether(函数调用)
        │
   msg.data 是否为空?
      /         
    否           是
    /             
函数名匹配?    receive() 存在?
  /              /       
 是    否        是        否
 /              /          
匹配函数  fallback()  receive()  fallback()

payable 检查

  • 如果 msg.value > 0 且目标函数没有 payable 修饰符 → 调用失败(自动 revert)
  • payable 修饰符的唯一作用就是允许函数接收 Ether

receive() 函数

receive() 是专门处理纯转账(calldata 为空)的函数,使 fallback 的职责更加清晰:

  • receive():处理纯 Ether 转账
  • fallback():处理调用不存在的函数
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract ReceiveEther {
    string public caller;

    receive() external payable {
        caller = "receive";
    }

    fallback() external payable {
        caller = "fallback";
    }

    function deposit() public payable {
        // 接收 Ether 的普通函数
    }

    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}

转账方式对比

方式 Gas Limit 推荐程度 说明
transfer 固定 2300 不推荐 旧设计,gas 不足以执行复杂逻辑
send 固定 2300 不推荐 旧设计,返回 bool 但常被忽略
call 可自定义 推荐 灵活,安全(需检查返回值)
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract SendEther {
    // 推荐方式:通过 call 转账
    function sendViaCall(address payable _to) public payable {
        (bool sent, ) = _to.call{value: msg.value}("");
        require(sent, "Failed to send Ether");
    }

    // 通过具名函数转账
    function sendViaFoo(address payable _to) public payable {
        ReceiveEther re = ReceiveEther(_to);
        re.deposit{value: msg.value}();
    }
}

综合实例:ERC20 Token + ICO

以下是一个简化的 ERC20 代币合约,结合了 ICO(首次代币发行)功能,展示了转账设计的实际应用:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract MyErc20Token {
    string public name = "MyDollar";
    string public symbol = "$";
    uint public decimals = 4;
    address public owner;
    mapping(address => uint) public balanceOf;

    constructor() {
        owner = msg.sender;
    }

    // 铸币:用户发送 ETH 购买代币
    function mint() external payable {
        balanceOf[msg.sender] += msg.value;
    }

    event TransferEvent(uint oldv, uint newv);

    modifier isOwner() {
        require(msg.sender == owner, "not owner!");
        _;
    }

    // 转账:从调用者账户转给目标地址
    function transfer(address to, uint amount) public {
        address from = msg.sender;
        uint current = balanceOf[from];
        require(current >= amount, "not enough balance!");
        uint toc = balanceOf[to];

        current -= amount;
        toc += amount;
        balanceOf[from] = current;
        balanceOf[to] = toc;
    }

    // 提现:仅 owner 可以将合约中的 ETH 提取到自己的地址
    function withdraw() external isOwner {
        (bool suc, ) = owner.call{value: address(this).balance}("");
        require(suc, "failed!");
    }
}

合约功能解析

  1. mint():用户发送 ETH 调用此函数,合约记录对应的代币余额(payable 允许接收 ETH)
  2. transfer():代币持有者之间的转账(注意这是代币层面的转账,不是 ETH 转账)
  3. withdraw():合约 owner 将合约持有的所有 ETH 提取出来,使用 call{value: ...} 方式转账
  4. isOwner modifier:权限控制,确保只有合约部署者可以提现

主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://walker-learn.xyz/archives/7496

(0)
Walker的头像Walker
上一篇 2026年5月12日 16:07
下一篇 2026年5月12日 13:53

相关推荐

  • 区块链核心技术

    区块链核心技术 学习目标 理解区块链底层核心技术:哈希函数、默克尔树、数字签名、加密技术 掌握主流共识机制的原理与分类 了解区块的运行原理与整体架构 认识联盟链的特点与应用场景 前置知识 基本的计算机科学概念(数据结构、算法) 对密码学有初步认知(非必须) 已阅读 01-Web3 概述与愿景 一、哈希函数 1.1 什么是哈希函数 哈希函数(Hash Func…

    2026年3月10日
    18800
  • 继承多态与库合约

    继承多态与库合约 学习目标 掌握 Solidity 继承机制与多态 理解 C3 线性化算法 掌握库合约(library)的定义和使用 继承基础 继承定义 使用 is 关键字 继承的实现方式是代码拷贝:部署后变成一个合约 可见性与继承 private:子合约不可见,但不能定义同名成员 internal:子合约可见 public:完全可见 event 和 mod…

    Web3与WASM 2026年3月10日
    10300
  • 存储位置与拷贝机制:storage、memory、calldata

    存储位置与拷贝机制:storage、memory、calldata 学习目标 理解 EVM 中三种数据存储位置的特点,以及引用类型在不同存储位置之间赋值时的拷贝规则。 前置知识 已学习值类型和引用类型(数组、结构体、映射、字符串)。 三种存储位置 storage —— 持久化存储 类似数据库,数据永久保存在区块链上 成员变量(状态变量)默认存储在 stora…

    Web3与WASM 2026年3月10日
    15000
  • 动态调用与Fallback机制

    动态调用与Fallback机制 学习目标 掌握 call 动态调用的语法与使用场景 理解 calldata 数据结构(selector + 参数编码) 掌握 fallback / receive 函数的触发机制 理解 tx、msg、block 三种上下文变量的区别 call 动态调用 基本语法 (bool success, bytes memory data…

    2026年3月10日
    11900
  • Web3 概述与愿景

    Web3 概述与愿景 学习目标 理解 Web1、Web2、Web3 的演进历程与核心区别 掌握 Web3 的核心理念:去中心化、数据确权、用户主权 了解 Web3 带来的创新机会与全新商业模式 熟悉 Web3 开发者的学习路线图 前置知识 基本的互联网使用经验 对软件开发有初步了解(非必须,但有助于理解技术部分) 一、Web1 → Web2 → Web3 的…

    Web3与WASM 2026年3月10日
    12000
简体中文 繁体中文 English