Solidity官方文档摘抄

2018-10-25笔记


这篇笔记是对官方文档一些内容的提取。顺序是从Introduction to Smart Contracts开始到Solidity In Depth章节结束。

访问状态变量

The keyword public automatically generates a function that allows you to access the current value of the state variable from outside of the contract.

在声明状态变量的时候,使用public关键字,编译器会自动帮你生成getter函数帮助你在外部访问这个变量。如果自己定义一个如下函数,

function minter() external view returns (address) {
    return minter; 
}

因为状态变量跟方法名一样,因此这样做是没有用的。


Mapping的概念

Mappings can be seen as hash tables which are virtually initialized such that every possible key exists from the start and is mapped to a value whose byte-representation is all zeros.

对于这段话我的理解是,solidity作为一个静态语言,在编译阶段就要确定变量的数据类型,为其分配内存空间。因此映射类型可以看作是一个很大的哈希表,已经包含了几乎所有可能存在的键,然后每一个键映射到0。


交易上链

Transactions are not guaranteed to be included in the next block or any specific future block, since it is not up to the submitter of a transaction, but up to the miners to determine in which block the transaction is included.
If you want to schedule future calls of your contract, you can use the alarm clock or a similar oracle service.

交易上链时间取决于矿工的打包的时间,而不是交易发起人的交易发起时间,如果要知道交易几时上链,可以通过使用回调的方式来获取(之前开发智能合约的时候,用来打印合约地址的提示语)


计算合约地址

the address of a contract is determined at the time the contract is created (it is derived from the creator address and the number of transactions sent from that address, the so-called “nonce”).

合约地址可以通过交易的from与交易编号计算出来,黄皮书好像有这个算法。


账户的storage空间

Every account has a persistent key-value store mapping 256-bit words to 256-bit words called storage.

无论是外部账户(即我们平时用的,存有Eth的账户),还是合约账户都有storage内存空间。


文件导入
  1. import "filename";
    This statement imports all global symbols from “filename” into the current global scope。
  2. The following example creates a new global symbol symbolName whose members are all the global symbols from "filename".
    import * as symbolName from "filename";

第一种做法,会将filename中的所有符号导入当前命名空间,存在命名空间污染的问题,类似于Python的from module import *。第二种做法,将文件中的符号导入到一个该文件的一个新的命名空间中。


整数的相反数
  1. The expression -x is equivalent to (T(0) - x) where T is the type of x. This means that -x will not be negative if the type of x is an unsigned integer type.
  2. There is another caveat also resulting from two’s complement representation:
    int x = -2**255;
    assert(-x == x);
  3. Exponentiation is only available for unsigned types.

无符号整数的相反数一定也是非负数;
符号整数中,正数相反数一定是负数,但负数相反数不一定是正数。以uint8为例,其中最小的负数是-128,最大的正数是127,那么-(-128)=128128导致溢出到最小值,也就是-128(从二进制表示的角度看,也可以很容易理解,-1271000000012701111111,则127+1就是b01111111 + b00000001 = b10000000),因此上面会有assert(-x == x)
科学记数法只用于无符号整数。


地址变量

The idea behind this distinction is that address payable is an address you can send Ether to, while a plain address cannot be sent Ether.
Address literals can be implicitly converted to address payable.
It might very well be that you do not need to care about the distinction between address and address payable and just use address everywhere.

Solidity0.5有两种地址变量,一种是address,另一种是address payable,后者带有transfer()send()可以用来发送比特币。地址字面值(相当于硬编码时候用的字符串,如0x123)可以隐式转换成address payable类型。编程时使用address即可,不用理会他们的区别。


授权调用

the function delegatecall can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, …) are taken from the current contract.

使用delegatecall的时候,代码是从别的合约拿的,其他的(storagebalance等)都是从当前合约中获取。delegatecall主要用于调用library中的代码。


字面值的运算精度

Number literal expressions retain arbitrary precision until they are converted to a non-literal type.
((2**800 + 1) - 2**800) == 1
(.5 * 8) == 4

使用字面值进行计算的时候,可以获得任意的精度,直到将他们赋值给未字面值的变量。意思是,uint a=2**800的时候,精度就会损失,因为a的字节已经限定好了为32字节。


整数除法

Division on integer literals used to truncate in Solidity prior to version 0.4.0, but it now converts into a rational number, i.e. 5 / 2 is not equal to 2, but to 2.5.

在0.5版本前,整数除法是直接截断小数部分,0.5之后会保留小数。


隐式转换

Disregarding types, the value of the expression assigned to b below evaluates to an integer. Because a is of type uint128, the expression 2.5 + a has to have a proper type, though. Since there is no common type for the type of 2.5 and uint128, the Solidity compiler does not accept this code.

uint128 a = 1;
uint128 b = 2.5 + a + 0.5;

只有数据类型一致才可以进行算术运算,因此第二行的代码,因为在进行2.5 + a的时候,需要将2.5uint128之间进行转换,但是小数与整数之间有没有一个通用类型可以进行隐式转换,因此会导致编译不通过。

带符号整型 <=> 无符号整型

In general, an implicit conversion between value-types is possible if it makes sense semantically and no information is lost: uint8 is convertible to uint16 and int128 to int256, but int8 is not convertible to uint256 (because uint256 cannot hold e.g. -1).

这里说明了,无符号整数可以通过隐式转换成带符号整数,但是带符号整数不可以隐式转换成无符号整数,比如无符号整数没有-1

隐式转换.png

数值字面值 => 整型

Decimal and hexadecimal number literals can be implicitly converted to any integer type that is large enough to represent it without truncation.

