Solidity: Beginner to Intermediate Smart Contracts

Solidity: Beginner to Intermediate Smart Contracts
CrystalYan LiuSolidity: Beginner to Intermediate Smart Contracts
Solidity:从初学者到中级智能合约
Solidity 是一种面向合约的编程语言,专门用于在 以太坊(Ethereum)等区块链平台上编写智能合约(Smart Contracts)。它是一种类似 JavaScript、Python 和 C++ 的高级语言,主要用于定义去中心化应用(DApps)的逻辑,确保在区块链上执行透明、安全、不可篡改的交易和合约。
Making the Zombie Factory
Chapter1: lesson overview
在这个课程中,我们要去建造一个创造僵尸军队的僵尸工厂。
- 工厂会有一个存放僵尸数据的数据库
- 工厂有一个创造僵尸的函数
- 每一个僵尸都有一个随机的独一无二的外表
How Zombie DNA Works

僵尸的外表是基于僵尸的DNA的,僵尸的DNA是一个16位的整数 belike:
8356281049284737
就和真的DNA一样,DNA的某些位置是和僵尸的外表对应的。比如【前两位对应僵尸的头的类型】【第二个两位对应僵尸的眼睛类型】
在这个tutorial中,头的类型为了便于调整只有7种,实际上两位数可以表示100种(0~99)。
例如:上面的例子中前两位是83,映射到7种就是83 % 7 + 1 = 7。所以僵尸会有第七个头的类型。
Chapter2:Contracts
Solidity 的代码封装在 合约(Contract) 中。合约是 以太坊应用程序(Ethereum Applications) 的基本构建块,所有的 变量(Variables) 和 函数(Functions) 都属于某个合约。这将是你所有项目的起点。
Solidity’s code is encapsulated in contracts. A contract is the fundamental building block of Ethereum applications — all variables and functions belong to a contract, and this will be the starting point of all your projects.
一个名为HelloWorld的空合约示例如下:
| 1 | contract HelloWorld { | 
Version Pragma
所有的solidity源代码都会以”version pragma”开头,这是对solidity版本的一个声明。在这一套课程中,我们会使用pragma solidiy >=0.5.0 <0.6.0;
放一起就是每次写一个代码之前必须在前面加的:
| 1 | pragma solidity >=0.5.0 <0.6.0; | 
在我们的僵尸工厂中,我们的Contract.sol为:
| 1 | pragma solidity >=0.5.0 <0.6.0; | 
Chapter3:State Variables & Integers
状态变量(State Variables)是 永久存储在合约存储(Contract Storage)  中的数据。
这意味着它们被 写入以太坊区块链,类似于向数据库(DB)写入数据。
例如:
| 1 | contract Example { | 
在这个示例合约中,我们创建了一个uint变量myUnsignedInteger并且设置为了100
Unsigned Integers:uint
这个数据类型是一个无符号整型,只能存非负数。
在Solidity中,
uint也是一个uint256一个256bit的无符号整数(意思是能存$0\sim2^{256}-1$的数字对于int256来说就是$-2^{256-1}\sim2^{256-1}-1$)同样的还有uint8,uint16等等。
Chapter4:Math Operations
Solidity中支持数学计算:
- 加法x + y
- 减法x - y
- 乘法x * y
- 除法x / y
- 取模x % y
同样还支持指数运算符:
| 1 | uint x = 5 ** 2; // equal to 5^2 = 25 | 
Chapter5:Structs
甚至和C++一样,Solidity提供了结构体的使用
| 1 | struct Person{ | 
Chapter6:Arrays
在Solidity中,有两种数组:fixed arrays dynamic arrays
| 1 | // Array with a fixed length of 2 elements: | 
甚至可以创建一个结构体数组:
| 1 | Person[] people; // dynamic Array, we can keep adding to it | 
Public Arrays
可以创建一个public数组,并且Solidity会自动创建一个getter方法。
| 1 | Person[] public people; | 
这样别的合约就只能读取内容,不能写入内容。
Chapter7:Fuction Declarations
在Solidity中,函数的声明长得像:
| 1 | function eatHambuger(string memory _name, uint _amount) public{ | 
这是一个有两个参数(uint和string 的函数)
这里
string是引用类型,必须指定是memory或者storage,memory不会存入区块链,storage会长期存储并消耗gas
在 Solidity 中,函数参数的传递方式有两种:
- 按值传递(By Value) 👉 创建副本,函数内的修改不会影响原变量。
- 按引用传递(By Reference) 👉 直接引用原变量,修改会影响原始数据。
Chapter8:Working With Structs and Arrays
Creating New Structs
首先创建一个结构体Person
| 1 | struct Person { | 
现在我们要创建一个新的Person,并且将它加入到people数组中:
| 1 | Person satoshi = Person(172, "Satoshi"); | 
这里的push是将元素放到数组的最后面。
Chapter9:Private/Public Functions
在Solidity中,函数默认是public,这意味着所有人或者所有合约都能够调用这个函数。
但是这会让我们的合约容易被攻击, 所以出现了private函数:
| 1 | uint[] numbers; | 
这里只有在我们自己合约中的函数才能够调用这个函数。一般来说private函数的开头总是有一个下划线_
Chapter10:More on Functions
Return Values
是函数返回的一个值(字面意思)
| 1 | string greeting = "What's up"; | 
在Solidity中,函数的声明也需要包含返回值的类型(在上面为string)
Function modifiers
上面的函数并没有改变任何状态,换言之就是没有写入或者是改变什么。
这里我们声明一个view函数,只viewing数据,但是不会修改:
| 1 | function sayHello() public view returns (string memory){} | 
在 Solidity 中,纯函数(Pure Functions) 指的是 不读取或修改区块链上的任何数据 的函数。
这意味着它们只能执行数学计算或处理传入的参数,不会访问 状态变量 或 合约存储。
Chapter 11:Keccak256 and Typecasting
Ethereum中有一个内置函数keccak256 (SHA3)能够将输入映射为一个256位的随机十六进制数。一个小小的改变都会导致输出的结果发生翻天覆地的变化:
| 1 | //6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5 | 
Typecasting
有时候我们需要再数据类型中转换:
| 1 | uint8 a = 5; | 
就像上面的代码一样,我们只需要在运算过程中进行转换即可。
Chapter 12:Putting It Together
这一章是对前面内容的一个小总结,目标是创建一个public函数,通过输入僵尸的名字来创建一个随机的僵尸DNA。这里直接贴出:
- Create a public function namedcreateRandomZombie. It will take one parameter named_name (astring with the data location set tomemory). (Note: Declare this function public just as you declared previous functions private )
- The first line of the function should run the _generateRandomDna function on_name, and store it in auint namedrandDna.
- The second line should run the _createZombie function and pass it_name andrandDna.
- The solution should be 4 lines of code (including the closing } of the function).
| 1 | function createRandomZombie(string memory _name) public { | 
Chapter 13:Events
事件(Events) 是智能合约与外部应用(如前端界面)之间通信的机制。合约通过触发事件,将特定信息记录在区块链的交易日志中,外部应用可以监听这些事件并在发生时采取相应的操作。
| 1 | // declare the event | 
外部应用会监听这个事件,对于JavaScript来说:
| 1 | YourContract.IntegersAdded(function(error, result) { | 







