区块链开发之Solidity编程基础
Posted BBinChina
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区块链开发之Solidity编程基础相关的知识,希望对你有一定的参考价值。
概要
由ETH为代表的第二代区块链技术,相比于第一代区块链技术而言,最大的特点就是智能合约的出现,让去中心化应用成为了可能。ETH节点为智能合约提供运行环境:EVM(Ethereum Virtual Machine)以太坊虚拟机。EVM是一个动态运行沙盒,可以将以太坊上所有的智能合约和周围环境全部隔离。因此,EVM上运行的智能合约无法访问网络、文件系统或者在EVM上运行的其他进程。
Solidity是一个基于合约高级编程语言,它是静态类型语言,支持继承、库和复杂的用户定义两类型等功能。它可以被编译成EVM的汇编语言,从而被链上的节点所执行。其他语言还有Serpent、Vyper和LLL,同样可被编程成EVM的汇编语言从而在其节点上运行。
solidity的IDE环境可使用:Remix
sol文件结构
编译开发
pragma关键字沿用c、c++编译指令概念。
pragma solidity ^0.4.0;
以上指令表明编译器版本需要高于0.4.0才可编译。
pragma solidity >= 0.4.22 < 0.6.0;
可以使用更复杂的规则来指定编译器的版本,表达式遵循 npm 版本语义。
引入其他文件
1、全局引入:
import "filename";
2、自定义命名空间
此语句将从 “filename” 中导入所有的全局符号到当前全局作用域中(不同于 ES6,Solidity 是向后兼容的)。
import * as symbolName from "filename";
…创建一个新的全局符号 symbolName,其成员均来自 “filename” 中全局符号。
另一种语法不属于 ES6,但或许更简便:
import "filename" as symbolName;
3、多包引入
import symbol1 as alias, symbol2 from "filename";
创建新的全局符号 alias 和 symbol2,分别从 “filename” 引用 symbol1 和 symbol2 。
4、路径
上文中的 filename 总是会按路径来处理,以 /
作为目录分割符、以 .
标示当前目录、以 ..
表示父目录。 当 .
或 ..
后面跟随的字符是 /
时,它们才能被当做当前目录或父目录。 只有路径以当前目录 .
或父目录 ..
开头时,才能被视为相对路径。
用 import "./x" as x;
语句导入当前源文件同目录下的文件 x 。 如果用 import "x" as x;
代替,可能会引入不同的文件(在全局 include directory 中)。
Remix 提供一个为 github 源代码平台的自动重映射,它将通过网络自动获取文件: 比如,你可以使用 import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;
导入一个 map 迭代器。
关于编译器的路径配置可以根据自己的编译器进行查找
注释
代码注释
// 这是一个单行注释。
/*
这是一个
多行注释。
*/
文档注释
pragma solidity ^0.4.0;
/** @title 形状计算器。 */
contract shapeCalculator
/** @dev 求矩形表明面积与周长。
* @param w 矩形宽度。
* @param h 矩形高度。
* @return s 求得表面积。
* @return p 求得周长。
*/
function rectangle(uint w, uint h) returns (uint s, uint p)
s = w * h;
p = 2 * (w + h);
合约
在 Solidity 中,合约类似于面向对象编程语言中的类。 每个合约中可以包含 状态变量、 函数、 函数修饰器、事件、 结构类型、 和 枚举类型 的声明,且合约可以从其他合约继承。
采用关键字 contract声明
pragma solidity ^0.4.0;
contract ContractExample
状态变量
状态变量是永久地存储在合约存储中的值,在合约里声明而不属于任何函数的都是状态变量。
pragma solidity ^0.4.0;
contract SimpleStorage
uint storedData; // 状态变量
// ...
类型
Solidity 是一种静态类型语言,这意味着每个变量(状态变量和局部变量)都需要在编译时指定变量的类型(或至少可以推导出变量类型 – 类型退到)。 Solidity 提供了几种基本类型,可以用来组合出复杂类型。
值类型
以下类型也称为值类型,因为这些类型的变量将始终按值来传递。 也就是说,当这些变量被用作函数参数或者用在赋值语句中时,总会进行值拷贝。
1、 布尔类型
bool
:可能的取值为字面常数值 true
和 false
。
运算符:
!
(逻辑非)
&&
(逻辑与, “and” )
||
(逻辑或, “or” )
==
(等于)
!=
(不等于)
运算符 ||
和 &&
都遵循同样的短路( short-circuiting )规则。就是说在表达式 f(x) || g(y) 中, 如果 f(x) 的值为 true ,那么 g(y) 就不会被执行,即使会出现一些副作用。
2、整型
int / uint
:分别表示有符号和无符号的不同位数的整型变量。 支持关键字 uint8
到 uint256
(无符号,从 8 位到 256 位)以及 int8
到 int256
,以 8 位为步长递增。 uint
和 int
分别是 uint256
和 int256
的别名。
运算符:
比较运算符: <= , < , == , != , >= , > (返回布尔值)
位运算符: & , | , ^ (异或), ~ (位取反)
算数运算符: + , - , 一元运算 - , 一元运算 + , * , / , % (取余) , ** (幂), << (左移位) , >> (右移位)
除法总是会截断的(仅被编译为 EVM 中的 DIV 操作码), 但如果操作数都是 字面常数(literals) (或者字面常数表达式),则不会截断。
除以零或者模零运算都会引发运行时异常。
移位运算的结果取决于运算符左边的类型。
表达式 x << y 与 x * 2**y
是等价的, x >> y 与 x / 2**y
是等价的。这意味对一个负数进行移位会导致其符号消失。 按负数位移动会引发运行时异常。
3、地址
address
:地址类型存储一个 20 字节的值(以太坊地址的大小)。 地址类型也有成员变量,并作为所有合约的基础。
运算符:<=, <, ==, !=, >= 和 >
ps:
从 0.5.0 版本开始,合约不会从地址类型派生,但仍然可以显式地转换成地址类型。
关于地址类型相关内容,在后文介绍
4、定长字节数组
关键字有:bytes1, bytes2, bytes3, ..., bytes32
。byte 是 bytes1
的别名。
可以通过16进制字面量或者数字字面量来设定bytesi:
bytes1 aa = 0x30; //16进制字面量
bytes2 bb = 10; //数字字面量
也可通过字符来设定bytesi:
bytes1 dd = ‘a’;
运算符:
比较运算符:<=, <, ==, !=, >=, > (返回布尔型)
位运算符: &, |, ^ (按位异或), ~ (按位取反), << (左移位), >> (右移位)
索引访问:如果 x 是 bytesI 类型,那么 x[k] (其中 0 <= k < I)返回第 k 个字节(只读)
。
该类型可以和作为右操作数的任何整数类型进行移位运算(但返回结果的类型和左操作数类型相同),右操作数表示需要移动的位数。 进行负数位移运算会引发运行时异常。
成员变量:
.length
表示这个字节数组的长度(只读).
5、有理数和整型字面量
- 整数字面量:1,10,-1,-100
- 字符字面量:“test”、‘test’,双引号或者单引号都可以
- 地址字面量:0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF
- 16进制字面量,以0x为前缀:0x9aaa
- 数字字面量:7.5,0.2
整数字面常数由范围在 0-9 的一串数字组成,表现成十进制。 例如,69 表示数字 69。 Solidity 中是没有八进制的,因此前置 0 是无效的。
十进制小数字面常数带有一个 .
,至少在其一边会有一个数字。 比如:1.
,.1
,和 1.3
。
科学符号也是支持的,尽管指数必须是整数,但底数可以是小数。 比如:2e10, -2e10, 2e-10, 2.5e1
。
数值字面常数表达式本身支持任意精度,除非它们被转换成了非字面常数类型(也就是说,当它们出现在非字面常数表达式中时就会发生转换)。 这意味着在数值常量表达式中, 计算不会溢出而除法也不会截断。
例如, (2800 + 1) - 2800 的结果是字面常数 1 (属于 uint8 类型),尽管计算的中间结果已经超过了 以太坊虚拟机Ethereum Virtual Machine(EVM) 的机器字长度。 此外, .5 * 8
的结果是整型 4 (尽管有非整型参与了计算)。
只要操作数是整型,任意整型支持的运算符都可以被运用在数值字面常数表达式中。 如果两个中的任一个数是小数,则不允许进行位运算。如果指数是小数的话,也不支持幂运算(因为这样可能会得到一个无理数)。
6、枚举类型
pragma solidity ^0.4.0;
contract test
enum ActionChoices GoLeft, GoRight, GoStraight, SitStill
ActionChoices choice;
ActionChoices constant defaultChoice = ActionChoices.GoStraight;
function setGoStraight() public
choice = ActionChoices.GoStraight;
// 由于枚举类型不属于 |ABI| 的一部分,因此对于所有来自 Solidity 外部的调用,
// "getChoice" 的签名会自动被改成 "getChoice() returns (uint8)"。
// 整数类型的大小已经足够存储所有枚举类型的值,随着值的个数增加,
// 可以逐渐使用 `uint16` 或更大的整数类型。
function getChoice() public view returns (ActionChoices)
return choice;
function getDefaultChoice() public pure returns (uint)
return uint(defaultChoice);
7、函数类型
函数类型是一种表示函数的类型。
- 可以将一个函数赋值给另一个函数类型的变量
- 也可以将一个函数作为参数进行传递
- 还能在函数调用中返回函数类型变量。
函数类型有两类:- 内部(internal) 函数和 外部(external) 函数:
- 内部函数
只能在当前合约内被调用(更具体来说,在当前代码块内,包括内部库函数和继承的函数中),因为它们不能在当前合约上下文的外部被执行。 调用一个内部函数是通过跳转到它的入口标签来实现的,就像在当前合约的内部调用一个函数。
- 外部函数
由一个地址和一个函数签名组成,可以通过外部函数调用传递或者返回。
函数类型表示成如下的形式
function (<parameter types>) internal(默认)|external [pure|constant|view|payable] [returns (<return types>)]
如果没有返回结果,则必须省略return
关键字
以上是关于区块链开发之Solidity编程基础的主要内容,如果未能解决你的问题,请参考以下文章