# 区块链技术与研究进展

区块链智能合约的优点:去中心化 多方验证 难以篡改

# Solidity 语言

Solidity 是一种用于实现智能合约的面向对象的高级语言。Solidity 语法接近于 JavaScript,且是目前较为成熟、流行的智能合约语言

# 特性

Solidity 在初期设计时的目标是为了编写以太坊上的智能合约,因此有部分语法与以太坊的工作原理是高度耦合的。Solidity 中具有一些特殊类型(如 address、event 等)Solidity 中具有一些特殊的关键字(如 payable、now 等)Solidity 需要结合以太坊智能合约的特性在编写过程中对变量进行具体存储位置的定义

在线编译器:http://remix.ethereum.org/ 中文文档:https://solidity-cn.readthedocs.io

# 基础语法

# 常用类型

布尔类型由 bool 声明,与传统编程语言类似,可取 true 或者 false。

整型由 int 声明有符号的整型变量,由 uint 声明无符号的整型变量,可取整数。声明变量时加上数字表示变量的位数,如 int8 表示 8 位长度的有符号整型变量,位数可取 8、16、……、256。未声明变量位数时,编译器在编译时将默认其为最长位数,即将 int 编译为 int256。

地址类型由 address 声明,指以太坊账户的地址类型,与以太坊账户长度相同,该类型实际为存储一个 20 字节的值。地址类型的变量将自带多个成员变量,可通过多个成员变量函数进行账号余额获取、跨账号的转账、调用等操作。

地址类型成员函数 balance:获取该地址余额,如

.balance (uint256);transfer:向该地址转账,失败则抛出异常,如
.transfer (uint256 amount);send:向该地址转账,失败则返回 false,如
.send (uint256 amount);call/callcode/delegatecall:向该地址发出相应的底层合约调用消息,如
.call(…)

映射由 mapping (键类型 => 值类型) 声明键类型不可以是:映射、变长数组、合约、枚举以及结构体在映射对应的以太坊状态树底层存储中,实际上并不存储键的值,而是存储键的 keccak256 哈希值,从而便于减小存储体积的同时查询实际的值。与数组不同的是,映射没有长度。

结构体由 struct 声明,可将多个基本变量组合为一个结构

指定变量的访问

在声明变量时,在类型名后,可以指定变量为 public 或 private 变量是否可以被合约的外部调用获取查询

指定变量的存储位置

在声明变量时,在类型名后,可以指定变量的存储位置为 storage 或 memory 变量保存在存储或是内存中。同样变量的不同存储位置涉及 Gas 计费的不同。一般情况下,各个变量有默认的存储位置,当编译器无法默认识别时,会提示开发者进行修改。

# 例子
// SPDX-License-Identifier: MIT
pragma solidity 0.6.0;
contract Test1{
    struct myStruct{
        bool myBool;
        uint myUint;
        address myAddress;
        string myString;
    }
    myStruct[] public myArray;
    mapping (uint=>string) public myMapping;
    constructor() public {
        myStruct memory myElement = myStruct(true,1,msg.sender,"Hello");
        myArray.push(myElement);
        myMapping[10086]="World";
    }
}
# 测试

image-20230527132344158

# 函数类型

函数的声明:在 Solidity 中,函数通过以下形式进行声明:

function (参数)

[pure|constant|view|payable] [returns (返回值)]

[] 中的选项为可选的函数类型描述。

# 特殊变量

特殊变量的由来以太坊虚拟机提供了获取部分区块链信息的操作码,在 Solidity 中,相对应地,也预设了一些特殊变量和函数在 Remix 编译器中可尝试得到各个变量的返回值

常用特殊变量

block.blockhash (区块号参数):近 256 个区块哈希;

block.coinbase: 合约交易所处区块的矿工地址;

block.difficulty: 合约交易所处区块的挖矿难度;

block.gaslimit: 合约交易所处区块的 gasLimit;

block.number: 合约交易所处区块的高度;

block.timestamp: 合约交易所处区块的时间戳;

# 事件日志

以太坊事件树

以太坊采用了事件日志进行记录,有别于状态树,事件树是单向输出、不可被合约读取的事件树为上层应用提供了高效的查询方式,使得上层应用能够观察特定合约的特定动作的发生及其内容

# 错误处理

背景

与传统计算机程序类似,以太坊智能合约的运行过程中,也可能出现由开发者定义的异常或错误,例如发起交易的地址不具有调用该函数的权限等。因此,需要对合约运行中的交易进行处理。

以太坊错误处理

在以太坊智能合约中,一般而言,交易在发生异常后,其交易修改的所有状态都将被回滚、都是无效的。

低级调用函数产生异常

通过 Solidity 提供的低级调用函数(call、delegatecall、callcode)进行合约子调用时若产生异常将返回 false,从而不会将子调用之外修改的状态回滚。

以太坊底层实现

以太坊通过记录状态根进行状态回滚,在发生异常时回到交易执行前的状态根、且不记录日志。

Solidity 错误处理函数

assert (条件参数)

如果条件参数为 false,则使当前交易没有效果,并消耗交易剩余的 gas。

require (条件参数,[消息参数])

如果条件参数为 false,则撤销状态更改,并且,如果还传入了消息参数,则提供一个错误消息。

revert ([消息参数])

终止运行并撤销状态更改,如果还传入了消息参数,则提供一个错误消息。

# 私有链搭建

复习考试 等几天再补上

# 现在水龙头难搞,测试币都领不到力

image-20230523154742681