十进制数与十六进制数的字面值,如果要转换成任何一种整数类型,必须要长度合适,如下所示:

uint8 a = 12; // fine
uint32 b = 1234; // fine
uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456
隐式转换2.png
数值字面值 => bytes

Decimal number literals cannot be implicitly converted to fixed-size byte arrays.
Hexadecimal number literals can be, but only if the number of hex digits exactly fits the size of the bytes type.
As an exception both decimal and hexadecimal literals which have a value of zero can be converted to any fixed-size bytes type.

要想从数值字面值转换成bytes,需要符合bytes的长度,其中十进制数只有0可以转换,举例如下:

bytes2 a = 54321;    // 不可以使用非0十进制
bytes2 b = 0x12;     // 字节长度不对应,0x12是1个字节
bytes2 c = 0x123;    // 字节长度不对应,0x123算是1个半字节
bytes2 d = 0x1234;   // fine
bytes2 e = 0x0012;   // fine
bytes4 f = 0;        // fine
bytes4 g = 0x0;      // fine

数组访问越界

Accessing elements outside the current length does not automatically resize the array and instead causes a failing assertion. Increasing the length adds new zero-initialised elements to the array. Reducing the length performs an implicit :ref:delete on each of the removed elements.

越界访问动态数组,不会使数组自动增长,反而会导致异常使交易回滚。调节数组长度要通过修改.length值来设置数组大小。增大.length会增加初始化为0的元素,减小.length相当于对末尾元素调用delete

delete

delete a assigns the initial value for the type to a.
I.e. for integers it is equivalent to a = 0, but it can also be used on arrays, where it assigns a dynamic array of length zero or a static array of the same length with all elements reset.For structs, it assigns a struct with all members reset.

对一个变量使用delete,实际上就是他赋值为初始值(因此对于指针类型要注意,他只会把指针重置,但是不会对其所指向的元素调用delete)。比如uint a,他的默认初始值使0,那么delete a等价于a = 0delete arr则将数组长度设置为0,对于元素就是逐个地调用delete

对Mapping使用delete

delete has no effect on mappings (as the keys of mappings may be arbitrary and are generally unknown). So if you delete a struct, it will reset all members that are not mappings and also recurse into the members unless they are mappings. However, individual keys and what they map to can be deleted: If a is a mapping, then delete a[x] will delete the value stored at x.

Mapping调用delete是没有任何影响的,但是对Mapping的某个键值对delete,则发生的与上面所述的一致。对struct调用delete的时候,会遍历所有的非Mapping元素,并且会递归的执行。


struct不允许自包含

It is not possible for a struct to contain a member of its own type, although the struct itself can be the value type of a mapping member or it can contain a dynamically-sized array of its type.


Bytes与Strings

As a rule of thumb, use bytes for arbitrary-length raw byte data and string for arbitrary-length string (UTF-8) data. If you can limit the length to a certain number of bytes, always use one of bytes1 to bytes32 because they are much cheaper.

Bytes与Strings的区别就相当于,Python3中Bytes和String的区别。


数组字面值

The type of an array literal is a memory array of fixed size whose base type is the common type of the given elements.The type of [1, 2, 3] is uint8[3] memory, because the type of each of these constants is uint8. Because of that, it is necessary to convert the first element in the example above to uint.
Note that currently, fixed size memory arrays cannot be assigned to dynamically-sized memory arrays, i.e. the following is not possible:

// The next line creates a type error because uint[3] memory
// cannot be converted to uint[] memory.
uint[] memory x = [uint(1), 3, 4];

首先一点是数组字面值是输入memory的;第二,数组中的整型字面值默认是uint8;第三,数组字面值不可以赋值给动态数组变量。


函数返回值

Return parameters can be used as any other local variable and they are zero-initialized; if they are not explicitly set, they stay zero.

函数返回值可以作为函数的局部变量使用,并且默认初始化为0


IF判断

Note that there is no type conversion from non-boolean to boolean types as there is in C and JavaScript, so if (1) { ... } is not valid Solidity.

非布尔类型不会隐式转换成布尔类型!因此条件判断的时候,要通过逻辑操作符等返回布尔值。

0.5版本的FOR循环

Variables declared in the initialization part of a for-loop are only visible until the end of the for-loop.

For初始化部分声明的变量,仅在For循环中可见,For循环结束后,变量就不存在了。

pragma solidity >0.4.99 <0.6.0;
contract hello {
        function f() pure public {
            int j;
            int k;
            for(int i=0; i < 10; i++) {
                j++;
            }
            k = i + 1;
        }
}
for循环外引用变量.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • 人们常说,你今天所流的泪,都是以前脑子里进的水。以前感觉这句话挺玩笑的,现在却觉得它说的是那么真。自己现在流的泪就...
    岳妹妹阅读 208评论 0 0
  • 我一直想写你,写纤纤葱根轻执金扇立于百花深处眼波流转的你,写飘飘青玉回眸一笑站在万人群中绝世独立的你,写脉脉秋水粉...
    梅琜卿阅读 3,008评论 12 22
  • 其实,你一直都在 邹阳 (这个娃有点像蓉儿!不信,你看!) 阳光下,一个胖胖的少年熟练的打着篮球。靠近篮球场的大树...
    为为道来阅读 403评论 0 2
  • 他有气无力的斜卧在两米大的床上,你只要看他一眼,那僵硬的姿势就能让你猜到:他已经带着呆滞的眼神面对天花板下悬挂着的...
    慢慢悠阅读 299评论 0 0