Solidaty学习——加密僵尸(一)

172 阅读5分钟

solidaty基础语法学习(一)

lesson 1

合约

pragma solidity ^0.4.19;//1. 版本指令

//2. 建立僵尸工厂智能合约
contract ZombieFactory {

}

状态变量和整数

状态变量是被永久地保存在合约中。也就是说它们被写入以太币区块链中,可以想象成写入一个数据库。

contract Example { 
// 这个无符号整数将会永久的被保存在区块链中 
uint myUnsignedInteger = 100; 
}

无符号整数: uint(uint256)

uint无符号数据类型,它的值不能是负数,uint存放有符号的整数

数学运算

  • 加法: x + y
  • 减法: x - y,
  • 乘法: x * y
  • 除法: x / y
  • 取模 / 求余: x % y  (例如, 13 % 5 余 3, 因为13除以5,余3)

Solidity 还支持 乘方操作 (如:x 的 y次方) // 例如: 5 ** 2 = 25

uint x = 5 ** 2; // equal to 5^2 = 25

结构体

struct Person { 
    uint age; 
    string name; 
}

结构体允许你生成一个更复杂的数据类型,它具有多个属性。

string类型,即字符串,用于保存任意长度的UTF-8编码数据

数组

如果你想建立一个集合,可以用  数组 这样的数据类型. Solidity 支持两种数组:  静态  数组和 动态  数组

// 固定长度为2的静态数组: 
uint[2] fixedArray; 
// 固定长度为5的string类型的静态数组: 
string[5] stringArray; 
// 动态数组,长度不固定,可以动态添加元素: 
uint[] dynamicArray;

也可以建立一个 结构体类型的数组 例如,上面提到的 Person:

Person[] people; // 这是动态数组,可以被不断地添加进元素

公共数组

可以定义 public 数组, Solidity 会自动创建 getter 方法. 语法如下:

Person[] public people;

其它的合约可以从这个数组读取数据(但不能写入数据),所以这在合约中是一个有用的保存公共数据的模式。

函数

在 Solidity 中函数定义的句法如下:

function eatWatermelon(uint _size, uint _amount) {

}

这是一个名为 eatHamburgers 的函数,它接受两个参数:一个 uint类型的size和 一个 uint类型的amount。现在函数内部还是空的。

注:: 习惯上函数里的变量都是以(_)开头 (但不是硬性规定) 以区别全局变量。

使用结构体和数组

创建新的结构体

沿用以上的Person结构体, 现在学习创建新的 Person 结构,然后把它加入到名为 people 的数组中。

// 创建一个新的Person:
Person satoshi = Person(172, "Satoshi");

// 将新创建的satoshi添加进people数组:
people.push(satoshi);

也可以两步并一步,用一行代码更简洁:

people.push(Person(16, "Vitalik"));

注:array.push() 在数组的 尾部 加入新元素 ,所以元素在数组中的顺序就是我们添加的顺序, 如:

uint[] numbers;
numbers.push(5);
numbers.push(10);
numbers.push(15);
// numbers is now equal to [5, 10, 15]

私有/公共函数

solidaty默认属性为公共,但有时还是需要设置成私有,只有当该函数需要被外界调用时才需要设置为公共
定义一个私有函数:

uint[] numbers; 

function _addToArray(uint _number) private { 
    numbers.push(_number); 
    }

这说明,只有我们合约中的其他函数才能调用这个private属性的函数,来给numbers数组添加新成员。

函数的更多属性

返回值

要想函数返回一个数值,按如下定义:

string greeting = "What's up dog";

function sayHello() public returns (string) {
  return greeting;
}

Solidity 里,函数的定义里可包含返回值的数据类型(如本例中 string)。

函数的修饰符

上面的函数实际上没有改变 Solidity 里的状态,即,它没有改变任何值或者写任何东西。

这种情况下我们可以把函数定义为 view, 意味着它只能读取数据不能更改数据:

function sayHello() public view returns (string) {

Solidity 还支持 pure 函数, 表明这个函数甚至都不访问应用里的数据,例如:

function _multiply(uint a, uint b) private pure returns (uint) {
  return a * b;
}

这个函数甚至都不读取应用里的状态 — 它的返回值完全取决于它的输入参数,在这种情况下我们把函数定义为 pure.

注:可能很难记住何时把函数标记为 pure/view。但Solidity 编辑器会给出提示,提醒你使用这些修饰符。

Keccak256和类型转换

Ethereum 内部有一个散列函数keccak256,它用了SHA3版本。一个散列函数基本上就是把一个字符串转换为一个256位的16进制数字。字符串的一个微小变化会引起散列数据极大变化。

这在 Ethereum 中有很多应用,但是现在我们只是用它造一个伪随机数。

例子:

//6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5
keccak256("aaaab");
//b1f078126895a1424524de5321b339ab00408010b7cf0e6ed451514981e58aa9
keccak256("aaaac");

显而易见,输入字符串只改变了一个字母,输出就已经天壤之别了。

注: 在区块链中安全地产生一个随机数是一个很难的问题

类型转换

有时你需要变换数据类型。例如:

uint8 a = 5;
uint b = 6;
// 将会抛出错误,因为 a * b 返回 uint, 而不是 uint8:
uint8 c = a * b;
// 我们需要将 b 转换为 uint8:
uint8 c = a * uint8(b);

上面, a * b 返回类型是 uint, 但是当我们尝试用 uint8 类型接收时, 就会造成潜在的错误。如果把它的数据类型转换为 uint8, 就可以了,编译器也不会出错。

事件

事件是合约和区块链通讯的一种机制。你的前端应用“监听”某些事件,并做出反应。

例如:

// 这里建立事件
event IntegersAdded(uint x, uint y, uint result);

function add(uint _x, uint _y) public {
  uint result = _x + _y;
  //触发事件,通知app
  IntegersAdded(_x, _y, result);
  return result;
}

你的 app 前端可以监听这个事件。JavaScript 实现如下:

YourContract.IntegersAdded(function(error, result) {
  // 干些事
})