jjzjj

Solidity教程一

凌少skier 2025-05-20 原文

合约的基础内容

  • 版本制定
  • 合约内容
    一个合约的模板如下所示
pragma solidity ^0.4.19;

contract HelloWorld {

}

状态变量和整数

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

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

无符号整数:uint
uint 无符号数据类型, 指其值不能是负数,对于有符号的整数存在名为 int 的数据类型。

数学运算

加法: x + y
减法: x - y,
乘法: x * y
除法: x / y
取模 / 求余: x % y
乘方:x**y

结构体

结构体允许使用更为复杂的数据结构

struct Person {
  uint age;
  string name;
}

数组

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

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

也可以创建一个结构体类型的数组

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

公共数组

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

Person[] public people;

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

定义函数

定义函数的语句如下

function eatHamburgers(string _name, uint _amount) {

}

使用结构体和数组

创建新的结构体

struct Person {
  uint age;
  string name;
}

Person[] public people;

然后把数据添加到数组中,采用push的方式

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

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

或者直接一步直接推进去
people.push(Person(16, "Vitalik"));

私有、公有函数

Solidity 定义的函数的属性默认为公共。 这就意味着任何一方 (或其它合约) 都可以调用你合约里的函数。

显然,不是什么时候都需要这样,而且这样的合约易于受到攻击。 所以将自己的函数定义为私有是一个好的编程习惯,只有当你需要外部世界调用它时才将它设置为公共。

以下为定义一个私有函数的方式

uint[] numbers;

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

这意味着只有我们合约中的其它函数才能够调用这个函数,给 numbers 数组添加新成员。

可以看到,在函数名字后面使用关键字 private 即可。和函数的参数类似,私有函数的名字用(_)起始。

函数的更多属性

返回值

string greeting = "What's up dog";

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

函数的修饰符

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

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

function sayHello() public view returns (string) {

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

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

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

Keccak256 和 类型转换

如何返回一个全随机的uint值呢

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) {
  // 干些事
})

Web3.js

我们的 Solidity 合约完工了! 现在我们要写一段 JavaScript 前端代码来调用这个合约。

以太坊有一个 JavaScript 库,名为Web3.js

在后面的里,我们会进一步地教你如何安装一个合约,如何设置Web3.js。 但是现在我们通过一段代码来了解 Web3.js 是如何和我们发布的合约交互的吧。

// 下面是调用合约的方式:
var abi = /* abi是由编译器生成的 */
var ZombieFactoryContract = web3.eth.contract(abi)
var contractAddress = /* 发布之后在以太坊上生成的合约地址 */
var ZombieFactory = ZombieFactoryContract.at(contractAddress)
// `ZombieFactory` 能访问公共的函数以及事件

// 某个监听文本输入的监听器:
$("#ourButton").click(function(e) {
  var name = $("#nameInput").val()
  //调用合约的 `createRandomZombie` 函数:
  ZombieFactory.createRandomZombie(name)
})

// 监听 `NewZombie` 事件, 并且更新UI
var event = ZombieFactory.NewZombie(function(error, result) {
  if (error) return
  generateZombie(result.zombieId, result.name, result.dna)
})

// 获取 Zombie 的 dna, 更新图像
function generateZombie(id, name, dna) {
  let dnaStr = String(dna)
  // 如果dna少于16位,在它前面用0补上
  while (dnaStr.length < 16)
    dnaStr = "0" + dnaStr

  let zombieDetails = {
    // 前两位数构成头部.我们可能有7种头部, 所以 % 7
    // 得到的数在0-6,再加上1,数的范围变成1-7
    // 通过这样计算:
    headChoice: dnaStr.substring(0, 2) % 7 + 1// 我们得到的图片名称从head1.png 到 head7.png

    // 接下来的两位数构成眼睛, 眼睛变化就对11取模:
    eyeChoice: dnaStr.substring(2, 4) % 11 + 1,
    // 再接下来的两位数构成衣服,衣服变化就对6取模:
    shirtChoice: dnaStr.substring(4, 6) % 6 + 1,
    //最后6位控制颜色. 用css选择器: hue-rotate来更新
    // 360度:
    skinColorChoice: parseInt(dnaStr.substring(6, 8) / 100 * 360),
    eyeColorChoice: parseInt(dnaStr.substring(8, 10) / 100 * 360),
    clothesColorChoice: parseInt(dnaStr.substring(10, 12) / 100 * 360),
    zombieName: name,
    zombieDescription: "A Level 1 CryptoZombie",
  }
  return zombieDetails
}

