【区块链笔记】ETH_Solidity关键字(06)

Page content

这篇文章简单的整理了Solidity关键字

1.Solidity源文件布局

pragma (版本杂注)

  • 源文件可以被版本杂注pragma所注解,表明要求的编译器版本
  • 例如:pragma solidity ^0.4.0;
  • 源文件将既不允许低于 0.4.0 版本的编译器编译,
    也不允许高于(包含)0.5.0 版本的编译器编译(第二个条件因使用 ^ 被添加)

import(导入其它源文件)

  • Solidity所支持的导入语句import,语法同 JavaScript(从 ES6 起)非常类似

2.Solidity源文件布局– import

import “filename”
从“filename”中导入所有的全局符号到当前全局作用域中

import * as symbolName from “filename”
创建一个新的全局符号symbolName,其成员均来自 “filename” 中全局符号

import {symbol1 as alias, symbol2} from “filename”
创建新的全局符号alias和symbol2,分别从"filename"引用symbol1和symbol2

import “filename” as symbolName
这条语句等同于 import* as symbolName from “filename”;

3.Solidity值类型

布尔(bool)

可能的取值为字符常量值 true 或 false

整型(int/uint)

分别表示有符号和无符号的不同位数的整型变量; 支持 关键字 uint8 到 uint256(无符号,从 8 位到 256 位)以及int8到int256, 以8位为步长递增

定长浮点型(fixed / ufixed)

表示各种大小的有符号和无符号的定长浮 点型;
在关键字ufixedMxN和fixedMxN中,M表示该类型占用的位数,N表示可用的小数位数

地址(address)

存储一个 20 字节的值(以太坊地址大小)

定长字节数组

关键字有 bytes1, bytes2, bytes3, …, bytes32

枚举(enum)

一种用户可以定义类型的方法,与C语言类似,默认从0开始递增,一般用来模拟合约的状态

函数(function)

一种表示函数的类型

4.Solidity引用类型

数组(Array)

  • 数组可以在声明时指定长度(定长数组),也可以动态调整大小(变长数组、动态数组)
  • 对于存储型(storage)的数组来说,元素类型可以是任意的(即元素也可以是数组类型,映射类型或者结构体);
    对于内存型 (memory)的数组来说,元素类型不能是映射(mapping)类型

结构(Struct)

  • Solidity 支持通过构造结构体的形式定义新的类型

映射(Mapping)

• 映射可以视作哈希表,在实际的初始化过程中创建每个可能的key,并将其映射到字节形式全是零的值(类型默认值)

5. Solidity地址类型

address

地址类型存储一个20 字节的值(以太坊地址的大小);
地址类型也有成员 变量,并作为所有合约的基础

address payable(v0.5.0引入)

• 与地址类型基本相同,不过多出了 transfer 和 send 两个成员变量

两者区别和转换

  • Payable 地址是可以发送ether的地址,而普通address不能
  • 允许从payable address到address的隐式转换,
    而反过来的直接转换是不可能的(唯一方法是通过uint160来进行中间转换)
  • 从0.5.0版本起,合约不再是从地址类型派生而来,
    但如果它有payable的回退函数,那同样可以显式转换为address或者address payable类型

地址类型成员变量

<address>.balance (uint256)

该地址的ether余额,以Wei为单位

<address payable>.transfer(uint256 amount)

向指定地址发送数量为amount的ether(以Wei为单位),
失败时抛出异常,发送2300gas的矿工费,不可调节

<address payable>.send(uint256 amount) returns (bool)

向指定地址发送数量为amount的ether(以Wei为单位),
失败时返回false,发送2300gas的矿工费用,不可调节

<address>.call(bytes memory) returns (bool, bytes memory)

发出底层函数 CALL,失败时返回 false,发送所有可用 gas,可调节

<address>.delegatecall(bytes memory) returns (bool, bytes memory)

发出底层函数 DELEGATECALL,失败时返回 false,发送所有可用 gas,可调节

<address>.staticcall(bytes memory) returns (bool, bytes memory)

发出底层函数 STATICCALL ,失败时返回 false,发送所有可用 gas,可调节

地址成员变量用法

balance 和 transfer

可以使用balance属性来查询一个地址的余额,
可以使用transfer函数向一个payable地址发送以太币Ether(以wei为单位)

address payable x = address(0x123);
address myAddress = address(this);
if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);

send

send是transfer的低级版本。如果执行失败,当前的合约不会因为异常而终止,但send会返回false

call

也可以用call来实现转币的操作,通过添加.gas()和.value()修饰器:

nameReg.call.gas(1000000).value(1ether)(abi.encodeWithSignature("register(string)", "MyName"));

6.字符数组(Byte Arrays)

定长字符数组

  • 属于值类型,bytes1,bytes2,…,bytes32分别代表了长度为1到32的字节序列
  • 有一个.length属性,返回数组长度(只读)

变长字符数组

属于引用类型,包括 bytes和string,不同的是bytes是Hex字符串,而string是UTF-8编码的字符串

7.枚举(Enum)

  • 枚举类型用来用户自定义一组常量值
  • 与C语言的枚举类型非常相似,对应整型值
pragma solidity >=0.4.0 <0.6.0; 
contract Purchase {
    enum State { Created, Locked, Inactive } 
}

8.数组(Array)

  • 固定大小k和元素类型T的数组被写为T[k],动态大小的数组为T[]。
    例如,一个由5个uint动态数组组成的数组是uint[][5]
  • 要访问第三个动态数组中的第二个uint,可以使用x[2][1]
  • 越界访问数组,会导致调用失败回退
  • 如果要添加新元素,则必须使用.push()或将.length增大
  • 变长的storage数组和bytes(不包括string)有一个push()方法。
    可以将一个新元素附加到数组末端,返回值为当前长度
pragma solidity >=0.4.16 <0.6.0; 
contract C {
    function f(uint len) public pure {
        uint[] memory a = new uint[](7);
        bytes memory b = new bytes(len); 
        assert(a.length == 7); 
        assert(b.length == len);
        a[6] = 8;
    } 
}

9.结构(Struct)

  • 结构类型可以在映射和数组中使用,它们本身可以包含映射和数组。
  • 结构不能包含自己类型的成员,但可以作为自己数组成员的类型,也可以作为自己映射成员的值类型
pragma solidity >=0.4.0 <0.6.0; 
contract Ballot {
    struct Voter {
        uint weight;
        bool voted;
        uint vote; 
    }
}

10.映射(Mapping)

  • 声明一个映射:mapping(_KeyType =>_ValueType)
  • _KeyType可以是任何基本类型。这意味着它可以是任何内置值类型加上字节和字符串。
    不允许使用用户定义的或复杂的类型,如枚举,映射,结构以及除bytes和string之外的任何数组类型。
  • _ValueType可以是任何类型,包括映射。
pragma solidity >=0.4.0 <0.6.0;
contract MappingExample { 
    mapping(address => uint) public balances; 
    function update(uint newBalance) public {
        balances[msg.sender] = newBalance;
    }
}
contract MappingUser {
    function f() public returns (uint) {
        MappingExample m = new MappingExample();
        m.update(100);
        return m.balances(address(this));
    }
}

欢迎大家的意见和交流

email: li_mingxie@163.com