DTeam 技术日志

Doer、Delivery、Dream

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

胡键 Posted at — Jul 9, 2022 阅读

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

Contact

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

典型使用:

可见性

可见性 类似 应用于 外部
可访问
子合约
可访问
external 函数
public public 函数 + 状态变量
internal protected 函数 + 状态变量
private private 函数 + 状态变量

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

关键要素

要素 说明 示例
状态变量 永久存储于链上,需耗费 gas uint 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 函数入参,非持久化 函数入参
stack EVM 调用栈

相关规则:

全局变量和方法

说明 举例
eth 单位 wei、gwei、ether 1 gwei
时间单位 seconds、minutes、hours、days、weeks 1 minutes
block block 对象
blockhash() 若入参为最近 256 个 block 之一,则为其 hash。
否则,0。
msg msg 对象
tx tx 对象
gasleft() 剩余 gas
abi abi 对象
address address 对象
this 当前合约对象,可显式转换成 address address(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);
}

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

付费文章

友情链接


相关文章