欢迎光临散文网 会员登陆 & 注册

Lesson 2: Welcome to Remix! Simple Storage

2023-03-06 18:14 作者:KID-Freak  | 我要投稿

第一行

Solidity 第一行用注释来写SPDX License Identifier

虽然是可选的,但是有些编译器会出现警告

用来定义license和代码分享规则

//SPDX-License-Identifier:MIT

MIT是限制最少的license之一,大多数代码都是用MIT

第二行

solidity是一个更新迭代比较快的语言,因此sol文件第二行用来声明版本

如下明确声明了只使用0.8.7版本

pragma solidity 0.8.7; // 使用双斜线进行注释,第一行是声明使用solidity的版本

同时也可以在0.8.7前面添加一个^ 用来声明此代码运行环境能在0.8.7及之后运行

pragma solidity ^0.8.7;

如果用一个区间表示,用如下方式表示本代码运行环境位于以下区间

pragma solidity >=0.8.7 <0.9.0; //表示0.8.7 0.8.8 0.8.9适用但0.9.0不适用

智能合约的开始

使用 contract 用来高速编译器后面的代码是定义智能合约的。contract 是智能合约的关键之之一。

类似于java 的 class  

//SPDX-License-Identifier:MIT pragma solidity 0.8.7; // 使用双斜线进行注释,第一行是声明使用solidity的版本 contract SimpleStorage { }

值类型

类型

描述

运算符

bool

布尔类型 true、false

  • ! (逻辑非)

  • && (逻辑与, “and” )

  • || (逻辑或, “or” )

  • == (等于)

  • != (不等于)

int/uint

分别表示有符号和无符号的不同位数的整型变量。 支持关键字 uint8uint256 (无符号,从 8 位到 256 位)以及 int8int256,以 8 位为步长递增。 uintint 分别是 uint256int256 的别名。最大uint256,默认也是uint256。通常开发时把分配空间写出来。 uint8表示分配了8个bit,二进制表示为11111111 8个1,所以最大能表示255。256就不能用uint8声明了。

  • 比较运算符: <=<==!=>=> (返回布尔值)

  • 位运算符: &|^ (异或), ~ (位取反)

  • 移位运算符: << (左移位) , >> (右移位)

  • 算数运算符: +- , 一元运算负 - (仅针对有符号整型), */% (取余或叫模运算) , ** (幂)

address

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

address payable

可支付地址,与 address 相同,不过有成员函数 transfersend

举例:

bool hasFavoriteNumber = true; uint8 favoriteNumber = 123; uint number = 123;

函数

//SPDX-License-Identifier:MIT pragma solidity 0.8.7; // 使用双斜线进行注释,第一行是声明使用solidity的版本 contract SimpleStorage {    int8 public number = 123;        //函数    function changeNumber (int8 _number) public {        number = _number;    } }

函数用 function 声明,类似于js。但要在后面跟一个访问修饰符

一共有四个访问修饰符

  • public:内部、外部均可见(参考为存储/状态变量创建 getter 函数)

  • private:仅在当前合约内可见

  • external:仅在外部可见(仅可修饰函数)——就是说,仅可用于消息调用(即使在合约内调用,也只能通过 this.func 的方式)

  • internal:仅在内部可见。只有这个合约或集成他的合约能读取(也就是在当前 Solidity 源代码文件内均可见,不仅限于当前合约内,译者注)

变量的默认访问修饰符时 internal

gas消耗

执行上面代码后,可以在控制台看到所消耗的gas是2472 gas

当在函数中添加一行 number = number +1 时,执行相同操作,可以看到消耗的gas增加了更多

solidity有两个关键字,标识函数调用不需要消耗gas。分别是 viewpure

在区块链中,只有更改状态的时候才支付gas,发起交易。

如下图,number 和 review 是蓝色,而 changeNumber是黄色,下图中有gas

下面的number调用记录就没有gas一行

上图中的 execution cost 2472 gas (Cost only applies when called by a contract) 表示调用这个函数所需要花费的gas

   function review() public view returns (int8){        return number;    }

view 表示只会读取这个合约的状态。如上面的review函数,只能读取number并返回。不允许修改任何状态。pure 也不允许修改任何状态。但 pure 还不允许读取区块链上的数据。所以用 pure 修饰不能读取number。

pure 修饰的方法类似于下面,可能是常用的方法,或者是某个不需要读取数据的算法。

function add() public pure returns (int256){    return (1 + 1); }int8 public number = 123; //带有public的变量可以看作是一个返回int8的view函数

结构体

一个简单的结构体示例

//定义 struct People{    int8 number;    string name; } //使用 People public person1 = People({number:2,name:"furao"});

部署合约后,点击 person1 可以看到

(在solidity中的结构体可以先使用后声明,同js一样)

数组

//声明一个动态数组(因为没有规定他的大小) People[] public peoples; //如果在中括号里加一个数字,则声明这个数组中大小是3,不可变 People[3] public peoples;

向数组中添加数据

   //定义    struct People{        int8 number;        string name;    }        //声明一个动态数组(因为没有规定他的大小)    People[] public peoples;    //向数组中添加一个数据    function addPerson (string memory _name,int8 _number) public {        //写法1        People memory newPerson = People({name:_name,number:_number});        peoples.push(newPerson);                //写法2 省略中间变量new Person        peoples.push(People({name:_name,number:_number}));                //写法3 根据people属性的顺序直接添加。同java,但没有new字        peoples.push(People(_number,_name));    }        

将代码放入编译器,运行

memory、storage、calldata

上述 addPerson 方法中,声明入参的时候有一个 memory 进行描述。如果删了它,则会编译报错。

TypeError: Data location must be "memory" or "calldata" for parameter in function, but none was given.

目前在solodity中,有6种方式进行存储数据

stake

memory

storage

calldata

code

logs

临时变量有 memorycalldatacalldata不能被修改(赋值)。memory 可以被修改。storage 是用永久变量。

     function addPerson (string memory _name,int8 _number) public {        //比如在这里,用memory声明的_name 可以被再次赋值        _name = "cat";       //如果使用calldata 声明 _name, 则上句话会报错    }        

那么在 addPerson 的入参中,为什么 _number 不用  memorycalldata 修改?

data location 只适用于数组,结构体或映射类型。因为 string 实际上是数组,所以需要用 datalocation 修饰

Mapping

功能同java的map

声明和使用:

   //声明一个mapping    mapping(string => int8) public nameAndNumber;        //使用    function addPerson (string memory _name,int8 _number) public {        nameAndNumber[_name] = _number;    }


Lesson 2: Welcome to Remix! Simple Storage的评论 (共 条)

分享到微博请遵守国家法律