DTeam 技术日志

Doer、Delivery、Dream

Solidity 非权威开发指南(2):语法摘要

胡键 Posted at — Jul 9, 2022 阅读

【注】:本文是这篇旧文的升级版。

Contact

类似 class,可以:abstract、继承和被其他 contract 调用。

典型使用:

可见性

可见性类似应用于外部
可访问
子合约
可访问
external函数
publicpublic函数 + 状态变量
internalprotected函数 + 状态变量
privateprivate函数 + 状态变量

注: 对于 public 变量,会自动生成对应的 getter(详见:Ethers.js 非权威开发指南(续))。

关键要素

要素说明示例
状态变量永久存储于链上,需耗费 gasuint data;
函数读/写两类,写方法需耗费 gas;
可存在于合约内部和外部
function func() public {...}
fallback()无法直接被外部调用,当请求合约中不存在函数时执行fallback() external { ... }
receive()无法直接被外部调用,当接收 eth 时执行receive() external payable {...}
modifier可复用的声明性约束,函数调用前执行。声明: modifier onlyOwner(){...}
使用:function func() public onlyOwner {...}
事件链上执行日志,可供日后查询。emit Event1(data);
structure自定义类型struct MyType { uint item1; bool item2; }
error自定义异常声明:error MyError(unit reason);
使用:revert MyError(200);
枚举有限常数值最佳选择enum State { Created, Locked, Inactive }

注:

关于在 dapp 中如何使用事件和查询日志,详见:Ethers.js 非权威开发指南(下)

Interface

类似其他语言中的 interface,可以:

Library

类似 contract,但:

两者关系类似:contract,可执行文件;library,动态链接库

数据类型

值类型和引用类型

类似
值类型bool、uint / int、address、byte、enum
引用类型数组(如 bytes / string)、structure、mapping

注:

存储位置

类似举例
storage持久化,合约内全局内存状态变量
memory函数的本地内存,非持久化函数入参
calldata函数入参,非持久化函数入参
stackEVM 调用栈

相关规则:

全局变量和方法

说明举例
eth 单位wei、gwei、ether1 gwei
时间单位seconds、minutes、hours、days、weeks1 minutes
blockblock 对象
blockhash()若入参为最近 256 个 block 之一,则为其 hash。
否则,0。
msgmsg 对象
txtx 对象
gasleft()剩余 gas
abiabi 对象
addressaddress 对象
this当前合约对象,可显式转换成 addressaddress(this).balance
type()类型信息
addmod(a + b) % k
mulmod(a * b) % k
哈希函数keccak256、sha256、ripemd160
ecrecover从签名恢复地址

详见:https://docs.soliditylang.org/en/latest/units-and-global-variables.html

注:

bytes memory payload = abi.encodeWithSignature("register(string)", "MyName");
(bool success, bytes memory returnData) = address(nameReg).call(payload);
require(success);
address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName"));

异常处理

异常类型:

合约抛出异常之后,状态回滚,当前有 3 种方式:

try…catch 语句示例:

try feed.getData(token) returns (uint v) {
    return (v, true);
} catch Error(string memory /*reason*/) {
    // require 导致
    errorCount++;
    return (0, false);
} catch Panic(uint /*errorCode*/) {
    // assert 导致
    errorCount++;
    return (0, false);
} catch (bytes memory /*lowLevelData*/) {
    // revert 导致
    errorCount++;
    return (0, false);
}

觉得有帮助的话,不妨考虑购买付费文章来支持我们 🙂 :

付费文章

友情链接


相关文章