我们的 JavaScript 所做的就是获取由zombieDetails 产生的数据, 并且利用浏览器里的 JavaScript 神奇功能 (我们用 Vue.js),置换出图像以及使用CSS过滤器。在后面的课程中,你可以看到全部的代码。

有关Solidity教程一的更多相关文章

  1. 玩以太坊链上项目的必备技能(初识智能合约语言-Solidity之旅一) - 2

    前面一篇关于智能合约翻译文讲到了,是一种计算机程序,既然是程序,那就可以使用程序语言去编写智能合约了。而若想玩区块链上的项目,大部分区块链项目都是开源的,能看得懂智能合约代码,或找出其中的漏洞,那么,学习Solidity这门高级的智能合约语言是有必要的,当然,这都得在公链``````以太坊上,毕竟国内的联盟链有些是不兼容Solidity。Solidity是一种面向对象的高级语言,用于实现智能合约。智能合约是管理以太坊状态下的账户行为的程序。Solidity是运行在以太坊(Ethereum)虚拟机(EVM)上,其语法受到了c++、python、javascript影响。Solidity是静态类型

  2. Solidity教程一 - 2

    合约的基础内容版本制定合约内容一个合约的模板如下所示pragmasolidity^0.4.19;contractHelloWorld{}状态变量和整数状态变量是被永久地保存在合约中。也就是说它们被写入以太币区块链中.想象成写入一个数据库。contractExample{//这个无符号整数将会永久的被保存在区块链中uintmyUnsignedInteger=100;}无符号整数:uintuint无符号数据类型,指其值不能是负数,对于有符号的整数存在名为int的数据类型。数学运算加法:x+y减法:x-y,乘法:x*y除法:x/y取模/求余:x%y乘方:x**y结构体结构体允许使用更为复杂的数据结构

  3. Solidity,智能合约的学习(1) - 2

    Solidity概述Solidity是一种智能合约高级语言,运行在Ethereum虚拟机(EVM)上,Solidity是面向对象的高级语言,用于实现智能合约。智能合约是管理以太坊状态内的账户行为的程序。BitPen认为,作为Web3的链上玩家,那么能够看懂Solidity代码将会是一项必备的技能,因为大多区块链项目都是在GitHub开源,如果你能看懂甚至编写Solidity代码,那么你在链上项目游玩的技能将大大提升,可以避免很多恶意合约以及有漏洞的Rug项目。开发工具:RemixRemix网址:remix.ethereum.org​​​​​​​Remix作为以太坊官方推荐的智能合约开发IDE,

  4. Solidity合约内创建合约以及引用其他合约的总结 - 2

    本文总结了在以太坊智能合约中使用Solidity在合约内创建合约以及引用其他合约的方法,包括了如何使用mochai进行测试的方法。在这之前先明白一个比较:Contract{}相当于面向对象语言的类当部署后获得到address后,address相当于对象,address0x.......本身就类似指针地址然后我们讨论下Solidity代码中对合约类,合约对象的操作。Solidity首先区分下三种写法:import'ContractB.sol';ConractBB=newConractB(arg1,arg2...);ContractBB=ContractB(Baddress);functionse

  5. solidity:智能合约结构介绍 - 2

    合约结构介绍1.SPDX版权声明bytecodemetadata介绍2.pragmasolidity版本限制3.contract关键字4.import导入声明5.interface:接口6.library:库合约合约结构介绍1.SPDX版权声明第1行//SPDX-License-Identifier:MIT就是合约的版权声明。其中SPDX-License-Identifier(SPDX许可标示)是标注当前的智能合约采用什么样的对外开放标准,该标准规定了别人是否拥有商业开发,学习使用等权利。代码中使用的MIT规定了其他人随便用该代码,但出问题不负责。MIT详细解释;SPDX许可标示的注释在文件的

  6. 以太坊Solidity迁移Flow Cadence指南8-ERC721/NFT迁移 - 2

    序言本小节是本系列短文的核心章节,主要介绍如何将solidity标准的ERC721合约迁移到flow cadence,大家前面也学了这么多了,就看这一节了!!!什么?前面几节都没看到。本来2022.5月就要写完的,结果5月笔者一直足不出户在家办公,主要在研究如下内容: 图 1用做菜的思路迁移代码笔者发现,有一种叫做“预制菜”的东西,不用开荒种地,不用掌握油盐酱醋配比,锅里一放,简单炒炒就是等级厨师的作品了。。。嗯,solidity ---->cadence迁移是否也能采用“预制菜”模式呢?给你想要的!填写你的以太坊ERC721合约地址,然后你就能得到:1Solidity ERC721合约对应的

  7. 智能合约学习笔记一 、——{Solidity语言详解——(1—2)小练习} - 2

    1.要求:1.根据提示,在指定位置写出编译版本,要求使用^符号,版本要求在0.6.0及以上。2.根据提示,在指定位置写出所定义的合约名称。3.为了查看程序的效果,我们使用在线Solidity开发工具RemixIDE编译和运行Solidity程序。中文在线版:在浏览器打开下方链接: Remix-中文版-智谷星图。第1步–在文件浏览器选项卡下,新建一个Firstapp.sol文件,把我们补充完整的代码直接复制过来。第2步–在SOLIDITY编译器选项卡下,选择0.6.5的那个编译器版本并单击 编译Firstapp.sol 按钮,开始编译。编译成功后会根据本地客户端和版本内容弹出提示,可以不用处理。

  8. solidity开发智能合约 - 2

    文章目录1Solidity与智能合约2智能合约概述3以太坊简介4以太坊交互工具5开发环境搭建5.1remix在线编译器5.2搭建本地网络5.2.1安装本地remix-ide5.2.2安装remixd5.3编译合约5.4编译原理6常见概念7Solidity基础语法7.1数据类型分类7.2remix的使用--第一个智能合约7.3值类型7.3.1布尔bool7.3.2整形intuint7.3.3函数类型7.3.4地址(Address)7.3.5枚举类型(enums)7.3.6定长字节数组7.4引用类型7.4.1不定长数组7.4.2字符串(string)7.4.3引用类型的内存分配(memory和st

  9. go - 运行线程一定时间 - 在被杀死之前 - 2

    如何运行10个线程,每个线程30秒,然后返回程序执行?比如我要生成10个线程并运行30秒。然后杀死所有线程然后second()运行(即在所有线程执行完毕后)到目前为止,我有以下内容,但是,当我这样做时,线程(显然)继续执行并且CPU使用率在30秒后保持在100%:funcmain(){fori:=0;i 最佳答案 您可以使用Golang上下文。这是我学习时的一些代码。packagemainimport("fmt""log""time""golang.org/x/net/context")funcmain(){someHandler(

  10. 如何用 Solidity 创建一个“Hello World”智能合约 - 2

    最近发几篇简单的入门文章,帮助刚刚进入行业的工程师。这篇文章将带你学习如何使用智能合约开发语言Solidity创建一个名为“HelloWorld”的智能合约。这篇文章不需要先验知识,初学者也很容易上手,跟着下面的步骤操作也可以轻松地的创建你的第一个智能合约。什么是智能合约智能合约是在区块链环境中发布和运行的计算机程序。由于它运行在区块链上,所以其运行不需要中心化的组织或服务器。由于区块链的不变性,智能合约一旦被发布,就无法对其更新或修改。但智能合约中可能编写有具有更改数据功能的函数。信息可以在一个块中记录并在另一个块中删除,其历史记录会被保存并可以对其审核。Solidity编程语言Solidi

随机推荐