【一步步一起学DApp开发】(三)Solidity语言讲解 | 用Solidity编写智能合约 上

简介: 【一步步一起学DApp开发】(三)Solidity语言讲解 | 用Solidity编写智能合约


有好几种语言可以用于编写以太坊智能合约,不过Solidity是最热门的语言。在本章中,我们将首先学习Solidity编程语言。然后创建一个DApp,用于证明在特定时间的存在、真实性和所有权,即证明一个文件在一个特定时间属于一个特定所有者。

要点:

  • Solidity源文件的布局
  • 理解Solidity的数据类型
  • 合约的特殊变量和函数
  • 控制结构
  • 合约的结构和功能
  • 编译和部署合约

Solidity源文件

Solidity源文件使用的扩展名为.sol。这里面我们使用的是0.4.2版本。

智能合约的结构

合约就像一个类(class),其中包含:

  • 状态变量(state variable)
  • 函数(function)
  • 函数修改器(function modifier)
  • 事件(event)
  • 结构(structure)
  • 枚举(enum)

同时,合约还支持继承与多态。

示例:

contract Sample
{
  //状态变量
  uint256 data;
  address owner;
  //定义事件
  event logData(uint256 dataToLog);
  //函数修改器
  modifier onlyOwner() {
    if(msg.sender!=owner) throw;
  }
  //构造器,名字与合约名一致
  function Sample(uint256 initData,address initOwner) {
    data = initData;
    owner = initOwner;
  }
  //函数
  function getData() returns (uint256 returnedData) {
  return data;  
  }
  function setData() returns (uint256 newData) onlyOwner {
    logData(newData);
    data = newData;
  }
}

代码注释:

  • contract 关键字:用于声明一个合约
  • data和owner:是两个状态变量。data包含一些数据,owner包含所有者的以太坊钱包地址,即部署合约者的以太坊地址
  • event logData 定义事件logData,用于通知客户端:一旦data发生变化,将触发这个事件。所有事件都保存在区块链中。
  • 函数修改器:onlyOwner。修改器用于在执行一个函数之前自动检测文件。这里的修改器用于检测合约所有者是否在调用函数。如果没有,则会抛出异常。
  • 合约函数构造器constructor:在部署合约时,构造器用于初始化状态变量。
  • function,getData()用于得到data状态变量的值,setData()用于改变data的值。

数据位置(较难理解)

通常,变量会存储在内存中。但是,在Solidity中,会根据不同的情况,变量可能会不存储在内存和文件系统中。

通常,在Solidity中,数据有一个默认位置。通常,存储有一个storage位置和一个memory位置,即本地存储与内存存储。

函数参数,包括其返还参数,默认用memory,本地变量默认用storage,例如状态变量,其数据位置强制使用storage。

注意:

  • 不能把memory中存储的复杂类型分配给storage;

###什么是不同的数据类型

首先明白3点;

  • Solidity是一种静态类型语言,变量存储的数据类型需要预先定义。
  • 所有变量默认值都是0。
  • 在Solidity中,变量是有函数作用范围的,也就是说,在函数中任何地方声明的变量将对整个函数存在适用范围。

那么Solidity提供了哪些数据类型——》

基本类型

除了数组类型、字符串类型、结构类型、枚举类型和map类型外,

其他类型均称为基本类型。

  • 无符号型:例如uint8,uint16,uint24,…,uint256分别用于存储无符号的8位,16
    位,24位,…,256位整数
  • 有符号型:例如,int8,int16,…,int256分别用于存储8位,16位,24位,…,256位整数
  • address类型:用于存储以太坊地址,用16进制表示。address类型有两个属性:balance和send。balance用于检测地址余额,send用于向地址发送以太币。send方法拿出需要转账那
    些数量的wei,并根据转账是否成功返回true或者false。

注意:

  • uint和int是uint256和int256的别名。
  • 如果一个数字超过256位,则使用256位数据类型存储该数字的近似值。
  • 数组:Solidity支持generic和byte两种数组类型。

数组有length属性,用于发现数组的长度。

注意:不可以在内存中改变数组大小,也不可以改变非动态数组大小。

字符串类型

有两种方法创建字符串:使用bytes和string。

bytes用于创建原始字符串,而string用于创建UTF-8字符串

示例:

contract sample {
    string myString = "";// string
    bytes myRawString;
    function sample(string initString,bytes rawStringInit) {
        myString = initString;
        string storage myString2 = myString;
        string memory myString3 = "ABCDE";
        myString3 = "imaginecode";
        myRawString = rawStringInit;
        myRawString.length++;
    }
}

结构类型struct

示例

contract sample {
  struct myStruct {
    bool myBool;
    string myString;
  }
  myStruct s1;
  myStruct s2 = myStruct{true,""}; 
  function sample(bool initBool,string initString){
    s1 = myStruct(initBool,initString);
    myStruct memory s3 = myStruct(initBool,initString);
  }
}

注意:函数参数不可以是结构类型,且函数不可以返回结构类型。

枚举类型 enum

示例

contract sample {
    enum OS {OSX, Linux,Unix,windows }
    OS choice;
    function sample(OS chosen) {
        choice = chosen;
    }
    function setLinux() {
        choice = OS.Linux;
    }
    function getChoice return (OS chosenOS) {
        return choice;
    }
}

mapping 类型

  • mapping类型只可以存在于storage中,不存在于memory中,因此它们是作为状态变量声明的。
  • mapping类型包含key/value对,不是实际存储key,而是存储key的keccak256哈希,用于查询value。
  • mapping不可以被分配给另一个mapping。
