Geek

博客园 首页 新随笔 联系 订阅 管理
  132 随笔 :: 2 文章 :: 7 评论 :: 41072 阅读

基础知识

gas

gas是衡量执行某些操作所需的计算量的单位,用来计算为了执行操作而需要支付给网络的费用数额。 通俗理解,Gas 是给矿工的佣金,并以 ETH 支付,无论是交易、执行智能合约并启动 DApps,还是支付数据存储费用,都需要用到 Gas。 Gas的目的是限制执行交易所需的工作量,同时为执行支付费用。当EVM执行交易时,Gas将按照特定规则被逐渐消耗,无论执行到什么位置,一旦Gas被耗尽,将会触发异常。当前调用帧所做的所有状态修改都将被回滚, 如果执行结束还有Gas剩余,这些Gas将被返还给发送账户。 每笔交易都包含gas limit和gas price。矿工可以有选择的打包这些交易并收取这些费用。gasprice 会影响到该笔交易被打包所需等待的时间。如果该交易的操作所使用的gas数量小于或等于所设置的gas limit,交易会被处理。但如果gas总消耗超过gas limit,所有的操作都会被重置,但手续费依旧会被收取。

以太坊客户端

若想使用以太坊提供的服务,不论是转账还是部署合约,都需要用以太坊客户端加入到以太坊网络中,说白了以太坊客户端就是实现了以太坊协议的软件,其概念可类比平时使用的P2P下载客户端。以太坊客户端可概述为:

全节点客户端 全节点客户端加入到以太坊网络时,会把以太坊全部的区块链数据都同步到本地,因此对配置的要求比较高。全节点支持的功能非常齐全,并且其安全性比较高,因为是直接和以太坊网络交互,中间不需要经过第三方。
轻节点客户端 轻节点客户端不会同步整个以太坊网络,它通过连接到其它的全节点来提供服务,因此其提供的服务往往有限,常常用于钱包场景。

Ether 和 Wei

交易是用ether支付的。 1ether等于 10^18wei

Solidity 中有 3 种类型的变量 local 在函数内部声明 不存储在区块链上 state 在函数外声明 存储在区块链上 global(提供有关区块链的信息) 例如msg.sender

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

contract Variables {
    // 状态变量存储在区块链上。
    string public text = "Hello";
    uint public num = 123;

    function doSomething() public {
        // 局部变量不会保存到区块链中。
        uint i = 456;

        // 下面是一些全局变量
        uint timestamp = block.timestamp; // 当前区块时间戳
        address sender = msg.sender; // 发送者的地址
    }
}
常量是不能被修改的变量。 它们的值是硬编码的,使用常数可以节省gas成本。

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

contract Constants {
    // 编码惯例为大写的常量变量
    // 类似js里面的const
    address public constant MY_ADDRESS = 0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc;
    uint public constant MY_UINT = 123;
}

不可变变量就像常量。不可变变量的值可以在构造函数中设置,但之后不能修改。

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

contract Immutable {
    // coding convention to uppercase constant variables
    address public immutable MY_ADDRESS;
    uint public immutable MY_UINT;

    constructor(uint _myUint) {
        MY_ADDRESS = msg.sender;
        MY_UINT = _myUint;
    }
}


你需要为一笔交易支付多少gas? 你要支付花费的gas = gas spend * gas price,其中ether一个计算单位 gas消耗是交易中使用的gas总量 gas price是你愿意为每个gas支付多少ether的单价 gas price较高的交易有较高的优先权被纳入一个区块中。 未消耗的gas将被退还。 Gas limit 你可以花费的gas量有两个上限

gas limint(你愿意为你的交易使用的gas,由你设定)
block gas limit(一个区块中允许的最大gas,由网络设置)

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

contract Gas {
    uint public i = 0;

    // Using up all of the gas that you send causes your transaction to fail.
    // State changes are undone.
    // Gas spent are not refunded.
    function forever() public {
        // Here we run a loop until all of the gas are spent
        // and the transaction fails
        while (true) {
            i += 1;
        }
    }
}

支持if/else 也支持 三元运算符

函数后面 pure/view 表示不需要花费gas

pure:不能读取也不能写入存储链上的数据 view:能读取状态,但是不能写入


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

contract IfElse {
    function foo(uint x) public pure returns(uint){
        if(x < 10){
            return 0;
        } else if (x <20) {
            return 1;
        } else {
            return 2;
        }
    }

    function ternary(uint _x) public pure returns(uint) {
        return _x < 10 ? 1: 2;
    }
}

Solidity 支持 for、while 和 do while 循环。 不要编写无界循环,因为这可能会达到 gas 限制,从而导致您的交易失败。 由于上述原因,很少使用 while 和 do while 循环。

Mapping

映射的创建语法是mapping(keyType => valueType)。 keyType可以是任何内置的值类型,字节,字符串,或任何合约。 valueType可以是任何类型,包括另一个映射或一个数组。 映射是不可迭代的。

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

contract Mapping {
    mapping(address => uint) public myMap;
    // 得到映射
    function get(address _addr) public view returns(uint){
        return myMap[_addr];
    }

    // 更新映射
    function set(address _addr, uint _i) public {
        myMap[_addr] = _i;
    }

    function remove(address _addr) public {
        delete myMap[_addr];
    }
}

Event 事件

Event允许记录到以太坊区块链。Event的一些用例是: 1.监听事件和更新用户界面 2.一种费用更低的存储方式

Solidity中的事件(event)是EVM上日志的抽象,它具有两个特点:

响应:应用程序(ether.js (opens new window))可以通过RPC接口订阅和监听这些事件,并在前端做响应。
经济:事件是EVM上比较经济的存储数据的方式,每个大概消耗2,000 gas;相比之下,链上存储一个新变量至少需要20,000 gas

事件的声明由event关键字开头,然后跟事件名称,括号里面写好事件需要记录的变量类型和变量名。以ERC20代币合约的Transfer事件为例:

event Transfer(address indexed from, address indexed to, uint256 value);

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

contract Event {
    // 事件声明,前面带 event
	// 最多可以索引 3 个参数。
	// 被索引的参数可以帮助你通过被索引的indexed来过滤日志,查询更快
    event Log(address indexed sender, string message);
    event AnotherLog();

    function test() public {
        emit Log(msg.sender, "Hello World!");
        emit Log(msg.sender, "Hello EVM!");
        emit AnotherLog();
    }
}

输出日志如下

[
    {
        "from": "0x9D7f74d0C41E726EC95884E0e97Fa6129e3b5E99",
        "topic": "0x0738f4da267a110d810e6e89fc59e46be6de0c37b1d5cd559b267dc3688e74e0",
        "event": "Log",
        "args": {
            "0": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "1": "Hello World!",
            "sender": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "message": "Hello World!"
        }
    },
    {
        "from": "0x9D7f74d0C41E726EC95884E0e97Fa6129e3b5E99",
        "topic": "0x0738f4da267a110d810e6e89fc59e46be6de0c37b1d5cd559b267dc3688e74e0",
        "event": "Log",
        "args": {
            "0": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "1": "Hello EVM!",
            "sender": "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",
            "message": "Hello EVM!"
        }
    },
    {
        "from": "0x9D7f74d0C41E726EC95884E0e97Fa6129e3b5E99",
        "topic": "0xfe1a3ad11e425db4b8e6af35d11c50118826a496df73006fc724cb27f2b99946",
        "event": "AnotherLog",
        "args": {}
    }
]

posted on   .geek  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示