Solidity知识记录

153 阅读5分钟

「本文已参与「新人创作礼」活动,一起开启掘金创作之路。」

基本信息

虽然语法接近于JS

但是

1.有一个特殊的Address数据类型,用于定位用户、定位合约、定位合约的代码

2.支持支付,可以在语言的层面进行支付如payable关键字

3.可以将数据存储在区块链上,数据的每个状态都可以永久存储, 所以需要确定变量使用的是内存还是区块

4.所有的执行都将被回撤,这主要是为了保证智能合约执行的原子性, 以避免中间状态出现的数据不一致,有点类似于数据库中的事务回滚。

任何一个 Solidity 程序,都必须至少有一个合约 在合约中可以编写Solidity函数。

类似于类中的方法. Solidity源代码文件的扩展名是sol。

一个 Solidity 源文件可以包含任意数量的合约定义、import指令和pragma指令。

安装本地remix环境

1.不管是在什么操作系统下安装 Remix,都必须安装 Node.js 如果安装过了,那就使用 git命令下载 Remix 的代码库( browser-solidity)

git clone https://github.com/ethereum/browser-solidity

2.在 browser-solidity 目录中执行下面的命令安装

browser-solidity npm install

3.如果没有装node 就安装包的方式安装 [nodejs.cn/download/] 在终端中可以查看对应版本

node -v

npm -v

如果要卸载之前的node

brew uninstall npm

which npm #查找npm的位置 将其整个删除

which node #查找node的位置 将其整个删除

4.yarn安装

curl -o- -L https://yarnpkg.com/install.sh | bash

5.nvm安装

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash

查看安装是否成功: nvm -v

6.remix-ide安装

npm install remix-ide -g

如果报错 根据报错的信息去修改内容

#!/usr/bin/env node 
var path = require('path') 
var httpServer = require('http-server') 
var server = httpServer.createServer({ 
    root:path.join(__dirname,'/../') 
}) 
var folder = process.argv.length > 2 ? process.argv[2] : process.cwd() server.listen(8080, '127.0.0.1', function () {}) 
console.log('\x1b[33m%s\x1b[0m', 'Starting Remix IDE at http://localhost:8080 and sharing ' + folder)

3.之后再次安装

sudo npm install remix-ide -g

remix-ide #启动本地remix环境

4.之后就可以访问localhost:8080

语法

Progma

pragma solidity >=0.4.0 <0.6.0; 表示 源代码是为Solidity version 0.4.0及以上版本编写的, 但不包括version 0.6.0及以上版本 pragma solidity ^0.4.0; 表示 源文件不能用低于0.4.0版本的编译器编译 pragma指令可以在 Solidity源代码文件中出现多次, 可以出现在合约(contract)外的任何位置, 不管使用多少次pragma指令,有效的总是指定Solidity编译器版本最高的pragma指令

导入文件

import "filename"; 
导入之后 进行使用 
using strings for *;//使用 strings.sol 中的名为 strings 的库 
import * as name from "filename"; 
name表示合约的全局名称 filename表示合约文件名

构造函数

construct() public { }

库(library)和合约(contract)的区别在于,库不能有fallback函数和payable关键字也不能定义storage变量 但是库可以修改和他们想链接的合约的storage变量 例如合约调用库的时候 传入的类型到库之后 库会进行修改 库不能有日志(Event),但是可以分发时间

不支持switch和goto语句,条件判断的括号不可以省略,单行语句中的打括号可以去掉

防止栈溢出:定义太多的本地变量,或者输入大于16的参数和变量 减少变量的使用,使函数尽量小,变量封装到结构体或者数组中,或者采用memory

变量类型

分成两类:固定大小的变量和动态变量

在合约里声明并且不属于任何函数的 都是状态变量

变量类型有以下几大类

1.值类型

int/uint (uint和int默认代表的是 uint256 / int256)

int8256/uint8256

fixed/ufixed 定长浮点型/无符号

fixedM(8256)xN(080)/ufixedM(8256)xN(080)

(M表示按类型取的位数,N表示小数点。 M应该能被8整除,从8到256。 N可以是0到80。 fixed与fixed128x18相同)

2.地址类型

地址类型表示以太坊地址,长度为20字节(20B(字节) 160bit(比特))

.balance方法获得余额 .transfer方法将余额转到另一个地址

3.引用类型

数组 (字符串与bytes是特殊的数组,所以也是引用类型)

struct (结构体)

map (映射) bytes 如果不在

bytes后面加 1~32 的数字,byte等于 bytes1 那么bytes就是一个可变长度的字节序 列, 而bytes不再是值类型,而且是引用类型, 可以使用bytes类型保存任意长度的数据。

变量作用域

1.Public

公共状态变量可以在内部访问,也可以通过消息访问。 对于公共状态变量,将生成一个自动getter函数

2.Internal

内部状态变量只能从当前合约或其派生合约内访问

3.Private

私有状态变量只能从当前合约内部访问,派生合约内不能访问

数据位置

1.storage 存储永久数据,可以被合约中的所有函数访问,相当于存储在磁盘中,所有数据都永久存储 存储区数据位置的成本较高

2.memory

本地内存变量

内存位置是临时数据,比存储位置便宜。

它只能在函数中访问 通常用于保存临时变量,一旦函数执行完毕,它的内容就会被丢弃 函数参数和返回值都是memory 基本类型默认memory 复杂类型默认是storage

3.calldata

所有函数调用的数据,包括函数参数的保存位置,不可修改

不可修改的非持久性数据位置,所有传递给函数的值,都存储在这里(实参)

4.stack

EVM维护的非持久性数据

总结:

函数参数包括返回的是memory,

默认的局部变量是storage

默认的状态变量(合约声明的公有变量) storage

复杂类型的数据存储位置可选storage 或 memory

变量的数据位置规则

1.状态变量

总是存储在存储区中,并且不能去声明规定位置 比如 uint memory number ;

2.函数参数与返回值

函数参数包括返回参数都存储在内存中

3.局部变量

值类型的局部变量存储在内存,如果是引用类型的局部变量就要声明数据位置

4.外部函数的参数

外部函数的参数(不包括返回参数)存储在Calldata中

赋值的数据位置规则

需要注意的是 存放在内存位置的引用变量赋值给引用变量内存位置 原先的赋值给新的之后 变化原先的内容 输出原先的会产生变化 新的同样也会 因为此时指向同一个位置 除此之外 存放在内存位置的值类型变量还有其他类型的变量 在赋值之后在去操作旧的数据 也不会导致新数据的变化