constract sample {
  mapping (int => string) myMap;
  function sample(){
    myMap[key] = value;
    mapping (int => string) myMap2 = myMap;
  }
}

注意:如果想访问mapping中不存在的key,返回的value为0。

delete 操作符

可用于操作任何类型的变量。

  • 对动态数组使用delete操作符,则删除所有元素,其长度变为0。
  • 对静态数组使用delete操作符,则重置所有索引
  • 对map类型使用delete操作符,什么都不会发生,但是,对map类型的一个键使用delete操作符,则会删除与该键相关的值

示例

contract sample {
    struct Struct {
        mapping (int => int) myMap;
        int myNumber;
    }
    int[] myArray;
    Struct myStruct;
    function sample(int key,int value,int number,int[] array) {
        myStruct = Struct(number);
        myStruct = Struct(number);
        myStruct.myMap[key] = value;//对某个键赋值
        myArray = array;
    }
    function reset() {
        delete myArray;//myArray数组长度为0
        delete myStruct;//myNumber为0,myMap不变
    }
    function deleteKey(int key) {
        delete myStruct.myMap[key];//删除myMap中的某个键的值
    }
}

基本类型之间的转换

  • 隐式转换:常用。通常来说,如果没有语义信息丢失,值和类型之间可以进行隐式转换:uint8可转换为uint16,int128可转换为int256,但是int8不可转换为uint256(因为uint256不能存储,例如-1)
  • Solidity也支持显式转换,如果编译器不允许在两种数据类型之间隐式转换,则可以进行显式转换。建议尽量避免显式转换,因为可能返回难以预料的结果。

示例:

uint32 a = 0x12345678;
uint16 b = uint16(a); // b = 0x5678,将uint32类型显式转换为uint16,也就是说,把较大类型转换为较小类型,因此高位被截掉了

var

使用关键字var声明的变量,其变量类型根据分配给它的第一个值来动态确定。一旦分配了值,类型就固定了,所以如果给它指定另一个类型,将引起类型转换。

int256 x= 12;
var y = x;//此时y的类型是int256
uint256 z = 9;
y = z;//此时,报出异常,因为uint256不能转换为int256类型

但要注意的是:

  • 在定义数组array和map时不能使用var。var也不能用于定义函数参数和状态变量


相关文章
|
6月前
|
前端开发 JavaScript 数据挖掘
《Solidity 简易速速上手小册》第9章:DApp 开发与 Solidity 集成(2024 最新版)(下)
《Solidity 简易速速上手小册》第9章:DApp 开发与 Solidity 集成(2024 最新版)
57 1
|
3月前
|
存储 安全 编译器
Metamask项目方给Solidity程序员的16个安全建议
文章是Metamask项目方Consensys在2020年发布的关于智能合约安全的博文,提供了16条Solidity程序员的安全建议,包括正确使用assert()、require()、revert()函数,避免使用tx.origin进行授权,注意整数除法舍入问题等,以帮助开发者提高智能合约的安全性。
38 0
|
6月前
|
存储 供应链 安全
《Solidity 简易速速上手小册》第1章:Solidity 和智能合约简介(2024 最新版)
《Solidity 简易速速上手小册》第1章:Solidity 和智能合约简介(2024 最新版)
175 1
|
6月前
|
存储 前端开发 安全
《Solidity 简易速速上手小册》第9章:DApp 开发与 Solidity 集成(2024 最新版)(上)
《Solidity 简易速速上手小册》第9章:DApp 开发与 Solidity 集成(2024 最新版)
100 0
|
区块链
竞技链游系统的开发逻辑代码示例,使用Solidity语言编写
竞技链游系统的开发逻辑代码示例,使用Solidity语言编写
|
存储 区块链 数据库
Solidity开发智能合约
一个简单的智能合约 在Solidity中,一个合约由一组代码(合约的函数)和数据(合约的状态)组成。合约位于以太坊区块链上的一个特殊地址。
1518 0
|
存储 JavaScript 前端开发
【一步步一起学DApp开发】(三)Solidity语言讲解 | 用Solidity编写智能合约 下
【一步步一起学DApp开发】(三)Solidity语言讲解 | 用Solidity编写智能合约
248 0
|
Web App开发 IDE 区块链
Solidity番外篇(一)Solidity在线or插件使用
Solidity番外篇(一)Solidity在线or插件使用
209 0
Solidity番外篇(一)Solidity在线or插件使用
|
Java 区块链
【智能合约】Solidity 进阶编程 | 注意一下合约中的细节
目录 1. 内置的全局变量 2. 错误处理 3. 访问函数 4. 创建合约 5. 合约继承 6. 修饰器modifier 最后
248 0
【智能合约】Solidity 进阶编程 | 注意一下合约中的细节
|
存储 JavaScript 前端开发
【智能合约】Solidity 基础知识 | 以太坊智能合约编程语言
目录 注意事项 编译器选择 一些说明 1. 变量 1.1 状态变量 1.2 局部变量 2. 数据类型 2.1 值类型 2.1.1 布尔类型(Booleans): 2.1.2 整型(Integers): 2.1.3 定长浮点型(Fixed Point Numbers): 2.1.4 定长字节数组(Fixed-size byte arrays) 2.1.5 有理数和整型常量(Rational and Integer Literals) 2.1.6 枚举(Enums) 2.1.7 函数类型(Function Types) 修饰符 函数定义 函数返回值 构造函数 2.1.8 地址类型(Address)
417 0
【智能合约】Solidity 基础知识 | 以太坊智能合约编程语言